Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip into trace/tip/tracing/core-7
Conflicts:
include/linux/ftrace_event.h
include/trace/ftrace.h
kernel/trace/trace_event_perf.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_syscalls.c
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index 1423d25..44c6dcc9 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -3,35 +3,79 @@
The CONFIG_RCU_CPU_STALL_DETECTOR kernel config parameter enables
RCU's CPU stall detector, which detects conditions that unduly delay
RCU grace periods. The stall detector's idea of what constitutes
-"unduly delayed" is controlled by a pair of C preprocessor macros:
+"unduly delayed" is controlled by a set of C preprocessor macros:
RCU_SECONDS_TILL_STALL_CHECK
This macro defines the period of time that RCU will wait from
the beginning of a grace period until it issues an RCU CPU
- stall warning. It is normally ten seconds.
+ stall warning. This time period is normally ten seconds.
RCU_SECONDS_TILL_STALL_RECHECK
This macro defines the period of time that RCU will wait after
- issuing a stall warning until it issues another stall warning.
- It is normally set to thirty seconds.
+ issuing a stall warning until it issues another stall warning
+ for the same stall. This time period is normally set to thirty
+ seconds.
RCU_STALL_RAT_DELAY
- The CPU stall detector tries to make the offending CPU rat on itself,
- as this often gives better-quality stack traces. However, if
- the offending CPU does not detect its own stall in the number
- of jiffies specified by RCU_STALL_RAT_DELAY, then other CPUs will
- complain. This is normally set to two jiffies.
+ The CPU stall detector tries to make the offending CPU print its
+ own warnings, as this often gives better-quality stack traces.
+ However, if the offending CPU does not detect its own stall in
+ the number of jiffies specified by RCU_STALL_RAT_DELAY, then
+ some other CPU will complain. This delay is normally set to
+ two jiffies.
-The following problems can result in an RCU CPU stall warning:
+When a CPU detects that it is stalling, it will print a message similar
+to the following:
+
+INFO: rcu_sched_state detected stall on CPU 5 (t=2500 jiffies)
+
+This message indicates that CPU 5 detected that it was causing a stall,
+and that the stall was affecting RCU-sched. This message will normally be
+followed by a stack dump of the offending CPU. On TREE_RCU kernel builds,
+RCU and RCU-sched are implemented by the same underlying mechanism,
+while on TREE_PREEMPT_RCU kernel builds, RCU is instead implemented
+by rcu_preempt_state.
+
+On the other hand, if the offending CPU fails to print out a stall-warning
+message quickly enough, some other CPU will print a message similar to
+the following:
+
+INFO: rcu_bh_state detected stalls on CPUs/tasks: { 3 5 } (detected by 2, 2502 jiffies)
+
+This message indicates that CPU 2 detected that CPUs 3 and 5 were both
+causing stalls, and that the stall was affecting RCU-bh. This message
+will normally be followed by stack dumps for each CPU. Please note that
+TREE_PREEMPT_RCU builds can be stalled by tasks as well as by CPUs,
+and that the tasks will be indicated by PID, for example, "P3421".
+It is even possible for a rcu_preempt_state stall to be caused by both
+CPUs -and- tasks, in which case the offending CPUs and tasks will all
+be called out in the list.
+
+Finally, if the grace period ends just as the stall warning starts
+printing, there will be a spurious stall-warning message:
+
+INFO: rcu_bh_state detected stalls on CPUs/tasks: { } (detected by 4, 2502 jiffies)
+
+This is rare, but does happen from time to time in real life.
+
+So your kernel printed an RCU CPU stall warning. The next question is
+"What caused it?" The following problems can result in RCU CPU stall
+warnings:
o A CPU looping in an RCU read-side critical section.
-o A CPU looping with interrupts disabled.
+o A CPU looping with interrupts disabled. This condition can
+ result in RCU-sched and RCU-bh stalls.
-o A CPU looping with preemption disabled.
+o A CPU looping with preemption disabled. This condition can
+ result in RCU-sched stalls and, if ksoftirqd is in use, RCU-bh
+ stalls.
+
+o A CPU looping with bottom halves disabled. This condition can
+ result in RCU-sched and RCU-bh stalls.
o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel
without invoking schedule().
@@ -39,20 +83,24 @@
o A bug in the RCU implementation.
o A hardware failure. This is quite unlikely, but has occurred
- at least once in a former life. A CPU failed in a running system,
+ at least once in real life. A CPU failed in a running system,
becoming unresponsive, but not causing an immediate crash.
This resulted in a series of RCU CPU stall warnings, eventually
leading the realization that the CPU had failed.
-The RCU, RCU-sched, and RCU-bh implementations have CPU stall warning.
-SRCU does not do so directly, but its calls to synchronize_sched() will
-result in RCU-sched detecting any CPU stalls that might be occurring.
+The RCU, RCU-sched, and RCU-bh implementations have CPU stall
+warning. SRCU does not have its own CPU stall warnings, but its
+calls to synchronize_sched() will result in RCU-sched detecting
+RCU-sched-related CPU stalls. Please note that RCU only detects
+CPU stalls when there is a grace period in progress. No grace period,
+no CPU stall warnings.
-To diagnose the cause of the stall, inspect the stack traces. The offending
-function will usually be near the top of the stack. If you have a series
-of stall warnings from a single extended stall, comparing the stack traces
-can often help determine where the stall is occurring, which will usually
-be in the function nearest the top of the stack that stays the same from
-trace to trace.
+To diagnose the cause of the stall, inspect the stack traces.
+The offending function will usually be near the top of the stack.
+If you have a series of stall warnings from a single extended stall,
+comparing the stack traces can often help determine where the stall
+is occurring, which will usually be in the function nearest the top of
+that portion of the stack which remains the same from trace to trace.
+If you can reliably trigger the stall, ftrace can be quite helpful.
RCU bugs can often be debugged with the help of CONFIG_RCU_TRACE.
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt
index 8608fd8..efd8cc9 100644
--- a/Documentation/RCU/trace.txt
+++ b/Documentation/RCU/trace.txt
@@ -256,23 +256,23 @@
The output of "cat rcu/rcu_pending" looks as follows:
rcu_sched:
- 0 np=255892 qsp=53936 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741
- 1 np=261224 qsp=54638 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792
- 2 np=237496 qsp=49664 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629
- 3 np=236249 qsp=48766 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723
- 4 np=221310 qsp=46850 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110
- 5 np=237332 qsp=48449 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456
- 6 np=219995 qsp=46718 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834
- 7 np=249893 qsp=49390 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888
+ 0 np=255892 qsp=53936 rpq=85 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741
+ 1 np=261224 qsp=54638 rpq=33 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792
+ 2 np=237496 qsp=49664 rpq=23 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629
+ 3 np=236249 qsp=48766 rpq=98 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723
+ 4 np=221310 qsp=46850 rpq=7 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110
+ 5 np=237332 qsp=48449 rpq=9 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456
+ 6 np=219995 qsp=46718 rpq=12 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834
+ 7 np=249893 qsp=49390 rpq=42 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888
rcu_bh:
- 0 np=146741 qsp=1419 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314
- 1 np=155792 qsp=12597 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180
- 2 np=136629 qsp=18680 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936
- 3 np=137723 qsp=2843 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863
- 4 np=123110 qsp=12433 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671
- 5 np=137456 qsp=4210 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235
- 6 np=120834 qsp=9902 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921
- 7 np=144888 qsp=26336 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542
+ 0 np=146741 qsp=1419 rpq=6 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314
+ 1 np=155792 qsp=12597 rpq=3 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180
+ 2 np=136629 qsp=18680 rpq=1 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936
+ 3 np=137723 qsp=2843 rpq=0 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863
+ 4 np=123110 qsp=12433 rpq=0 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671
+ 5 np=137456 qsp=4210 rpq=1 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235
+ 6 np=120834 qsp=9902 rpq=2 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921
+ 7 np=144888 qsp=26336 rpq=0 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542
As always, this is once again split into "rcu_sched" and "rcu_bh"
portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional
@@ -284,6 +284,9 @@
o "qsp" is the number of times that the RCU was waiting for a
quiescent state from this CPU.
+o "rpq" is the number of times that the CPU had passed through
+ a quiescent state, but not yet reported it to RCU.
+
o "cbr" is the number of times that this CPU had RCU callbacks
that had passed through a grace period, and were thus ready
to be invoked.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index ed511af..05df0b7 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -589,3 +589,26 @@
Generally invoked by accident today.
Seen as doing more harm than good.
Who: Len Brown <len.brown@intel.com>
+
+----------------------------
+
+What: video4linux /dev/vtx teletext API support
+When: 2.6.35
+Files: drivers/media/video/saa5246a.c drivers/media/video/saa5249.c
+ include/linux/videotext.h
+Why: The vtx device nodes have been superseded by vbi device nodes
+ for many years. No applications exist that use the vtx support.
+ Of the two i2c drivers that actually support this API the saa5249
+ has been impossible to use for a year now and no known hardware
+ that supports this device exists. The saa5246a is theoretically
+ supported by the old mxb boards, but it never actually worked.
+
+ In summary: there is no hardware that can use this API and there
+ are no applications actually implementing this API.
+
+ The vtx support still reserves minors 192-223 and we would really
+ like to reuse those for upcoming new functionality. In the unlikely
+ event that new hardware appears that wants to use the functionality
+ provided by the vtx API, then that functionality should be build
+ around the sliced VBI API instead.
+Who: Hans Verkuil <hverkuil@xs4all.nl>
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index a4f30fa..1e359b6 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -316,7 +316,7 @@
08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
0804a000-0806b000 rw-p 00000000 00:00 0 [heap]
a7cb1000-a7cb2000 ---p 00000000 00:00 0
-a7cb2000-a7eb2000 rw-p 00000000 00:00 0 [threadstack:001ff4b4]
+a7cb2000-a7eb2000 rw-p 00000000 00:00 0
a7eb2000-a7eb3000 ---p 00000000 00:00 0
a7eb3000-a7ed5000 rw-p 00000000 00:00 0
a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
@@ -352,7 +352,6 @@
[stack] = the stack of the main process
[vdso] = the "virtual dynamic shared object",
the kernel system call handler
- [threadstack:xxxxxxxx] = the stack of the thread, xxxxxxxx is the stack size
or if empty, the mapping is anonymous.
diff --git a/Documentation/intel_txt.txt b/Documentation/intel_txt.txt
index f40a1f0..87c8990 100644
--- a/Documentation/intel_txt.txt
+++ b/Documentation/intel_txt.txt
@@ -161,13 +161,15 @@
has been restored, it will restore the TPM PCRs and then
transfer control back to the kernel's S3 resume vector.
In order to preserve system integrity across S3, the kernel
- provides tboot with a set of memory ranges (kernel
- code/data/bss, S3 resume code, and AP trampoline) that tboot
- will calculate a MAC (message authentication code) over and then
- seal with the TPM. On resume and once the measured environment
- has been re-established, tboot will re-calculate the MAC and
- verify it against the sealed value. Tboot's policy determines
- what happens if the verification fails.
+ provides tboot with a set of memory ranges (RAM and RESERVED_KERN
+ in the e820 table, but not any memory that BIOS might alter over
+ the S3 transition) that tboot will calculate a MAC (message
+ authentication code) over and then seal with the TPM. On resume
+ and once the measured environment has been re-established, tboot
+ will re-calculate the MAC and verify it against the sealed value.
+ Tboot's policy determines what happens if the verification fails.
+ Note that the c/s 194 of tboot which has the new MAC code supports
+ this.
That's pretty much it for TXT support.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 907010c..567b7a8 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -324,6 +324,8 @@
they are unmapped. Otherwise they are
flushed before they will be reused, which
is a lot of faster
+ off - do not initialize any AMD IOMMU found in
+ the system
amijoy.map= [HW,JOY] Amiga joystick support
Map of devices attached to JOY0DAT and JOY1DAT
diff --git a/Documentation/rbtree.txt b/Documentation/rbtree.txt
index aae8355..221f38b 100644
--- a/Documentation/rbtree.txt
+++ b/Documentation/rbtree.txt
@@ -190,3 +190,61 @@
for (node = rb_first(&mytree); node; node = rb_next(node))
printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring);
+Support for Augmented rbtrees
+-----------------------------
+
+Augmented rbtree is an rbtree with "some" additional data stored in each node.
+This data can be used to augment some new functionality to rbtree.
+Augmented rbtree is an optional feature built on top of basic rbtree
+infrastructure. rbtree user who wants this feature will have an augment
+callback function in rb_root initialized.
+
+This callback function will be called from rbtree core routines whenever
+a node has a change in one or both of its children. It is the responsibility
+of the callback function to recalculate the additional data that is in the
+rb node using new children information. Note that if this new additional
+data affects the parent node's additional data, then callback function has
+to handle it and do the recursive updates.
+
+
+Interval tree is an example of augmented rb tree. Reference -
+"Introduction to Algorithms" by Cormen, Leiserson, Rivest and Stein.
+More details about interval trees:
+
+Classical rbtree has a single key and it cannot be directly used to store
+interval ranges like [lo:hi] and do a quick lookup for any overlap with a new
+lo:hi or to find whether there is an exact match for a new lo:hi.
+
+However, rbtree can be augmented to store such interval ranges in a structured
+way making it possible to do efficient lookup and exact match.
+
+This "extra information" stored in each node is the maximum hi
+(max_hi) value among all the nodes that are its descendents. This
+information can be maintained at each node just be looking at the node
+and its immediate children. And this will be used in O(log n) lookup
+for lowest match (lowest start address among all possible matches)
+with something like:
+
+find_lowest_match(lo, hi, node)
+{
+ lowest_match = NULL;
+ while (node) {
+ if (max_hi(node->left) > lo) {
+ // Lowest overlap if any must be on left side
+ node = node->left;
+ } else if (overlap(lo, hi, node)) {
+ lowest_match = node;
+ break;
+ } else if (lo > node->lo) {
+ // Lowest overlap if any must be on right side
+ node = node->right;
+ } else {
+ break;
+ }
+ }
+ return lowest_match;
+}
+
+Finding exact match will be to first find lowest match and then to follow
+successor nodes looking for exact match, until the start of a node is beyond
+the hi value we are looking for.
diff --git a/MAINTAINERS b/MAINTAINERS
index 5085c90..3d2651b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2953,6 +2953,17 @@
F: Documentation/networking/README.ipw2200
F: drivers/net/wireless/ipw2x00/ipw2200.*
+INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
+M: Joseph Cihula <joseph.cihula@intel.com>
+M: Shane Wang <shane.wang@intel.com>
+L: tboot-devel@lists.sourceforge.net
+W: http://tboot.sourceforge.net
+T: Mercurial http://www.bughost.org/repos.hg/tboot.hg
+S: Supported
+F: Documentation/intel_txt.txt
+F: include/linux/tboot.h
+F: arch/x86/kernel/tboot.c
+
INTEL WIRELESS WIMAX CONNECTION 2400
M: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
M: linux-wimax@intel.com
@@ -4165,6 +4176,7 @@
M: Robert Richter <robert.richter@amd.com>
L: oprofile-list@lists.sf.net
S: Maintained
+F: arch/*/include/asm/oprofile*.h
F: arch/*/oprofile/
F: drivers/oprofile/
F: include/linux/oprofile.h
@@ -5492,7 +5504,7 @@
F: drivers/mmc/host/tmio_mmc.*
TMPFS (SHMEM FILESYSTEM)
-M: Hugh Dickins <hugh.dickins@tiscali.co.uk>
+M: Hugh Dickins <hughd@google.com>
L: linux-mm@kvack.org
S: Maintained
F: include/linux/shmem_fs.h
diff --git a/Makefile b/Makefile
index 5f05f8c..ebc8225 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 34
-EXTRAVERSION = -rc6
+EXTRAVERSION =
NAME = Sheep on Meth
# *DOCUMENTATION*
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index 610dff4..e756d04 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -17,8 +17,8 @@
#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
#define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } )
-#define atomic_read(v) ((v)->counter + 0)
-#define atomic64_read(v) ((v)->counter + 0)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
+#define atomic64_read(v) (*(volatile long *)&(v)->counter)
#define atomic_set(v,i) ((v)->counter = (i))
#define atomic64_set(v,i) ((v)->counter = (i))
diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h
index 15f3ae2..296da1d 100644
--- a/arch/alpha/include/asm/bitops.h
+++ b/arch/alpha/include/asm/bitops.h
@@ -405,29 +405,31 @@
#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67)
/* Whee. EV67 can calculate it directly. */
-static inline unsigned long hweight64(unsigned long w)
+static inline unsigned long __arch_hweight64(unsigned long w)
{
return __kernel_ctpop(w);
}
-static inline unsigned int hweight32(unsigned int w)
+static inline unsigned int __arch_weight32(unsigned int w)
{
- return hweight64(w);
+ return __arch_hweight64(w);
}
-static inline unsigned int hweight16(unsigned int w)
+static inline unsigned int __arch_hweight16(unsigned int w)
{
- return hweight64(w & 0xffff);
+ return __arch_hweight64(w & 0xffff);
}
-static inline unsigned int hweight8(unsigned int w)
+static inline unsigned int __arch_hweight8(unsigned int w)
{
- return hweight64(w & 0xff);
+ return __arch_hweight64(w & 0xff);
}
#else
-#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/arch_hweight.h>
#endif
+#include <asm-generic/bitops/const_hweight.h>
+
#endif /* __KERNEL__ */
#include <asm-generic/bitops/find.h>
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 6ab6b33..c5191b1 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -685,8 +685,8 @@
W(b) __armv4_mmu_cache_off
W(b) __armv4_mmu_cache_flush
- .word 0x56056930
- .word 0xff0ffff0 @ PXA935
+ .word 0x56056900
+ .word 0xffffff00 @ PXA9xx
W(b) __armv4_mmu_cache_on
W(b) __armv4_mmu_cache_off
W(b) __armv4_mmu_cache_flush
@@ -697,12 +697,6 @@
W(b) __armv4_mmu_cache_off
W(b) __armv5tej_mmu_cache_flush
- .word 0x56056930
- .word 0xff0ffff0 @ PXA935
- W(b) __armv4_mmu_cache_on
- W(b) __armv4_mmu_cache_off
- W(b) __armv4_mmu_cache_flush
-
.word 0x56050000 @ Feroceon
.word 0xff0f0000
W(b) __armv4_mmu_cache_on
diff --git a/arch/arm/configs/imote2_defconfig b/arch/arm/configs/imote2_defconfig
index 95d2bec..21f2bff 100644
--- a/arch/arm/configs/imote2_defconfig
+++ b/arch/arm/configs/imote2_defconfig
@@ -1,13 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.33-rc8
-# Sat Feb 13 21:48:53 2010
+# Linux kernel version: 2.6.34-rc2
+# Thu Apr 8 14:49:08 2010
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_HAVE_PROC_CPU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -19,6 +20,7 @@
CONFIG_ARCH_HAS_CPUFREQ=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_ARCH_MTD_XIP=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -60,11 +62,6 @@
# CONFIG_TREE_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_GROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
@@ -97,10 +94,14 @@
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
#
# Kernel Performance Events And Counters
#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
@@ -184,6 +185,7 @@
# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_GEMINI is not set
# CONFIG_ARCH_EBSA110 is not set
@@ -193,7 +195,6 @@
# CONFIG_ARCH_STMP3XXX is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_NOMADIK is not set
# CONFIG_ARCH_IOP13XX is not set
# CONFIG_ARCH_IOP32X is not set
# CONFIG_ARCH_IOP33X is not set
@@ -210,21 +211,26 @@
# CONFIG_ARCH_KS8695 is not set
# CONFIG_ARCH_NS9XXX is not set
# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
# CONFIG_ARCH_PNX4008 is not set
CONFIG_ARCH_PXA=y
# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P6440 is not set
+# CONFIG_ARCH_S5P6442 is not set
# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_S5PV210 is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
# CONFIG_ARCH_DAVINCI is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_BCMRING is not set
-# CONFIG_ARCH_U8500 is not set
#
# Intel PXA2xx/PXA3xx Implementations
@@ -253,6 +259,7 @@
# CONFIG_MACH_EM_X270 is not set
# CONFIG_MACH_EXEDA is not set
# CONFIG_MACH_CM_X300 is not set
+# CONFIG_MACH_CAPC7117 is not set
# CONFIG_ARCH_GUMSTIX is not set
CONFIG_MACH_INTELMOTE2=y
# CONFIG_MACH_STARGATE2 is not set
@@ -275,7 +282,11 @@
# CONFIG_PXA_EZX is not set
# CONFIG_MACH_MP900C is not set
# CONFIG_ARCH_PXA_PALM is not set
+# CONFIG_MACH_RAUMFELD_RC is not set
+# CONFIG_MACH_RAUMFELD_CONNECTOR is not set
+# CONFIG_MACH_RAUMFELD_SPEAKER is not set
# CONFIG_PXA_SHARPSL is not set
+# CONFIG_MACH_ICONTROL is not set
# CONFIG_ARCH_PXA_ESERIES is not set
CONFIG_PXA27x=y
CONFIG_PXA_SSP=y
@@ -302,6 +313,7 @@
CONFIG_ARM_L1_CACHE_SHIFT=5
CONFIG_IWMMXT=y
CONFIG_XSCALE_PMU=y
+CONFIG_CPU_HAS_PMU=y
CONFIG_COMMON_CLKDEV=y
#
@@ -352,7 +364,7 @@
#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=tty1 root=/dev/mmcblk0p2 rootfstype=ext2 rootdelay=3 ip=192.168.0.202:192.168.0.200:192.168.0.200:255.255.255.0 debug"
+CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=jffs2 console=ttyS2,115200 mem=32M"
# CONFIG_XIP_KERNEL is not set
CONFIG_KEXEC=y
CONFIG_ATAGS_PROC=y
@@ -360,24 +372,8 @@
#
# CPU Power Management
#
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-CONFIG_CPU_FREQ_DEBUG=y
-CONFIG_CPU_FREQ_STAT=y
-# CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=m
-CONFIG_CPU_FREQ_GOV_USERSPACE=m
-CONFIG_CPU_FREQ_GOV_ONDEMAND=m
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
-CONFIG_CPU_IDLE=y
-CONFIG_CPU_IDLE_GOV_LADDER=y
-CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
#
# Floating point emulation
@@ -409,6 +405,7 @@
CONFIG_SUSPEND_FREEZER=y
CONFIG_APM_EMULATION=y
CONFIG_PM_RUNTIME=y
+CONFIG_PM_OPS=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
@@ -416,7 +413,6 @@
# Networking options
#
CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
@@ -506,6 +502,7 @@
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_CT is not set
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_LED=m
@@ -622,6 +619,7 @@
# CONFIG_ATM is not set
CONFIG_STP=m
CONFIG_BRIDGE=m
+# CONFIG_BRIDGE_IGMP_SNOOPING is not set
# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
@@ -646,32 +644,7 @@
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-
-#
-# Bluetooth device drivers
-#
-CONFIG_BT_HCIBTUSB=m
-CONFIG_BT_HCIBTSDIO=m
-CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_H4=y
-# CONFIG_BT_HCIUART_BCSP is not set
-# CONFIG_BT_HCIUART_LL is not set
-CONFIG_BT_HCIBCM203X=m
-CONFIG_BT_HCIBPA10X=m
-CONFIG_BT_HCIBFUSB=m
-CONFIG_BT_HCIVHCI=m
-CONFIG_BT_MRVL=m
-CONFIG_BT_MRVL_SDIO=m
-# CONFIG_BT_ATH3K is not set
+# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
CONFIG_FIB_RULES=y
# CONFIG_WIRELESS is not set
@@ -687,7 +660,8 @@
# Generic Driver Options
#
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_DEVTMPFS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
@@ -703,9 +677,9 @@
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-# CONFIG_MTD_AR7_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_AFS_PARTS=y
+CONFIG_MTD_AR7_PARTS=y
#
# User Modules And Translation Layers
@@ -812,6 +786,7 @@
#
# SCSI device support
#
+CONFIG_SCSI_MOD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_DMA is not set
@@ -965,6 +940,7 @@
CONFIG_SERIAL_PXA_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
@@ -993,6 +969,7 @@
CONFIG_I2C_PXA=y
# CONFIG_I2C_PXA_SLAVE is not set
# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
#
# External I2C/SMBus adapter drivers
@@ -1006,15 +983,9 @@
#
# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_STUB is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
CONFIG_SPI=y
# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
@@ -1046,10 +1017,12 @@
#
# Memory mapped GPIO expanders:
#
+# CONFIG_GPIO_IT8761E is not set
#
# I2C GPIO expanders:
#
+# CONFIG_GPIO_MAX7300 is not set
# CONFIG_GPIO_MAX732X is not set
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCF857X is not set
@@ -1093,10 +1066,12 @@
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_88PM860X is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_MFD_ASIC3 is not set
# CONFIG_HTC_EGPIO is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
# CONFIG_TPS65010 is not set
# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
@@ -1105,22 +1080,25 @@
# CONFIG_MFD_TC6393XB is not set
CONFIG_PMIC_DA903X=y
# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM831X is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
# CONFIG_MFD_PCF50633 is not set
# CONFIG_MFD_MC13783 is not set
# CONFIG_AB3100_CORE is not set
# CONFIG_EZX_PCAP is not set
-# CONFIG_MFD_88PM8607 is not set
# CONFIG_AB4500_CORE is not set
CONFIG_REGULATOR=y
CONFIG_REGULATOR_DEBUG=y
+# CONFIG_REGULATOR_DUMMY is not set
# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
CONFIG_REGULATOR_USERSPACE_CONSUMER=y
# CONFIG_REGULATOR_BQ24022 is not set
# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
# CONFIG_REGULATOR_MAX8660 is not set
CONFIG_REGULATOR_DA903X=y
# CONFIG_REGULATOR_LP3971 is not set
@@ -1218,6 +1196,7 @@
# CONFIG_VIDEO_SAA7191 is not set
# CONFIG_VIDEO_TVP514X is not set
# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_TVP7002 is not set
# CONFIG_VIDEO_VPX3220 is not set
#
@@ -1264,15 +1243,7 @@
CONFIG_VIDEO_PXA27x=y
# CONFIG_VIDEO_SH_MOBILE_CEU is not set
# CONFIG_V4L_USB_DRIVERS is not set
-CONFIG_RADIO_ADAPTERS=y
-# CONFIG_I2C_SI4713 is not set
-# CONFIG_RADIO_SI4713 is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_RADIO_SI470X is not set
-# CONFIG_USB_MR800 is not set
-CONFIG_RADIO_TEA5764=y
-CONFIG_RADIO_TEA5764_XTAL=y
-# CONFIG_RADIO_TEF6862 is not set
+# CONFIG_RADIO_ADAPTERS is not set
# CONFIG_DAB is not set
#
@@ -1398,8 +1369,6 @@
#
# Special HID drivers
#
-CONFIG_HID_APPLE=m
-# CONFIG_HID_WACOM is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1477,7 +1446,6 @@
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1489,7 +1457,6 @@
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_VST is not set
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG is not set
# CONFIG_USB_GADGET_DEBUG_FILES is not set
@@ -1529,6 +1496,7 @@
# CONFIG_USB_MIDI_GADGET is not set
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_NOKIA is not set
# CONFIG_USB_G_MULTI is not set
#
@@ -1555,8 +1523,6 @@
#
CONFIG_MMC_PXA=y
# CONFIG_MMC_SDHCI is not set
-# CONFIG_MMC_AT91 is not set
-# CONFIG_MMC_ATMELMCI is not set
CONFIG_MMC_SPI=y
# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
@@ -1574,11 +1540,11 @@
# CONFIG_LEDS_REGULATOR is not set
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_LT3593 is not set
+CONFIG_LEDS_TRIGGERS=y
#
# LED Triggers
#
-CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
@@ -1656,7 +1622,7 @@
# on-CPU RTC drivers
#
# CONFIG_RTC_DRV_SA1100 is not set
-# CONFIG_RTC_DRV_PXA is not set
+CONFIG_RTC_DRV_PXA=y
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
@@ -1681,19 +1647,10 @@
CONFIG_JBD=m
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_DEBUG is not set
+# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_BTRFS_FS is not set
# CONFIG_NILFS2_FS is not set
@@ -1716,9 +1673,7 @@
#
# CD-ROM/DVD Filesystems
#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
+# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
@@ -1750,12 +1705,14 @@
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_FS_WBUF_VERIFY=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
CONFIG_JFFS2_COMPRESSION_OPTIONS=y
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_LZO=y
@@ -1765,6 +1722,7 @@
CONFIG_JFFS2_CMODE_PRIORITY=y
# CONFIG_JFFS2_CMODE_SIZE is not set
# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_LOGFS is not set
CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m
# CONFIG_SQUASHFS_EMBEDDED is not set
@@ -1802,6 +1760,7 @@
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CEPH_FS is not set
CONFIG_CIFS=m
CONFIG_CIFS_STATS=y
# CONFIG_CIFS_STATS2 is not set
@@ -1895,6 +1854,7 @@
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_PROVE_LOCKING=y
+# CONFIG_PROVE_RCU is not set
CONFIG_LOCKDEP=y
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_LOCKDEP is not set
@@ -1918,6 +1878,7 @@
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
@@ -2061,9 +2022,9 @@
CONFIG_CRC7=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_LZO_COMPRESS=m
-CONFIG_LZO_DECOMPRESS=m
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
@@ -2075,3 +2036,4 @@
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index e8ddec2..a0162fa 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -24,7 +24,7 @@
* strex/ldrex monitor on some implementations. The reason we can use it for
* atomic_set() is the clrex or dummy strex done on every exception return.
*/
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
#if __LINUX_ARM_ARCH__ >= 6
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 0d08d41..4656a24 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -371,6 +371,10 @@
#ifdef CONFIG_ARM_ERRATA_411920
extern void v6_icache_inval_all(void);
v6_icache_inval_all();
+#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7
+ asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n"
+ :
+ : "r" (0));
#else
asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n"
:
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index bff0564..51662fe 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -9,6 +9,8 @@
#include <asm/ptrace.h>
#include <asm/user.h>
+struct task_struct;
+
typedef unsigned long elf_greg_t;
typedef unsigned long elf_freg_t[3];
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index 7be0978..634f357 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -1,6 +1,23 @@
#ifndef __ASMARM_SMP_TWD_H
#define __ASMARM_SMP_TWD_H
+#define TWD_TIMER_LOAD 0x00
+#define TWD_TIMER_COUNTER 0x04
+#define TWD_TIMER_CONTROL 0x08
+#define TWD_TIMER_INTSTAT 0x0C
+
+#define TWD_WDOG_LOAD 0x20
+#define TWD_WDOG_COUNTER 0x24
+#define TWD_WDOG_CONTROL 0x28
+#define TWD_WDOG_INTSTAT 0x2C
+#define TWD_WDOG_RESETSTAT 0x30
+#define TWD_WDOG_DISABLE 0x34
+
+#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
+#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
+#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
+#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
+
struct clock_event_device;
extern void __iomem *twd_base;
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index e085e2c..bd863d8 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -46,6 +46,9 @@
#define TLB_V7_UIS_FULL (1 << 20)
#define TLB_V7_UIS_ASID (1 << 21)
+/* Inner Shareable BTB operation (ARMv7 MP extensions) */
+#define TLB_V7_IS_BTB (1 << 22)
+
#define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */
#define TLB_DCLEAN (1 << 30)
#define TLB_WB (1 << 31)
@@ -183,7 +186,7 @@
#endif
#ifdef CONFIG_SMP
-#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
+#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
#else
#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
@@ -339,6 +342,12 @@
dsb();
isb();
}
+ if (tlb_flag(TLB_V7_IS_BTB)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+ dsb();
+ isb();
+ }
}
static inline void local_flush_tlb_mm(struct mm_struct *mm)
@@ -376,6 +385,12 @@
asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
dsb();
}
+ if (tlb_flag(TLB_V7_IS_BTB)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+ dsb();
+ isb();
+ }
}
static inline void
@@ -416,6 +431,12 @@
asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
dsb();
}
+ if (tlb_flag(TLB_V7_IS_BTB)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+ dsb();
+ isb();
+ }
}
static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -454,6 +475,12 @@
dsb();
isb();
}
+ if (tlb_flag(TLB_V7_IS_BTB)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc");
+ dsb();
+ isb();
+ }
}
/*
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index e6a0fb0..7ee48e7 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -676,10 +676,10 @@
* lr = unrecognised FP instruction return address
*/
- .data
+ .pushsection .data
ENTRY(fp_enter)
.word no_fp
- .text
+ .popsection
ENTRY(no_fp)
mov pc, lr
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 577543f..a01194e 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -86,6 +86,12 @@
return PTR_ERR(idle);
}
ci->idle = idle;
+ } else {
+ /*
+ * Since this idle thread is being re-used, call
+ * init_idle() to reinitialize the thread structure.
+ */
+ init_idle(idle, cpu);
}
/*
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index ea02a7b..7c5f0c0 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -21,23 +21,6 @@
#include <asm/smp_twd.h>
#include <asm/hardware/gic.h>
-#define TWD_TIMER_LOAD 0x00
-#define TWD_TIMER_COUNTER 0x04
-#define TWD_TIMER_CONTROL 0x08
-#define TWD_TIMER_INTSTAT 0x0C
-
-#define TWD_WDOG_LOAD 0x20
-#define TWD_WDOG_COUNTER 0x24
-#define TWD_WDOG_CONTROL 0x28
-#define TWD_WDOG_INTSTAT 0x2C
-#define TWD_WDOG_RESETSTAT 0x30
-#define TWD_WDOG_DISABLE 0x34
-
-#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
-#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
-#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
-#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
-
/* set up by the platform code */
void __iomem *twd_base;
diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S
index 5e3f996..14a0d98 100644
--- a/arch/arm/lib/clear_user.S
+++ b/arch/arm/lib/clear_user.S
@@ -45,6 +45,7 @@
mov r0, #0
ldmfd sp!, {r1, pc}
ENDPROC(__clear_user)
+ENDPROC(__clear_user_std)
.pushsection .fixup,"ax"
.align 0
diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S
index 027b69b..d066df6 100644
--- a/arch/arm/lib/copy_to_user.S
+++ b/arch/arm/lib/copy_to_user.S
@@ -93,6 +93,7 @@
#include "copy_template.S"
ENDPROC(__copy_to_user)
+ENDPROC(__copy_to_user_std)
.pushsection .fixup,"ax"
.align 0
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 122e61a..e8cb982 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -410,7 +410,7 @@
CLK("davinci-mcasp.0", NULL, &mcasp0_clk),
CLK("davinci-mcasp.1", NULL, &mcasp1_clk),
CLK("davinci-mcasp.2", NULL, &mcasp2_clk),
- CLK("musb_hdrc", NULL, &usb20_clk),
+ CLK(NULL, "usb20", &usb20_clk),
CLK(NULL, "aemif", &aemif_clk),
CLK(NULL, "aintc", &aintc_clk),
CLK(NULL, "secu_mgr", &secu_mgr_clk),
diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index 8f85f73..1ee6ce4 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <asm/clkdev.h>
+#include <asm/div64.h>
#include <mach/hardware.h>
#include <mach/common.h>
diff --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h
index 811743c..5f2ba8d 100644
--- a/arch/arm/mach-pxa/include/mach/colibri.h
+++ b/arch/arm/mach-pxa/include/mach/colibri.h
@@ -2,6 +2,7 @@
#define _COLIBRI_H_
#include <net/ax88796.h>
+#include <mach/mfp.h>
/*
* common settings for all modules
diff --git a/arch/arm/mach-pxa/include/mach/hardware.h b/arch/arm/mach-pxa/include/mach/hardware.h
index 7515757..3d8d8cb 100644
--- a/arch/arm/mach-pxa/include/mach/hardware.h
+++ b/arch/arm/mach-pxa/include/mach/hardware.h
@@ -202,7 +202,7 @@
#define __cpu_is_pxa950(id) \
({ \
unsigned int _id = (id) >> 4 & 0xfff; \
- id == 0x697; \
+ _id == 0x697; \
})
#else
#define __cpu_is_pxa950(id) (0)
diff --git a/arch/arm/mach-pxa/include/mach/regs-u2d.h b/arch/arm/mach-pxa/include/mach/regs-u2d.h
index 44b0b20..c15c0c5 100644
--- a/arch/arm/mach-pxa/include/mach/regs-u2d.h
+++ b/arch/arm/mach-pxa/include/mach/regs-u2d.h
@@ -166,7 +166,8 @@
#define U2DMACSR_BUSERRTYPE (7 << 10) /* PX Bus Error Type */
#define U2DMACSR_EORINTR (1 << 9) /* End Of Receive */
#define U2DMACSR_REQPEND (1 << 8) /* Request Pending */
-#define U2DMACSR_RASINTR (1 << 4) /* Request After Channel Stopped (read / write 1 clear) */#define U2DMACSR_STOPINTR (1 << 3) /* Stop Interrupt (read only) */
+#define U2DMACSR_RASINTR (1 << 4) /* Request After Channel Stopped (read / write 1 clear) */
+#define U2DMACSR_STOPINTR (1 << 3) /* Stop Interrupt (read only) */
#define U2DMACSR_ENDINTR (1 << 2) /* End Interrupt (read / write 1 clear) */
#define U2DMACSR_STARTINTR (1 << 1) /* Start Interrupt (read / write 1 clear) */
#define U2DMACSR_BUSERRINTR (1 << 0) /* Bus Error Interrupt (read / write 1 clear) */
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 44bb675..d12667b 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -983,7 +983,7 @@
int i;
for (i = 0; i < ARRAY_SIZE(gpio_keys_button); i++)
- if (!strcmp(gpio_keys_button[i].desc, "on/off button"))
+ if (!strcmp(gpio_keys_button[i].desc, "on_off button"))
gpio_keys_button[i].active_low = 1;
}
@@ -1009,8 +1009,7 @@
gpio_direction_output(GPIO_W2W_PDN, 0);
/* this can be used to switch off the device */
- ret = gpio_request(GPIO_SHUTDOWN_SUPPLY,
- "supply shutdown");
+ ret = gpio_request(GPIO_SHUTDOWN_SUPPLY, "supply shutdown");
if (ret < 0)
pr_warning("Unable to request GPIO_SHUTDOWN_SUPPLY\n");
else
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 19b5109..01bdd75 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -363,7 +363,7 @@
.type = EV_PWR,
.code = KEY_SUSPEND,
.gpio = SPITZ_GPIO_ON_KEY,
- .desc = "On/Off",
+ .desc = "On Off",
.wakeup = 1,
},
/* Two buttons detecting the lid state */
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 9e0c5c3..e90114a 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -34,6 +34,7 @@
#include <linux/pm.h>
#include <linux/sched.h>
#include <linux/gpio.h>
+#include <linux/jiffies.h>
#include <linux/i2c-gpio.h>
#include <linux/serial_8250.h>
#include <linux/smc91x.h>
@@ -454,7 +455,7 @@
.sda_pin = VIPER_RTC_I2C_SDA_GPIO,
.scl_pin = VIPER_RTC_I2C_SCL_GPIO,
.udelay = 10,
- .timeout = 100,
+ .timeout = HZ,
};
static struct platform_device i2c_bus_device = {
@@ -779,7 +780,7 @@
.sda_pin = VIPER_TPM_I2C_SDA_GPIO,
.scl_pin = VIPER_TPM_I2C_SCL_GPIO,
.udelay = 10,
- .timeout = 100,
+ .timeout = HZ,
};
char *errstr;
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index b17d52f..fd4c52b 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -57,7 +57,7 @@
config SA1100_H3100
bool "Compaq iPAQ H3100"
select HTC_EGPIO
- select CPU_FREQ_SA1100
+ select CPU_FREQ_SA1110
help
Say Y here if you intend to run this kernel on the Compaq iPAQ
H3100 handheld computer. Information about this machine and the
@@ -68,7 +68,7 @@
config SA1100_H3600
bool "Compaq iPAQ H3600/H3700"
select HTC_EGPIO
- select CPU_FREQ_SA1100
+ select CPU_FREQ_SA1110
help
Say Y here if you intend to run this kernel on the Compaq iPAQ
H3600 handheld computer. Information about this machine and the
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 63b32b6..7252874 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -363,6 +363,9 @@
struct sdram_params *sdram;
const char *name = sdram_name;
+ if (!cpu_is_sa1110())
+ return -ENODEV;
+
if (!name[0]) {
if (machine_is_assabet())
name = "TC59SM716-CL3";
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 9d89c67..e46ecd8 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -211,6 +211,9 @@
mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line
#endif
1:
+#ifdef CONFIG_SMP
+ str r0, [r0] @ write for ownership
+#endif
#ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c6, 1 @ invalidate D line
#else
@@ -231,6 +234,9 @@
v6_dma_clean_range:
bic r0, r0, #D_CACHE_LINE_SIZE - 1
1:
+#ifdef CONFIG_SMP
+ ldr r2, [r0] @ read for ownership
+#endif
#ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c10, 1 @ clean D line
#else
@@ -251,6 +257,10 @@
ENTRY(v6_dma_flush_range)
bic r0, r0, #D_CACHE_LINE_SIZE - 1
1:
+#ifdef CONFIG_SMP
+ ldr r2, [r0] @ read for ownership
+ str r2, [r0] @ write for ownership
+#endif
#ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line
#else
@@ -273,7 +283,9 @@
add r1, r1, r0
teq r2, #DMA_FROM_DEVICE
beq v6_dma_inv_range
- b v6_dma_clean_range
+ teq r2, #DMA_TO_DEVICE
+ beq v6_dma_clean_range
+ b v6_dma_flush_range
ENDPROC(v6_dma_map_area)
/*
@@ -283,9 +295,6 @@
* - dir - DMA direction
*/
ENTRY(v6_dma_unmap_area)
- add r1, r1, r0
- teq r2, #DMA_TO_DEVICE
- bne v6_dma_inv_range
mov pc, lr
ENDPROC(v6_dma_unmap_area)
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index bcd64f2..06a90dc 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -167,7 +167,11 @@
cmp r0, r1
blo 1b
mov r0, #0
+#ifdef CONFIG_SMP
+ mcr p15, 0, r0, c7, c1, 6 @ invalidate BTB Inner Shareable
+#else
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
+#endif
dsb
isb
mov pc, lr
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 83db12a..0ed29bf 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -86,9 +86,6 @@
printk("Mem-info:\n");
show_free_areas();
for_each_online_node(node) {
- pg_data_t *n = NODE_DATA(node);
- struct page *map = pgdat_page_nr(n, 0) - n->node_start_pfn;
-
for_each_nodebank (i,mi,node) {
struct membank *bank = &mi->bank[i];
unsigned int pfn1, pfn2;
@@ -97,8 +94,8 @@
pfn1 = bank_pfn_start(bank);
pfn2 = bank_pfn_end(bank);
- page = map + pfn1;
- end = map + pfn2;
+ page = pfn_to_page(pfn1);
+ end = pfn_to_page(pfn2 - 1) + 1;
do {
total++;
@@ -603,9 +600,6 @@
reserved_pages = free_pages = 0;
for_each_online_node(node) {
- pg_data_t *n = NODE_DATA(node);
- struct page *map = pgdat_page_nr(n, 0) - n->node_start_pfn;
-
for_each_nodebank(i, &meminfo, node) {
struct membank *bank = &meminfo.bank[i];
unsigned int pfn1, pfn2;
@@ -614,8 +608,8 @@
pfn1 = bank_pfn_start(bank);
pfn2 = bank_pfn_end(bank);
- page = map + pfn1;
- end = map + pfn2;
+ page = pfn_to_page(pfn1);
+ end = pfn_to_page(pfn2 - 1) + 1;
do {
if (PageReserved(page))
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 9bfeb6b..33b3273 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -65,6 +65,15 @@
}
EXPORT_SYMBOL(flush_dcache_page);
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+ unsigned long uaddr, void *dst, const void *src,
+ unsigned long len)
+{
+ memcpy(dst, src, len);
+ if (vma->vm_flags & VM_EXEC)
+ __cpuc_coherent_user_range(uaddr, uaddr + len);
+}
+
void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset,
size_t size, unsigned int mtype)
{
@@ -87,8 +96,8 @@
}
EXPORT_SYMBOL(__arm_ioremap);
-void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,
- unsigned int mtype, void *caller)
+void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size,
+ unsigned int mtype, void *caller)
{
return __arm_ioremap(phys_addr, size, mtype);
}
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index 0cb1848..f3f288a 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -50,7 +50,11 @@
cmp r0, r1
blo 1b
mov ip, #0
+#ifdef CONFIG_SMP
+ mcr p15, 0, ip, c7, c1, 6 @ flush BTAC/BTB Inner Shareable
+#else
mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB
+#endif
dsb
mov pc, lr
ENDPROC(v7wbi_flush_user_tlb_range)
@@ -79,7 +83,11 @@
cmp r0, r1
blo 1b
mov r2, #0
+#ifdef CONFIG_SMP
+ mcr p15, 0, r2, c7, c1, 6 @ flush BTAC/BTB Inner Shareable
+#else
mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
+#endif
dsb
isb
mov pc, lr
diff --git a/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h b/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h
index 07be8ad..7c4870b 100644
--- a/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h
+++ b/arch/arm/plat-mxc/include/mach/dma-mx1-mx2.h
@@ -31,7 +31,13 @@
#define DMA_MODE_WRITE 1
#define DMA_MODE_MASK 1
-#define DMA_BASE IO_ADDRESS(DMA_BASE_ADDR)
+#define MX1_DMA_REG(offset) MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR + (offset))
+
+/* DMA Interrupt Mask Register */
+#define MX1_DMA_DIMR MX1_DMA_REG(0x08)
+
+/* Channel Control Register */
+#define MX1_DMA_CCR(x) MX1_DMA_REG(0x8c + ((x) << 6))
#define IMX_DMA_MEMSIZE_32 (0 << 4)
#define IMX_DMA_MEMSIZE_8 (1 << 4)
diff --git a/arch/arm/plat-pxa/dma.c b/arch/arm/plat-pxa/dma.c
index 742350e..2d3c19d 100644
--- a/arch/arm/plat-pxa/dma.c
+++ b/arch/arm/plat-pxa/dma.c
@@ -245,7 +245,7 @@
dbgfs_chan = kmalloc(sizeof(*dbgfs_state) * num_dma_channels,
GFP_KERNEL);
- if (!dbgfs_state)
+ if (!dbgfs_chan)
goto err_alloc;
chandir = debugfs_create_dir("channels", dbgfs_root);
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 1536f17..8f10d24 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# Last update: Sat Mar 20 15:35:41 2010
+# Last update: Sat May 1 10:36:42 2010
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -2749,3 +2749,58 @@
h6053 MACH_H6053 H6053 2762
smint01 MACH_SMINT01 SMINT01 2763
prtlvt2 MACH_PRTLVT2 PRTLVT2 2764
+ap420 MACH_AP420 AP420 2765
+htcshift MACH_HTCSHIFT HTCSHIFT 2766
+davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767
+msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768
+msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769
+esl_vamana MACH_ESL_VAMANA ESL_VAMANA 2770
+sbc35 MACH_SBC35 SBC35 2771
+mpx6446 MACH_MPX6446 MPX6446 2772
+oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773
+kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774
+ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775
+cns3420vb MACH_CNS3420VB CNS3420VB 2776
+lpc2 MACH_LPC2 LPC2 2777
+olympus MACH_OLYMPUS OLYMPUS 2778
+vortex MACH_VORTEX VORTEX 2779
+s5pc200 MACH_S5PC200 S5PC200 2780
+ecucore_9263 MACH_ECUCORE_9263 ECUCORE_9263 2781
+smdkc200 MACH_SMDKC200 SMDKC200 2782
+emsiso_sx27 MACH_EMSISO_SX27 EMSISO_SX27 2783
+apx_som9g45_ek MACH_APX_SOM9G45_EK APX_SOM9G45_EK 2784
+songshan MACH_SONGSHAN SONGSHAN 2785
+tianshan MACH_TIANSHAN TIANSHAN 2786
+vpx500 MACH_VPX500 VPX500 2787
+am3517sam MACH_AM3517SAM AM3517SAM 2788
+skat91_sim508 MACH_SKAT91_SIM508 SKAT91_SIM508 2789
+skat91_s3e MACH_SKAT91_S3E SKAT91_S3E 2790
+omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791
+df7220 MACH_DF7220 DF7220 2792
+nemini MACH_NEMINI NEMINI 2793
+t8200 MACH_T8200 T8200 2794
+apf51 MACH_APF51 APF51 2795
+dr_rc_unit MACH_DR_RC_UNIT DR_RC_UNIT 2796
+bordeaux MACH_BORDEAUX BORDEAUX 2797
+catania_b MACH_CATANIA_B CATANIA_B 2798
+mx51_ocean MACH_MX51_OCEAN MX51_OCEAN 2799
+ti8168evm MACH_TI8168EVM TI8168EVM 2800
+neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801
+withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802
+dbps MACH_DBPS DBPS 2803
+sbc9261 MACH_SBC9261 SBC9261 2804
+pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805
+speedy MACH_SPEEDY SPEEDY 2806
+chrysaor MACH_CHRYSAOR CHRYSAOR 2807
+tango MACH_TANGO TANGO 2808
+synology_dsx11 MACH_SYNOLOGY_DSX11 SYNOLOGY_DSX11 2809
+hanlin_v3ext MACH_HANLIN_V3EXT HANLIN_V3EXT 2810
+hanlin_v5 MACH_HANLIN_V5 HANLIN_V5 2811
+hanlin_v3plus MACH_HANLIN_V3PLUS HANLIN_V3PLUS 2812
+iriver_story MACH_IRIVER_STORY IRIVER_STORY 2813
+irex_iliad MACH_IREX_ILIAD IREX_ILIAD 2814
+irex_dr1000 MACH_IREX_DR1000 IREX_DR1000 2815
+teton_bga MACH_TETON_BGA TETON_BGA 2816
+snapper9g45 MACH_SNAPPER9G45 SNAPPER9G45 2817
+tam3517 MACH_TAM3517 TAM3517 2818
+pdc100 MACH_PDC100 PDC100 2819
diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h
index b131c27..bbce6a1c 100644
--- a/arch/avr32/include/asm/atomic.h
+++ b/arch/avr32/include/asm/atomic.h
@@ -19,7 +19,7 @@
#define ATOMIC_INIT(i) { (i) }
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v, i) (((v)->counter) = i)
/*
diff --git a/arch/cris/include/asm/atomic.h b/arch/cris/include/asm/atomic.h
index a6aca81..88dc9b9 100644
--- a/arch/cris/include/asm/atomic.h
+++ b/arch/cris/include/asm/atomic.h
@@ -15,7 +15,7 @@
#define ATOMIC_INIT(i) { (i) }
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
/* These should be written in asm but we do it in C for now. */
diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h
index 00a57af..fae32c7 100644
--- a/arch/frv/include/asm/atomic.h
+++ b/arch/frv/include/asm/atomic.h
@@ -36,7 +36,7 @@
#define smp_mb__after_atomic_inc() barrier()
#define ATOMIC_INIT(i) { (i) }
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v, i) (((v)->counter) = (i))
#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h
index 33c8c0f..e936804 100644
--- a/arch/h8300/include/asm/atomic.h
+++ b/arch/h8300/include/asm/atomic.h
@@ -10,7 +10,7 @@
#define ATOMIC_INIT(i) { (i) }
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v, i) (((v)->counter) = i)
#include <asm/system.h>
diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h
index 88405cb..4e19484 100644
--- a/arch/ia64/include/asm/atomic.h
+++ b/arch/ia64/include/asm/atomic.h
@@ -21,8 +21,8 @@
#define ATOMIC_INIT(i) ((atomic_t) { (i) })
#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
-#define atomic_read(v) ((v)->counter)
-#define atomic64_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
+#define atomic64_read(v) (*(volatile long *)&(v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
#define atomic64_set(v,i) (((v)->counter) = (i))
diff --git a/arch/ia64/include/asm/bitops.h b/arch/ia64/include/asm/bitops.h
index 6ebc229..9da3df6 100644
--- a/arch/ia64/include/asm/bitops.h
+++ b/arch/ia64/include/asm/bitops.h
@@ -437,17 +437,18 @@
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/
-static __inline__ unsigned long
-hweight64 (unsigned long x)
+static __inline__ unsigned long __arch_hweight64(unsigned long x)
{
unsigned long result;
result = ia64_popcnt(x);
return result;
}
-#define hweight32(x) (unsigned int) hweight64((x) & 0xfffffffful)
-#define hweight16(x) (unsigned int) hweight64((x) & 0xfffful)
-#define hweight8(x) (unsigned int) hweight64((x) & 0xfful)
+#define __arch_hweight32(x) ((unsigned int) __arch_hweight64((x) & 0xfffffffful))
+#define __arch_hweight16(x) ((unsigned int) __arch_hweight64((x) & 0xfffful))
+#define __arch_hweight8(x) ((unsigned int) __arch_hweight64((x) & 0xfful))
+
+#include <asm-generic/bitops/const_hweight.h>
#endif /* __KERNEL__ */
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 4d1a7e9..c6c90f3 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -785,6 +785,14 @@
return 0;
}
+int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
+{
+ if (isa_irq >= 16)
+ return -1;
+ *gsi = isa_irq;
+ return 0;
+}
+
/*
* ACPI based hotplug CPU support
*/
diff --git a/arch/m32r/include/asm/atomic.h b/arch/m32r/include/asm/atomic.h
index 63f0cf0..d44a51e 100644
--- a/arch/m32r/include/asm/atomic.h
+++ b/arch/m32r/include/asm/atomic.h
@@ -26,7 +26,7 @@
*
* Atomically reads the value of @v.
*/
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
/**
* atomic_set - set atomic variable
diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
index 6a0d765..11dd30b 100644
--- a/arch/m68k/amiga/Makefile
+++ b/arch/m68k/amiga/Makefile
@@ -2,6 +2,6 @@
# Makefile for Linux arch/m68k/amiga source directory
#
-obj-y := config.o amiints.o cia.o chipram.o amisound.o
+obj-y := config.o amiints.o cia.o chipram.o amisound.o platform.o
obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o
diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c
new file mode 100644
index 0000000..38f18bf
--- /dev/null
+++ b/arch/m68k/amiga/platform.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007-2009 Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/zorro.h>
+
+#include <asm/amigahw.h>
+
+
+#ifdef CONFIG_ZORRO
+
+static const struct resource zorro_resources[] __initconst = {
+ /* Zorro II regions (on Zorro II/III) */
+ {
+ .name = "Zorro II exp",
+ .start = 0x00e80000,
+ .end = 0x00efffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "Zorro II mem",
+ .start = 0x00200000,
+ .end = 0x009fffff,
+ .flags = IORESOURCE_MEM,
+ },
+ /* Zorro III regions (on Zorro III only) */
+ {
+ .name = "Zorro III exp",
+ .start = 0xff000000,
+ .end = 0xffffffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "Zorro III cfg",
+ .start = 0x40000000,
+ .end = 0x7fffffff,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+
+static int __init amiga_init_bus(void)
+{
+ if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
+ return -ENODEV;
+
+ platform_device_register_simple("amiga-zorro", -1, zorro_resources,
+ AMIGAHW_PRESENT(ZORRO3) ? 4 : 2);
+ return 0;
+}
+
+subsys_initcall(amiga_init_bus);
+
+#endif /* CONFIG_ZORRO */
+
+
+static int __init amiga_init_devices(void)
+{
+ if (!MACH_IS_AMIGA)
+ return -ENODEV;
+
+ /* video hardware */
+ if (AMIGAHW_PRESENT(AMI_VIDEO))
+ platform_device_register_simple("amiga-video", -1, NULL, 0);
+
+
+ /* sound hardware */
+ if (AMIGAHW_PRESENT(AMI_AUDIO))
+ platform_device_register_simple("amiga-audio", -1, NULL, 0);
+
+
+ /* storage interfaces */
+ if (AMIGAHW_PRESENT(AMI_FLOPPY))
+ platform_device_register_simple("amiga-floppy", -1, NULL, 0);
+
+ return 0;
+}
+
+device_initcall(amiga_init_devices);
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index b46ea17..cb8617b 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -9,7 +9,6 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <linux/capability.h>
#include <linux/fcntl.h>
@@ -35,10 +34,9 @@
static unsigned char days_in_mo[] =
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static char rtc_status;
+static atomic_t rtc_status = ATOMIC_INIT(1);
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
unsigned char msr;
@@ -132,29 +130,20 @@
}
/*
- * We enforce only one user at a time here with the open/close.
- * Also clear the previous interrupt data on an open, and clean
- * up things on a close.
+ * We enforce only one user at a time here with the open/close.
*/
-
static int rtc_open(struct inode *inode, struct file *file)
{
- lock_kernel();
- if(rtc_status) {
- unlock_kernel();
+ if (!atomic_dec_and_test(&rtc_status)) {
+ atomic_inc(&rtc_status);
return -EBUSY;
}
-
- rtc_status = 1;
- unlock_kernel();
return 0;
}
static int rtc_release(struct inode *inode, struct file *file)
{
- lock_kernel();
- rtc_status = 0;
- unlock_kernel();
+ atomic_inc(&rtc_status);
return 0;
}
@@ -163,9 +152,9 @@
*/
static const struct file_operations rtc_fops = {
- .ioctl = rtc_ioctl,
- .open = rtc_open,
- .release = rtc_release,
+ .unlocked_ioctl = rtc_ioctl,
+ .open = rtc_open,
+ .release = rtc_release,
};
static struct miscdevice rtc_dev = {
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
index f5b3d09..7b98242 100644
--- a/arch/m68k/hp300/time.h
+++ b/arch/m68k/hp300/time.h
@@ -1,4 +1,2 @@
extern void hp300_sched_init(irq_handler_t vector);
-extern unsigned long hp300_gettimeoffset (void);
-
-
+extern unsigned long hp300_gettimeoffset(void);
diff --git a/arch/m68k/include/asm/atomic_mm.h b/arch/m68k/include/asm/atomic_mm.h
index d9d2ed6..6a223b3 100644
--- a/arch/m68k/include/asm/atomic_mm.h
+++ b/arch/m68k/include/asm/atomic_mm.h
@@ -15,7 +15,7 @@
#define ATOMIC_INIT(i) { (i) }
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v, i) (((v)->counter) = i)
static inline void atomic_add(int i, atomic_t *v)
diff --git a/arch/m68k/include/asm/atomic_no.h b/arch/m68k/include/asm/atomic_no.h
index 5674cb9..289310c 100644
--- a/arch/m68k/include/asm/atomic_no.h
+++ b/arch/m68k/include/asm/atomic_no.h
@@ -15,7 +15,7 @@
#define ATOMIC_INIT(i) { (i) }
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v, i) (((v)->counter) = i)
static __inline__ void atomic_add(int i, atomic_t *v)
diff --git a/arch/m68k/include/asm/bitops_mm.h b/arch/m68k/include/asm/bitops_mm.h
index 9bde784..b4ecdaa 100644
--- a/arch/m68k/include/asm/bitops_mm.h
+++ b/arch/m68k/include/asm/bitops_mm.h
@@ -365,6 +365,10 @@
#define ext2_set_bit_atomic(lock, nr, addr) test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
#define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
#define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
+#define ext2_find_next_zero_bit(addr, size, offset) \
+ generic_find_next_zero_le_bit((unsigned long *)addr, size, offset)
+#define ext2_find_next_bit(addr, size, offset) \
+ generic_find_next_le_bit((unsigned long *)addr, size, offset)
static inline int ext2_test_bit(int nr, const void *vaddr)
{
@@ -394,10 +398,9 @@
return (p - addr) * 32 + res;
}
-static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size,
- unsigned offset)
+static inline unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
+ unsigned long size, unsigned long offset)
{
- const unsigned long *addr = vaddr;
const unsigned long *p = addr + (offset >> 5);
int bit = offset & 31UL, res;
@@ -437,10 +440,9 @@
return (p - addr) * 32 + res;
}
-static inline int ext2_find_next_bit(const void *vaddr, unsigned size,
- unsigned offset)
+static inline unsigned long generic_find_next_le_bit(const unsigned long *addr,
+ unsigned long size, unsigned long offset)
{
- const unsigned long *addr = vaddr;
const unsigned long *p = addr + (offset >> 5);
int bit = offset & 31UL, res;
diff --git a/arch/m68k/include/asm/param.h b/arch/m68k/include/asm/param.h
index 85c41b7..36265cc 100644
--- a/arch/m68k/include/asm/param.h
+++ b/arch/m68k/include/asm/param.h
@@ -1,26 +1,12 @@
#ifndef _M68K_PARAM_H
#define _M68K_PARAM_H
-#ifdef __KERNEL__
-# define HZ CONFIG_HZ /* Internal kernel timer frequency */
-# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
-# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
#ifdef __uClinux__
#define EXEC_PAGESIZE 4096
#else
#define EXEC_PAGESIZE 8192
#endif
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
+#include <asm-generic/param.h>
#endif /* _M68K_PARAM_H */
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index aacd6d1..ada4f4c 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -455,7 +455,7 @@
if (do_page_fault(&fp->ptregs, addr, errorcode)) {
#ifdef DEBUG
- printk("do_page_fault() !=0 \n");
+ printk("do_page_fault() !=0\n");
#endif
if (user_mode(&fp->ptregs)){
/* delay writebacks after signal delivery */
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 0356da9..1c16b1b 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -148,7 +148,7 @@
void __init config_mac(void)
{
if (!MACH_IS_MAC)
- printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
+ printk(KERN_ERR "ERROR: no Mac, but config_mac() called!!\n");
mach_sched_init = mac_sched_init;
mach_init_IRQ = mac_init_IRQ;
@@ -867,7 +867,7 @@
*/
iop_preinit();
- printk(KERN_INFO "Detected Macintosh model: %d \n", model);
+ printk(KERN_INFO "Detected Macintosh model: %d\n", model);
/*
* Report booter data:
@@ -878,12 +878,12 @@
mac_bi_data.videoaddr, mac_bi_data.videorow,
mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF,
mac_bi_data.dimensions >> 16);
- printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
+ printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx\n",
mac_bi_data.videological, mac_orig_videoaddr,
mac_bi_data.sccbase);
- printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
+ printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx\n",
mac_bi_data.boottime, mac_bi_data.gmtbias);
- printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
+ printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx\n",
mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
iop_init();
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index d0e35cf..a96394a 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -154,7 +154,6 @@
* the fault.
*/
- survive:
fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
#ifdef DEBUG
printk("handle_mm_fault returns %d\n",fault);
@@ -180,15 +179,10 @@
*/
out_of_memory:
up_read(&mm->mmap_sem);
- if (is_global_init(current)) {
- yield();
- down_read(&mm->mmap_sem);
- goto survive;
- }
-
- printk("VM: killing process %s\n", current->comm);
- if (user_mode(regs))
- do_group_exit(SIGKILL);
+ if (!user_mode(regs))
+ goto no_context;
+ pagefault_out_of_memory();
+ return 0;
no_context:
current->thread.signo = SIGBUS;
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index 8da9c25..11ac6f6 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -9,7 +9,6 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <linux/capability.h>
#include <linux/fcntl.h>
@@ -36,8 +35,7 @@
static atomic_t rtc_ready = ATOMIC_INIT(1);
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE;
unsigned long flags;
@@ -120,22 +118,15 @@
}
/*
- * We enforce only one user at a time here with the open/close.
- * Also clear the previous interrupt data on an open, and clean
- * up things on a close.
+ * We enforce only one user at a time here with the open/close.
*/
-
static int rtc_open(struct inode *inode, struct file *file)
{
- lock_kernel();
if( !atomic_dec_and_test(&rtc_ready) )
{
atomic_inc( &rtc_ready );
- unlock_kernel();
return -EBUSY;
}
- unlock_kernel();
-
return 0;
}
@@ -150,9 +141,9 @@
*/
static const struct file_operations rtc_fops = {
- .ioctl = rtc_ioctl,
- .open = rtc_open,
- .release = rtc_release,
+ .unlocked_ioctl = rtc_ioctl,
+ .open = rtc_open,
+ .release = rtc_release,
};
static struct miscdevice rtc_dev=
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 31ab3f0..ad10fec 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -126,7 +126,7 @@
{
halted = 1;
printk("\n\n*******************************************\n"
- "Called q40_reset : press the RESET button!! \n"
+ "Called q40_reset : press the RESET button!!\n"
"*******************************************\n");
Q40_LED_ON();
while (1)
diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig
index 6fced1f..3c91cf6 100644
--- a/arch/microblaze/configs/mmu_defconfig
+++ b/arch/microblaze/configs/mmu_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.33-rc6
-# Wed Feb 3 10:02:59 2010
+# Linux kernel version: 2.6.34-rc6
+# Thu May 6 11:22:14 2010
#
CONFIG_MICROBLAZE=y
# CONFIG_SWAP is not set
@@ -22,8 +22,6 @@
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-# CONFIG_PCI is not set
-CONFIG_NO_DMA=y
CONFIG_DTC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_CONSTRUCTORS=y
@@ -56,7 +54,6 @@
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
@@ -106,6 +103,8 @@
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_API_DEBUG=y
#
# GCOV-based kernel profiling
@@ -245,13 +244,20 @@
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Bus Options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
@@ -341,7 +347,9 @@
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
+CONFIG_OF_FLATTREE=y
CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
@@ -370,6 +378,7 @@
#
# SCSI device support
#
+CONFIG_SCSI_MOD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_DMA is not set
@@ -383,9 +392,30 @@
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
@@ -394,6 +424,7 @@
# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
# CONFIG_KS8842 is not set
# CONFIG_KS8851_MLL is not set
CONFIG_XILINX_EMACLITE=y
@@ -444,6 +475,7 @@
CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
@@ -471,6 +503,12 @@
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -502,6 +540,7 @@
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
@@ -572,6 +611,7 @@
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_LOGFS is not set
# CONFIG_CRAMFS is not set
# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
@@ -595,6 +635,7 @@
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
+# CONFIG_CEPH_FS is not set
CONFIG_CIFS=y
CONFIG_CIFS_STATS=y
CONFIG_CIFS_STATS2=y
@@ -696,6 +737,7 @@
# CONFIG_DEBUG_OBJECTS is not set
CONFIG_DEBUG_SLAB=y
# CONFIG_DEBUG_SLAB_LEAK is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
CONFIG_DEBUG_SPINLOCK=y
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
@@ -741,6 +783,7 @@
# CONFIG_KMEMTRACE is not set
# CONFIG_WORKQUEUE_TRACER is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_EARLY_PRINTK=y
# CONFIG_HEART_BEAT is not set
@@ -862,5 +905,6 @@
CONFIG_DECOMPRESS_GZIP=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
CONFIG_NLATTR=y
diff --git a/arch/microblaze/configs/nommu_defconfig b/arch/microblaze/configs/nommu_defconfig
index ce2da53..dd3a494 100644
--- a/arch/microblaze/configs/nommu_defconfig
+++ b/arch/microblaze/configs/nommu_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.33-rc6
-# Wed Feb 3 10:03:21 2010
+# Linux kernel version: 2.6.34-rc6
+# Thu May 6 11:25:12 2010
#
CONFIG_MICROBLAZE=y
# CONFIG_SWAP is not set
@@ -22,8 +22,6 @@
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-# CONFIG_PCI is not set
-CONFIG_NO_DMA=y
CONFIG_DTC=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_CONSTRUCTORS=y
@@ -58,7 +56,6 @@
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_GROUP_SCHED is not set
# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
@@ -96,6 +93,8 @@
# CONFIG_MMAP_ALLOW_UNINITIALIZED is not set
# CONFIG_PROFILING is not set
CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_API_DEBUG=y
#
# GCOV-based kernel profiling
@@ -209,11 +208,14 @@
#
# Advanced setup
#
+# CONFIG_ADVANCED_OPTIONS is not set
#
# Default settings for advanced configuration options are used
#
+CONFIG_LOWMEM_SIZE=0x30000000
CONFIG_KERNEL_START=0x90000000
+CONFIG_TASK_SIZE=0x80000000
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -235,13 +237,20 @@
# CONFIG_BINFMT_SHARED_FLAT is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Bus Options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
@@ -413,6 +422,7 @@
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
+CONFIG_OF_FLATTREE=y
CONFIG_OF_DEVICE=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
@@ -442,6 +452,7 @@
#
# SCSI device support
#
+CONFIG_SCSI_MOD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_DMA is not set
@@ -458,6 +469,7 @@
# CONFIG_PHYLIB is not set
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
# CONFIG_DNET is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
@@ -466,6 +478,7 @@
# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
# CONFIG_KS8842 is not set
# CONFIG_KS8851_MLL is not set
# CONFIG_XILINX_EMACLITE is not set
@@ -516,6 +529,7 @@
CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
# CONFIG_SERIAL_GRLIB_GAISLER_APBUART is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
@@ -544,6 +558,12 @@
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
#
# Multifunction device drivers
@@ -593,6 +613,7 @@
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
@@ -661,6 +682,7 @@
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
+# CONFIG_LOGFS is not set
CONFIG_CRAMFS=y
# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
@@ -689,6 +711,7 @@
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
+# CONFIG_CEPH_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -733,6 +756,7 @@
# CONFIG_DEBUG_OBJECTS_WORK is not set
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -758,6 +782,7 @@
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
@@ -782,6 +807,7 @@
# CONFIG_WORKQUEUE_TRACER is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_EARLY_PRINTK=y
# CONFIG_HEART_BEAT is not set
@@ -901,5 +927,6 @@
CONFIG_ZLIB_INFLATE=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
CONFIG_HAVE_LMB=y
CONFIG_NLATTR=y
diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h
index e522108..4efe96a 100644
--- a/arch/microblaze/include/asm/cache.h
+++ b/arch/microblaze/include/asm/cache.h
@@ -15,7 +15,7 @@
#include <asm/registers.h>
-#define L1_CACHE_SHIFT 2
+#define L1_CACHE_SHIFT 5
/* word-granular cache in microblaze */
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
diff --git a/arch/microblaze/include/asm/dma.h b/arch/microblaze/include/asm/dma.h
index 08c073b..0d73d0c 100644
--- a/arch/microblaze/include/asm/dma.h
+++ b/arch/microblaze/include/asm/dma.h
@@ -18,4 +18,10 @@
#define MAX_DMA_ADDRESS (CONFIG_KERNEL_START + memory_size - 1)
#endif
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy (0)
+#endif
+
#endif /* _ASM_MICROBLAZE_DMA_H */
diff --git a/arch/microblaze/include/asm/exceptions.h b/arch/microblaze/include/asm/exceptions.h
index 90731df..4c7b5d0 100644
--- a/arch/microblaze/include/asm/exceptions.h
+++ b/arch/microblaze/include/asm/exceptions.h
@@ -64,12 +64,6 @@
void die(const char *str, struct pt_regs *fp, long err);
void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
-#ifdef CONFIG_MMU
-void __bug(const char *file, int line, void *data);
-int bad_trap(int trap_num, struct pt_regs *regs);
-int debug_trap(struct pt_regs *regs);
-#endif /* CONFIG_MMU */
-
#if defined(CONFIG_KGDB)
void (*debugger)(struct pt_regs *regs);
int (*debugger_bpt)(struct pt_regs *regs);
diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h
index e45a6ee..00b5398 100644
--- a/arch/microblaze/include/asm/io.h
+++ b/arch/microblaze/include/asm/io.h
@@ -139,8 +139,6 @@
#ifdef CONFIG_MMU
-#define mm_ptov(addr) ((void *)__phys_to_virt(addr))
-#define mm_vtop(addr) ((unsigned long)__virt_to_phys(addr))
#define phys_to_virt(addr) ((void *)__phys_to_virt(addr))
#define virt_to_phys(addr) ((unsigned long)__virt_to_phys(addr))
#define virt_to_bus(addr) ((unsigned long)__virt_to_phys(addr))
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h
index 2dd1d04..de493f8 100644
--- a/arch/microblaze/include/asm/page.h
+++ b/arch/microblaze/include/asm/page.h
@@ -31,6 +31,9 @@
#ifndef __ASSEMBLY__
+/* MS be sure that SLAB allocates aligned objects */
+#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES
+
#define PAGE_UP(addr) (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1)))
#define PAGE_DOWN(addr) ((addr)&(~((PAGE_SIZE)-1)))
@@ -70,14 +73,7 @@
#endif /* CONFIG_MMU */
-# ifndef CONFIG_MMU
-# define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
-# define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
-# define free_user_page(page, addr) free_page(addr)
-# else /* CONFIG_MMU */
-extern void copy_page(void *to, void *from);
-# endif /* CONFIG_MMU */
-
+# define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
# define clear_page(pgaddr) memset((pgaddr), 0, PAGE_SIZE)
# define clear_user_page(pgaddr, vaddr, page) memset((pgaddr), 0, PAGE_SIZE)
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index bdd65aa..5a388ee 100644
--- a/arch/microblaze/include/asm/pci.h
+++ b/arch/microblaze/include/asm/pci.h
@@ -94,14 +94,6 @@
#define HAVE_PCI_LEGACY 1
-/* pci_unmap_{page,single} is a nop so... */
-#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
-#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
-#define pci_unmap_addr(PTR, ADDR_NAME) (0)
-#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
-#define pci_unmap_len(PTR, LEN_NAME) (0)
-#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-
/* The PCI address space does equal the physical memory
* address space (no IOMMU). The IDE and SCSI device layers use
* this boolean for bounce buffer decisions.
diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h
index f44b0d6..c614a89 100644
--- a/arch/microblaze/include/asm/pgalloc.h
+++ b/arch/microblaze/include/asm/pgalloc.h
@@ -108,21 +108,7 @@
#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); })
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
- unsigned long address)
-{
- pte_t *pte;
- extern void *early_get_page(void);
- if (mem_init_done) {
- pte = (pte_t *)__get_free_page(GFP_KERNEL |
- __GFP_REPEAT | __GFP_ZERO);
- } else {
- pte = (pte_t *)early_get_page();
- if (pte)
- clear_page(pte);
- }
- return pte;
-}
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
static inline struct page *pte_alloc_one(struct mm_struct *mm,
unsigned long address)
diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h
index dd2bb60..ca2d928 100644
--- a/arch/microblaze/include/asm/pgtable.h
+++ b/arch/microblaze/include/asm/pgtable.h
@@ -512,15 +512,6 @@
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
/*
- * When flushing the tlb entry for a page, we also need to flush the hash
- * table entry. flush_hash_page is assembler (for speed) in hashtable.S.
- */
-extern int flush_hash_page(unsigned context, unsigned long va, pte_t *ptep);
-
-/* Add an HPTE to the hash table */
-extern void add_hash_page(unsigned context, unsigned long va, pte_t *ptep);
-
-/*
* Encode and decode a swap entry.
* Note that the bits we use in a PTE for representing a swap entry
* must not include the _PAGE_PRESENT bit, or the _PAGE_HASHPTE bit
@@ -533,15 +524,7 @@
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 2 })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 2 })
-
-/* CONFIG_APUS */
-/* For virtual address to physical address conversion */
-extern void cache_clear(__u32 addr, int length);
-extern void cache_push(__u32 addr, int length);
-extern int mm_end_of_chunk(unsigned long addr, int len);
extern unsigned long iopa(unsigned long addr);
-/* extern unsigned long mm_ptov(unsigned long addr) \
- __attribute__ ((const)); TBD */
/* Values for nocacheflag and cmode */
/* These are not used by the APUS kernel_map, but prevents
@@ -552,18 +535,6 @@
#define IOMAP_NOCACHE_NONSER 2
#define IOMAP_NO_COPYBACK 3
-/*
- * Map some physical address range into the kernel address space.
- */
-extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
- int nocacheflag, unsigned long *memavailp);
-
-/*
- * Set cache mode of (kernel space) address range.
- */
-extern void kernel_set_cachemode(unsigned long address, unsigned long size,
- unsigned int cmode);
-
/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
#define kern_addr_valid(addr) (1)
@@ -577,10 +548,6 @@
void do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
-void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
- unsigned int size, int flags);
-
-void __init adjust_total_lowmem(void);
void mapin_ram(void);
int map_page(unsigned long va, phys_addr_t pa, int flags);
@@ -601,7 +568,7 @@
extern unsigned long ioremap_bot, ioremap_base;
void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
-void consistent_free(void *vaddr);
+void consistent_free(size_t size, void *vaddr);
void consistent_sync(void *vaddr, size_t size, int direction);
void consistent_sync_page(struct page *page, unsigned long offset,
size_t size, int direction);
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index 446bec2..26460d1 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -182,6 +182,39 @@
* Returns zero on success, or -EFAULT on error.
* On error, the variable @x is set to zero.
*/
+#define get_user(x, ptr) \
+ __get_user_check((x), (ptr), sizeof(*(ptr)))
+
+#define __get_user_check(x, ptr, size) \
+({ \
+ unsigned long __gu_val = 0; \
+ const typeof(*(ptr)) __user *__gu_addr = (ptr); \
+ int __gu_err = 0; \
+ \
+ if (access_ok(VERIFY_READ, __gu_addr, size)) { \
+ switch (size) { \
+ case 1: \
+ __get_user_asm("lbu", __gu_addr, __gu_val, \
+ __gu_err); \
+ break; \
+ case 2: \
+ __get_user_asm("lhu", __gu_addr, __gu_val, \
+ __gu_err); \
+ break; \
+ case 4: \
+ __get_user_asm("lw", __gu_addr, __gu_val, \
+ __gu_err); \
+ break; \
+ default: \
+ __gu_err = __user_bad(); \
+ break; \
+ } \
+ } else { \
+ __gu_err = -EFAULT; \
+ } \
+ x = (typeof(*(ptr)))__gu_val; \
+ __gu_err; \
+})
#define __get_user(x, ptr) \
({ \
@@ -206,12 +239,6 @@
})
-#define get_user(x, ptr) \
-({ \
- access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) \
- ? __get_user((x), (ptr)) : -EFAULT; \
-})
-
#define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \
({ \
__asm__ __volatile__ ( \
@@ -266,6 +293,42 @@
*
* Returns zero on success, or -EFAULT on error.
*/
+#define put_user(x, ptr) \
+ __put_user_check((x), (ptr), sizeof(*(ptr)))
+
+#define __put_user_check(x, ptr, size) \
+({ \
+ typeof(*(ptr)) __pu_val; \
+ typeof(*(ptr)) __user *__pu_addr = (ptr); \
+ int __pu_err = 0; \
+ \
+ __pu_val = (x); \
+ if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \
+ switch (size) { \
+ case 1: \
+ __put_user_asm("sb", __pu_addr, __pu_val, \
+ __pu_err); \
+ break; \
+ case 2: \
+ __put_user_asm("sh", __pu_addr, __pu_val, \
+ __pu_err); \
+ break; \
+ case 4: \
+ __put_user_asm("sw", __pu_addr, __pu_val, \
+ __pu_err); \
+ break; \
+ case 8: \
+ __put_user_asm_8(__pu_addr, __pu_val, __pu_err);\
+ break; \
+ default: \
+ __pu_err = __user_bad(); \
+ break; \
+ } \
+ } else { \
+ __pu_err = -EFAULT; \
+ } \
+ __pu_err; \
+})
#define __put_user(x, ptr) \
({ \
@@ -290,18 +353,6 @@
__gu_err; \
})
-#ifndef CONFIG_MMU
-
-#define put_user(x, ptr) __put_user((x), (ptr))
-
-#else /* CONFIG_MMU */
-
-#define put_user(x, ptr) \
-({ \
- access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) \
- ? __put_user((x), (ptr)) : -EFAULT; \
-})
-#endif /* CONFIG_MMU */
/* copy_to_from_user */
#define __copy_from_user(to, from, n) \
diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c
index 0071260..c1b459c 100644
--- a/arch/microblaze/kernel/asm-offsets.c
+++ b/arch/microblaze/kernel/asm-offsets.c
@@ -16,6 +16,7 @@
#include <linux/hardirq.h>
#include <linux/thread_info.h>
#include <linux/kbuild.h>
+#include <asm/cpuinfo.h>
int main(int argc, char *argv[])
{
diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c
index f04d8a8..109876e 100644
--- a/arch/microblaze/kernel/cpu/cache.c
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -96,13 +96,16 @@
}
-/* Helper macro for computing the limits of cache range loops */
+/* Helper macro for computing the limits of cache range loops
+ *
+ * End address can be unaligned which is OK for C implementation.
+ * ASM implementation align it in ASM macros
+ */
#define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \
do { \
int align = ~(cache_line_length - 1); \
end = min(start + cache_size, end); \
start &= align; \
- end = ((end & align) + cache_line_length); \
} while (0);
/*
@@ -111,9 +114,9 @@
*/
#define CACHE_ALL_LOOP(cache_size, line_length, op) \
do { \
- unsigned int len = cache_size; \
+ unsigned int len = cache_size - line_length; \
int step = -line_length; \
- BUG_ON(step >= 0); \
+ WARN_ON(step >= 0); \
\
__asm__ __volatile__ (" 1: " #op " %0, r0; \
bgtid %0, 1b; \
@@ -122,26 +125,22 @@
: "memory"); \
} while (0);
-
-#define CACHE_ALL_LOOP2(cache_size, line_length, op) \
-do { \
- unsigned int len = cache_size; \
- int step = -line_length; \
- BUG_ON(step >= 0); \
- \
- __asm__ __volatile__ (" 1: " #op " r0, %0; \
- bgtid %0, 1b; \
- addk %0, %0, %1; \
- " : : "r" (len), "r" (step) \
- : "memory"); \
-} while (0);
-
-/* for wdc.flush/clear */
+/* Used for wdc.flush/clear which can use rB for offset which is not possible
+ * to use for simple wdc or wic.
+ *
+ * start address is cache aligned
+ * end address is not aligned, if end is aligned then I have to substract
+ * cacheline length because I can't flush/invalidate the next cacheline.
+ * If is not, I align it because I will flush/invalidate whole line.
+ */
#define CACHE_RANGE_LOOP_2(start, end, line_length, op) \
do { \
int step = -line_length; \
- int count = end - start; \
- BUG_ON(count <= 0); \
+ int align = ~(line_length - 1); \
+ int count; \
+ end = ((end & align) == end) ? end - line_length : end & align; \
+ count = end - start; \
+ WARN_ON(count < 0); \
\
__asm__ __volatile__ (" 1: " #op " %0, %1; \
bgtid %1, 1b; \
@@ -154,7 +153,9 @@
#define CACHE_RANGE_LOOP_1(start, end, line_length, op) \
do { \
int volatile temp; \
- BUG_ON(end - start <= 0); \
+ int align = ~(line_length - 1); \
+ end = ((end & align) == end) ? end - line_length : end & align; \
+ WARN_ON(end - start < 0); \
\
__asm__ __volatile__ (" 1: " #op " %1, r0; \
cmpu %0, %1, %2; \
@@ -360,8 +361,12 @@
#endif
}
-/* FIXME this is weird - should be only wdc but not work
- * MS: I am getting bus errors and other weird things */
+/* FIXME It is blindly invalidation as is expected
+ * but can't be called on noMMU in microblaze_cache_init below
+ *
+ * MS: noMMU kernel won't boot if simple wdc is used
+ * The reason should be that there are discared data which kernel needs
+ */
static void __invalidate_dcache_all_wb(void)
{
#ifndef ASM_LOOP
@@ -369,12 +374,12 @@
#endif
pr_debug("%s\n", __func__);
#ifdef ASM_LOOP
- CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
- wdc.clear)
+ CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
+ wdc)
#else
for (i = 0; i < cpuinfo.dcache_size;
i += cpuinfo.dcache_line_length)
- __asm__ __volatile__ ("wdc.clear %0, r0;" \
+ __asm__ __volatile__ ("wdc %0, r0;" \
: : "r" (i));
#endif
}
@@ -393,7 +398,7 @@
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc.clear %0, r0;" \
: : "r" (i));
#endif
@@ -413,7 +418,7 @@
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc %0, r0;" \
: : "r" (i));
#endif
@@ -437,7 +442,7 @@
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc %0, r0;" \
: : "r" (i));
#endif
@@ -465,7 +470,7 @@
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc %0, r0;" \
: : "r" (i));
#endif
@@ -504,7 +509,7 @@
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc.flush %0, r0;" \
: : "r" (i));
#endif
@@ -650,7 +655,11 @@
}
}
}
- invalidate_dcache();
+/* FIXME Invalidation is done in U-BOOT
+ * WT cache: Data is already written to main memory
+ * WB cache: Discard data on noMMU which caused that kernel doesn't boot
+ */
+ /* invalidate_dcache(); */
enable_dcache();
invalidate_icache();
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index 0c912b2..4216eb1 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -98,15 +98,17 @@
if (cpuinfo.use_icache)
count += seq_printf(m,
- "Icache:\t\t%ukB\n",
- cpuinfo.icache_size >> 10);
+ "Icache:\t\t%ukB\tline length:\t%dB\n",
+ cpuinfo.icache_size >> 10,
+ cpuinfo.icache_line_length);
else
count += seq_printf(m, "Icache:\t\tno\n");
if (cpuinfo.use_dcache) {
count += seq_printf(m,
- "Dcache:\t\t%ukB\n",
- cpuinfo.dcache_size >> 10);
+ "Dcache:\t\t%ukB\tline length:\t%dB\n",
+ cpuinfo.dcache_size >> 10,
+ cpuinfo.dcache_line_length);
if (cpuinfo.dcache_wb)
count += seq_printf(m, "\t\twrite-back\n");
else
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index ce72dd4..9dcd90b 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -74,7 +74,7 @@
void *vaddr, dma_addr_t dma_handle)
{
#ifdef NOT_COHERENT_CACHE
- consistent_free(vaddr);
+ consistent_free(size, vaddr);
#else
free_pages((unsigned long)vaddr, get_order(size));
#endif
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
index 391d619..8cc18cd 100644
--- a/arch/microblaze/kernel/entry-nommu.S
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -476,6 +476,8 @@
nop
work_pending:
+ enable_irq
+
andi r11, r19, _TIF_NEED_RESCHED
beqi r11, 1f
bralid r15, schedule
diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c
index d9f70f8..02cbdfe 100644
--- a/arch/microblaze/kernel/exceptions.c
+++ b/arch/microblaze/kernel/exceptions.c
@@ -121,7 +121,7 @@
}
printk(KERN_WARNING "Divide by zero exception " \
"in kernel mode.\n");
- die("Divide by exception", regs, SIGBUS);
+ die("Divide by zero exception", regs, SIGBUS);
break;
case MICROBLAZE_FPU_EXCEPTION:
pr_debug(KERN_WARNING "FPU exception\n");
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S
index da6a5f5..1bf7398 100644
--- a/arch/microblaze/kernel/head.S
+++ b/arch/microblaze/kernel/head.S
@@ -28,6 +28,7 @@
* for more details.
*/
+#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/page.h>
@@ -49,7 +50,7 @@
#endif /* CONFIG_MMU */
- .text
+ __HEAD
ENTRY(_start)
#if CONFIG_KERNEL_BASE_ADDR == 0
brai TOPHYS(real_start)
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index 6f39e2c..8f120ac 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -9,6 +9,7 @@
*/
#include <linux/init.h>
+#include <linux/ftrace.h>
#include <linux/kernel.h>
#include <linux/hardirq.h>
#include <linux/interrupt.h>
@@ -32,7 +33,7 @@
static u32 concurrent_irq;
-void do_IRQ(struct pt_regs *regs)
+void __irq_entry do_IRQ(struct pt_regs *regs)
{
unsigned int irq;
struct pt_regs *old_regs = set_irq_regs(regs);
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
index bc4dcb7..ff85f77 100644
--- a/arch/microblaze/kernel/microblaze_ksyms.c
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
@@ -52,3 +52,14 @@
extern void _mcount(void);
EXPORT_SYMBOL(_mcount);
#endif
+
+/*
+ * Assembly functions that may be used (directly or indirectly) by modules
+ */
+EXPORT_SYMBOL(__copy_tofrom_user);
+EXPORT_SYMBOL(__strncpy_user);
+
+#ifdef CONFIG_OPT_LIB_ASM
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+#endif
diff --git a/arch/microblaze/kernel/misc.S b/arch/microblaze/kernel/misc.S
index 7cf8649..0fb5fc6 100644
--- a/arch/microblaze/kernel/misc.S
+++ b/arch/microblaze/kernel/misc.S
@@ -93,39 +93,3 @@
nop
.size early_console_reg_tlb_alloc, . - early_console_reg_tlb_alloc
-
-/*
- * Copy a whole page (4096 bytes).
- */
-#define COPY_16_BYTES \
- lwi r7, r6, 0; \
- lwi r8, r6, 4; \
- lwi r9, r6, 8; \
- lwi r10, r6, 12; \
- swi r7, r5, 0; \
- swi r8, r5, 4; \
- swi r9, r5, 8; \
- swi r10, r5, 12
-
-
-/* FIXME DCACHE_LINE_BYTES (CONFIG_XILINX_MICROBLAZE0_DCACHE_LINE_LEN * 4)*/
-#define DCACHE_LINE_BYTES (4 * 4)
-
-.globl copy_page;
-.type copy_page, @function
-.align 4;
-copy_page:
- ori r11, r0, (PAGE_SIZE/DCACHE_LINE_BYTES) - 1
-_copy_page_loop:
- COPY_16_BYTES
-#if DCACHE_LINE_BYTES >= 32
- COPY_16_BYTES
-#endif
- addik r6, r6, DCACHE_LINE_BYTES
- addik r5, r5, DCACHE_LINE_BYTES
- bneid r11, _copy_page_loop
- addik r11, r11, -1
- rtsd r15, 8
- nop
-
- .size copy_page, . - copy_page
diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c
index cbecf11..0e73f66 100644
--- a/arch/microblaze/kernel/module.c
+++ b/arch/microblaze/kernel/module.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
void *module_alloc(unsigned long size)
{
@@ -151,6 +152,7 @@
int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
struct module *module)
{
+ flush_dcache();
return 0;
}
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c
index 5e4570e..75e4920 100644
--- a/arch/microblaze/kernel/traps.c
+++ b/arch/microblaze/kernel/traps.c
@@ -95,37 +95,3 @@
show_stack(NULL, NULL);
}
EXPORT_SYMBOL(dump_stack);
-
-#ifdef CONFIG_MMU
-void __bug(const char *file, int line, void *data)
-{
- if (data)
- printk(KERN_CRIT "kernel BUG at %s:%d (data = %p)!\n",
- file, line, data);
- else
- printk(KERN_CRIT "kernel BUG at %s:%d!\n", file, line);
-
- machine_halt();
-}
-
-int bad_trap(int trap_num, struct pt_regs *regs)
-{
- printk(KERN_CRIT
- "unimplemented trap %d called at 0x%08lx, pid %d!\n",
- trap_num, regs->pc, current->pid);
- return -ENOSYS;
-}
-
-int debug_trap(struct pt_regs *regs)
-{
- int i;
- printk(KERN_CRIT "debug trap\n");
- for (i = 0; i < 32; i++) {
- /* printk("r%i:%08X\t",i,regs->gpr[i]); */
- if ((i % 4) == 3)
- printk(KERN_CRIT "\n");
- }
- printk(KERN_CRIT "pc:%08lX\tmsr:%08lX\n", regs->pc, regs->msr);
- return -ENOSYS;
-}
-#endif
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 5ef619a..db72d71 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -24,7 +24,8 @@
.text : AT(ADDR(.text) - LOAD_OFFSET) {
_text = . ;
_stext = . ;
- *(.text .text.*)
+ HEAD_TEXT
+ TEXT_TEXT
*(.fixup)
EXIT_TEXT
EXIT_CALL
diff --git a/arch/microblaze/mm/consistent.c b/arch/microblaze/mm/consistent.c
index f956e24..5a59dad 100644
--- a/arch/microblaze/mm/consistent.c
+++ b/arch/microblaze/mm/consistent.c
@@ -42,11 +42,12 @@
#include <linux/uaccess.h>
#include <asm/pgtable.h>
#include <asm/cpuinfo.h>
+#include <asm/tlbflush.h>
#ifndef CONFIG_MMU
-
/* I have to use dcache values because I can't relate on ram size */
-#define UNCACHED_SHADOW_MASK (cpuinfo.dcache_high - cpuinfo.dcache_base + 1)
+# define UNCACHED_SHADOW_MASK (cpuinfo.dcache_high - cpuinfo.dcache_base + 1)
+#endif
/*
* Consistent memory allocators. Used for DMA devices that want to
@@ -60,71 +61,16 @@
*/
void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
{
- struct page *page, *end, *free;
- unsigned long order;
- void *ret, *virt;
+ unsigned long order, vaddr;
+ void *ret;
+ unsigned int i, err = 0;
+ struct page *page, *end;
- if (in_interrupt())
- BUG();
-
- size = PAGE_ALIGN(size);
- order = get_order(size);
-
- page = alloc_pages(gfp, order);
- if (!page)
- goto no_page;
-
- /* We could do with a page_to_phys and page_to_bus here. */
- virt = page_address(page);
- ret = ioremap(virt_to_phys(virt), size);
- if (!ret)
- goto no_remap;
-
- /*
- * Here's the magic! Note if the uncached shadow is not implemented,
- * it's up to the calling code to also test that condition and make
- * other arranegments, such as manually flushing the cache and so on.
- */
-#ifdef CONFIG_XILINX_UNCACHED_SHADOW
- ret = (void *)((unsigned) ret | UNCACHED_SHADOW_MASK);
-#endif
- /* dma_handle is same as physical (shadowed) address */
- *dma_handle = (dma_addr_t)ret;
-
- /*
- * free wasted pages. We skip the first page since we know
- * that it will have count = 1 and won't require freeing.
- * We also mark the pages in use as reserved so that
- * remap_page_range works.
- */
- page = virt_to_page(virt);
- free = page + (size >> PAGE_SHIFT);
- end = page + (1 << order);
-
- for (; page < end; page++) {
- init_page_count(page);
- if (page >= free)
- __free_page(page);
- else
- SetPageReserved(page);
- }
-
- return ret;
-no_remap:
- __free_pages(page, order);
-no_page:
- return NULL;
-}
-
-#else
-
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
-{
- int order, err, i;
- unsigned long page, va, flags;
+#ifdef CONFIG_MMU
phys_addr_t pa;
struct vm_struct *area;
- void *ret;
+ unsigned long va;
+#endif
if (in_interrupt())
BUG();
@@ -133,71 +79,133 @@
size = PAGE_ALIGN(size);
order = get_order(size);
- page = __get_free_pages(gfp, order);
- if (!page) {
- BUG();
+ vaddr = __get_free_pages(gfp, order);
+ if (!vaddr)
return NULL;
- }
/*
* we need to ensure that there are no cachelines in use,
* or worse dirty in this area.
*/
- flush_dcache_range(virt_to_phys(page), virt_to_phys(page) + size);
+ flush_dcache_range(virt_to_phys((void *)vaddr),
+ virt_to_phys((void *)vaddr) + size);
+#ifndef CONFIG_MMU
+ ret = (void *)vaddr;
+ /*
+ * Here's the magic! Note if the uncached shadow is not implemented,
+ * it's up to the calling code to also test that condition and make
+ * other arranegments, such as manually flushing the cache and so on.
+ */
+# ifdef CONFIG_XILINX_UNCACHED_SHADOW
+ ret = (void *)((unsigned) ret | UNCACHED_SHADOW_MASK);
+# endif
+ if ((unsigned int)ret > cpuinfo.dcache_base &&
+ (unsigned int)ret < cpuinfo.dcache_high)
+ printk(KERN_WARNING
+ "ERROR: Your cache coherent area is CACHED!!!\n");
+
+ /* dma_handle is same as physical (shadowed) address */
+ *dma_handle = (dma_addr_t)ret;
+#else
/* Allocate some common virtual space to map the new pages. */
area = get_vm_area(size, VM_ALLOC);
- if (area == NULL) {
- free_pages(page, order);
+ if (!area) {
+ free_pages(vaddr, order);
return NULL;
}
va = (unsigned long) area->addr;
ret = (void *)va;
/* This gives us the real physical address of the first page. */
- *dma_handle = pa = virt_to_bus((void *)page);
-
- /* MS: This is the whole magic - use cache inhibit pages */
- flags = _PAGE_KERNEL | _PAGE_NO_CACHE;
+ *dma_handle = pa = virt_to_bus((void *)vaddr);
+#endif
/*
- * Set refcount=1 on all pages in an order>0
- * allocation so that vfree() will actually
- * free all pages that were allocated.
+ * free wasted pages. We skip the first page since we know
+ * that it will have count = 1 and won't require freeing.
+ * We also mark the pages in use as reserved so that
+ * remap_page_range works.
*/
- if (order > 0) {
- struct page *rpage = virt_to_page(page);
- for (i = 1; i < (1 << order); i++)
- init_page_count(rpage+i);
+ page = virt_to_page(vaddr);
+ end = page + (1 << order);
+
+ split_page(page, order);
+
+ for (i = 0; i < size && err == 0; i += PAGE_SIZE) {
+#ifdef CONFIG_MMU
+ /* MS: This is the whole magic - use cache inhibit pages */
+ err = map_page(va + i, pa + i, _PAGE_KERNEL | _PAGE_NO_CACHE);
+#endif
+
+ SetPageReserved(page);
+ page++;
}
- err = 0;
- for (i = 0; i < size && err == 0; i += PAGE_SIZE)
- err = map_page(va+i, pa+i, flags);
+ /* Free the otherwise unused pages. */
+ while (page < end) {
+ __free_page(page);
+ page++;
+ }
if (err) {
- vfree((void *)va);
+ free_pages(vaddr, order);
return NULL;
}
return ret;
}
-#endif /* CONFIG_MMU */
EXPORT_SYMBOL(consistent_alloc);
/*
* free page(s) as defined by the above mapping.
*/
-void consistent_free(void *vaddr)
+void consistent_free(size_t size, void *vaddr)
{
+ struct page *page;
+
if (in_interrupt())
BUG();
+ size = PAGE_ALIGN(size);
+
+#ifndef CONFIG_MMU
/* Clear SHADOW_MASK bit in address, and free as per usual */
-#ifdef CONFIG_XILINX_UNCACHED_SHADOW
+# ifdef CONFIG_XILINX_UNCACHED_SHADOW
vaddr = (void *)((unsigned)vaddr & ~UNCACHED_SHADOW_MASK);
+# endif
+ page = virt_to_page(vaddr);
+
+ do {
+ ClearPageReserved(page);
+ __free_page(page);
+ page++;
+ } while (size -= PAGE_SIZE);
+#else
+ do {
+ pte_t *ptep;
+ unsigned long pfn;
+
+ ptep = pte_offset_kernel(pmd_offset(pgd_offset_k(
+ (unsigned int)vaddr),
+ (unsigned int)vaddr),
+ (unsigned int)vaddr);
+ if (!pte_none(*ptep) && pte_present(*ptep)) {
+ pfn = pte_pfn(*ptep);
+ pte_clear(&init_mm, (unsigned int)vaddr, ptep);
+ if (pfn_valid(pfn)) {
+ page = pfn_to_page(pfn);
+
+ ClearPageReserved(page);
+ __free_page(page);
+ }
+ }
+ vaddr += PAGE_SIZE;
+ } while (size -= PAGE_SIZE);
+
+ /* flush tlb */
+ flush_tlb_all();
#endif
- vfree(vaddr);
}
EXPORT_SYMBOL(consistent_free);
@@ -221,7 +229,7 @@
case PCI_DMA_NONE:
BUG();
case PCI_DMA_FROMDEVICE: /* invalidate only */
- flush_dcache_range(start, end);
+ invalidate_dcache_range(start, end);
break;
case PCI_DMA_TODEVICE: /* writeback only */
flush_dcache_range(start, end);
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c
index 7af87f4..bab9229 100644
--- a/arch/microblaze/mm/fault.c
+++ b/arch/microblaze/mm/fault.c
@@ -273,16 +273,11 @@
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- if (current->pid == 1) {
- yield();
- down_read(&mm->mmap_sem);
- goto survive;
- }
up_read(&mm->mmap_sem);
- printk(KERN_WARNING "VM: killing process %s\n", current->comm);
- if (user_mode(regs))
- do_exit(SIGKILL);
- bad_page_fault(regs, address, SIGKILL);
+ if (!user_mode(regs))
+ bad_page_fault(regs, address, SIGKILL);
+ else
+ pagefault_out_of_memory();
return;
do_sigbus:
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
index f42c2dd..cca3579 100644
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -47,6 +47,7 @@
EXPORT_SYMBOL(memory_start);
unsigned long memory_end; /* due to mm/nommu.c */
unsigned long memory_size;
+EXPORT_SYMBOL(memory_size);
/*
* paging_init() sets up the page tables - in fact we've already done this.
diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c
index d31312c..59bf233 100644
--- a/arch/microblaze/mm/pgtable.c
+++ b/arch/microblaze/mm/pgtable.c
@@ -42,6 +42,7 @@
unsigned long ioremap_base;
unsigned long ioremap_bot;
+EXPORT_SYMBOL(ioremap_bot);
/* The maximum lowmem defaults to 768Mb, but this can be configured to
* another value.
@@ -161,24 +162,6 @@
return err;
}
-void __init adjust_total_lowmem(void)
-{
-/* TBD */
-#if 0
- unsigned long max_low_mem = MAX_LOW_MEM;
-
- if (total_lowmem > max_low_mem) {
- total_lowmem = max_low_mem;
-#ifndef CONFIG_HIGHMEM
- printk(KERN_INFO "Warning, memory limited to %ld Mb, use "
- "CONFIG_HIGHMEM to reach %ld Mb\n",
- max_low_mem >> 20, total_memory >> 20);
- total_memory = total_lowmem;
-#endif /* CONFIG_HIGHMEM */
- }
-#endif
-}
-
/*
* Map in all of physical memory starting at CONFIG_KERNEL_START.
*/
@@ -206,24 +189,6 @@
/* is x a power of 2? */
#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
-/*
- * Set up a mapping for a block of I/O.
- * virt, phys, size must all be page-aligned.
- * This should only be called before ioremap is called.
- */
-void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
- unsigned int size, int flags)
-{
- int i;
-
- if (virt > CONFIG_KERNEL_START && virt < ioremap_bot)
- ioremap_bot = ioremap_base = virt;
-
- /* Put it in the page tables. */
- for (i = 0; i < size; i += PAGE_SIZE)
- map_page(virt + i, phys + i, flags);
-}
-
/* Scan the real Linux page tables and return a PTE pointer for
* a virtual address in a context.
* Returns true (1) if PTE was found, zero otherwise. The pointer to
@@ -274,3 +239,18 @@
return pa;
}
+
+__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+ unsigned long address)
+{
+ pte_t *pte;
+ if (mem_init_done) {
+ pte = (pte_t *)__get_free_page(GFP_KERNEL |
+ __GFP_REPEAT | __GFP_ZERO);
+ } else {
+ pte = (pte_t *)early_get_page();
+ if (pte)
+ clear_page(pte);
+ }
+ return pte;
+}
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 740bb32..9cb782b 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -1025,7 +1025,7 @@
struct pci_dev *dev = bus->self;
- for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+ pci_bus_for_each_resource(bus, res, i) {
res = bus->resource[i];
if (!res)
continue;
@@ -1131,21 +1131,20 @@
* but we want to try to avoid allocating at 0x2900-0x2bff
* which might have be mirrored at 0x0100-0x03ff..
*/
-void pcibios_align_resource(void *data, struct resource *res,
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
+ resource_size_t start = res->start;
if (res->flags & IORESOURCE_IO) {
- resource_size_t start = res->start;
-
if (skip_isa_ioresource_align(dev))
- return;
- if (start & 0x300) {
+ return start;
+ if (start & 0x300)
start = (start + 0x3ff) & ~0x3ff;
- res->start = start;
- }
}
+
+ return start;
}
EXPORT_SYMBOL(pcibios_align_resource);
@@ -1228,7 +1227,7 @@
pr_debug("PCI: Allocating bus resources for %04x:%02x...\n",
pci_domain_nr(bus), bus->number);
- for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
+ pci_bus_for_each_resource(bus, res, i) {
res = bus->resource[i];
if (!res || !res->flags
|| res->start > res->end || res->parent)
@@ -1508,7 +1507,7 @@
pci_bus_add_devices(bus);
/* Fixup EEH */
- eeh_add_device_tree_late(bus);
+ /* eeh_add_device_tree_late(bus); */
}
EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 519197e..59dc0c7 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -29,7 +29,7 @@
*
* Atomically reads the value of @v.
*/
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
/*
* atomic_set - set atomic variable
@@ -410,7 +410,7 @@
* @v: pointer of type atomic64_t
*
*/
-#define atomic64_read(v) ((v)->counter)
+#define atomic64_read(v) (*(volatile long *)&(v)->counter)
/*
* atomic64_set - set atomic variable
diff --git a/arch/mips/include/asm/i8253.h b/arch/mips/include/asm/i8253.h
index 032ca73..48bb823 100644
--- a/arch/mips/include/asm/i8253.h
+++ b/arch/mips/include/asm/i8253.h
@@ -12,7 +12,7 @@
#define PIT_CH0 0x40
#define PIT_CH2 0x42
-extern spinlock_t i8253_lock;
+extern raw_spinlock_t i8253_lock;
extern void setup_pit_timer(void);
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 49382d5..c6e3c93 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -135,6 +135,12 @@
#define FPU_CSR_COND7 0x80000000 /* $fcc7 */
/*
+ * Bits 18 - 20 of the FPU Status Register will be read as 0,
+ * and should be written as zero.
+ */
+#define FPU_CSR_RSVD 0x001c0000
+
+/*
* X the exception cause indicator
* E the exception enable
* S the sticky/flag bit
@@ -161,7 +167,8 @@
#define FPU_CSR_UDF_S 0x00000008
#define FPU_CSR_INE_S 0x00000004
-/* rounding mode */
+/* Bits 0 and 1 of FPU Status Register specify the rounding mode */
+#define FPU_CSR_RM 0x00000003
#define FPU_CSR_RN 0x0 /* nearest */
#define FPU_CSR_RZ 0x1 /* towards zero */
#define FPU_CSR_RU 0x2 /* towards +Infinity */
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index ed5c441..9479406 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -15,7 +15,7 @@
#include <asm/io.h>
#include <asm/time.h>
-DEFINE_SPINLOCK(i8253_lock);
+DEFINE_RAW_SPINLOCK(i8253_lock);
EXPORT_SYMBOL(i8253_lock);
/*
@@ -26,7 +26,7 @@
static void init_pit_timer(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- spin_lock(&i8253_lock);
+ raw_spin_lock(&i8253_lock);
switch(mode) {
case CLOCK_EVT_MODE_PERIODIC:
@@ -55,7 +55,7 @@
/* Nothing to do here */
break;
}
- spin_unlock(&i8253_lock);
+ raw_spin_unlock(&i8253_lock);
}
/*
@@ -65,10 +65,10 @@
*/
static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
{
- spin_lock(&i8253_lock);
+ raw_spin_lock(&i8253_lock);
outb_p(delta & 0xff , PIT_CH0); /* LSB */
outb(delta >> 8 , PIT_CH0); /* MSB */
- spin_unlock(&i8253_lock);
+ raw_spin_unlock(&i8253_lock);
return 0;
}
@@ -137,7 +137,7 @@
static int old_count;
static u32 old_jifs;
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
/*
* Although our caller may have the read side of xtime_lock,
* this is now a seqlock, and we are cheating in this routine
@@ -183,7 +183,7 @@
old_count = count;
old_jifs = jifs;
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
count = (LATCH - 1) - count;
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 44337ba..a5297e2 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -385,7 +385,7 @@
PTR sys_fchmodat
PTR sys_faccessat
PTR compat_sys_pselect6
- PTR sys_ppoll /* 6265 */
+ PTR compat_sys_ppoll /* 6265 */
PTR sys_unshare
PTR sys_splice
PTR sys_sync_file_range
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 8f2f8e9..f2338d1 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -78,6 +78,9 @@
#define FPCREG_RID 0 /* $0 = revision id */
#define FPCREG_CSR 31 /* $31 = csr */
+/* Determine rounding mode from the RM bits of the FCSR */
+#define modeindex(v) ((v) & FPU_CSR_RM)
+
/* Convert Mips rounding mode (0..3) to IEEE library modes. */
static const unsigned char ieee_rm[4] = {
[FPU_CSR_RN] = IEEE754_RN,
@@ -384,10 +387,14 @@
(void *) (xcp->cp0_epc),
MIPSInst_RT(ir), value);
#endif
- value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
- ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03);
- /* convert to ieee library modes */
- ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3];
+
+ /*
+ * Don't write reserved bits,
+ * and convert to ieee library modes
+ */
+ ctx->fcr31 = (value &
+ ~(FPU_CSR_RSVD | FPU_CSR_RM)) |
+ ieee_rm[modeindex(value)];
}
if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
return SIGFPE;
diff --git a/arch/mips/oprofile/op_model_loongson2.c b/arch/mips/oprofile/op_model_loongson2.c
index 29e2326..fa3bf66 100644
--- a/arch/mips/oprofile/op_model_loongson2.c
+++ b/arch/mips/oprofile/op_model_loongson2.c
@@ -122,7 +122,7 @@
*/
/* Check whether the irq belongs to me */
- enabled = read_c0_perfcnt() & LOONGSON2_PERFCNT_INT_EN;
+ enabled = read_c0_perfctrl() & LOONGSON2_PERFCNT_INT_EN;
if (!enabled)
return IRQ_NONE;
enabled = reg.cnt1_enabled | reg.cnt2_enabled;
diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h
index 5bf5be9..e41222d 100644
--- a/arch/mn10300/include/asm/atomic.h
+++ b/arch/mn10300/include/asm/atomic.h
@@ -31,7 +31,7 @@
* Atomically reads the value of @v. Note that the guaranteed
* useful range of an atomic_t is only 24 bits.
*/
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
/**
* atomic_set - set atomic variable
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
index 716634d..f819559 100644
--- a/arch/parisc/include/asm/atomic.h
+++ b/arch/parisc/include/asm/atomic.h
@@ -189,7 +189,7 @@
static __inline__ int atomic_read(const atomic_t *v)
{
- return v->counter;
+ return (*(volatile int *)&(v)->counter);
}
/* exported interface */
@@ -286,7 +286,7 @@
static __inline__ s64
atomic64_read(const atomic64_t *v)
{
- return v->counter;
+ return (*(volatile long *)&(v)->counter);
}
#define atomic64_add(i,v) ((void)(__atomic64_add_return( ((s64)(i)),(v))))
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index 9f4c9d4f..bd100fc 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -130,43 +130,5 @@
*/
struct irq_chip;
-#ifdef CONFIG_PERF_EVENTS
-
-#ifdef CONFIG_PPC64
-static inline unsigned long test_perf_event_pending(void)
-{
- unsigned long x;
-
- asm volatile("lbz %0,%1(13)"
- : "=r" (x)
- : "i" (offsetof(struct paca_struct, perf_event_pending)));
- return x;
-}
-
-static inline void set_perf_event_pending(void)
-{
- asm volatile("stb %0,%1(13)" : :
- "r" (1),
- "i" (offsetof(struct paca_struct, perf_event_pending)));
-}
-
-static inline void clear_perf_event_pending(void)
-{
- asm volatile("stb %0,%1(13)" : :
- "r" (0),
- "i" (offsetof(struct paca_struct, perf_event_pending)));
-}
-#endif /* CONFIG_PPC64 */
-
-#else /* CONFIG_PERF_EVENTS */
-
-static inline unsigned long test_perf_event_pending(void)
-{
- return 0;
-}
-
-static inline void clear_perf_event_pending(void) {}
-#endif /* CONFIG_PERF_EVENTS */
-
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HW_IRQ_H */
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 957ceb7..c09138d 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -133,7 +133,6 @@
DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
- DEFINE(PACAPERFPEND, offsetof(struct paca_struct, perf_event_pending));
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
#ifdef CONFIG_PPC_MM_SLICES
DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index 59c9285..4ff4da2c 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -1,7 +1,8 @@
/*
* Contains routines needed to support swiotlb for ppc.
*
- * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
+ * Author: Becky Bruce
*
* 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
@@ -70,7 +71,7 @@
sd->max_direct_dma_addr = 0;
/* May need to bounce if the device can't address all of DRAM */
- if (dma_get_mask(dev) < lmb_end_of_DRAM())
+ if ((dma_get_mask(dev) + 1) < lmb_end_of_DRAM())
set_dma_ops(dev, &swiotlb_dma_ops);
return NOTIFY_DONE;
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 07109d8..42e9d90 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -556,15 +556,6 @@
2:
TRACE_AND_RESTORE_IRQ(r5);
-#ifdef CONFIG_PERF_EVENTS
- /* check paca->perf_event_pending if we're enabling ints */
- lbz r3,PACAPERFPEND(r13)
- and. r3,r3,r5
- beq 27f
- bl .perf_event_do_pending
-27:
-#endif /* CONFIG_PERF_EVENTS */
-
/* extract EE bit and use it to restore paca->hard_enabled */
ld r3,_MSR(r1)
rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 64f6f20..066bd31 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -53,7 +53,6 @@
#include <linux/bootmem.h>
#include <linux/pci.h>
#include <linux/debugfs.h>
-#include <linux/perf_event.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -145,11 +144,6 @@
}
#endif /* CONFIG_PPC_STD_MMU_64 */
- if (test_perf_event_pending()) {
- clear_perf_event_pending();
- perf_event_do_pending();
- }
-
/*
* if (get_paca()->hard_enabled) return;
* But again we need to take care that gcc gets hard_enabled directly
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 1b16b9a..0441bbd 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -532,25 +532,60 @@
}
#endif /* CONFIG_PPC_ISERIES */
-#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_PPC32)
-DEFINE_PER_CPU(u8, perf_event_pending);
+#ifdef CONFIG_PERF_EVENTS
-void set_perf_event_pending(void)
+/*
+ * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable...
+ */
+#ifdef CONFIG_PPC64
+static inline unsigned long test_perf_event_pending(void)
{
- get_cpu_var(perf_event_pending) = 1;
- set_dec(1);
- put_cpu_var(perf_event_pending);
+ unsigned long x;
+
+ asm volatile("lbz %0,%1(13)"
+ : "=r" (x)
+ : "i" (offsetof(struct paca_struct, perf_event_pending)));
+ return x;
}
+static inline void set_perf_event_pending_flag(void)
+{
+ asm volatile("stb %0,%1(13)" : :
+ "r" (1),
+ "i" (offsetof(struct paca_struct, perf_event_pending)));
+}
+
+static inline void clear_perf_event_pending(void)
+{
+ asm volatile("stb %0,%1(13)" : :
+ "r" (0),
+ "i" (offsetof(struct paca_struct, perf_event_pending)));
+}
+
+#else /* 32-bit */
+
+DEFINE_PER_CPU(u8, perf_event_pending);
+
+#define set_perf_event_pending_flag() __get_cpu_var(perf_event_pending) = 1
#define test_perf_event_pending() __get_cpu_var(perf_event_pending)
#define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0
-#else /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */
+#endif /* 32 vs 64 bit */
+
+void set_perf_event_pending(void)
+{
+ preempt_disable();
+ set_perf_event_pending_flag();
+ set_dec(1);
+ preempt_enable();
+}
+
+#else /* CONFIG_PERF_EVENTS */
#define test_perf_event_pending() 0
#define clear_perf_event_pending()
-#endif /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */
+#endif /* CONFIG_PERF_EVENTS */
/*
* For iSeries shared processors, we have to let the hypervisor
@@ -582,10 +617,6 @@
set_dec(DECREMENTER_MAX);
#ifdef CONFIG_PPC32
- if (test_perf_event_pending()) {
- clear_perf_event_pending();
- perf_event_do_pending();
- }
if (atomic_read(&ppc_n_lost_interrupts) != 0)
do_IRQ(regs);
#endif
@@ -604,6 +635,11 @@
calculate_steal_time();
+ if (test_perf_event_pending()) {
+ clear_perf_event_pending();
+ perf_event_do_pending();
+ }
+
#ifdef CONFIG_PPC_ISERIES
if (firmware_has_feature(FW_FEATURE_ISERIES))
get_lppaca()->int_dword.fields.decr_int = 0;
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 2570fcc..81231254 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -440,7 +440,7 @@
unsigned int gtlb_index;
gtlb_index = kvmppc_get_gpr(vcpu, ra);
- if (gtlb_index > KVM44x_GUEST_TLB_SIZE) {
+ if (gtlb_index >= KVM44x_GUEST_TLB_SIZE) {
printk("%s: index %d\n", __func__, gtlb_index);
kvmppc_dump_vcpu(vcpu);
return EMULATE_FAIL;
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index 1bbcc49..b8f8dc1 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -82,7 +82,7 @@
_ehead:
#ifdef CONFIG_SHARED_KERNEL
- .org 0x100000
+ .org 0x100000 - 0x11000 # head.o ends at 0x11000
#endif
#
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 1f70970..cdef687 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -80,7 +80,7 @@
_ehead:
#ifdef CONFIG_SHARED_KERNEL
- .org 0x100000
+ .org 0x100000 - 0x11000 # head.o ends at 0x11000
#endif
#
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 33fdc5a..9f654da 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -640,7 +640,7 @@
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
- long ret;
+ long ret = 0;
/* Do the secure computing check first. */
secure_computing(regs->gprs[2]);
@@ -649,7 +649,6 @@
* The sysc_tracesys code in entry.S stored the system
* call number to gprs[2].
*/
- ret = regs->gprs[2];
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
(tracehook_report_syscall_entry(regs) ||
regs->gprs[2] >= NR_syscalls)) {
@@ -671,7 +670,7 @@
regs->gprs[2], regs->orig_gpr2,
regs->gprs[3], regs->gprs[4],
regs->gprs[5]);
- return ret;
+ return ret ?: regs->gprs[2];
}
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig
index fba1f62..dba024d72 100644
--- a/arch/sh/configs/rts7751r2d1_defconfig
+++ b/arch/sh/configs/rts7751r2d1_defconfig
@@ -877,7 +877,7 @@
#
# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=1
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig
index a8d538f..6d511d0 100644
--- a/arch/sh/configs/rts7751r2dplus_defconfig
+++ b/arch/sh/configs/rts7751r2dplus_defconfig
@@ -963,7 +963,7 @@
#
# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=1
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 17811e5..f98141b 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include "pci-sh4.h"
#include <asm/addrspace.h>
+#include <asm/sizes.h>
static int __init __area_sdram_check(struct pci_channel *chan,
unsigned int area)
@@ -47,8 +48,8 @@
static struct resource sh7751_pci_resources[] = {
{
.name = "SH7751_IO",
- .start = SH7751_PCI_IO_BASE,
- .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+ .start = 0x1000,
+ .end = SZ_4M - 1,
.flags = IORESOURCE_IO
}, {
.name = "SH7751_mem",
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index 275a448..c798312 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -13,7 +13,7 @@
#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v,i) ((v)->counter = (i))
#if defined(CONFIG_GUSA_RB)
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-register.h b/arch/sh/include/cpu-sh4/cpu/dma-register.h
index 55f9fec..de23595 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma-register.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma-register.h
@@ -76,7 +76,7 @@
}
#define TS_INDEX2VAL(i) ((((i) & 3) << CHCR_TS_LOW_SHIFT) | \
- ((((i) >> 2) & 3) << CHCR_TS_HIGH_SHIFT))
+ (((i) & 0xc) << CHCR_TS_HIGH_SHIFT))
#else /* CONFIG_CPU_SH4A */
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h
index f0d343c..7ae128b 100644
--- a/arch/sparc/include/asm/atomic_32.h
+++ b/arch/sparc/include/asm/atomic_32.h
@@ -25,7 +25,7 @@
extern int atomic_add_unless(atomic_t *, int, int);
extern void atomic_set(atomic_t *, int);
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_add(i, v) ((void)__atomic_add_return( (int)(i), (v)))
#define atomic_sub(i, v) ((void)__atomic_add_return(-(int)(i), (v)))
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
index f2e4800..2050ca0 100644
--- a/arch/sparc/include/asm/atomic_64.h
+++ b/arch/sparc/include/asm/atomic_64.h
@@ -13,8 +13,8 @@
#define ATOMIC_INIT(i) { (i) }
#define ATOMIC64_INIT(i) { (i) }
-#define atomic_read(v) ((v)->counter)
-#define atomic64_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
+#define atomic64_read(v) (*(volatile long *)&(v)->counter)
#define atomic_set(v, i) (((v)->counter) = i)
#define atomic64_set(v, i) (((v)->counter) = i)
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
index e72ac9c..766121a 100644
--- a/arch/sparc/include/asm/bitops_64.h
+++ b/arch/sparc/include/asm/bitops_64.h
@@ -44,7 +44,7 @@
#ifdef ULTRA_HAS_POPULATION_COUNT
-static inline unsigned int hweight64(unsigned long w)
+static inline unsigned int __arch_hweight64(unsigned long w)
{
unsigned int res;
@@ -52,7 +52,7 @@
return res;
}
-static inline unsigned int hweight32(unsigned int w)
+static inline unsigned int __arch_hweight32(unsigned int w)
{
unsigned int res;
@@ -60,7 +60,7 @@
return res;
}
-static inline unsigned int hweight16(unsigned int w)
+static inline unsigned int __arch_hweight16(unsigned int w)
{
unsigned int res;
@@ -68,7 +68,7 @@
return res;
}
-static inline unsigned int hweight8(unsigned int w)
+static inline unsigned int __arch_hweight8(unsigned int w)
{
unsigned int res;
@@ -78,9 +78,10 @@
#else
-#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/arch_hweight.h>
#endif
+#include <asm-generic/bitops/const_hweight.h>
#include <asm-generic/bitops/lock.h>
#endif /* __KERNEL__ */
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index e277193..cf4ce26 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -91,6 +91,8 @@
/* Enabled/disable state. */
int enabled;
+
+ unsigned int group_flag;
};
DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, };
@@ -980,53 +982,6 @@
return n;
}
-static void event_sched_in(struct perf_event *event)
-{
- event->state = PERF_EVENT_STATE_ACTIVE;
- event->oncpu = smp_processor_id();
- event->tstamp_running += event->ctx->time - event->tstamp_stopped;
- if (is_software_event(event))
- event->pmu->enable(event);
-}
-
-int hw_perf_group_sched_in(struct perf_event *group_leader,
- struct perf_cpu_context *cpuctx,
- struct perf_event_context *ctx)
-{
- struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
- struct perf_event *sub;
- int n0, n;
-
- if (!sparc_pmu)
- return 0;
-
- n0 = cpuc->n_events;
- n = collect_events(group_leader, perf_max_events - n0,
- &cpuc->event[n0], &cpuc->events[n0],
- &cpuc->current_idx[n0]);
- if (n < 0)
- return -EAGAIN;
- if (check_excludes(cpuc->event, n0, n))
- return -EINVAL;
- if (sparc_check_constraints(cpuc->event, cpuc->events, n + n0))
- return -EAGAIN;
- cpuc->n_events = n0 + n;
- cpuc->n_added += n;
-
- cpuctx->active_oncpu += n;
- n = 1;
- event_sched_in(group_leader);
- list_for_each_entry(sub, &group_leader->sibling_list, group_entry) {
- if (sub->state != PERF_EVENT_STATE_OFF) {
- event_sched_in(sub);
- n++;
- }
- }
- ctx->nr_active += n;
-
- return 1;
-}
-
static int sparc_pmu_enable(struct perf_event *event)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
@@ -1044,11 +999,20 @@
cpuc->events[n0] = event->hw.event_base;
cpuc->current_idx[n0] = PIC_NO_INDEX;
+ /*
+ * If group events scheduling transaction was started,
+ * skip the schedulability test here, it will be peformed
+ * at commit time(->commit_txn) as a whole
+ */
+ if (cpuc->group_flag & PERF_EVENT_TXN_STARTED)
+ goto nocheck;
+
if (check_excludes(cpuc->event, n0, 1))
goto out;
if (sparc_check_constraints(cpuc->event, cpuc->events, n0 + 1))
goto out;
+nocheck:
cpuc->n_events++;
cpuc->n_added++;
@@ -1128,11 +1092,61 @@
return 0;
}
+/*
+ * Start group events scheduling transaction
+ * Set the flag to make pmu::enable() not perform the
+ * schedulability test, it will be performed at commit time
+ */
+static void sparc_pmu_start_txn(const struct pmu *pmu)
+{
+ struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+
+ cpuhw->group_flag |= PERF_EVENT_TXN_STARTED;
+}
+
+/*
+ * Stop group events scheduling transaction
+ * Clear the flag and pmu::enable() will perform the
+ * schedulability test.
+ */
+static void sparc_pmu_cancel_txn(const struct pmu *pmu)
+{
+ struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+
+ cpuhw->group_flag &= ~PERF_EVENT_TXN_STARTED;
+}
+
+/*
+ * Commit group events scheduling transaction
+ * Perform the group schedulability test as a whole
+ * Return 0 if success
+ */
+static int sparc_pmu_commit_txn(const struct pmu *pmu)
+{
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+ int n;
+
+ if (!sparc_pmu)
+ return -EINVAL;
+
+ cpuc = &__get_cpu_var(cpu_hw_events);
+ n = cpuc->n_events;
+ if (check_excludes(cpuc->event, 0, n))
+ return -EINVAL;
+ if (sparc_check_constraints(cpuc->event, cpuc->events, n))
+ return -EAGAIN;
+
+ return 0;
+}
+
static const struct pmu pmu = {
.enable = sparc_pmu_enable,
.disable = sparc_pmu_disable,
.read = sparc_pmu_read,
.unthrottle = sparc_pmu_unthrottle,
+ .start_txn = sparc_pmu_start_txn,
+ .cancel_txn = sparc_pmu_cancel_txn,
+ .commit_txn = sparc_pmu_commit_txn,
};
const struct pmu *hw_perf_event_init(struct perf_event *event)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 01177dc..a2d3a5f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -201,20 +201,17 @@
# Use the generic interrupt handling code in kernel/irq/:
config GENERIC_HARDIRQS
- bool
- default y
+ def_bool y
config GENERIC_HARDIRQS_NO__DO_IRQ
def_bool y
config GENERIC_IRQ_PROBE
- bool
- default y
+ def_bool y
config GENERIC_PENDING_IRQ
- bool
+ def_bool y
depends on GENERIC_HARDIRQS && SMP
- default y
config USE_GENERIC_SMP_HELPERS
def_bool y
@@ -229,19 +226,22 @@
depends on X86_64 && SMP
config X86_HT
- bool
+ def_bool y
depends on SMP
- default y
config X86_TRAMPOLINE
- bool
+ def_bool y
depends on SMP || (64BIT && ACPI_SLEEP)
- default y
config X86_32_LAZY_GS
def_bool y
depends on X86_32 && !CC_STACKPROTECTOR
+config ARCH_HWEIGHT_CFLAGS
+ string
+ default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
+ default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
+
config KTIME_SCALAR
def_bool X86_32
source "init/Kconfig"
@@ -451,7 +451,7 @@
firmware with - send email to <Martin.Bligh@us.ibm.com>.
config X86_SUPPORTS_MEMORY_FAILURE
- bool
+ def_bool y
# MCE code calls memory_failure():
depends on X86_MCE
# On 32-bit this adds too big of NODES_SHIFT and we run out of page flags:
@@ -459,7 +459,6 @@
# On 32-bit SPARSEMEM adds too big of SECTIONS_WIDTH:
depends on X86_64 || !SPARSEMEM
select ARCH_SUPPORTS_MEMORY_FAILURE
- default y
config X86_VISWS
bool "SGI 320/540 (Visual Workstation)"
@@ -574,7 +573,6 @@
config PARAVIRT_CLOCK
bool
- default n
endif
@@ -753,7 +751,6 @@
bool "Configure Maximum number of SMP Processors and NUMA Nodes"
depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL
select CPUMASK_OFFSTACK
- default n
---help---
Configure maximum number of CPUS and NUMA Nodes for this architecture.
If unsure, say N.
@@ -833,7 +830,6 @@
config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
bool "Reroute for broken boot IRQs"
- default n
depends on X86_IO_APIC
---help---
This option enables a workaround that fixes a source of
@@ -880,9 +876,8 @@
the DRAM Error Threshold.
config X86_ANCIENT_MCE
- def_bool n
+ bool "Support for old Pentium 5 / WinChip machine checks"
depends on X86_32 && X86_MCE
- prompt "Support for old Pentium 5 / WinChip machine checks"
---help---
Include support for machine check handling on old Pentium 5 or WinChip
systems. These typically need to be enabled explicitely on the command
@@ -890,8 +885,7 @@
config X86_MCE_THRESHOLD
depends on X86_MCE_AMD || X86_MCE_INTEL
- bool
- default y
+ def_bool y
config X86_MCE_INJECT
depends on X86_MCE
@@ -1030,8 +1024,8 @@
choice
prompt "High Memory Support"
- default HIGHMEM4G if !X86_NUMAQ
default HIGHMEM64G if X86_NUMAQ
+ default HIGHMEM4G
depends on X86_32
config NOHIGHMEM
@@ -1289,7 +1283,7 @@
config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
- depends on X86_32 && (HIGHMEM4G || HIGHMEM64G)
+ depends on HIGHMEM
---help---
The VM uses one page table entry for each page of physical memory.
For systems with a lot of RAM, this can be wasteful of precious
@@ -1373,8 +1367,7 @@
kernel, it won't hurt.
config MTRR
- bool
- default y
+ def_bool y
prompt "MTRR (Memory Type Range Register) support" if EMBEDDED
---help---
On Intel P6 family processors (Pentium Pro, Pentium II and later)
@@ -1440,8 +1433,7 @@
mtrr_spare_reg_nr=N on the kernel command line.
config X86_PAT
- bool
- default y
+ def_bool y
prompt "x86 PAT support" if EMBEDDED
depends on MTRR
---help---
@@ -1609,8 +1601,7 @@
depends on X86_32 && RELOCATABLE
config PHYSICAL_ALIGN
- hex
- prompt "Alignment value to which kernel should be aligned" if X86_32
+ hex "Alignment value to which kernel should be aligned" if X86_32
default "0x1000000"
range 0x2000 0x1000000
---help---
@@ -1657,7 +1648,6 @@
config CMDLINE_BOOL
bool "Built-in kernel command line"
- default n
---help---
Allow for specifying boot arguments to the kernel at
build time. On some systems (e.g. embedded ones), it is
@@ -1691,7 +1681,6 @@
config CMDLINE_OVERRIDE
bool "Built-in command line overrides boot loader arguments"
- default n
depends on CMDLINE_BOOL
---help---
Set this option to 'Y' to have the kernel ignore the boot loader
@@ -1727,8 +1716,7 @@
source "drivers/sfi/Kconfig"
config X86_APM_BOOT
- bool
- default y
+ def_bool y
depends on APM || APM_MODULE
menuconfig APM
@@ -1957,8 +1945,7 @@
experimental.
config DMAR_BROKEN_GFX_WA
- def_bool n
- prompt "Workaround broken graphics drivers (going away soon)"
+ bool "Workaround broken graphics drivers (going away soon)"
depends on DMAR && BROKEN
---help---
Current Graphics drivers tend to use physical address
@@ -2056,7 +2043,6 @@
config OLPC
bool "One Laptop Per Child support"
select GPIOLIB
- default n
---help---
Add support for detecting the unique features of the OLPC
XO hardware.
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 918fbb1..2ac9069 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -338,6 +338,10 @@
def_bool y
depends on M586MMX || M586TSC || M586 || M486 || M386
+config X86_INVD_BUG
+ def_bool y
+ depends on M486 || M386
+
config X86_WP_WORKS_OK
def_bool y
depends on !M386
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index bd58c8a..7508508 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -45,7 +45,6 @@
config EARLY_PRINTK_DBGP
bool "Early printk via EHCI debug port"
- default n
depends on EARLY_PRINTK && PCI
---help---
Write kernel log output directly into the EHCI debug port.
@@ -76,7 +75,6 @@
bool "Debug access to per_cpu maps"
depends on DEBUG_KERNEL
depends on SMP
- default n
---help---
Say Y to verify that the per_cpu map being accessed has
been setup. Adds a fair amount of code to kernel memory
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 0a43dc5..8aa1b59 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -95,8 +95,9 @@
cfi := $(call as-instr,.cfi_startproc\n.cfi_rel_offset $(sp-y)$(comma)0\n.cfi_endproc,-DCONFIG_AS_CFI=1)
# is .cfi_signal_frame supported too?
cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1)
-KBUILD_AFLAGS += $(cfi) $(cfi-sigframe)
-KBUILD_CFLAGS += $(cfi) $(cfi-sigframe)
+cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTIONS=1)
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections)
LDFLAGS := -m elf_$(UTS_MACHINE)
diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h
index b97f786..a63a68b 100644
--- a/arch/x86/include/asm/alternative-asm.h
+++ b/arch/x86/include/asm/alternative-asm.h
@@ -6,8 +6,8 @@
.macro LOCK_PREFIX
1: lock
.section .smp_locks,"a"
- _ASM_ALIGN
- _ASM_PTR 1b
+ .balign 4
+ .long 1b - .
.previous
.endm
#else
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index b09ec55..03b6bb53 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -28,20 +28,20 @@
*/
#ifdef CONFIG_SMP
-#define LOCK_PREFIX \
+#define LOCK_PREFIX_HERE \
".section .smp_locks,\"a\"\n" \
- _ASM_ALIGN "\n" \
- _ASM_PTR "661f\n" /* address */ \
+ ".balign 4\n" \
+ ".long 671f - .\n" /* offset */ \
".previous\n" \
- "661:\n\tlock; "
+ "671:"
+
+#define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; "
#else /* ! CONFIG_SMP */
+#define LOCK_PREFIX_HERE ""
#define LOCK_PREFIX ""
#endif
-/* This must be included *after* the definition of LOCK_PREFIX */
-#include <asm/cpufeature.h>
-
struct alt_instr {
u8 *instr; /* original instruction */
u8 *replacement;
@@ -96,6 +96,12 @@
".previous"
/*
+ * This must be included *after* the definition of ALTERNATIVE due to
+ * <asm/arch_hweight.h>
+ */
+#include <asm/cpufeature.h>
+
+/*
* Alternative instructions for different CPU types or capabilities.
*
* This allows to use optimized instructions even on generic binary
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index 86a0ff0..7014e88 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -174,6 +174,40 @@
(~((1ULL << (12 + ((lvl) * 9))) - 1)))
#define PM_ALIGNED(lvl, addr) ((PM_MAP_MASK(lvl) & (addr)) == (addr))
+/*
+ * Returns the page table level to use for a given page size
+ * Pagesize is expected to be a power-of-two
+ */
+#define PAGE_SIZE_LEVEL(pagesize) \
+ ((__ffs(pagesize) - 12) / 9)
+/*
+ * Returns the number of ptes to use for a given page size
+ * Pagesize is expected to be a power-of-two
+ */
+#define PAGE_SIZE_PTE_COUNT(pagesize) \
+ (1ULL << ((__ffs(pagesize) - 12) % 9))
+
+/*
+ * Aligns a given io-virtual address to a given page size
+ * Pagesize is expected to be a power-of-two
+ */
+#define PAGE_SIZE_ALIGN(address, pagesize) \
+ ((address) & ~((pagesize) - 1))
+/*
+ * Creates an IOMMU PTE for an address an a given pagesize
+ * The PTE has no permission bits set
+ * Pagesize is expected to be a power-of-two larger than 4096
+ */
+#define PAGE_SIZE_PTE(address, pagesize) \
+ (((address) | ((pagesize) - 1)) & \
+ (~(pagesize >> 1)) & PM_ADDR_MASK)
+
+/*
+ * Takes a PTE value with mode=0x07 and returns the page size it maps
+ */
+#define PTE_PAGE_SIZE(pte) \
+ (1ULL << (1 + ffz(((pte) | 0xfffULL))))
+
#define IOMMU_PTE_P (1ULL << 0)
#define IOMMU_PTE_TV (1ULL << 1)
#define IOMMU_PTE_U (1ULL << 59)
diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h
new file mode 100644
index 0000000..9686c3d
--- /dev/null
+++ b/arch/x86/include/asm/arch_hweight.h
@@ -0,0 +1,61 @@
+#ifndef _ASM_X86_HWEIGHT_H
+#define _ASM_X86_HWEIGHT_H
+
+#ifdef CONFIG_64BIT
+/* popcnt %edi, %eax -- redundant REX prefix for alignment */
+#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
+/* popcnt %rdi, %rax */
+#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
+#define REG_IN "D"
+#define REG_OUT "a"
+#else
+/* popcnt %eax, %eax */
+#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
+#define REG_IN "a"
+#define REG_OUT "a"
+#endif
+
+/*
+ * __sw_hweightXX are called from within the alternatives below
+ * and callee-clobbered registers need to be taken care of. See
+ * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
+ * compiler switches.
+ */
+static inline unsigned int __arch_hweight32(unsigned int w)
+{
+ unsigned int res = 0;
+
+ asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
+ : "="REG_OUT (res)
+ : REG_IN (w));
+
+ return res;
+}
+
+static inline unsigned int __arch_hweight16(unsigned int w)
+{
+ return __arch_hweight32(w & 0xffff);
+}
+
+static inline unsigned int __arch_hweight8(unsigned int w)
+{
+ return __arch_hweight32(w & 0xff);
+}
+
+static inline unsigned long __arch_hweight64(__u64 w)
+{
+ unsigned long res = 0;
+
+#ifdef CONFIG_X86_32
+ return __arch_hweight32((u32)w) +
+ __arch_hweight32((u32)(w >> 32));
+#else
+ asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
+ : "="REG_OUT (res)
+ : REG_IN (w));
+#endif /* CONFIG_X86_32 */
+
+ return res;
+}
+
+#endif
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 8f8217b..952a826 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -22,7 +22,7 @@
*/
static inline int atomic_read(const atomic_t *v)
{
- return v->counter;
+ return (*(volatile int *)&(v)->counter);
}
/**
@@ -246,6 +246,29 @@
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+/*
+ * atomic_dec_if_positive - decrement by 1 if old value positive
+ * @v: pointer of type atomic_t
+ *
+ * The function returns the old value of *v minus 1, even if
+ * the atomic variable, v, was not decremented.
+ */
+static inline int atomic_dec_if_positive(atomic_t *v)
+{
+ int c, old, dec;
+ c = atomic_read(v);
+ for (;;) {
+ dec = c - 1;
+ if (unlikely(dec < 0))
+ break;
+ old = atomic_cmpxchg((v), c, dec);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+ return dec;
+}
+
/**
* atomic_inc_short - increment of a short integer
* @v: pointer to type int
diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h
index 03027bf..2a934aa 100644
--- a/arch/x86/include/asm/atomic64_32.h
+++ b/arch/x86/include/asm/atomic64_32.h
@@ -14,109 +14,193 @@
#define ATOMIC64_INIT(val) { (val) }
-extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val);
+#ifdef CONFIG_X86_CMPXCHG64
+#define ATOMIC64_ALTERNATIVE_(f, g) "call atomic64_" #g "_cx8"
+#else
+#define ATOMIC64_ALTERNATIVE_(f, g) ALTERNATIVE("call atomic64_" #f "_386", "call atomic64_" #g "_cx8", X86_FEATURE_CX8)
+#endif
+
+#define ATOMIC64_ALTERNATIVE(f) ATOMIC64_ALTERNATIVE_(f, f)
+
+/**
+ * atomic64_cmpxchg - cmpxchg atomic64 variable
+ * @p: pointer to type atomic64_t
+ * @o: expected value
+ * @n: new value
+ *
+ * Atomically sets @v to @n if it was equal to @o and returns
+ * the old value.
+ */
+
+static inline long long atomic64_cmpxchg(atomic64_t *v, long long o, long long n)
+{
+ return cmpxchg64(&v->counter, o, n);
+}
/**
* atomic64_xchg - xchg atomic64 variable
- * @ptr: pointer to type atomic64_t
- * @new_val: value to assign
+ * @v: pointer to type atomic64_t
+ * @n: value to assign
*
- * Atomically xchgs the value of @ptr to @new_val and returns
+ * Atomically xchgs the value of @v to @n and returns
* the old value.
*/
-extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val);
+static inline long long atomic64_xchg(atomic64_t *v, long long n)
+{
+ long long o;
+ unsigned high = (unsigned)(n >> 32);
+ unsigned low = (unsigned)n;
+ asm volatile(ATOMIC64_ALTERNATIVE(xchg)
+ : "=A" (o), "+b" (low), "+c" (high)
+ : "S" (v)
+ : "memory"
+ );
+ return o;
+}
/**
* atomic64_set - set atomic64 variable
- * @ptr: pointer to type atomic64_t
- * @new_val: value to assign
+ * @v: pointer to type atomic64_t
+ * @n: value to assign
*
- * Atomically sets the value of @ptr to @new_val.
+ * Atomically sets the value of @v to @n.
*/
-extern void atomic64_set(atomic64_t *ptr, u64 new_val);
+static inline void atomic64_set(atomic64_t *v, long long i)
+{
+ unsigned high = (unsigned)(i >> 32);
+ unsigned low = (unsigned)i;
+ asm volatile(ATOMIC64_ALTERNATIVE(set)
+ : "+b" (low), "+c" (high)
+ : "S" (v)
+ : "eax", "edx", "memory"
+ );
+}
/**
* atomic64_read - read atomic64 variable
- * @ptr: pointer to type atomic64_t
+ * @v: pointer to type atomic64_t
*
- * Atomically reads the value of @ptr and returns it.
+ * Atomically reads the value of @v and returns it.
*/
-static inline u64 atomic64_read(atomic64_t *ptr)
+static inline long long atomic64_read(atomic64_t *v)
{
- u64 res;
-
- /*
- * Note, we inline this atomic64_t primitive because
- * it only clobbers EAX/EDX and leaves the others
- * untouched. We also (somewhat subtly) rely on the
- * fact that cmpxchg8b returns the current 64-bit value
- * of the memory location we are touching:
- */
- asm volatile(
- "mov %%ebx, %%eax\n\t"
- "mov %%ecx, %%edx\n\t"
- LOCK_PREFIX "cmpxchg8b %1\n"
- : "=&A" (res)
- : "m" (*ptr)
- );
-
- return res;
-}
-
-extern u64 atomic64_read(atomic64_t *ptr);
+ long long r;
+ asm volatile(ATOMIC64_ALTERNATIVE(read)
+ : "=A" (r), "+c" (v)
+ : : "memory"
+ );
+ return r;
+ }
/**
* atomic64_add_return - add and return
- * @delta: integer value to add
- * @ptr: pointer to type atomic64_t
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
*
- * Atomically adds @delta to @ptr and returns @delta + *@ptr
+ * Atomically adds @i to @v and returns @i + *@v
*/
-extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr);
+static inline long long atomic64_add_return(long long i, atomic64_t *v)
+{
+ asm volatile(ATOMIC64_ALTERNATIVE(add_return)
+ : "+A" (i), "+c" (v)
+ : : "memory"
+ );
+ return i;
+}
/*
* Other variants with different arithmetic operators:
*/
-extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr);
-extern u64 atomic64_inc_return(atomic64_t *ptr);
-extern u64 atomic64_dec_return(atomic64_t *ptr);
+static inline long long atomic64_sub_return(long long i, atomic64_t *v)
+{
+ asm volatile(ATOMIC64_ALTERNATIVE(sub_return)
+ : "+A" (i), "+c" (v)
+ : : "memory"
+ );
+ return i;
+}
+
+static inline long long atomic64_inc_return(atomic64_t *v)
+{
+ long long a;
+ asm volatile(ATOMIC64_ALTERNATIVE(inc_return)
+ : "=A" (a)
+ : "S" (v)
+ : "memory", "ecx"
+ );
+ return a;
+}
+
+static inline long long atomic64_dec_return(atomic64_t *v)
+{
+ long long a;
+ asm volatile(ATOMIC64_ALTERNATIVE(dec_return)
+ : "=A" (a)
+ : "S" (v)
+ : "memory", "ecx"
+ );
+ return a;
+}
/**
* atomic64_add - add integer to atomic64 variable
- * @delta: integer value to add
- * @ptr: pointer to type atomic64_t
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
*
- * Atomically adds @delta to @ptr.
+ * Atomically adds @i to @v.
*/
-extern void atomic64_add(u64 delta, atomic64_t *ptr);
+static inline long long atomic64_add(long long i, atomic64_t *v)
+{
+ asm volatile(ATOMIC64_ALTERNATIVE_(add, add_return)
+ : "+A" (i), "+c" (v)
+ : : "memory"
+ );
+ return i;
+}
/**
* atomic64_sub - subtract the atomic64 variable
- * @delta: integer value to subtract
- * @ptr: pointer to type atomic64_t
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
*
- * Atomically subtracts @delta from @ptr.
+ * Atomically subtracts @i from @v.
*/
-extern void atomic64_sub(u64 delta, atomic64_t *ptr);
+static inline long long atomic64_sub(long long i, atomic64_t *v)
+{
+ asm volatile(ATOMIC64_ALTERNATIVE_(sub, sub_return)
+ : "+A" (i), "+c" (v)
+ : : "memory"
+ );
+ return i;
+}
/**
* atomic64_sub_and_test - subtract value from variable and test result
- * @delta: integer value to subtract
- * @ptr: pointer to type atomic64_t
- *
- * Atomically subtracts @delta from @ptr and returns
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v and returns
* true if the result is zero, or false for all
* other cases.
*/
-extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr);
+static inline int atomic64_sub_and_test(long long i, atomic64_t *v)
+{
+ return atomic64_sub_return(i, v) == 0;
+}
/**
* atomic64_inc - increment atomic64 variable
- * @ptr: pointer to type atomic64_t
+ * @v: pointer to type atomic64_t
*
- * Atomically increments @ptr by 1.
+ * Atomically increments @v by 1.
*/
-extern void atomic64_inc(atomic64_t *ptr);
+static inline void atomic64_inc(atomic64_t *v)
+{
+ asm volatile(ATOMIC64_ALTERNATIVE_(inc, inc_return)
+ : : "S" (v)
+ : "memory", "eax", "ecx", "edx"
+ );
+}
/**
* atomic64_dec - decrement atomic64 variable
@@ -124,37 +208,97 @@
*
* Atomically decrements @ptr by 1.
*/
-extern void atomic64_dec(atomic64_t *ptr);
+static inline void atomic64_dec(atomic64_t *v)
+{
+ asm volatile(ATOMIC64_ALTERNATIVE_(dec, dec_return)
+ : : "S" (v)
+ : "memory", "eax", "ecx", "edx"
+ );
+}
/**
* atomic64_dec_and_test - decrement and test
- * @ptr: pointer to type atomic64_t
+ * @v: pointer to type atomic64_t
*
- * Atomically decrements @ptr by 1 and
+ * Atomically decrements @v by 1 and
* returns true if the result is 0, or false for all other
* cases.
*/
-extern int atomic64_dec_and_test(atomic64_t *ptr);
+static inline int atomic64_dec_and_test(atomic64_t *v)
+{
+ return atomic64_dec_return(v) == 0;
+}
/**
* atomic64_inc_and_test - increment and test
- * @ptr: pointer to type atomic64_t
+ * @v: pointer to type atomic64_t
*
- * Atomically increments @ptr by 1
+ * Atomically increments @v by 1
* and returns true if the result is zero, or false for all
* other cases.
*/
-extern int atomic64_inc_and_test(atomic64_t *ptr);
+static inline int atomic64_inc_and_test(atomic64_t *v)
+{
+ return atomic64_inc_return(v) == 0;
+}
/**
* atomic64_add_negative - add and test if negative
- * @delta: integer value to add
- * @ptr: pointer to type atomic64_t
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
*
- * Atomically adds @delta to @ptr and returns true
+ * Atomically adds @i to @v and returns true
* if the result is negative, or false when
* result is greater than or equal to zero.
*/
-extern int atomic64_add_negative(u64 delta, atomic64_t *ptr);
+static inline int atomic64_add_negative(long long i, atomic64_t *v)
+{
+ return atomic64_add_return(i, v) < 0;
+}
+
+/**
+ * atomic64_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic64_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns non-zero if @v was not @u, and zero otherwise.
+ */
+static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
+{
+ unsigned low = (unsigned)u;
+ unsigned high = (unsigned)(u >> 32);
+ asm volatile(ATOMIC64_ALTERNATIVE(add_unless) "\n\t"
+ : "+A" (a), "+c" (v), "+S" (low), "+D" (high)
+ : : "memory");
+ return (int)a;
+}
+
+
+static inline int atomic64_inc_not_zero(atomic64_t *v)
+{
+ int r;
+ asm volatile(ATOMIC64_ALTERNATIVE(inc_not_zero)
+ : "=a" (r)
+ : "S" (v)
+ : "ecx", "edx", "memory"
+ );
+ return r;
+}
+
+static inline long long atomic64_dec_if_positive(atomic64_t *v)
+{
+ long long r;
+ asm volatile(ATOMIC64_ALTERNATIVE(dec_if_positive)
+ : "=A" (r)
+ : "S" (v)
+ : "ecx", "memory"
+ );
+ return r;
+}
+
+#undef ATOMIC64_ALTERNATIVE
+#undef ATOMIC64_ALTERNATIVE_
#endif /* _ASM_X86_ATOMIC64_32_H */
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 51c5b40..49fd1ea 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -18,7 +18,7 @@
*/
static inline long atomic64_read(const atomic64_t *v)
{
- return v->counter;
+ return (*(volatile long *)&(v)->counter);
}
/**
@@ -221,4 +221,27 @@
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
+/*
+ * atomic64_dec_if_positive - decrement by 1 if old value positive
+ * @v: pointer of type atomic_t
+ *
+ * The function returns the old value of *v minus 1, even if
+ * the atomic variable, v, was not decremented.
+ */
+static inline long atomic64_dec_if_positive(atomic64_t *v)
+{
+ long c, old, dec;
+ c = atomic64_read(v);
+ for (;;) {
+ dec = c - 1;
+ if (unlikely(dec < 0))
+ break;
+ old = atomic64_cmpxchg((v), c, dec);
+ if (likely(old == c))
+ break;
+ c = old;
+ }
+ return dec;
+}
+
#endif /* _ASM_X86_ATOMIC64_64_H */
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 02b47a6..545776e 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -444,7 +444,9 @@
#define ARCH_HAS_FAST_MULTIPLIER 1
-#include <asm-generic/bitops/hweight.h>
+#include <asm/arch_hweight.h>
+
+#include <asm-generic/bitops/const_hweight.h>
#endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
index 7a10659..3b62ab5 100644
--- a/arch/x86/include/asm/boot.h
+++ b/arch/x86/include/asm/boot.h
@@ -24,7 +24,7 @@
#define MIN_KERNEL_ALIGN (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2)
#if (CONFIG_PHYSICAL_ALIGN & (CONFIG_PHYSICAL_ALIGN-1)) || \
- (CONFIG_PHYSICAL_ALIGN < (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2))
+ (CONFIG_PHYSICAL_ALIGN < MIN_KERNEL_ALIGN)
#error "Invalid value for CONFIG_PHYSICAL_ALIGN"
#endif
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index 634c40a..c70068d 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -44,9 +44,6 @@
memcpy(dst, src, len);
}
-#define PG_WC PG_arch_1
-PAGEFLAG(WC, WC)
-
#ifdef CONFIG_X86_PAT
/*
* X86 PAT uses page flags WC and Uncached together to keep track of
@@ -55,16 +52,24 @@
* _PAGE_CACHE_UC_MINUS and fourth state where page's memory type has not
* been changed from its default (value of -1 used to denote this).
* Note we do not support _PAGE_CACHE_UC here.
- *
- * Caller must hold memtype_lock for atomicity.
*/
+
+#define _PGMT_DEFAULT 0
+#define _PGMT_WC (1UL << PG_arch_1)
+#define _PGMT_UC_MINUS (1UL << PG_uncached)
+#define _PGMT_WB (1UL << PG_uncached | 1UL << PG_arch_1)
+#define _PGMT_MASK (1UL << PG_uncached | 1UL << PG_arch_1)
+#define _PGMT_CLEAR_MASK (~_PGMT_MASK)
+
static inline unsigned long get_page_memtype(struct page *pg)
{
- if (!PageUncached(pg) && !PageWC(pg))
+ unsigned long pg_flags = pg->flags & _PGMT_MASK;
+
+ if (pg_flags == _PGMT_DEFAULT)
return -1;
- else if (!PageUncached(pg) && PageWC(pg))
+ else if (pg_flags == _PGMT_WC)
return _PAGE_CACHE_WC;
- else if (PageUncached(pg) && !PageWC(pg))
+ else if (pg_flags == _PGMT_UC_MINUS)
return _PAGE_CACHE_UC_MINUS;
else
return _PAGE_CACHE_WB;
@@ -72,25 +77,26 @@
static inline void set_page_memtype(struct page *pg, unsigned long memtype)
{
+ unsigned long memtype_flags = _PGMT_DEFAULT;
+ unsigned long old_flags;
+ unsigned long new_flags;
+
switch (memtype) {
case _PAGE_CACHE_WC:
- ClearPageUncached(pg);
- SetPageWC(pg);
+ memtype_flags = _PGMT_WC;
break;
case _PAGE_CACHE_UC_MINUS:
- SetPageUncached(pg);
- ClearPageWC(pg);
+ memtype_flags = _PGMT_UC_MINUS;
break;
case _PAGE_CACHE_WB:
- SetPageUncached(pg);
- SetPageWC(pg);
- break;
- default:
- case -1:
- ClearPageUncached(pg);
- ClearPageWC(pg);
+ memtype_flags = _PGMT_WB;
break;
}
+
+ do {
+ old_flags = pg->flags;
+ new_flags = (old_flags & _PGMT_CLEAR_MASK) | memtype_flags;
+ } while (cmpxchg(&pg->flags, old_flags, new_flags) != old_flags);
}
#else
static inline unsigned long get_page_memtype(struct page *pg) { return -1; }
diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h
index ffb9bb6..8859e12 100644
--- a/arch/x86/include/asm/cmpxchg_32.h
+++ b/arch/x86/include/asm/cmpxchg_32.h
@@ -271,7 +271,8 @@
__typeof__(*(ptr)) __ret; \
__typeof__(*(ptr)) __old = (o); \
__typeof__(*(ptr)) __new = (n); \
- alternative_io("call cmpxchg8b_emu", \
+ alternative_io(LOCK_PREFIX_HERE \
+ "call cmpxchg8b_emu", \
"lock; cmpxchg8b (%%esi)" , \
X86_FEATURE_CX8, \
"=A" (__ret), \
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 0cd82d0..dca9c54 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -161,6 +161,7 @@
*/
#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */
#define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */
+#define X86_FEATURE_CPB (7*32+ 2) /* AMD Core Performance Boost */
/* Virtualization flags: Linux defined */
#define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */
@@ -175,6 +176,7 @@
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#include <asm/asm.h>
#include <linux/bitops.h>
extern const char * const x86_cap_flags[NCAPINTS*32];
@@ -283,6 +285,62 @@
#endif /* CONFIG_X86_64 */
+/*
+ * Static testing of CPU features. Used the same as boot_cpu_has().
+ * These are only valid after alternatives have run, but will statically
+ * patch the target code for additional performance.
+ *
+ */
+static __always_inline __pure bool __static_cpu_has(u8 bit)
+{
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+ asm goto("1: jmp %l[t_no]\n"
+ "2:\n"
+ ".section .altinstructions,\"a\"\n"
+ _ASM_ALIGN "\n"
+ _ASM_PTR "1b\n"
+ _ASM_PTR "0\n" /* no replacement */
+ " .byte %P0\n" /* feature bit */
+ " .byte 2b - 1b\n" /* source len */
+ " .byte 0\n" /* replacement len */
+ " .byte 0xff + 0 - (2b-1b)\n" /* padding */
+ ".previous\n"
+ : : "i" (bit) : : t_no);
+ return true;
+ t_no:
+ return false;
+#else
+ u8 flag;
+ /* Open-coded due to __stringify() in ALTERNATIVE() */
+ asm volatile("1: movb $0,%0\n"
+ "2:\n"
+ ".section .altinstructions,\"a\"\n"
+ _ASM_ALIGN "\n"
+ _ASM_PTR "1b\n"
+ _ASM_PTR "3f\n"
+ " .byte %P1\n" /* feature bit */
+ " .byte 2b - 1b\n" /* source len */
+ " .byte 4f - 3f\n" /* replacement len */
+ " .byte 0xff + (4f-3f) - (2b-1b)\n" /* padding */
+ ".previous\n"
+ ".section .altinstr_replacement,\"ax\"\n"
+ "3: movb $1,%0\n"
+ "4:\n"
+ ".previous\n"
+ : "=qm" (flag) : "i" (bit));
+ return flag;
+#endif
+}
+
+#define static_cpu_has(bit) \
+( \
+ __builtin_constant_p(boot_cpu_has(bit)) ? \
+ boot_cpu_has(bit) : \
+ (__builtin_constant_p(bit) && !((bit) & ~0xff)) ? \
+ __static_cpu_has(bit) : \
+ boot_cpu_has(bit) \
+)
+
#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
#endif /* _ASM_X86_CPUFEATURE_H */
diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
index ae6253a..733f7e9 100644
--- a/arch/x86/include/asm/dwarf2.h
+++ b/arch/x86/include/asm/dwarf2.h
@@ -34,6 +34,18 @@
#define CFI_SIGNAL_FRAME
#endif
+#if defined(CONFIG_AS_CFI_SECTIONS) && defined(__ASSEMBLY__)
+ /*
+ * Emit CFI data in .debug_frame sections, not .eh_frame sections.
+ * The latter we currently just discard since we don't do DWARF
+ * unwinding at runtime. So only the offline DWARF information is
+ * useful to anyone. Note we should not use this directive if this
+ * file is used in the vDSO assembly, or if vmlinux.lds.S gets
+ * changed so it doesn't discard .eh_frame.
+ */
+ .cfi_sections .debug_frame
+#endif
+
#else
/*
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 0e22296..ec8a52d 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -45,7 +45,12 @@
#define E820_NVS 4
#define E820_UNUSABLE 5
-/* reserved RAM used by kernel itself */
+/*
+ * reserved RAM used by kernel itself
+ * if CONFIG_INTEL_TXT is enabled, memory of this type will be
+ * included in the S3 integrity calculation and so should not include
+ * any memory that BIOS might alter over the S3 transition
+ */
#define E820_RESERVED_KERN 128
#ifndef __ASSEMBLY__
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 0f85764..aeab29a 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -35,7 +35,7 @@
#define __ARCH_IRQ_STAT
-#define inc_irq_stat(member) percpu_add(irq_stat.member, 1)
+#define inc_irq_stat(member) percpu_inc(irq_stat.member)
#define local_softirq_pending() percpu_read(irq_stat.__softirq_pending)
diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h
index e153a2b3..5df477a 100644
--- a/arch/x86/include/asm/hyperv.h
+++ b/arch/x86/include/asm/hyperv.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_X86_KVM_HYPERV_H
-#define _ASM_X86_KVM_HYPERV_H
+#ifndef _ASM_X86_HYPERV_H
+#define _ASM_X86_HYPERV_H
#include <linux/types.h>
@@ -14,6 +14,10 @@
#define HYPERV_CPUID_ENLIGHTMENT_INFO 0x40000004
#define HYPERV_CPUID_IMPLEMENT_LIMITS 0x40000005
+#define HYPERV_HYPERVISOR_PRESENT_BIT 0x80000000
+#define HYPERV_CPUID_MIN 0x40000005
+#define HYPERV_CPUID_MAX 0x4000ffff
+
/*
* Feature identification. EAX indicates which features are available
* to the partition based upon the current partition privileges.
@@ -129,6 +133,9 @@
/* MSR used to provide vcpu index */
#define HV_X64_MSR_VP_INDEX 0x40000002
+/* MSR used to read the per-partition time reference counter */
+#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
+
/* Define the virtual APIC registers */
#define HV_X64_MSR_EOI 0x40000070
#define HV_X64_MSR_ICR 0x40000071
diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
index b78c094..70abda7 100644
--- a/arch/x86/include/asm/hypervisor.h
+++ b/arch/x86/include/asm/hypervisor.h
@@ -17,10 +17,33 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
-#ifndef ASM_X86__HYPERVISOR_H
-#define ASM_X86__HYPERVISOR_H
+#ifndef _ASM_X86_HYPERVISOR_H
+#define _ASM_X86_HYPERVISOR_H
extern void init_hypervisor(struct cpuinfo_x86 *c);
extern void init_hypervisor_platform(void);
+/*
+ * x86 hypervisor information
+ */
+struct hypervisor_x86 {
+ /* Hypervisor name */
+ const char *name;
+
+ /* Detection routine */
+ bool (*detect)(void);
+
+ /* Adjust CPU feature bits (run once per CPU) */
+ void (*set_cpu_features)(struct cpuinfo_x86 *);
+
+ /* Platform setup (run once per boot) */
+ void (*init_platform)(void);
+};
+
+extern const struct hypervisor_x86 *x86_hyper;
+
+/* Recognized hypervisors */
+extern const struct hypervisor_x86 x86_hyper_vmware;
+extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
+
#endif
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index da29309..c991b3a 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -16,7 +16,9 @@
#include <linux/kernel_stat.h>
#include <linux/regset.h>
#include <linux/hardirq.h>
+#include <linux/slab.h>
#include <asm/asm.h>
+#include <asm/cpufeature.h>
#include <asm/processor.h>
#include <asm/sigcontext.h>
#include <asm/user.h>
@@ -56,6 +58,11 @@
#define X87_FSW_ES (1 << 7) /* Exception Summary */
+static __always_inline __pure bool use_xsave(void)
+{
+ return static_cpu_has(X86_FEATURE_XSAVE);
+}
+
#ifdef CONFIG_X86_64
/* Ignore delayed exceptions from user space */
@@ -91,15 +98,15 @@
values. The kernel data segment can be sometimes 0 and sometimes
new user value. Both should be ok.
Use the PDA as safe address because it should be already in L1. */
-static inline void clear_fpu_state(struct task_struct *tsk)
+static inline void fpu_clear(struct fpu *fpu)
{
- struct xsave_struct *xstate = &tsk->thread.xstate->xsave;
- struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave;
+ struct xsave_struct *xstate = &fpu->state->xsave;
+ struct i387_fxsave_struct *fx = &fpu->state->fxsave;
/*
* xsave header may indicate the init state of the FP.
*/
- if ((task_thread_info(tsk)->status & TS_XSAVE) &&
+ if (use_xsave() &&
!(xstate->xsave_hdr.xstate_bv & XSTATE_FP))
return;
@@ -111,6 +118,11 @@
X86_FEATURE_FXSAVE_LEAK);
}
+static inline void clear_fpu_state(struct task_struct *tsk)
+{
+ fpu_clear(&tsk->thread.fpu);
+}
+
static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
{
int err;
@@ -135,7 +147,7 @@
return err;
}
-static inline void fxsave(struct task_struct *tsk)
+static inline void fpu_fxsave(struct fpu *fpu)
{
/* Using "rex64; fxsave %0" is broken because, if the memory operand
uses any extended registers for addressing, a second REX prefix
@@ -145,42 +157,45 @@
/* Using "fxsaveq %0" would be the ideal choice, but is only supported
starting with gas 2.16. */
__asm__ __volatile__("fxsaveq %0"
- : "=m" (tsk->thread.xstate->fxsave));
+ : "=m" (fpu->state->fxsave));
#elif 0
/* Using, as a workaround, the properly prefixed form below isn't
accepted by any binutils version so far released, complaining that
the same type of prefix is used twice if an extended register is
needed for addressing (fix submitted to mainline 2005-11-21). */
__asm__ __volatile__("rex64/fxsave %0"
- : "=m" (tsk->thread.xstate->fxsave));
+ : "=m" (fpu->state->fxsave));
#else
/* This, however, we can work around by forcing the compiler to select
an addressing mode that doesn't require extended registers. */
__asm__ __volatile__("rex64/fxsave (%1)"
- : "=m" (tsk->thread.xstate->fxsave)
- : "cdaSDb" (&tsk->thread.xstate->fxsave));
+ : "=m" (fpu->state->fxsave)
+ : "cdaSDb" (&fpu->state->fxsave));
#endif
}
+static inline void fpu_save_init(struct fpu *fpu)
+{
+ if (use_xsave())
+ fpu_xsave(fpu);
+ else
+ fpu_fxsave(fpu);
+
+ fpu_clear(fpu);
+}
+
static inline void __save_init_fpu(struct task_struct *tsk)
{
- if (task_thread_info(tsk)->status & TS_XSAVE)
- xsave(tsk);
- else
- fxsave(tsk);
-
- clear_fpu_state(tsk);
+ fpu_save_init(&tsk->thread.fpu);
task_thread_info(tsk)->status &= ~TS_USEDFPU;
}
#else /* CONFIG_X86_32 */
#ifdef CONFIG_MATH_EMULATION
-extern void finit_task(struct task_struct *tsk);
+extern void finit_soft_fpu(struct i387_soft_struct *soft);
#else
-static inline void finit_task(struct task_struct *tsk)
-{
-}
+static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
#endif
static inline void tolerant_fwait(void)
@@ -216,13 +231,13 @@
/*
* These must be called with preempt disabled
*/
-static inline void __save_init_fpu(struct task_struct *tsk)
+static inline void fpu_save_init(struct fpu *fpu)
{
- if (task_thread_info(tsk)->status & TS_XSAVE) {
- struct xsave_struct *xstate = &tsk->thread.xstate->xsave;
- struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave;
+ if (use_xsave()) {
+ struct xsave_struct *xstate = &fpu->state->xsave;
+ struct i387_fxsave_struct *fx = &fpu->state->fxsave;
- xsave(tsk);
+ fpu_xsave(fpu);
/*
* xsave header may indicate the init state of the FP.
@@ -246,8 +261,8 @@
"fxsave %[fx]\n"
"bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
X86_FEATURE_FXSR,
- [fx] "m" (tsk->thread.xstate->fxsave),
- [fsw] "m" (tsk->thread.xstate->fxsave.swd) : "memory");
+ [fx] "m" (fpu->state->fxsave),
+ [fsw] "m" (fpu->state->fxsave.swd) : "memory");
clear_state:
/* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
is pending. Clear the x87 state here by setting it to fixed
@@ -259,17 +274,34 @@
X86_FEATURE_FXSAVE_LEAK,
[addr] "m" (safe_address));
end:
+ ;
+}
+
+static inline void __save_init_fpu(struct task_struct *tsk)
+{
+ fpu_save_init(&tsk->thread.fpu);
task_thread_info(tsk)->status &= ~TS_USEDFPU;
}
+
#endif /* CONFIG_X86_64 */
+static inline int fpu_fxrstor_checking(struct fpu *fpu)
+{
+ return fxrstor_checking(&fpu->state->fxsave);
+}
+
+static inline int fpu_restore_checking(struct fpu *fpu)
+{
+ if (use_xsave())
+ return fpu_xrstor_checking(fpu);
+ else
+ return fpu_fxrstor_checking(fpu);
+}
+
static inline int restore_fpu_checking(struct task_struct *tsk)
{
- if (task_thread_info(tsk)->status & TS_XSAVE)
- return xrstor_checking(&tsk->thread.xstate->xsave);
- else
- return fxrstor_checking(&tsk->thread.xstate->fxsave);
+ return fpu_restore_checking(&tsk->thread.fpu);
}
/*
@@ -397,30 +429,59 @@
static inline unsigned short get_fpu_cwd(struct task_struct *tsk)
{
if (cpu_has_fxsr) {
- return tsk->thread.xstate->fxsave.cwd;
+ return tsk->thread.fpu.state->fxsave.cwd;
} else {
- return (unsigned short)tsk->thread.xstate->fsave.cwd;
+ return (unsigned short)tsk->thread.fpu.state->fsave.cwd;
}
}
static inline unsigned short get_fpu_swd(struct task_struct *tsk)
{
if (cpu_has_fxsr) {
- return tsk->thread.xstate->fxsave.swd;
+ return tsk->thread.fpu.state->fxsave.swd;
} else {
- return (unsigned short)tsk->thread.xstate->fsave.swd;
+ return (unsigned short)tsk->thread.fpu.state->fsave.swd;
}
}
static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk)
{
if (cpu_has_xmm) {
- return tsk->thread.xstate->fxsave.mxcsr;
+ return tsk->thread.fpu.state->fxsave.mxcsr;
} else {
return MXCSR_DEFAULT;
}
}
+static bool fpu_allocated(struct fpu *fpu)
+{
+ return fpu->state != NULL;
+}
+
+static inline int fpu_alloc(struct fpu *fpu)
+{
+ if (fpu_allocated(fpu))
+ return 0;
+ fpu->state = kmem_cache_alloc(task_xstate_cachep, GFP_KERNEL);
+ if (!fpu->state)
+ return -ENOMEM;
+ WARN_ON((unsigned long)fpu->state & 15);
+ return 0;
+}
+
+static inline void fpu_free(struct fpu *fpu)
+{
+ if (fpu->state) {
+ kmem_cache_free(task_xstate_cachep, fpu->state);
+ fpu->state = NULL;
+ }
+}
+
+static inline void fpu_copy(struct fpu *dst, struct fpu *src)
+{
+ memcpy(dst->state, src->state, xstate_size);
+}
+
#endif /* __ASSEMBLY__ */
#define PSHUFB_XMM5_XMM0 .byte 0x66, 0x0f, 0x38, 0x00, 0xc5
diff --git a/arch/x86/include/asm/i8253.h b/arch/x86/include/asm/i8253.h
index 1edbf89..fc1f579 100644
--- a/arch/x86/include/asm/i8253.h
+++ b/arch/x86/include/asm/i8253.h
@@ -6,7 +6,7 @@
#define PIT_CH0 0x40
#define PIT_CH2 0x42
-extern spinlock_t i8253_lock;
+extern raw_spinlock_t i8253_lock;
extern struct clock_event_device *global_clock_event;
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 35832a0..63cb409 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -159,7 +159,6 @@
extern int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr);
void setup_IO_APIC_irq_extra(u32 gsi);
-extern int (*ioapic_renumber_irq)(int ioapic, int irq);
extern void ioapic_init_mappings(void);
extern void ioapic_insert_resources(void);
@@ -180,12 +179,13 @@
extern void setup_ioapic_ids_from_mpc(void);
struct mp_ioapic_gsi{
- int gsi_base;
- int gsi_end;
+ u32 gsi_base;
+ u32 gsi_end;
};
extern struct mp_ioapic_gsi mp_gsi_routing[];
-int mp_find_ioapic(int gsi);
-int mp_find_ioapic_pin(int ioapic, int gsi);
+extern u32 gsi_end;
+int mp_find_ioapic(u32 gsi);
+int mp_find_ioapic_pin(int ioapic, u32 gsi);
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
extern void __init pre_init_apic_IRQ0(void);
@@ -197,7 +197,8 @@
static inline void ioapic_init_mappings(void) { }
static inline void ioapic_insert_resources(void) { }
static inline void probe_nr_irqs_gsi(void) { }
-static inline int mp_find_ioapic(int gsi) { return 0; }
+#define gsi_end (NR_IRQS_LEGACY - 1)
+static inline int mp_find_ioapic(u32 gsi) { return 0; }
struct io_apic_irq_attr;
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/include/asm/k8.h b/arch/x86/include/asm/k8.h
index f70e600..af00bd1 100644
--- a/arch/x86/include/asm/k8.h
+++ b/arch/x86/include/asm/k8.h
@@ -16,11 +16,16 @@
extern int k8_scan_nodes(void);
#ifdef CONFIG_K8_NB
+extern int num_k8_northbridges;
+
static inline struct pci_dev *node_to_k8_nb_misc(int node)
{
return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL;
}
+
#else
+#define num_k8_northbridges 0
+
static inline struct pci_dev *node_to_k8_nb_misc(int node)
{
return NULL;
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index d8bf23a..c82868e 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -105,16 +105,6 @@
struct device;
extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
int active_high_low);
-extern int acpi_probe_gsi(void);
-#ifdef CONFIG_X86_IO_APIC
-extern int mp_find_ioapic(int gsi);
-extern int mp_find_ioapic_pin(int ioapic, int gsi);
-#endif
-#else /* !CONFIG_ACPI: */
-static inline int acpi_probe_gsi(void)
-{
- return 0;
-}
#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
new file mode 100644
index 0000000..79ce568
--- /dev/null
+++ b/arch/x86/include/asm/mshyperv.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_X86_MSHYPER_H
+#define _ASM_X86_MSHYPER_H
+
+#include <linux/types.h>
+#include <asm/hyperv.h>
+
+struct ms_hyperv_info {
+ u32 features;
+ u32 hints;
+};
+
+extern struct ms_hyperv_info ms_hyperv;
+
+#endif
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 66a272d..0ec6d12 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -190,6 +190,29 @@
pfo_ret__; \
})
+#define percpu_unary_op(op, var) \
+({ \
+ switch (sizeof(var)) { \
+ case 1: \
+ asm(op "b "__percpu_arg(0) \
+ : "+m" (var)); \
+ break; \
+ case 2: \
+ asm(op "w "__percpu_arg(0) \
+ : "+m" (var)); \
+ break; \
+ case 4: \
+ asm(op "l "__percpu_arg(0) \
+ : "+m" (var)); \
+ break; \
+ case 8: \
+ asm(op "q "__percpu_arg(0) \
+ : "+m" (var)); \
+ break; \
+ default: __bad_percpu_size(); \
+ } \
+})
+
/*
* percpu_read() makes gcc load the percpu variable every time it is
* accessed while percpu_read_stable() allows the value to be cached.
@@ -207,6 +230,7 @@
#define percpu_and(var, val) percpu_to_op("and", var, val)
#define percpu_or(var, val) percpu_to_op("or", var, val)
#define percpu_xor(var, val) percpu_to_op("xor", var, val)
+#define percpu_inc(var) percpu_unary_op("inc", var)
#define __this_cpu_read_1(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
#define __this_cpu_read_2(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h
index b05400a..64a8ebf 100644
--- a/arch/x86/include/asm/perf_event_p4.h
+++ b/arch/x86/include/asm/perf_event_p4.h
@@ -89,7 +89,8 @@
P4_CCCR_ENABLE)
/* HT mask */
-#define P4_CCCR_MASK_HT (P4_CCCR_MASK | P4_CCCR_THREAD_ANY)
+#define P4_CCCR_MASK_HT \
+ (P4_CCCR_MASK | P4_CCCR_OVF_PMI_T1 | P4_CCCR_THREAD_ANY)
#define P4_GEN_ESCR_EMASK(class, name, bit) \
class##__##name = ((1 << bit) << P4_ESCR_EVENTMASK_SHIFT)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 32428b4..5a51379 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -113,7 +113,6 @@
/* Index into per_cpu list: */
u16 cpu_index;
#endif
- unsigned int x86_hyper_vendor;
} __attribute__((__aligned__(SMP_CACHE_BYTES)));
#define X86_VENDOR_INTEL 0
@@ -127,9 +126,6 @@
#define X86_VENDOR_UNKNOWN 0xff
-#define X86_HYPER_VENDOR_NONE 0
-#define X86_HYPER_VENDOR_VMWARE 1
-
/*
* capabilities of CPUs
*/
@@ -380,6 +376,10 @@
struct xsave_struct xsave;
};
+struct fpu {
+ union thread_xstate *state;
+};
+
#ifdef CONFIG_X86_64
DECLARE_PER_CPU(struct orig_ist, orig_ist);
@@ -457,7 +457,7 @@
unsigned long trap_no;
unsigned long error_code;
/* floating point and extended processor state */
- union thread_xstate *xstate;
+ struct fpu fpu;
#ifdef CONFIG_X86_32
/* Virtual 86 mode info */
struct vm86_struct __user *vm86_info;
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index d017ed55..d4092fac 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -242,7 +242,6 @@
#define TS_POLLING 0x0004 /* true if in idle loop
and not sleeping */
#define TS_RESTORE_SIGMASK 0x0008 /* restore signal mask in do_signal() */
-#define TS_XSAVE 0x0010 /* Use xsave/xrstor */
#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 4da91ad..f66cda5 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -79,7 +79,7 @@
extern int panic_on_unrecovered_nmi;
-void math_error(void __user *);
+void math_error(struct pt_regs *, int, int);
void math_emulate(struct math_emu_info *);
#ifndef CONFIG_X86_32
asmlinkage void smp_thermal_interrupt(void);
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index b414d2b..aa558ac 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -27,13 +27,14 @@
* set 2 is at BASE + 2*512, set 3 at BASE + 3*512, and so on.
*
* We will use 31 sets, one for sending BAU messages from each of the 32
- * cpu's on the node.
+ * cpu's on the uvhub.
*
* TLB shootdown will use the first of the 8 descriptors of each set.
* Each of the descriptors is 64 bytes in size (8*64 = 512 bytes in a set).
*/
#define UV_ITEMS_PER_DESCRIPTOR 8
+#define MAX_BAU_CONCURRENT 3
#define UV_CPUS_PER_ACT_STATUS 32
#define UV_ACT_STATUS_MASK 0x3
#define UV_ACT_STATUS_SIZE 2
@@ -45,6 +46,9 @@
#define UV_PAYLOADQ_PNODE_SHIFT 49
#define UV_PTC_BASENAME "sgi_uv/ptc_statistics"
#define uv_physnodeaddr(x) ((__pa((unsigned long)(x)) & uv_mmask))
+#define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15
+#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16
+#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL
/*
* bits in UVH_LB_BAU_SB_ACTIVATION_STATUS_0/1
@@ -55,15 +59,29 @@
#define DESC_STATUS_SOURCE_TIMEOUT 3
/*
- * source side thresholds at which message retries print a warning
+ * source side threshholds at which message retries print a warning
*/
#define SOURCE_TIMEOUT_LIMIT 20
#define DESTINATION_TIMEOUT_LIMIT 20
/*
+ * misc. delays, in microseconds
+ */
+#define THROTTLE_DELAY 10
+#define TIMEOUT_DELAY 10
+#define BIOS_TO 1000
+/* BIOS is assumed to set the destination timeout to 1003520 nanoseconds */
+
+/*
+ * threshholds at which to use IPI to free resources
+ */
+#define PLUGSB4RESET 100
+#define TIMEOUTSB4RESET 100
+
+/*
* number of entries in the destination side payload queue
*/
-#define DEST_Q_SIZE 17
+#define DEST_Q_SIZE 20
/*
* number of destination side software ack resources
*/
@@ -72,9 +90,10 @@
/*
* completion statuses for sending a TLB flush message
*/
-#define FLUSH_RETRY 1
-#define FLUSH_GIVEUP 2
-#define FLUSH_COMPLETE 3
+#define FLUSH_RETRY_PLUGGED 1
+#define FLUSH_RETRY_TIMEOUT 2
+#define FLUSH_GIVEUP 3
+#define FLUSH_COMPLETE 4
/*
* Distribution: 32 bytes (256 bits) (bytes 0-0x1f of descriptor)
@@ -86,14 +105,14 @@
* 'base_dest_nodeid' field of the header corresponds to the
* destination nodeID associated with that specified bit.
*/
-struct bau_target_nodemask {
- unsigned long bits[BITS_TO_LONGS(256)];
+struct bau_target_uvhubmask {
+ unsigned long bits[BITS_TO_LONGS(UV_DISTRIBUTION_SIZE)];
};
/*
- * mask of cpu's on a node
+ * mask of cpu's on a uvhub
* (during initialization we need to check that unsigned long has
- * enough bits for max. cpu's per node)
+ * enough bits for max. cpu's per uvhub)
*/
struct bau_local_cpumask {
unsigned long bits;
@@ -135,8 +154,8 @@
struct bau_msg_header {
unsigned int dest_subnodeid:6; /* must be 0x10, for the LB */
/* bits 5:0 */
- unsigned int base_dest_nodeid:15; /* nasid>>1 (pnode) of */
- /* bits 20:6 */ /* first bit in node_map */
+ unsigned int base_dest_nodeid:15; /* nasid (pnode<<1) of */
+ /* bits 20:6 */ /* first bit in uvhub map */
unsigned int command:8; /* message type */
/* bits 28:21 */
/* 0x38: SN3net EndPoint Message */
@@ -146,26 +165,38 @@
unsigned int rsvd_2:9; /* must be zero */
/* bits 40:32 */
/* Suppl_A is 56-41 */
- unsigned int payload_2a:8;/* becomes byte 16 of msg */
- /* bits 48:41 */ /* not currently using */
- unsigned int payload_2b:8;/* becomes byte 17 of msg */
- /* bits 56:49 */ /* not currently using */
+ unsigned int sequence:16;/* message sequence number */
+ /* bits 56:41 */ /* becomes bytes 16-17 of msg */
/* Address field (96:57) is never used as an
address (these are address bits 42:3) */
+
unsigned int rsvd_3:1; /* must be zero */
/* bit 57 */
/* address bits 27:4 are payload */
- /* these 24 bits become bytes 12-14 of msg */
+ /* these next 24 (58-81) bits become bytes 12-14 of msg */
+
+ /* bits 65:58 land in byte 12 */
unsigned int replied_to:1;/* sent as 0 by the source to byte 12 */
/* bit 58 */
+ unsigned int msg_type:3; /* software type of the message*/
+ /* bits 61:59 */
+ unsigned int canceled:1; /* message canceled, resource to be freed*/
+ /* bit 62 */
+ unsigned int payload_1a:1;/* not currently used */
+ /* bit 63 */
+ unsigned int payload_1b:2;/* not currently used */
+ /* bits 65:64 */
- unsigned int payload_1a:5;/* not currently used */
- /* bits 63:59 */
- unsigned int payload_1b:8;/* not currently used */
- /* bits 71:64 */
- unsigned int payload_1c:8;/* not currently used */
- /* bits 79:72 */
- unsigned int payload_1d:2;/* not currently used */
+ /* bits 73:66 land in byte 13 */
+ unsigned int payload_1ca:6;/* not currently used */
+ /* bits 71:66 */
+ unsigned int payload_1c:2;/* not currently used */
+ /* bits 73:72 */
+
+ /* bits 81:74 land in byte 14 */
+ unsigned int payload_1d:6;/* not currently used */
+ /* bits 79:74 */
+ unsigned int payload_1e:2;/* not currently used */
/* bits 81:80 */
unsigned int rsvd_4:7; /* must be zero */
@@ -178,7 +209,7 @@
/* bits 95:90 */
unsigned int rsvd_6:5; /* must be zero */
/* bits 100:96 */
- unsigned int int_both:1;/* if 1, interrupt both sockets on the blade */
+ unsigned int int_both:1;/* if 1, interrupt both sockets on the uvhub */
/* bit 101*/
unsigned int fairness:3;/* usually zero */
/* bits 104:102 */
@@ -191,13 +222,18 @@
/* bits 127:107 */
};
+/* see msg_type: */
+#define MSG_NOOP 0
+#define MSG_REGULAR 1
+#define MSG_RETRY 2
+
/*
* The activation descriptor:
* The format of the message to send, plus all accompanying control
* Should be 64 bytes
*/
struct bau_desc {
- struct bau_target_nodemask distribution;
+ struct bau_target_uvhubmask distribution;
/*
* message template, consisting of header and payload:
*/
@@ -237,19 +273,25 @@
unsigned short acknowledge_count; /* filled in by destination */
/* 16 bits, bytes 10-11 */
- unsigned short replied_to:1; /* sent as 0 by the source */
- /* 1 bit */
- unsigned short unused1:7; /* not currently using */
- /* 7 bits: byte 12) */
+ /* these next 3 bytes come from bits 58-81 of the message header */
+ unsigned short replied_to:1; /* sent as 0 by the source */
+ unsigned short msg_type:3; /* software message type */
+ unsigned short canceled:1; /* sent as 0 by the source */
+ unsigned short unused1:3; /* not currently using */
+ /* byte 12 */
- unsigned char unused2[2]; /* not currently using */
- /* bytes 13-14 */
+ unsigned char unused2a; /* not currently using */
+ /* byte 13 */
+ unsigned char unused2; /* not currently using */
+ /* byte 14 */
unsigned char sw_ack_vector; /* filled in by the hardware */
/* byte 15 (bits 127:120) */
- unsigned char unused4[3]; /* not currently using bytes 17-19 */
- /* bytes 17-19 */
+ unsigned short sequence; /* message sequence number */
+ /* bytes 16-17 */
+ unsigned char unused4[2]; /* not currently using bytes 18-19 */
+ /* bytes 18-19 */
int number_of_cpus; /* filled in at destination */
/* 32 bits, bytes 20-23 (aligned) */
@@ -259,63 +301,93 @@
};
/*
- * one for every slot in the destination payload queue
- */
-struct bau_msg_status {
- struct bau_local_cpumask seen_by; /* map of cpu's */
-};
-
-/*
- * one for every slot in the destination software ack resources
- */
-struct bau_sw_ack_status {
- struct bau_payload_queue_entry *msg; /* associated message */
- int watcher; /* cpu monitoring, or -1 */
-};
-
-/*
- * one on every node and per-cpu; to locate the software tables
+ * one per-cpu; to locate the software tables
*/
struct bau_control {
struct bau_desc *descriptor_base;
- struct bau_payload_queue_entry *bau_msg_head;
struct bau_payload_queue_entry *va_queue_first;
struct bau_payload_queue_entry *va_queue_last;
- struct bau_msg_status *msg_statuses;
- int *watching; /* pointer to array */
+ struct bau_payload_queue_entry *bau_msg_head;
+ struct bau_control *uvhub_master;
+ struct bau_control *socket_master;
+ unsigned long timeout_interval;
+ atomic_t active_descriptor_count;
+ int max_concurrent;
+ int max_concurrent_constant;
+ int retry_message_scans;
+ int plugged_tries;
+ int timeout_tries;
+ int ipi_attempts;
+ int conseccompletes;
+ short cpu;
+ short uvhub_cpu;
+ short uvhub;
+ short cpus_in_socket;
+ short cpus_in_uvhub;
+ unsigned short message_number;
+ unsigned short uvhub_quiesce;
+ short socket_acknowledge_count[DEST_Q_SIZE];
+ cycles_t send_message;
+ spinlock_t masks_lock;
+ spinlock_t uvhub_lock;
+ spinlock_t queue_lock;
};
/*
* This structure is allocated per_cpu for UV TLB shootdown statistics.
*/
struct ptc_stats {
- unsigned long ptc_i; /* number of IPI-style flushes */
- unsigned long requestor; /* number of nodes this cpu sent to */
- unsigned long requestee; /* times cpu was remotely requested */
- unsigned long alltlb; /* times all tlb's on this cpu were flushed */
- unsigned long onetlb; /* times just one tlb on this cpu was flushed */
- unsigned long s_retry; /* retries on source side timeouts */
- unsigned long d_retry; /* retries on destination side timeouts */
- unsigned long sflush; /* cycles spent in uv_flush_tlb_others */
- unsigned long dflush; /* cycles spent on destination side */
- unsigned long retriesok; /* successes on retries */
- unsigned long nomsg; /* interrupts with no message */
- unsigned long multmsg; /* interrupts with multiple messages */
- unsigned long ntargeted;/* nodes targeted */
+ /* sender statistics */
+ unsigned long s_giveup; /* number of fall backs to IPI-style flushes */
+ unsigned long s_requestor; /* number of shootdown requests */
+ unsigned long s_stimeout; /* source side timeouts */
+ unsigned long s_dtimeout; /* destination side timeouts */
+ unsigned long s_time; /* time spent in sending side */
+ unsigned long s_retriesok; /* successful retries */
+ unsigned long s_ntargcpu; /* number of cpus targeted */
+ unsigned long s_ntarguvhub; /* number of uvhubs targeted */
+ unsigned long s_ntarguvhub16; /* number of times >= 16 target hubs */
+ unsigned long s_ntarguvhub8; /* number of times >= 8 target hubs */
+ unsigned long s_ntarguvhub4; /* number of times >= 4 target hubs */
+ unsigned long s_ntarguvhub2; /* number of times >= 2 target hubs */
+ unsigned long s_ntarguvhub1; /* number of times == 1 target hub */
+ unsigned long s_resets_plug; /* ipi-style resets from plug state */
+ unsigned long s_resets_timeout; /* ipi-style resets from timeouts */
+ unsigned long s_busy; /* status stayed busy past s/w timer */
+ unsigned long s_throttles; /* waits in throttle */
+ unsigned long s_retry_messages; /* retry broadcasts */
+ /* destination statistics */
+ unsigned long d_alltlb; /* times all tlb's on this cpu were flushed */
+ unsigned long d_onetlb; /* times just one tlb on this cpu was flushed */
+ unsigned long d_multmsg; /* interrupts with multiple messages */
+ unsigned long d_nomsg; /* interrupts with no message */
+ unsigned long d_time; /* time spent on destination side */
+ unsigned long d_requestee; /* number of messages processed */
+ unsigned long d_retries; /* number of retry messages processed */
+ unsigned long d_canceled; /* number of messages canceled by retries */
+ unsigned long d_nocanceled; /* retries that found nothing to cancel */
+ unsigned long d_resets; /* number of ipi-style requests processed */
+ unsigned long d_rcanceled; /* number of messages canceled by resets */
};
-static inline int bau_node_isset(int node, struct bau_target_nodemask *dstp)
+static inline int bau_uvhub_isset(int uvhub, struct bau_target_uvhubmask *dstp)
{
- return constant_test_bit(node, &dstp->bits[0]);
+ return constant_test_bit(uvhub, &dstp->bits[0]);
}
-static inline void bau_node_set(int node, struct bau_target_nodemask *dstp)
+static inline void bau_uvhub_set(int uvhub, struct bau_target_uvhubmask *dstp)
{
- __set_bit(node, &dstp->bits[0]);
+ __set_bit(uvhub, &dstp->bits[0]);
}
-static inline void bau_nodes_clear(struct bau_target_nodemask *dstp, int nbits)
+static inline void bau_uvhubs_clear(struct bau_target_uvhubmask *dstp,
+ int nbits)
{
bitmap_zero(&dstp->bits[0], nbits);
}
+static inline int bau_uvhub_weight(struct bau_target_uvhubmask *dstp)
+{
+ return bitmap_weight((unsigned long *)&dstp->bits[0],
+ UV_DISTRIBUTION_SIZE);
+}
static inline void bau_cpubits_clear(struct bau_local_cpumask *dstp, int nbits)
{
@@ -328,4 +400,35 @@
extern void uv_bau_message_intr1(void);
extern void uv_bau_timeout_intr1(void);
+struct atomic_short {
+ short counter;
+};
+
+/**
+ * atomic_read_short - read a short atomic variable
+ * @v: pointer of type atomic_short
+ *
+ * Atomically reads the value of @v.
+ */
+static inline int atomic_read_short(const struct atomic_short *v)
+{
+ return v->counter;
+}
+
+/**
+ * atomic_add_short_return - add and return a short int
+ * @i: short value to add
+ * @v: pointer of type atomic_short
+ *
+ * Atomically adds @i to @v and returns @i + @v
+ */
+static inline int atomic_add_short_return(short i, struct atomic_short *v)
+{
+ short __i = i;
+ asm volatile(LOCK_PREFIX "xaddw %0, %1"
+ : "+r" (i), "+m" (v->counter)
+ : : "memory");
+ return i + __i;
+}
+
#endif /* _ASM_X86_UV_UV_BAU_H */
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index 14cc74b..bf6b88e 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -307,7 +307,7 @@
* Access Global MMR space using the MMR space located at the top of physical
* memory.
*/
-static inline unsigned long *uv_global_mmr64_address(int pnode, unsigned long offset)
+static inline volatile void __iomem *uv_global_mmr64_address(int pnode, unsigned long offset)
{
return __va(UV_GLOBAL_MMR64_BASE |
UV_GLOBAL_MMR64_PNODE_BITS(pnode) | offset);
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h
index 2cae46c..b2f2d2e 100644
--- a/arch/x86/include/asm/uv/uv_mmrs.h
+++ b/arch/x86/include/asm/uv/uv_mmrs.h
@@ -1,4 +1,3 @@
-
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -15,13 +14,25 @@
#define UV_MMR_ENABLE (1UL << 63)
/* ========================================================================= */
+/* UVH_BAU_DATA_BROADCAST */
+/* ========================================================================= */
+#define UVH_BAU_DATA_BROADCAST 0x61688UL
+#define UVH_BAU_DATA_BROADCAST_32 0x0440
+
+#define UVH_BAU_DATA_BROADCAST_ENABLE_SHFT 0
+#define UVH_BAU_DATA_BROADCAST_ENABLE_MASK 0x0000000000000001UL
+
+union uvh_bau_data_broadcast_u {
+ unsigned long v;
+ struct uvh_bau_data_broadcast_s {
+ unsigned long enable : 1; /* RW */
+ unsigned long rsvd_1_63: 63; /* */
+ } s;
+};
+
+/* ========================================================================= */
/* UVH_BAU_DATA_CONFIG */
/* ========================================================================= */
-#define UVH_LB_BAU_MISC_CONTROL 0x320170UL
-#define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15
-#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16
-#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL
-/* 1011 timebase 7 (168millisec) * 3 ticks -> 500ms */
#define UVH_BAU_DATA_CONFIG 0x61680UL
#define UVH_BAU_DATA_CONFIG_32 0x0438
@@ -604,6 +615,68 @@
#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS_32 0x0a70
/* ========================================================================= */
+/* UVH_LB_BAU_MISC_CONTROL */
+/* ========================================================================= */
+#define UVH_LB_BAU_MISC_CONTROL 0x320170UL
+#define UVH_LB_BAU_MISC_CONTROL_32 0x00a10
+
+#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0
+#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL
+#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8
+#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10
+#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL
+#define UVH_LB_BAU_MISC_CONTROL_CSI_AGENT_PRESENCE_VECTOR_SHFT 11
+#define UVH_LB_BAU_MISC_CONTROL_CSI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
+#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
+#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
+#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
+#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
+#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
+#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
+#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
+#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
+#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23
+#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
+#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24
+#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
+#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27
+#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
+#define UVH_LB_BAU_MISC_CONTROL_FUN_SHFT 48
+#define UVH_LB_BAU_MISC_CONTROL_FUN_MASK 0xffff000000000000UL
+
+union uvh_lb_bau_misc_control_u {
+ unsigned long v;
+ struct uvh_lb_bau_misc_control_s {
+ unsigned long rejection_delay : 8; /* RW */
+ unsigned long apic_mode : 1; /* RW */
+ unsigned long force_broadcast : 1; /* RW */
+ unsigned long force_lock_nop : 1; /* RW */
+ unsigned long csi_agent_presence_vector : 3; /* RW */
+ unsigned long descriptor_fetch_mode : 1; /* RW */
+ unsigned long enable_intd_soft_ack_mode : 1; /* RW */
+ unsigned long intd_soft_ack_timeout_period : 4; /* RW */
+ unsigned long enable_dual_mapping_mode : 1; /* RW */
+ unsigned long vga_io_port_decode_enable : 1; /* RW */
+ unsigned long vga_io_port_16_bit_decode : 1; /* RW */
+ unsigned long suppress_dest_registration : 1; /* RW */
+ unsigned long programmed_initial_priority : 3; /* RW */
+ unsigned long use_incoming_priority : 1; /* RW */
+ unsigned long enable_programmed_initial_priority : 1; /* RW */
+ unsigned long rsvd_29_47 : 19; /* */
+ unsigned long fun : 16; /* RW */
+ } s;
+};
+
+/* ========================================================================= */
/* UVH_LB_BAU_SB_ACTIVATION_CONTROL */
/* ========================================================================= */
#define UVH_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
@@ -681,334 +754,6 @@
};
/* ========================================================================= */
-/* UVH_LB_MCAST_AOERR0_RPT_ENABLE */
-/* ========================================================================= */
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE 0x50b20UL
-
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_OBESE_MSG_SHFT 0
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_OBESE_MSG_MASK 0x0000000000000001UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_DATA_SB_ERR_SHFT 1
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_DATA_SB_ERR_MASK 0x0000000000000002UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_NACK_BUFF_PARITY_SHFT 2
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_NACK_BUFF_PARITY_MASK 0x0000000000000004UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_TIMEOUT_SHFT 3
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_TIMEOUT_MASK 0x0000000000000008UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_INACTIVE_REPLY_SHFT 4
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_INACTIVE_REPLY_MASK 0x0000000000000010UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_UPGRADE_ERROR_SHFT 5
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_UPGRADE_ERROR_MASK 0x0000000000000020UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_REG_COUNT_UNDERFLOW_SHFT 6
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_REG_COUNT_UNDERFLOW_MASK 0x0000000000000040UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_REP_OBESE_MSG_SHFT 7
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_REP_OBESE_MSG_MASK 0x0000000000000080UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_RUNT_MSG_SHFT 8
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_RUNT_MSG_MASK 0x0000000000000100UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_OBESE_MSG_SHFT 9
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_OBESE_MSG_MASK 0x0000000000000200UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_DATA_SB_ERR_SHFT 10
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_DATA_SB_ERR_MASK 0x0000000000000400UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_RUNT_MSG_SHFT 11
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_RUNT_MSG_MASK 0x0000000000000800UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_OBESE_MSG_SHFT 12
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_OBESE_MSG_MASK 0x0000000000001000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_DATA_SB_ERR_SHFT 13
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_DATA_SB_ERR_MASK 0x0000000000002000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_COMMAND_ERR_SHFT 14
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_COMMAND_ERR_MASK 0x0000000000004000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_PEND_TIMEOUT_SHFT 15
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_PEND_TIMEOUT_MASK 0x0000000000008000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_RUNT_MSG_SHFT 16
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_RUNT_MSG_MASK 0x0000000000010000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_OBESE_MSG_SHFT 17
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_OBESE_MSG_MASK 0x0000000000020000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_DATA_SB_ERR_SHFT 18
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_DATA_SB_ERR_MASK 0x0000000000040000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_RUNT_MSG_SHFT 19
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_RUNT_MSG_MASK 0x0000000000080000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_OBESE_MSG_SHFT 20
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_OBESE_MSG_MASK 0x0000000000100000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_DATA_SB_ERR_SHFT 21
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_DATA_SB_ERR_MASK 0x0000000000200000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_AMO_TIMEOUT_SHFT 22
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_AMO_TIMEOUT_MASK 0x0000000000400000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_PUT_TIMEOUT_SHFT 23
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_PUT_TIMEOUT_MASK 0x0000000000800000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_SPURIOUS_EVENT_SHFT 24
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_SPURIOUS_EVENT_MASK 0x0000000001000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_IOH_DESTINATION_TABLE_PARITY_SHFT 25
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_IOH_DESTINATION_TABLE_PARITY_MASK 0x0000000002000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_GET_HAD_ERROR_REPLY_SHFT 26
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_GET_HAD_ERROR_REPLY_MASK 0x0000000004000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_GET_TIMEOUT_SHFT 27
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_GET_TIMEOUT_MASK 0x0000000008000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_LOCK_MANAGER_HAD_ERROR_REPLY_SHFT 28
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_LOCK_MANAGER_HAD_ERROR_REPLY_MASK 0x0000000010000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_PUT_HAD_ERROR_REPLY_SHFT 29
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_PUT_HAD_ERROR_REPLY_MASK 0x0000000020000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_PUT_TIMEOUT_SHFT 30
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_PUT_TIMEOUT_MASK 0x0000000040000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_SB_ACTIVATION_OVERRUN_SHFT 31
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_SB_ACTIVATION_OVERRUN_MASK 0x0000000080000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_COMPLETED_GB_ACTIVATION_HAD_ERROR_REPLY_SHFT 32
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_COMPLETED_GB_ACTIVATION_HAD_ERROR_REPLY_MASK 0x0000000100000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_COMPLETED_GB_ACTIVATION_TIMEOUT_SHFT 33
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_COMPLETED_GB_ACTIVATION_TIMEOUT_MASK 0x0000000200000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_DESCRIPTOR_BUFFER_0_PARITY_SHFT 34
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_DESCRIPTOR_BUFFER_0_PARITY_MASK 0x0000000400000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_DESCRIPTOR_BUFFER_1_PARITY_SHFT 35
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_DESCRIPTOR_BUFFER_1_PARITY_MASK 0x0000000800000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_SOCKET_DESTINATION_TABLE_PARITY_SHFT 36
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_SOCKET_DESTINATION_TABLE_PARITY_MASK 0x0000001000000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_BAU_REPLY_PAYLOAD_CORRUPTION_SHFT 37
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_BAU_REPLY_PAYLOAD_CORRUPTION_MASK 0x0000002000000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_IO_PORT_DESTINATION_TABLE_PARITY_SHFT 38
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_IO_PORT_DESTINATION_TABLE_PARITY_MASK 0x0000004000000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INTD_SOFT_ACK_TIMEOUT_SHFT 39
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INTD_SOFT_ACK_TIMEOUT_MASK 0x0000008000000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_REP_OBESE_MSG_SHFT 40
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_REP_OBESE_MSG_MASK 0x0000010000000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_REP_COMMAND_ERR_SHFT 41
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_REP_COMMAND_ERR_MASK 0x0000020000000000UL
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_TIMEOUT_SHFT 42
-#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_TIMEOUT_MASK 0x0000040000000000UL
-
-union uvh_lb_mcast_aoerr0_rpt_enable_u {
- unsigned long v;
- struct uvh_lb_mcast_aoerr0_rpt_enable_s {
- unsigned long mcast_obese_msg : 1; /* RW */
- unsigned long mcast_data_sb_err : 1; /* RW */
- unsigned long mcast_nack_buff_parity : 1; /* RW */
- unsigned long mcast_timeout : 1; /* RW */
- unsigned long mcast_inactive_reply : 1; /* RW */
- unsigned long mcast_upgrade_error : 1; /* RW */
- unsigned long mcast_reg_count_underflow : 1; /* RW */
- unsigned long mcast_rep_obese_msg : 1; /* RW */
- unsigned long ucache_req_runt_msg : 1; /* RW */
- unsigned long ucache_req_obese_msg : 1; /* RW */
- unsigned long ucache_req_data_sb_err : 1; /* RW */
- unsigned long ucache_rep_runt_msg : 1; /* RW */
- unsigned long ucache_rep_obese_msg : 1; /* RW */
- unsigned long ucache_rep_data_sb_err : 1; /* RW */
- unsigned long ucache_rep_command_err : 1; /* RW */
- unsigned long ucache_pend_timeout : 1; /* RW */
- unsigned long macc_req_runt_msg : 1; /* RW */
- unsigned long macc_req_obese_msg : 1; /* RW */
- unsigned long macc_req_data_sb_err : 1; /* RW */
- unsigned long macc_rep_runt_msg : 1; /* RW */
- unsigned long macc_rep_obese_msg : 1; /* RW */
- unsigned long macc_rep_data_sb_err : 1; /* RW */
- unsigned long macc_amo_timeout : 1; /* RW */
- unsigned long macc_put_timeout : 1; /* RW */
- unsigned long macc_spurious_event : 1; /* RW */
- unsigned long ioh_destination_table_parity : 1; /* RW */
- unsigned long get_had_error_reply : 1; /* RW */
- unsigned long get_timeout : 1; /* RW */
- unsigned long lock_manager_had_error_reply : 1; /* RW */
- unsigned long put_had_error_reply : 1; /* RW */
- unsigned long put_timeout : 1; /* RW */
- unsigned long sb_activation_overrun : 1; /* RW */
- unsigned long completed_gb_activation_had_error_reply : 1; /* RW */
- unsigned long completed_gb_activation_timeout : 1; /* RW */
- unsigned long descriptor_buffer_0_parity : 1; /* RW */
- unsigned long descriptor_buffer_1_parity : 1; /* RW */
- unsigned long socket_destination_table_parity : 1; /* RW */
- unsigned long bau_reply_payload_corruption : 1; /* RW */
- unsigned long io_port_destination_table_parity : 1; /* RW */
- unsigned long intd_soft_ack_timeout : 1; /* RW */
- unsigned long int_rep_obese_msg : 1; /* RW */
- unsigned long int_rep_command_err : 1; /* RW */
- unsigned long int_timeout : 1; /* RW */
- unsigned long rsvd_43_63 : 21; /* */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_LOCAL_INT0_CONFIG */
-/* ========================================================================= */
-#define UVH_LOCAL_INT0_CONFIG 0x61000UL
-
-#define UVH_LOCAL_INT0_CONFIG_VECTOR_SHFT 0
-#define UVH_LOCAL_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_LOCAL_INT0_CONFIG_DM_SHFT 8
-#define UVH_LOCAL_INT0_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_LOCAL_INT0_CONFIG_DESTMODE_SHFT 11
-#define UVH_LOCAL_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_LOCAL_INT0_CONFIG_STATUS_SHFT 12
-#define UVH_LOCAL_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_LOCAL_INT0_CONFIG_P_SHFT 13
-#define UVH_LOCAL_INT0_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_LOCAL_INT0_CONFIG_T_SHFT 15
-#define UVH_LOCAL_INT0_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_LOCAL_INT0_CONFIG_M_SHFT 16
-#define UVH_LOCAL_INT0_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_LOCAL_INT0_CONFIG_APIC_ID_SHFT 32
-#define UVH_LOCAL_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_local_int0_config_u {
- unsigned long v;
- struct uvh_local_int0_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_LOCAL_INT0_ENABLE */
-/* ========================================================================= */
-#define UVH_LOCAL_INT0_ENABLE 0x65000UL
-
-#define UVH_LOCAL_INT0_ENABLE_LB_HCERR_SHFT 0
-#define UVH_LOCAL_INT0_ENABLE_LB_HCERR_MASK 0x0000000000000001UL
-#define UVH_LOCAL_INT0_ENABLE_GR0_HCERR_SHFT 1
-#define UVH_LOCAL_INT0_ENABLE_GR0_HCERR_MASK 0x0000000000000002UL
-#define UVH_LOCAL_INT0_ENABLE_GR1_HCERR_SHFT 2
-#define UVH_LOCAL_INT0_ENABLE_GR1_HCERR_MASK 0x0000000000000004UL
-#define UVH_LOCAL_INT0_ENABLE_LH_HCERR_SHFT 3
-#define UVH_LOCAL_INT0_ENABLE_LH_HCERR_MASK 0x0000000000000008UL
-#define UVH_LOCAL_INT0_ENABLE_RH_HCERR_SHFT 4
-#define UVH_LOCAL_INT0_ENABLE_RH_HCERR_MASK 0x0000000000000010UL
-#define UVH_LOCAL_INT0_ENABLE_XN_HCERR_SHFT 5
-#define UVH_LOCAL_INT0_ENABLE_XN_HCERR_MASK 0x0000000000000020UL
-#define UVH_LOCAL_INT0_ENABLE_SI_HCERR_SHFT 6
-#define UVH_LOCAL_INT0_ENABLE_SI_HCERR_MASK 0x0000000000000040UL
-#define UVH_LOCAL_INT0_ENABLE_LB_AOERR0_SHFT 7
-#define UVH_LOCAL_INT0_ENABLE_LB_AOERR0_MASK 0x0000000000000080UL
-#define UVH_LOCAL_INT0_ENABLE_GR0_AOERR0_SHFT 8
-#define UVH_LOCAL_INT0_ENABLE_GR0_AOERR0_MASK 0x0000000000000100UL
-#define UVH_LOCAL_INT0_ENABLE_GR1_AOERR0_SHFT 9
-#define UVH_LOCAL_INT0_ENABLE_GR1_AOERR0_MASK 0x0000000000000200UL
-#define UVH_LOCAL_INT0_ENABLE_LH_AOERR0_SHFT 10
-#define UVH_LOCAL_INT0_ENABLE_LH_AOERR0_MASK 0x0000000000000400UL
-#define UVH_LOCAL_INT0_ENABLE_RH_AOERR0_SHFT 11
-#define UVH_LOCAL_INT0_ENABLE_RH_AOERR0_MASK 0x0000000000000800UL
-#define UVH_LOCAL_INT0_ENABLE_XN_AOERR0_SHFT 12
-#define UVH_LOCAL_INT0_ENABLE_XN_AOERR0_MASK 0x0000000000001000UL
-#define UVH_LOCAL_INT0_ENABLE_SI_AOERR0_SHFT 13
-#define UVH_LOCAL_INT0_ENABLE_SI_AOERR0_MASK 0x0000000000002000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_AOERR1_SHFT 14
-#define UVH_LOCAL_INT0_ENABLE_LB_AOERR1_MASK 0x0000000000004000UL
-#define UVH_LOCAL_INT0_ENABLE_GR0_AOERR1_SHFT 15
-#define UVH_LOCAL_INT0_ENABLE_GR0_AOERR1_MASK 0x0000000000008000UL
-#define UVH_LOCAL_INT0_ENABLE_GR1_AOERR1_SHFT 16
-#define UVH_LOCAL_INT0_ENABLE_GR1_AOERR1_MASK 0x0000000000010000UL
-#define UVH_LOCAL_INT0_ENABLE_LH_AOERR1_SHFT 17
-#define UVH_LOCAL_INT0_ENABLE_LH_AOERR1_MASK 0x0000000000020000UL
-#define UVH_LOCAL_INT0_ENABLE_RH_AOERR1_SHFT 18
-#define UVH_LOCAL_INT0_ENABLE_RH_AOERR1_MASK 0x0000000000040000UL
-#define UVH_LOCAL_INT0_ENABLE_XN_AOERR1_SHFT 19
-#define UVH_LOCAL_INT0_ENABLE_XN_AOERR1_MASK 0x0000000000080000UL
-#define UVH_LOCAL_INT0_ENABLE_SI_AOERR1_SHFT 20
-#define UVH_LOCAL_INT0_ENABLE_SI_AOERR1_MASK 0x0000000000100000UL
-#define UVH_LOCAL_INT0_ENABLE_RH_VPI_INT_SHFT 21
-#define UVH_LOCAL_INT0_ENABLE_RH_VPI_INT_MASK 0x0000000000200000UL
-#define UVH_LOCAL_INT0_ENABLE_SYSTEM_SHUTDOWN_INT_SHFT 22
-#define UVH_LOCAL_INT0_ENABLE_SYSTEM_SHUTDOWN_INT_MASK 0x0000000000400000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_0_SHFT 23
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_0_MASK 0x0000000000800000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_1_SHFT 24
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_1_MASK 0x0000000001000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_2_SHFT 25
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_2_MASK 0x0000000002000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_3_SHFT 26
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_3_MASK 0x0000000004000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_4_SHFT 27
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_4_MASK 0x0000000008000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_5_SHFT 28
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_5_MASK 0x0000000010000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_6_SHFT 29
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_6_MASK 0x0000000020000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_7_SHFT 30
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_7_MASK 0x0000000040000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_8_SHFT 31
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_8_MASK 0x0000000080000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_9_SHFT 32
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_9_MASK 0x0000000100000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_10_SHFT 33
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_10_MASK 0x0000000200000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_11_SHFT 34
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_11_MASK 0x0000000400000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_12_SHFT 35
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_12_MASK 0x0000000800000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_13_SHFT 36
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_13_MASK 0x0000001000000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_14_SHFT 37
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_14_MASK 0x0000002000000000UL
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_15_SHFT 38
-#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_15_MASK 0x0000004000000000UL
-#define UVH_LOCAL_INT0_ENABLE_L1_NMI_INT_SHFT 39
-#define UVH_LOCAL_INT0_ENABLE_L1_NMI_INT_MASK 0x0000008000000000UL
-#define UVH_LOCAL_INT0_ENABLE_STOP_CLOCK_SHFT 40
-#define UVH_LOCAL_INT0_ENABLE_STOP_CLOCK_MASK 0x0000010000000000UL
-#define UVH_LOCAL_INT0_ENABLE_ASIC_TO_L1_SHFT 41
-#define UVH_LOCAL_INT0_ENABLE_ASIC_TO_L1_MASK 0x0000020000000000UL
-#define UVH_LOCAL_INT0_ENABLE_L1_TO_ASIC_SHFT 42
-#define UVH_LOCAL_INT0_ENABLE_L1_TO_ASIC_MASK 0x0000040000000000UL
-#define UVH_LOCAL_INT0_ENABLE_LTC_INT_SHFT 43
-#define UVH_LOCAL_INT0_ENABLE_LTC_INT_MASK 0x0000080000000000UL
-#define UVH_LOCAL_INT0_ENABLE_LA_SEQ_TRIGGER_SHFT 44
-#define UVH_LOCAL_INT0_ENABLE_LA_SEQ_TRIGGER_MASK 0x0000100000000000UL
-
-union uvh_local_int0_enable_u {
- unsigned long v;
- struct uvh_local_int0_enable_s {
- unsigned long lb_hcerr : 1; /* RW */
- unsigned long gr0_hcerr : 1; /* RW */
- unsigned long gr1_hcerr : 1; /* RW */
- unsigned long lh_hcerr : 1; /* RW */
- unsigned long rh_hcerr : 1; /* RW */
- unsigned long xn_hcerr : 1; /* RW */
- unsigned long si_hcerr : 1; /* RW */
- unsigned long lb_aoerr0 : 1; /* RW */
- unsigned long gr0_aoerr0 : 1; /* RW */
- unsigned long gr1_aoerr0 : 1; /* RW */
- unsigned long lh_aoerr0 : 1; /* RW */
- unsigned long rh_aoerr0 : 1; /* RW */
- unsigned long xn_aoerr0 : 1; /* RW */
- unsigned long si_aoerr0 : 1; /* RW */
- unsigned long lb_aoerr1 : 1; /* RW */
- unsigned long gr0_aoerr1 : 1; /* RW */
- unsigned long gr1_aoerr1 : 1; /* RW */
- unsigned long lh_aoerr1 : 1; /* RW */
- unsigned long rh_aoerr1 : 1; /* RW */
- unsigned long xn_aoerr1 : 1; /* RW */
- unsigned long si_aoerr1 : 1; /* RW */
- unsigned long rh_vpi_int : 1; /* RW */
- unsigned long system_shutdown_int : 1; /* RW */
- unsigned long lb_irq_int_0 : 1; /* RW */
- unsigned long lb_irq_int_1 : 1; /* RW */
- unsigned long lb_irq_int_2 : 1; /* RW */
- unsigned long lb_irq_int_3 : 1; /* RW */
- unsigned long lb_irq_int_4 : 1; /* RW */
- unsigned long lb_irq_int_5 : 1; /* RW */
- unsigned long lb_irq_int_6 : 1; /* RW */
- unsigned long lb_irq_int_7 : 1; /* RW */
- unsigned long lb_irq_int_8 : 1; /* RW */
- unsigned long lb_irq_int_9 : 1; /* RW */
- unsigned long lb_irq_int_10 : 1; /* RW */
- unsigned long lb_irq_int_11 : 1; /* RW */
- unsigned long lb_irq_int_12 : 1; /* RW */
- unsigned long lb_irq_int_13 : 1; /* RW */
- unsigned long lb_irq_int_14 : 1; /* RW */
- unsigned long lb_irq_int_15 : 1; /* RW */
- unsigned long l1_nmi_int : 1; /* RW */
- unsigned long stop_clock : 1; /* RW */
- unsigned long asic_to_l1 : 1; /* RW */
- unsigned long l1_to_asic : 1; /* RW */
- unsigned long ltc_int : 1; /* RW */
- unsigned long la_seq_trigger : 1; /* RW */
- unsigned long rsvd_45_63 : 19; /* */
- } s;
-};
-
-/* ========================================================================= */
/* UVH_NODE_ID */
/* ========================================================================= */
#define UVH_NODE_ID 0x0UL
@@ -1112,26 +857,6 @@
};
/* ========================================================================= */
-/* UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR */
-/* ========================================================================= */
-#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR 0x1600020UL
-
-#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_BASE_SHFT 26
-#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL
-#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63
-#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
-
-union uvh_rh_gam_cfg_overlay_config_mmr_u {
- unsigned long v;
- struct uvh_rh_gam_cfg_overlay_config_mmr_s {
- unsigned long rsvd_0_25: 26; /* */
- unsigned long base : 20; /* RW */
- unsigned long rsvd_46_62: 17; /* */
- unsigned long enable : 1; /* RW */
- } s;
-};
-
-/* ========================================================================= */
/* UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR */
/* ========================================================================= */
#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
@@ -1263,101 +988,6 @@
};
/* ========================================================================= */
-/* UVH_RTC2_INT_CONFIG */
-/* ========================================================================= */
-#define UVH_RTC2_INT_CONFIG 0x61600UL
-
-#define UVH_RTC2_INT_CONFIG_VECTOR_SHFT 0
-#define UVH_RTC2_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_RTC2_INT_CONFIG_DM_SHFT 8
-#define UVH_RTC2_INT_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_RTC2_INT_CONFIG_DESTMODE_SHFT 11
-#define UVH_RTC2_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_RTC2_INT_CONFIG_STATUS_SHFT 12
-#define UVH_RTC2_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_RTC2_INT_CONFIG_P_SHFT 13
-#define UVH_RTC2_INT_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_RTC2_INT_CONFIG_T_SHFT 15
-#define UVH_RTC2_INT_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_RTC2_INT_CONFIG_M_SHFT 16
-#define UVH_RTC2_INT_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_RTC2_INT_CONFIG_APIC_ID_SHFT 32
-#define UVH_RTC2_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_rtc2_int_config_u {
- unsigned long v;
- struct uvh_rtc2_int_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RTC3_INT_CONFIG */
-/* ========================================================================= */
-#define UVH_RTC3_INT_CONFIG 0x61640UL
-
-#define UVH_RTC3_INT_CONFIG_VECTOR_SHFT 0
-#define UVH_RTC3_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL
-#define UVH_RTC3_INT_CONFIG_DM_SHFT 8
-#define UVH_RTC3_INT_CONFIG_DM_MASK 0x0000000000000700UL
-#define UVH_RTC3_INT_CONFIG_DESTMODE_SHFT 11
-#define UVH_RTC3_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL
-#define UVH_RTC3_INT_CONFIG_STATUS_SHFT 12
-#define UVH_RTC3_INT_CONFIG_STATUS_MASK 0x0000000000001000UL
-#define UVH_RTC3_INT_CONFIG_P_SHFT 13
-#define UVH_RTC3_INT_CONFIG_P_MASK 0x0000000000002000UL
-#define UVH_RTC3_INT_CONFIG_T_SHFT 15
-#define UVH_RTC3_INT_CONFIG_T_MASK 0x0000000000008000UL
-#define UVH_RTC3_INT_CONFIG_M_SHFT 16
-#define UVH_RTC3_INT_CONFIG_M_MASK 0x0000000000010000UL
-#define UVH_RTC3_INT_CONFIG_APIC_ID_SHFT 32
-#define UVH_RTC3_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL
-
-union uvh_rtc3_int_config_u {
- unsigned long v;
- struct uvh_rtc3_int_config_s {
- unsigned long vector_ : 8; /* RW */
- unsigned long dm : 3; /* RW */
- unsigned long destmode : 1; /* RW */
- unsigned long status : 1; /* RO */
- unsigned long p : 1; /* RO */
- unsigned long rsvd_14 : 1; /* */
- unsigned long t : 1; /* RO */
- unsigned long m : 1; /* RW */
- unsigned long rsvd_17_31: 15; /* */
- unsigned long apic_id : 32; /* RW */
- } s;
-};
-
-/* ========================================================================= */
-/* UVH_RTC_INC_RATIO */
-/* ========================================================================= */
-#define UVH_RTC_INC_RATIO 0x350000UL
-
-#define UVH_RTC_INC_RATIO_FRACTION_SHFT 0
-#define UVH_RTC_INC_RATIO_FRACTION_MASK 0x00000000000fffffUL
-#define UVH_RTC_INC_RATIO_RATIO_SHFT 20
-#define UVH_RTC_INC_RATIO_RATIO_MASK 0x0000000000700000UL
-
-union uvh_rtc_inc_ratio_u {
- unsigned long v;
- struct uvh_rtc_inc_ratio_s {
- unsigned long fraction : 20; /* RW */
- unsigned long ratio : 3; /* RW */
- unsigned long rsvd_23_63: 41; /* */
- } s;
-};
-
-/* ========================================================================= */
/* UVH_SI_ADDR_MAP_CONFIG */
/* ========================================================================= */
#define UVH_SI_ADDR_MAP_CONFIG 0xc80000UL
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
deleted file mode 100644
index e49ed6d..0000000
--- a/arch/x86/include/asm/vmware.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2008, VMware, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-#ifndef ASM_X86__VMWARE_H
-#define ASM_X86__VMWARE_H
-
-extern void vmware_platform_setup(void);
-extern int vmware_platform(void);
-extern void vmware_set_feature_bits(struct cpuinfo_x86 *c);
-
-#endif
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index ddc04cc..2c4390c 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -37,8 +37,9 @@
void __user *fpstate,
struct _fpx_sw_bytes *sw);
-static inline int xrstor_checking(struct xsave_struct *fx)
+static inline int fpu_xrstor_checking(struct fpu *fpu)
{
+ struct xsave_struct *fx = &fpu->state->xsave;
int err;
asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
@@ -110,12 +111,12 @@
: "memory");
}
-static inline void xsave(struct task_struct *tsk)
+static inline void fpu_xsave(struct fpu *fpu)
{
/* This, however, we can work around by forcing the compiler to select
an addressing mode that doesn't require extended registers. */
__asm__ __volatile__(".byte " REX_PREFIX "0x0f,0xae,0x27"
- : : "D" (&(tsk->thread.xstate->xsave)),
+ : : "D" (&(fpu->state->xsave)),
"a" (-1), "d"(-1) : "memory");
}
#endif
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index cd40aba..9a5ed58 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -94,6 +94,53 @@
/*
+ * ISA irqs by default are the first 16 gsis but can be
+ * any gsi as specified by an interrupt source override.
+ */
+static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static unsigned int gsi_to_irq(unsigned int gsi)
+{
+ unsigned int irq = gsi + NR_IRQS_LEGACY;
+ unsigned int i;
+
+ for (i = 0; i < NR_IRQS_LEGACY; i++) {
+ if (isa_irq_to_gsi[i] == gsi) {
+ return i;
+ }
+ }
+
+ /* Provide an identity mapping of gsi == irq
+ * except on truly weird platforms that have
+ * non isa irqs in the first 16 gsis.
+ */
+ if (gsi >= NR_IRQS_LEGACY)
+ irq = gsi;
+ else
+ irq = gsi_end + 1 + gsi;
+
+ return irq;
+}
+
+static u32 irq_to_gsi(int irq)
+{
+ unsigned int gsi;
+
+ if (irq < NR_IRQS_LEGACY)
+ gsi = isa_irq_to_gsi[irq];
+ else if (irq <= gsi_end)
+ gsi = irq;
+ else if (irq <= (gsi_end + NR_IRQS_LEGACY))
+ gsi = irq - gsi_end;
+ else
+ gsi = 0xffffffff;
+
+ return gsi;
+}
+
+/*
* Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
* to map the target physical address. The problem is that set_fixmap()
* provides a single page, and it is possible that the page is not
@@ -313,7 +360,7 @@
/*
* Parse Interrupt Source Override for the ACPI SCI
*/
-static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
+static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, u32 gsi)
{
if (trigger == 0) /* compatible SCI trigger is level */
trigger = 3;
@@ -333,7 +380,7 @@
* If GSI is < 16, this will update its flags,
* else it will create a new mp_irqs[] entry.
*/
- mp_override_legacy_irq(gsi, polarity, trigger, gsi);
+ mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
/*
* stash over-ride to indicate we've been here
@@ -357,9 +404,10 @@
acpi_table_print_madt_entry(header);
if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
- acpi_sci_ioapic_setup(intsrc->global_irq,
+ acpi_sci_ioapic_setup(intsrc->source_irq,
intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
- (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
+ (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2,
+ intsrc->global_irq);
return 0;
}
@@ -448,7 +496,7 @@
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
{
- *irq = gsi;
+ *irq = gsi_to_irq(gsi);
#ifdef CONFIG_X86_IO_APIC
if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
@@ -458,6 +506,14 @@
return 0;
}
+int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
+{
+ if (isa_irq >= 16)
+ return -1;
+ *gsi = irq_to_gsi(isa_irq);
+ return 0;
+}
+
/*
* success: return IRQ number (>=0)
* failure: return < 0
@@ -482,7 +538,7 @@
plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
}
#endif
- irq = plat_gsi;
+ irq = gsi_to_irq(plat_gsi);
return irq;
}
@@ -867,29 +923,6 @@
extern int es7000_plat;
#endif
-int __init acpi_probe_gsi(void)
-{
- int idx;
- int gsi;
- int max_gsi = 0;
-
- if (acpi_disabled)
- return 0;
-
- if (!acpi_ioapic)
- return 0;
-
- max_gsi = 0;
- for (idx = 0; idx < nr_ioapics; idx++) {
- gsi = mp_gsi_routing[idx].gsi_end;
-
- if (gsi > max_gsi)
- max_gsi = gsi;
- }
-
- return max_gsi + 1;
-}
-
static void assign_to_mp_irq(struct mpc_intsrc *m,
struct mpc_intsrc *mp_irq)
{
@@ -947,13 +980,13 @@
mp_irq.dstirq = pin; /* INTIN# */
save_mp_irq(&mp_irq);
+
+ isa_irq_to_gsi[bus_irq] = gsi;
}
void __init mp_config_acpi_legacy_irqs(void)
{
int i;
- int ioapic;
- unsigned int dstapic;
struct mpc_intsrc mp_irq;
#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
@@ -974,19 +1007,27 @@
#endif
/*
- * Locate the IOAPIC that manages the ISA IRQs (0-15).
- */
- ioapic = mp_find_ioapic(0);
- if (ioapic < 0)
- return;
- dstapic = mp_ioapics[ioapic].apicid;
-
- /*
* Use the default configuration for the IRQs 0-15. Unless
* overridden by (MADT) interrupt source override entries.
*/
for (i = 0; i < 16; i++) {
+ int ioapic, pin;
+ unsigned int dstapic;
int idx;
+ u32 gsi;
+
+ /* Locate the gsi that irq i maps to. */
+ if (acpi_isa_irq_to_gsi(i, &gsi))
+ continue;
+
+ /*
+ * Locate the IOAPIC that manages the ISA IRQ.
+ */
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
+ continue;
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ dstapic = mp_ioapics[ioapic].apicid;
for (idx = 0; idx < mp_irq_entries; idx++) {
struct mpc_intsrc *irq = mp_irqs + idx;
@@ -996,7 +1037,7 @@
break;
/* Do we already have a mapping for this IOAPIC pin */
- if (irq->dstapic == dstapic && irq->dstirq == i)
+ if (irq->dstapic == dstapic && irq->dstirq == pin)
break;
}
@@ -1011,7 +1052,7 @@
mp_irq.dstapic = dstapic;
mp_irq.irqtype = mp_INT;
mp_irq.srcbusirq = i; /* Identity mapped */
- mp_irq.dstirq = i;
+ mp_irq.dstirq = pin;
save_mp_irq(&mp_irq);
}
@@ -1076,11 +1117,6 @@
ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
-#ifdef CONFIG_X86_32
- if (ioapic_renumber_irq)
- gsi = ioapic_renumber_irq(ioapic, gsi);
-#endif
-
if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
printk(KERN_ERR "Invalid reference to IOAPIC pin "
"%d-%d\n", mp_ioapics[ioapic].apicid,
@@ -1094,7 +1130,7 @@
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- io_apic_set_pci_routing(dev, gsi, &irq_attr);
+ io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
return gsi;
}
@@ -1154,7 +1190,8 @@
* pretend we got one so we can set the SCI flags.
*/
if (!acpi_sci_override_gsi)
- acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0);
+ acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0,
+ acpi_gbl_FADT.sci_interrupt);
/* Fill in identity legacy mappings where no override */
mp_config_acpi_legacy_irqs();
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 1a160d5..7023773 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -194,7 +194,7 @@
}
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
-extern u8 *__smp_locks[], *__smp_locks_end[];
+extern s32 __smp_locks[], __smp_locks_end[];
static void *text_poke_early(void *addr, const void *opcode, size_t len);
/* Replace instructions with better alternatives for this CPU type.
@@ -235,37 +235,41 @@
#ifdef CONFIG_SMP
-static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
+static void alternatives_smp_lock(const s32 *start, const s32 *end,
+ u8 *text, u8 *text_end)
{
- u8 **ptr;
+ const s32 *poff;
mutex_lock(&text_mutex);
- for (ptr = start; ptr < end; ptr++) {
- if (*ptr < text)
- continue;
- if (*ptr > text_end)
+ for (poff = start; poff < end; poff++) {
+ u8 *ptr = (u8 *)poff + *poff;
+
+ if (!*poff || ptr < text || ptr >= text_end)
continue;
/* turn DS segment override prefix into lock prefix */
- text_poke(*ptr, ((unsigned char []){0xf0}), 1);
+ if (*ptr == 0x3e)
+ text_poke(ptr, ((unsigned char []){0xf0}), 1);
};
mutex_unlock(&text_mutex);
}
-static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
+static void alternatives_smp_unlock(const s32 *start, const s32 *end,
+ u8 *text, u8 *text_end)
{
- u8 **ptr;
+ const s32 *poff;
if (noreplace_smp)
return;
mutex_lock(&text_mutex);
- for (ptr = start; ptr < end; ptr++) {
- if (*ptr < text)
- continue;
- if (*ptr > text_end)
+ for (poff = start; poff < end; poff++) {
+ u8 *ptr = (u8 *)poff + *poff;
+
+ if (!*poff || ptr < text || ptr >= text_end)
continue;
/* turn lock prefix into DS segment override prefix */
- text_poke(*ptr, ((unsigned char []){0x3E}), 1);
+ if (*ptr == 0xf0)
+ text_poke(ptr, ((unsigned char []){0x3E}), 1);
};
mutex_unlock(&text_mutex);
}
@@ -276,8 +280,8 @@
char *name;
/* ptrs to lock prefixes */
- u8 **locks;
- u8 **locks_end;
+ const s32 *locks;
+ const s32 *locks_end;
/* .text segment, needed to avoid patching init code ;) */
u8 *text;
@@ -398,16 +402,19 @@
int alternatives_text_reserved(void *start, void *end)
{
struct smp_alt_module *mod;
- u8 **ptr;
+ const s32 *poff;
u8 *text_start = start;
u8 *text_end = end;
list_for_each_entry(mod, &smp_alt_modules, next) {
if (mod->text > text_end || mod->text_end < text_start)
continue;
- for (ptr = mod->locks; ptr < mod->locks_end; ptr++)
- if (text_start <= *ptr && text_end >= *ptr)
+ for (poff = mod->locks; poff < mod->locks_end; poff++) {
+ const u8 *ptr = (const u8 *)poff + *poff;
+
+ if (text_start <= ptr && text_end > ptr)
return 1;
+ }
}
return 0;
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index f854d89b..fa5a1474 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -731,18 +731,22 @@
static u64 *alloc_pte(struct protection_domain *domain,
unsigned long address,
- int end_lvl,
+ unsigned long page_size,
u64 **pte_page,
gfp_t gfp)
{
+ int level, end_lvl;
u64 *pte, *page;
- int level;
+
+ BUG_ON(!is_power_of_2(page_size));
while (address > PM_LEVEL_SIZE(domain->mode))
increase_address_space(domain, gfp);
- level = domain->mode - 1;
- pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+ level = domain->mode - 1;
+ pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+ address = PAGE_SIZE_ALIGN(address, page_size);
+ end_lvl = PAGE_SIZE_LEVEL(page_size);
while (level > end_lvl) {
if (!IOMMU_PTE_PRESENT(*pte)) {
@@ -752,6 +756,10 @@
*pte = PM_LEVEL_PDE(level, virt_to_phys(page));
}
+ /* No level skipping support yet */
+ if (PM_PTE_LEVEL(*pte) != level)
+ return NULL;
+
level -= 1;
pte = IOMMU_PTE_PAGE(*pte);
@@ -769,28 +777,47 @@
* This function checks if there is a PTE for a given dma address. If
* there is one, it returns the pointer to it.
*/
-static u64 *fetch_pte(struct protection_domain *domain,
- unsigned long address, int map_size)
+static u64 *fetch_pte(struct protection_domain *domain, unsigned long address)
{
int level;
u64 *pte;
- level = domain->mode - 1;
- pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+ if (address > PM_LEVEL_SIZE(domain->mode))
+ return NULL;
- while (level > map_size) {
+ level = domain->mode - 1;
+ pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)];
+
+ while (level > 0) {
+
+ /* Not Present */
if (!IOMMU_PTE_PRESENT(*pte))
return NULL;
+ /* Large PTE */
+ if (PM_PTE_LEVEL(*pte) == 0x07) {
+ unsigned long pte_mask, __pte;
+
+ /*
+ * If we have a series of large PTEs, make
+ * sure to return a pointer to the first one.
+ */
+ pte_mask = PTE_PAGE_SIZE(*pte);
+ pte_mask = ~((PAGE_SIZE_PTE_COUNT(pte_mask) << 3) - 1);
+ __pte = ((unsigned long)pte) & pte_mask;
+
+ return (u64 *)__pte;
+ }
+
+ /* No level skipping support yet */
+ if (PM_PTE_LEVEL(*pte) != level)
+ return NULL;
+
level -= 1;
+ /* Walk to the next level */
pte = IOMMU_PTE_PAGE(*pte);
pte = &pte[PM_LEVEL_INDEX(level, address)];
-
- if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) {
- pte = NULL;
- break;
- }
}
return pte;
@@ -807,44 +834,84 @@
unsigned long bus_addr,
unsigned long phys_addr,
int prot,
- int map_size)
+ unsigned long page_size)
{
u64 __pte, *pte;
-
- bus_addr = PAGE_ALIGN(bus_addr);
- phys_addr = PAGE_ALIGN(phys_addr);
-
- BUG_ON(!PM_ALIGNED(map_size, bus_addr));
- BUG_ON(!PM_ALIGNED(map_size, phys_addr));
+ int i, count;
if (!(prot & IOMMU_PROT_MASK))
return -EINVAL;
- pte = alloc_pte(dom, bus_addr, map_size, NULL, GFP_KERNEL);
+ bus_addr = PAGE_ALIGN(bus_addr);
+ phys_addr = PAGE_ALIGN(phys_addr);
+ count = PAGE_SIZE_PTE_COUNT(page_size);
+ pte = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL);
- if (IOMMU_PTE_PRESENT(*pte))
- return -EBUSY;
+ for (i = 0; i < count; ++i)
+ if (IOMMU_PTE_PRESENT(pte[i]))
+ return -EBUSY;
- __pte = phys_addr | IOMMU_PTE_P;
+ if (page_size > PAGE_SIZE) {
+ __pte = PAGE_SIZE_PTE(phys_addr, page_size);
+ __pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC;
+ } else
+ __pte = phys_addr | IOMMU_PTE_P | IOMMU_PTE_FC;
+
if (prot & IOMMU_PROT_IR)
__pte |= IOMMU_PTE_IR;
if (prot & IOMMU_PROT_IW)
__pte |= IOMMU_PTE_IW;
- *pte = __pte;
+ for (i = 0; i < count; ++i)
+ pte[i] = __pte;
update_domain(dom);
return 0;
}
-static void iommu_unmap_page(struct protection_domain *dom,
- unsigned long bus_addr, int map_size)
+static unsigned long iommu_unmap_page(struct protection_domain *dom,
+ unsigned long bus_addr,
+ unsigned long page_size)
{
- u64 *pte = fetch_pte(dom, bus_addr, map_size);
+ unsigned long long unmap_size, unmapped;
+ u64 *pte;
- if (pte)
- *pte = 0;
+ BUG_ON(!is_power_of_2(page_size));
+
+ unmapped = 0;
+
+ while (unmapped < page_size) {
+
+ pte = fetch_pte(dom, bus_addr);
+
+ if (!pte) {
+ /*
+ * No PTE for this address
+ * move forward in 4kb steps
+ */
+ unmap_size = PAGE_SIZE;
+ } else if (PM_PTE_LEVEL(*pte) == 0) {
+ /* 4kb PTE found for this address */
+ unmap_size = PAGE_SIZE;
+ *pte = 0ULL;
+ } else {
+ int count, i;
+
+ /* Large PTE found which maps this address */
+ unmap_size = PTE_PAGE_SIZE(*pte);
+ count = PAGE_SIZE_PTE_COUNT(unmap_size);
+ for (i = 0; i < count; i++)
+ pte[i] = 0ULL;
+ }
+
+ bus_addr = (bus_addr & ~(unmap_size - 1)) + unmap_size;
+ unmapped += unmap_size;
+ }
+
+ BUG_ON(!is_power_of_2(unmapped));
+
+ return unmapped;
}
/*
@@ -878,7 +945,7 @@
for (addr = e->address_start; addr < e->address_end;
addr += PAGE_SIZE) {
ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot,
- PM_MAP_4k);
+ PAGE_SIZE);
if (ret)
return ret;
/*
@@ -1006,7 +1073,7 @@
u64 *pte, *pte_page;
for (i = 0; i < num_ptes; ++i) {
- pte = alloc_pte(&dma_dom->domain, address, PM_MAP_4k,
+ pte = alloc_pte(&dma_dom->domain, address, PAGE_SIZE,
&pte_page, gfp);
if (!pte)
goto out_free;
@@ -1042,7 +1109,7 @@
for (i = dma_dom->aperture[index]->offset;
i < dma_dom->aperture_size;
i += PAGE_SIZE) {
- u64 *pte = fetch_pte(&dma_dom->domain, i, PM_MAP_4k);
+ u64 *pte = fetch_pte(&dma_dom->domain, i);
if (!pte || !IOMMU_PTE_PRESENT(*pte))
continue;
@@ -1712,7 +1779,7 @@
pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)];
if (!pte) {
- pte = alloc_pte(&dom->domain, address, PM_MAP_4k, &pte_page,
+ pte = alloc_pte(&dom->domain, address, PAGE_SIZE, &pte_page,
GFP_ATOMIC);
aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page;
} else
@@ -2439,12 +2506,11 @@
return ret;
}
-static int amd_iommu_map_range(struct iommu_domain *dom,
- unsigned long iova, phys_addr_t paddr,
- size_t size, int iommu_prot)
+static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
+ phys_addr_t paddr, int gfp_order, int iommu_prot)
{
+ unsigned long page_size = 0x1000UL << gfp_order;
struct protection_domain *domain = dom->priv;
- unsigned long i, npages = iommu_num_pages(paddr, size, PAGE_SIZE);
int prot = 0;
int ret;
@@ -2453,61 +2519,50 @@
if (iommu_prot & IOMMU_WRITE)
prot |= IOMMU_PROT_IW;
- iova &= PAGE_MASK;
- paddr &= PAGE_MASK;
-
mutex_lock(&domain->api_lock);
-
- for (i = 0; i < npages; ++i) {
- ret = iommu_map_page(domain, iova, paddr, prot, PM_MAP_4k);
- if (ret)
- return ret;
-
- iova += PAGE_SIZE;
- paddr += PAGE_SIZE;
- }
-
+ ret = iommu_map_page(domain, iova, paddr, prot, page_size);
mutex_unlock(&domain->api_lock);
- return 0;
+ return ret;
}
-static void amd_iommu_unmap_range(struct iommu_domain *dom,
- unsigned long iova, size_t size)
+static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
+ int gfp_order)
{
-
struct protection_domain *domain = dom->priv;
- unsigned long i, npages = iommu_num_pages(iova, size, PAGE_SIZE);
+ unsigned long page_size, unmap_size;
- iova &= PAGE_MASK;
+ page_size = 0x1000UL << gfp_order;
mutex_lock(&domain->api_lock);
-
- for (i = 0; i < npages; ++i) {
- iommu_unmap_page(domain, iova, PM_MAP_4k);
- iova += PAGE_SIZE;
- }
+ unmap_size = iommu_unmap_page(domain, iova, page_size);
+ mutex_unlock(&domain->api_lock);
iommu_flush_tlb_pde(domain);
- mutex_unlock(&domain->api_lock);
+ return get_order(unmap_size);
}
static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
unsigned long iova)
{
struct protection_domain *domain = dom->priv;
- unsigned long offset = iova & ~PAGE_MASK;
+ unsigned long offset_mask;
phys_addr_t paddr;
- u64 *pte;
+ u64 *pte, __pte;
- pte = fetch_pte(domain, iova, PM_MAP_4k);
+ pte = fetch_pte(domain, iova);
if (!pte || !IOMMU_PTE_PRESENT(*pte))
return 0;
- paddr = *pte & IOMMU_PAGE_MASK;
- paddr |= offset;
+ if (PM_PTE_LEVEL(*pte) == 0)
+ offset_mask = PAGE_SIZE - 1;
+ else
+ offset_mask = PTE_PAGE_SIZE(*pte) - 1;
+
+ __pte = *pte & PM_ADDR_MASK;
+ paddr = (__pte & ~offset_mask) | (iova & offset_mask);
return paddr;
}
@@ -2523,8 +2578,8 @@
.domain_destroy = amd_iommu_domain_destroy,
.attach_dev = amd_iommu_attach_device,
.detach_dev = amd_iommu_detach_device,
- .map = amd_iommu_map_range,
- .unmap = amd_iommu_unmap_range,
+ .map = amd_iommu_map,
+ .unmap = amd_iommu_unmap,
.iova_to_phys = amd_iommu_iova_to_phys,
.domain_has_cap = amd_iommu_domain_has_cap,
};
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 6360abf..3bacb4d 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -120,6 +120,7 @@
bool amd_iommu_dump;
static int __initdata amd_iommu_detected;
+static bool __initdata amd_iommu_disabled;
u16 amd_iommu_last_bdf; /* largest PCI device id we have
to handle */
@@ -1372,6 +1373,9 @@
if (no_iommu || (iommu_detected && !gart_iommu_aperture))
return;
+ if (amd_iommu_disabled)
+ return;
+
if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
iommu_detected = 1;
amd_iommu_detected = 1;
@@ -1401,6 +1405,8 @@
for (; *str; ++str) {
if (strncmp(str, "fullflush", 9) == 0)
amd_iommu_unmap_flush = true;
+ if (strncmp(str, "off", 3) == 0)
+ amd_iommu_disabled = true;
}
return 1;
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index 03ba1b8..425e53a 100644
--- a/arch/x86/kernel/apic/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -131,24 +131,6 @@
static unsigned int base;
-static int
-es7000_rename_gsi(int ioapic, int gsi)
-{
- if (es7000_plat == ES7000_ZORRO)
- return gsi;
-
- if (!base) {
- int i;
- for (i = 0; i < nr_ioapics; i++)
- base += nr_ioapic_registers[i];
- }
-
- if (!ioapic && (gsi < 16))
- gsi += base;
-
- return gsi;
-}
-
static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
{
unsigned long vect = 0, psaival = 0;
@@ -190,7 +172,6 @@
es7000_plat = ES7000_ZORRO;
else
es7000_plat = ES7000_CLASSIC;
- ioapic_renumber_irq = es7000_rename_gsi;
}
/*
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index eb2789c..33f3563 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -89,6 +89,9 @@
/* IO APIC gsi routing info */
struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS];
+/* The last gsi number used */
+u32 gsi_end;
+
/* MP IRQ source entries */
struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
@@ -1013,10 +1016,9 @@
return MPBIOS_trigger(idx);
}
-int (*ioapic_renumber_irq)(int ioapic, int irq);
static int pin_2_irq(int idx, int apic, int pin)
{
- int irq, i;
+ int irq;
int bus = mp_irqs[idx].srcbus;
/*
@@ -1028,18 +1030,12 @@
if (test_bit(bus, mp_bus_not_pci)) {
irq = mp_irqs[idx].srcbusirq;
} else {
- /*
- * PCI IRQs are mapped in order
- */
- i = irq = 0;
- while (i < apic)
- irq += nr_ioapic_registers[i++];
- irq += pin;
- /*
- * For MPS mode, so far only needed by ES7000 platform
- */
- if (ioapic_renumber_irq)
- irq = ioapic_renumber_irq(apic, irq);
+ u32 gsi = mp_gsi_routing[apic].gsi_base + pin;
+
+ if (gsi >= NR_IRQS_LEGACY)
+ irq = gsi;
+ else
+ irq = gsi_end + 1 + gsi;
}
#ifdef CONFIG_X86_32
@@ -1950,20 +1946,8 @@
void __init enable_IO_APIC(void)
{
- union IO_APIC_reg_01 reg_01;
int i8259_apic, i8259_pin;
int apic;
- unsigned long flags;
-
- /*
- * The number of IO-APIC IRQ registers (== #pins):
- */
- for (apic = 0; apic < nr_ioapics; apic++) {
- raw_spin_lock_irqsave(&ioapic_lock, flags);
- reg_01.raw = io_apic_read(apic, 1);
- raw_spin_unlock_irqrestore(&ioapic_lock, flags);
- nr_ioapic_registers[apic] = reg_01.bits.entries+1;
- }
if (!legacy_pic->nr_legacy_irqs)
return;
@@ -3858,27 +3842,20 @@
reg_01.raw = io_apic_read(ioapic, 1);
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
- return reg_01.bits.entries;
+ /* The register returns the maximum index redir index
+ * supported, which is one less than the total number of redir
+ * entries.
+ */
+ return reg_01.bits.entries + 1;
}
void __init probe_nr_irqs_gsi(void)
{
- int nr = 0;
+ int nr;
- nr = acpi_probe_gsi();
- if (nr > nr_irqs_gsi) {
+ nr = gsi_end + 1 + NR_IRQS_LEGACY;
+ if (nr > nr_irqs_gsi)
nr_irqs_gsi = nr;
- } else {
- /* for acpi=off or acpi is not compiled in */
- int idx;
-
- nr = 0;
- for (idx = 0; idx < nr_ioapics; idx++)
- nr += io_apic_get_redir_entries(idx) + 1;
-
- if (nr > nr_irqs_gsi)
- nr_irqs_gsi = nr;
- }
printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
}
@@ -4085,22 +4062,27 @@
return reg_01.bits.version;
}
-int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
+int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity)
{
- int i;
+ int ioapic, pin, idx;
if (skip_ioapic_setup)
return -1;
- for (i = 0; i < mp_irq_entries; i++)
- if (mp_irqs[i].irqtype == mp_INT &&
- mp_irqs[i].srcbusirq == bus_irq)
- break;
- if (i >= mp_irq_entries)
+ ioapic = mp_find_ioapic(gsi);
+ if (ioapic < 0)
return -1;
- *trigger = irq_trigger(i);
- *polarity = irq_polarity(i);
+ pin = mp_find_ioapic_pin(ioapic, gsi);
+ if (pin < 0)
+ return -1;
+
+ idx = find_irq_entry(ioapic, pin, mp_INT);
+ if (idx < 0)
+ return -1;
+
+ *trigger = irq_trigger(idx);
+ *polarity = irq_polarity(idx);
return 0;
}
@@ -4241,7 +4223,7 @@
}
}
-int mp_find_ioapic(int gsi)
+int mp_find_ioapic(u32 gsi)
{
int i = 0;
@@ -4256,7 +4238,7 @@
return -1;
}
-int mp_find_ioapic_pin(int ioapic, int gsi)
+int mp_find_ioapic_pin(int ioapic, u32 gsi)
{
if (WARN_ON(ioapic == -1))
return -1;
@@ -4284,6 +4266,7 @@
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
{
int idx = 0;
+ int entries;
if (bad_ioapic(address))
return;
@@ -4302,9 +4285,17 @@
* Build basic GSI lookup table to facilitate gsi->io_apic lookups
* and to prevent reprogramming of IOAPIC pins (PCI GSIs).
*/
+ entries = io_apic_get_redir_entries(idx);
mp_gsi_routing[idx].gsi_base = gsi_base;
- mp_gsi_routing[idx].gsi_end = gsi_base +
- io_apic_get_redir_entries(idx);
+ mp_gsi_routing[idx].gsi_end = gsi_base + entries - 1;
+
+ /*
+ * The number of IO-APIC IRQ registers (== #pins):
+ */
+ nr_ioapic_registers[idx] = entries;
+
+ if (mp_gsi_routing[idx].gsi_end > gsi_end)
+ gsi_end = mp_gsi_routing[idx].gsi_end;
printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
"GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index c085d52..e46f98f 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -735,9 +735,6 @@
uv_node_to_blade[nid] = blade;
uv_cpu_to_blade[cpu] = blade;
max_pnode = max(pnode, max_pnode);
-
- printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, lcpu %d, blade %d\n",
- cpu, apicid, pnode, nid, lcpu, blade);
}
/* Add blade/pnode info for nodes without cpus */
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 031aa88..c4f9182 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1224,7 +1224,7 @@
#ifdef INIT_TIMER_AFTER_SUSPEND
unsigned long flags;
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
/* set the clock to HZ */
outb_pit(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */
udelay(10);
@@ -1232,7 +1232,7 @@
udelay(10);
outb_pit(LATCH >> 8, PIT_CH0); /* MSB */
udelay(10);
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
#endif
}
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index c202b62..3a785da 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -14,7 +14,7 @@
obj-y := intel_cacheinfo.o addon_cpuid_features.o
obj-y += proc.o capflags.o powerflags.o common.o
-obj-y += vmware.o hypervisor.o sched.o
+obj-y += vmware.o hypervisor.o sched.o mshyperv.o
obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o
obj-$(CONFIG_X86_64) += bugs_64.o
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c
index 97ad79c..10fa568 100644
--- a/arch/x86/kernel/cpu/addon_cpuid_features.c
+++ b/arch/x86/kernel/cpu/addon_cpuid_features.c
@@ -30,12 +30,14 @@
const struct cpuid_bit *cb;
static const struct cpuid_bit __cpuinitconst cpuid_bits[] = {
- { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
- { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 },
- { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a },
- { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a },
- { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a },
- { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a },
+ { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
+ { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 },
+ { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006 },
+ { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007 },
+ { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a },
+ { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a },
+ { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a },
+ { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a },
{ 0, 0, 0, 0 }
};
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 01a2652..c39576c 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -86,7 +86,7 @@
static void __init check_hlt(void)
{
- if (paravirt_enabled())
+ if (boot_cpu_data.x86 >= 5 || paravirt_enabled())
return;
printk(KERN_INFO "Checking 'hlt' instruction... ");
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4868e4a..c1c00d0 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1243,10 +1243,7 @@
/*
* Force FPU initialization:
*/
- if (cpu_has_xsave)
- current_thread_info()->status = TS_XSAVE;
- else
- current_thread_info()->status = 0;
+ current_thread_info()->status = 0;
clear_used_math();
mxcsr_feature_mask_init();
diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile
index 1840c0a..bd54bf6 100644
--- a/arch/x86/kernel/cpu/cpufreq/Makefile
+++ b/arch/x86/kernel/cpu/cpufreq/Makefile
@@ -2,8 +2,8 @@
# K8 systems. ACPI is preferred to all other hardware-specific drivers.
# speedstep-* is preferred over p4-clockmod.
-obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
-obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
+obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o mperf.o
+obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o
obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index 4591680..1d3cdda 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -46,6 +46,7 @@
#include <asm/msr.h>
#include <asm/processor.h>
#include <asm/cpufeature.h>
+#include "mperf.h"
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
"acpi-cpufreq", msg)
@@ -71,8 +72,6 @@
static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
-static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf);
-
/* acpi_perf_data is a pointer to percpu data. */
static struct acpi_processor_performance *acpi_perf_data;
@@ -240,45 +239,6 @@
return cmd.val;
}
-/* Called via smp_call_function_single(), on the target CPU */
-static void read_measured_perf_ctrs(void *_cur)
-{
- struct aperfmperf *am = _cur;
-
- get_aperfmperf(am);
-}
-
-/*
- * Return the measured active (C0) frequency on this CPU since last call
- * to this function.
- * Input: cpu number
- * Return: Average CPU frequency in terms of max frequency (zero on error)
- *
- * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance
- * over a period of time, while CPU is in C0 state.
- * IA32_MPERF counts at the rate of max advertised frequency
- * IA32_APERF counts at the rate of actual CPU frequency
- * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
- * no meaning should be associated with absolute values of these MSRs.
- */
-static unsigned int get_measured_perf(struct cpufreq_policy *policy,
- unsigned int cpu)
-{
- struct aperfmperf perf;
- unsigned long ratio;
- unsigned int retval;
-
- if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1))
- return 0;
-
- ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf);
- per_cpu(acfreq_old_perf, cpu) = perf;
-
- retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT;
-
- return retval;
-}
-
static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
{
struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu);
@@ -702,7 +662,7 @@
/* Check for APERF/MPERF support in hardware */
if (cpu_has(c, X86_FEATURE_APERFMPERF))
- acpi_cpufreq_driver.getavg = get_measured_perf;
+ acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf;
dprintk("CPU%u - ACPI performance management activated.\n", cpu);
for (i = 0; i < perf->state_count; i++)
diff --git a/arch/x86/kernel/cpu/cpufreq/mperf.c b/arch/x86/kernel/cpu/cpufreq/mperf.c
new file mode 100644
index 0000000..911e193
--- /dev/null
+++ b/arch/x86/kernel/cpu/cpufreq/mperf.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/slab.h>
+
+#include "mperf.h"
+
+static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf);
+
+/* Called via smp_call_function_single(), on the target CPU */
+static void read_measured_perf_ctrs(void *_cur)
+{
+ struct aperfmperf *am = _cur;
+
+ get_aperfmperf(am);
+}
+
+/*
+ * Return the measured active (C0) frequency on this CPU since last call
+ * to this function.
+ * Input: cpu number
+ * Return: Average CPU frequency in terms of max frequency (zero on error)
+ *
+ * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance
+ * over a period of time, while CPU is in C0 state.
+ * IA32_MPERF counts at the rate of max advertised frequency
+ * IA32_APERF counts at the rate of actual CPU frequency
+ * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
+ * no meaning should be associated with absolute values of these MSRs.
+ */
+unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy,
+ unsigned int cpu)
+{
+ struct aperfmperf perf;
+ unsigned long ratio;
+ unsigned int retval;
+
+ if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1))
+ return 0;
+
+ ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf);
+ per_cpu(acfreq_old_perf, cpu) = perf;
+
+ retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT;
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf);
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/kernel/cpu/cpufreq/mperf.h b/arch/x86/kernel/cpu/cpufreq/mperf.h
new file mode 100644
index 0000000..5dbf295
--- /dev/null
+++ b/arch/x86/kernel/cpu/cpufreq/mperf.h
@@ -0,0 +1,9 @@
+/*
+ * (c) 2010 Advanced Micro Devices, Inc.
+ * Your use of this code is subject to the terms and conditions of the
+ * GNU general public license version 2. See "COPYING" or
+ * http://www.gnu.org/licenses/gpl.html
+ */
+
+unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy,
+ unsigned int cpu);
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index b6215b9..6f3dc8f 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -1,6 +1,5 @@
-
/*
- * (c) 2003-2006 Advanced Micro Devices, Inc.
+ * (c) 2003-2010 Advanced Micro Devices, Inc.
* Your use of this code is subject to the terms and conditions of the
* GNU general public license version 2. See "COPYING" or
* http://www.gnu.org/licenses/gpl.html
@@ -46,6 +45,7 @@
#define PFX "powernow-k8: "
#define VERSION "version 2.20.00"
#include "powernow-k8.h"
+#include "mperf.h"
/* serialize freq changes */
static DEFINE_MUTEX(fidvid_mutex);
@@ -54,6 +54,12 @@
static int cpu_family = CPU_OPTERON;
+/* core performance boost */
+static bool cpb_capable, cpb_enabled;
+static struct msr __percpu *msrs;
+
+static struct cpufreq_driver cpufreq_amd64_driver;
+
#ifndef CONFIG_SMP
static inline const struct cpumask *cpu_core_mask(int cpu)
{
@@ -1249,6 +1255,7 @@
struct powernow_k8_data *data;
struct init_on_cpu init_on_cpu;
int rc;
+ struct cpuinfo_x86 *c = &cpu_data(pol->cpu);
if (!cpu_online(pol->cpu))
return -ENODEV;
@@ -1323,6 +1330,10 @@
return -EINVAL;
}
+ /* Check for APERF/MPERF support in hardware */
+ if (cpu_has(c, X86_FEATURE_APERFMPERF))
+ cpufreq_amd64_driver.getavg = cpufreq_get_measured_perf;
+
cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
if (cpu_family == CPU_HW_PSTATE)
@@ -1394,8 +1405,77 @@
return khz;
}
+static void _cpb_toggle_msrs(bool t)
+{
+ int cpu;
+
+ get_online_cpus();
+
+ rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
+
+ for_each_cpu(cpu, cpu_online_mask) {
+ struct msr *reg = per_cpu_ptr(msrs, cpu);
+ if (t)
+ reg->l &= ~BIT(25);
+ else
+ reg->l |= BIT(25);
+ }
+ wrmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
+
+ put_online_cpus();
+}
+
+/*
+ * Switch on/off core performance boosting.
+ *
+ * 0=disable
+ * 1=enable.
+ */
+static void cpb_toggle(bool t)
+{
+ if (!cpb_capable)
+ return;
+
+ if (t && !cpb_enabled) {
+ cpb_enabled = true;
+ _cpb_toggle_msrs(t);
+ printk(KERN_INFO PFX "Core Boosting enabled.\n");
+ } else if (!t && cpb_enabled) {
+ cpb_enabled = false;
+ _cpb_toggle_msrs(t);
+ printk(KERN_INFO PFX "Core Boosting disabled.\n");
+ }
+}
+
+static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
+ size_t count)
+{
+ int ret = -EINVAL;
+ unsigned long val = 0;
+
+ ret = strict_strtoul(buf, 10, &val);
+ if (!ret && (val == 0 || val == 1) && cpb_capable)
+ cpb_toggle(val);
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
+{
+ return sprintf(buf, "%u\n", cpb_enabled);
+}
+
+#define define_one_rw(_name) \
+static struct freq_attr _name = \
+__ATTR(_name, 0644, show_##_name, store_##_name)
+
+define_one_rw(cpb);
+
static struct freq_attr *powernow_k8_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
+ &cpb,
NULL,
};
@@ -1411,10 +1491,51 @@
.attr = powernow_k8_attr,
};
+/*
+ * Clear the boost-disable flag on the CPU_DOWN path so that this cpu
+ * cannot block the remaining ones from boosting. On the CPU_UP path we
+ * simply keep the boost-disable flag in sync with the current global
+ * state.
+ */
+static int __cpuinit cpb_notify(struct notifier_block *nb, unsigned long action,
+ void *hcpu)
+{
+ unsigned cpu = (long)hcpu;
+ u32 lo, hi;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+
+ if (!cpb_enabled) {
+ rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
+ lo |= BIT(25);
+ wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi);
+ }
+ break;
+
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
+ lo &= ~BIT(25);
+ wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi);
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata cpb_nb = {
+ .notifier_call = cpb_notify,
+};
+
/* driver entry point for init */
static int __cpuinit powernowk8_init(void)
{
- unsigned int i, supported_cpus = 0;
+ unsigned int i, supported_cpus = 0, cpu;
for_each_online_cpu(i) {
int rc;
@@ -1423,15 +1544,36 @@
supported_cpus++;
}
- if (supported_cpus == num_online_cpus()) {
- printk(KERN_INFO PFX "Found %d %s "
- "processors (%d cpu cores) (" VERSION ")\n",
- num_online_nodes(),
- boot_cpu_data.x86_model_id, supported_cpus);
- return cpufreq_register_driver(&cpufreq_amd64_driver);
+ if (supported_cpus != num_online_cpus())
+ return -ENODEV;
+
+ printk(KERN_INFO PFX "Found %d %s (%d cpu cores) (" VERSION ")\n",
+ num_online_nodes(), boot_cpu_data.x86_model_id, supported_cpus);
+
+ if (boot_cpu_has(X86_FEATURE_CPB)) {
+
+ cpb_capable = true;
+
+ register_cpu_notifier(&cpb_nb);
+
+ msrs = msrs_alloc();
+ if (!msrs) {
+ printk(KERN_ERR "%s: Error allocating msrs!\n", __func__);
+ return -ENOMEM;
+ }
+
+ rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
+
+ for_each_cpu(cpu, cpu_online_mask) {
+ struct msr *reg = per_cpu_ptr(msrs, cpu);
+ cpb_enabled |= !(!!(reg->l & BIT(25)));
+ }
+
+ printk(KERN_INFO PFX "Core Performance Boosting: %s.\n",
+ (cpb_enabled ? "on" : "off"));
}
- return -ENODEV;
+ return cpufreq_register_driver(&cpufreq_amd64_driver);
}
/* driver entry point for term */
@@ -1439,6 +1581,13 @@
{
dprintk("exit\n");
+ if (boot_cpu_has(X86_FEATURE_CPB)) {
+ msrs_free(msrs);
+ msrs = NULL;
+
+ unregister_cpu_notifier(&cpb_nb);
+ }
+
cpufreq_unregister_driver(&cpufreq_amd64_driver);
}
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
index 02ce824..df3529b 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
@@ -5,7 +5,6 @@
* http://www.gnu.org/licenses/gpl.html
*/
-
enum pstate {
HW_PSTATE_INVALID = 0xff,
HW_PSTATE_0 = 0,
@@ -55,7 +54,6 @@
struct cpumask *available_cores;
};
-
/* processor's cpuid instruction support */
#define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */
#define CPUID_XFAM 0x0ff00000 /* extended family */
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index 08be922..dd531cc 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -21,37 +21,55 @@
*
*/
+#include <linux/module.h>
#include <asm/processor.h>
-#include <asm/vmware.h>
#include <asm/hypervisor.h>
-static inline void __cpuinit
-detect_hypervisor_vendor(struct cpuinfo_x86 *c)
+/*
+ * Hypervisor detect order. This is specified explicitly here because
+ * some hypervisors might implement compatibility modes for other
+ * hypervisors and therefore need to be detected in specific sequence.
+ */
+static const __initconst struct hypervisor_x86 * const hypervisors[] =
{
- if (vmware_platform())
- c->x86_hyper_vendor = X86_HYPER_VENDOR_VMWARE;
- else
- c->x86_hyper_vendor = X86_HYPER_VENDOR_NONE;
-}
+ &x86_hyper_vmware,
+ &x86_hyper_ms_hyperv,
+};
-static inline void __cpuinit
-hypervisor_set_feature_bits(struct cpuinfo_x86 *c)
+const struct hypervisor_x86 *x86_hyper;
+EXPORT_SYMBOL(x86_hyper);
+
+static inline void __init
+detect_hypervisor_vendor(void)
{
- if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) {
- vmware_set_feature_bits(c);
- return;
+ const struct hypervisor_x86 *h, * const *p;
+
+ for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) {
+ h = *p;
+ if (h->detect()) {
+ x86_hyper = h;
+ printk(KERN_INFO "Hypervisor detected: %s\n", h->name);
+ break;
+ }
}
}
void __cpuinit init_hypervisor(struct cpuinfo_x86 *c)
{
- detect_hypervisor_vendor(c);
- hypervisor_set_feature_bits(c);
+ if (x86_hyper && x86_hyper->set_cpu_features)
+ x86_hyper->set_cpu_features(c);
}
void __init init_hypervisor_platform(void)
{
+
+ detect_hypervisor_vendor();
+
+ if (!x86_hyper)
+ return;
+
init_hypervisor(&boot_cpu_data);
- if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE)
- vmware_platform_setup();
+
+ if (x86_hyper->init_platform)
+ x86_hyper->init_platform();
}
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index f5e5390..85f69cd 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -372,12 +372,6 @@
set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
}
- if (c->cpuid_level > 6) {
- unsigned ecx = cpuid_ecx(6);
- if (ecx & 0x01)
- set_cpu_cap(c, X86_FEATURE_APERFMPERF);
- }
-
if (cpu_has_xmm2)
set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
if (cpu_has_ds) {
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index b3eeb66..33eae20 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -148,13 +148,19 @@
u32 full;
};
+struct amd_l3_cache {
+ struct pci_dev *dev;
+ bool can_disable;
+ unsigned indices;
+ u8 subcaches[4];
+};
+
struct _cpuid4_info {
union _cpuid4_leaf_eax eax;
union _cpuid4_leaf_ebx ebx;
union _cpuid4_leaf_ecx ecx;
unsigned long size;
- bool can_disable;
- unsigned int l3_indices;
+ struct amd_l3_cache *l3;
DECLARE_BITMAP(shared_cpu_map, NR_CPUS);
};
@@ -164,8 +170,7 @@
union _cpuid4_leaf_ebx ebx;
union _cpuid4_leaf_ecx ecx;
unsigned long size;
- bool can_disable;
- unsigned int l3_indices;
+ struct amd_l3_cache *l3;
};
unsigned short num_cache_leaves;
@@ -302,87 +307,163 @@
};
#ifdef CONFIG_CPU_SUP_AMD
-static unsigned int __cpuinit amd_calc_l3_indices(void)
+
+/*
+ * L3 cache descriptors
+ */
+static struct amd_l3_cache **__cpuinitdata l3_caches;
+
+static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
{
- /*
- * We're called over smp_call_function_single() and therefore
- * are on the correct cpu.
- */
- int cpu = smp_processor_id();
- int node = cpu_to_node(cpu);
- struct pci_dev *dev = node_to_k8_nb_misc(node);
unsigned int sc0, sc1, sc2, sc3;
u32 val = 0;
- pci_read_config_dword(dev, 0x1C4, &val);
+ pci_read_config_dword(l3->dev, 0x1C4, &val);
/* calculate subcache sizes */
- sc0 = !(val & BIT(0));
- sc1 = !(val & BIT(4));
- sc2 = !(val & BIT(8)) + !(val & BIT(9));
- sc3 = !(val & BIT(12)) + !(val & BIT(13));
+ l3->subcaches[0] = sc0 = !(val & BIT(0));
+ l3->subcaches[1] = sc1 = !(val & BIT(4));
+ l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9));
+ l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
- return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+ l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+}
+
+static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
+{
+ struct amd_l3_cache *l3;
+ struct pci_dev *dev = node_to_k8_nb_misc(node);
+
+ l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC);
+ if (!l3) {
+ printk(KERN_WARNING "Error allocating L3 struct\n");
+ return NULL;
+ }
+
+ l3->dev = dev;
+
+ amd_calc_l3_indices(l3);
+
+ return l3;
}
static void __cpuinit
amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf)
{
+ int node;
+
+ if (boot_cpu_data.x86 != 0x10)
+ return;
+
if (index < 3)
return;
- if (boot_cpu_data.x86 == 0x11)
- return;
-
/* see errata #382 and #388 */
- if ((boot_cpu_data.x86 == 0x10) &&
- ((boot_cpu_data.x86_model < 0x8) ||
- (boot_cpu_data.x86_mask < 0x1)))
+ if (boot_cpu_data.x86_model < 0x8)
return;
- this_leaf->can_disable = true;
- this_leaf->l3_indices = amd_calc_l3_indices();
+ if ((boot_cpu_data.x86_model == 0x8 ||
+ boot_cpu_data.x86_model == 0x9)
+ &&
+ boot_cpu_data.x86_mask < 0x1)
+ return;
+
+ /* not in virtualized environments */
+ if (num_k8_northbridges == 0)
+ return;
+
+ /*
+ * Strictly speaking, the amount in @size below is leaked since it is
+ * never freed but this is done only on shutdown so it doesn't matter.
+ */
+ if (!l3_caches) {
+ int size = num_k8_northbridges * sizeof(struct amd_l3_cache *);
+
+ l3_caches = kzalloc(size, GFP_ATOMIC);
+ if (!l3_caches)
+ return;
+ }
+
+ node = amd_get_nb_id(smp_processor_id());
+
+ if (!l3_caches[node]) {
+ l3_caches[node] = amd_init_l3_cache(node);
+ l3_caches[node]->can_disable = true;
+ }
+
+ WARN_ON(!l3_caches[node]);
+
+ this_leaf->l3 = l3_caches[node];
}
static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
- unsigned int index)
+ unsigned int slot)
{
- int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
- int node = amd_get_nb_id(cpu);
- struct pci_dev *dev = node_to_k8_nb_misc(node);
+ struct pci_dev *dev = this_leaf->l3->dev;
unsigned int reg = 0;
- if (!this_leaf->can_disable)
+ if (!this_leaf->l3 || !this_leaf->l3->can_disable)
return -EINVAL;
if (!dev)
return -EINVAL;
- pci_read_config_dword(dev, 0x1BC + index * 4, ®);
+ pci_read_config_dword(dev, 0x1BC + slot * 4, ®);
return sprintf(buf, "0x%08x\n", reg);
}
-#define SHOW_CACHE_DISABLE(index) \
+#define SHOW_CACHE_DISABLE(slot) \
static ssize_t \
-show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \
+show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf) \
{ \
- return show_cache_disable(this_leaf, buf, index); \
+ return show_cache_disable(this_leaf, buf, slot); \
}
SHOW_CACHE_DISABLE(0)
SHOW_CACHE_DISABLE(1)
-static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
- const char *buf, size_t count, unsigned int index)
+static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu,
+ unsigned slot, unsigned long idx)
{
+ int i;
+
+ idx |= BIT(30);
+
+ /*
+ * disable index in all 4 subcaches
+ */
+ for (i = 0; i < 4; i++) {
+ u32 reg = idx | (i << 20);
+
+ if (!l3->subcaches[i])
+ continue;
+
+ pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg);
+
+ /*
+ * We need to WBINVD on a core on the node containing the L3
+ * cache which indices we disable therefore a simple wbinvd()
+ * is not sufficient.
+ */
+ wbinvd_on_cpu(cpu);
+
+ reg |= BIT(31);
+ pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg);
+ }
+}
+
+
+static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
+ const char *buf, size_t count,
+ unsigned int slot)
+{
+ struct pci_dev *dev = this_leaf->l3->dev;
int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map));
- int node = amd_get_nb_id(cpu);
- struct pci_dev *dev = node_to_k8_nb_misc(node);
unsigned long val = 0;
#define SUBCACHE_MASK (3UL << 20)
#define SUBCACHE_INDEX 0xfff
- if (!this_leaf->can_disable)
+ if (!this_leaf->l3 || !this_leaf->l3->can_disable)
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
@@ -396,26 +477,20 @@
/* do not allow writes outside of allowed bits */
if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) ||
- ((val & SUBCACHE_INDEX) > this_leaf->l3_indices))
+ ((val & SUBCACHE_INDEX) > this_leaf->l3->indices))
return -EINVAL;
- val |= BIT(30);
- pci_write_config_dword(dev, 0x1BC + index * 4, val);
- /*
- * We need to WBINVD on a core on the node containing the L3 cache which
- * indices we disable therefore a simple wbinvd() is not sufficient.
- */
- wbinvd_on_cpu(cpu);
- pci_write_config_dword(dev, 0x1BC + index * 4, val | BIT(31));
+ amd_l3_disable_index(this_leaf->l3, cpu, slot, val);
+
return count;
}
-#define STORE_CACHE_DISABLE(index) \
+#define STORE_CACHE_DISABLE(slot) \
static ssize_t \
-store_cache_disable_##index(struct _cpuid4_info *this_leaf, \
+store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \
const char *buf, size_t count) \
{ \
- return store_cache_disable(this_leaf, buf, count, index); \
+ return store_cache_disable(this_leaf, buf, count, slot); \
}
STORE_CACHE_DISABLE(0)
STORE_CACHE_DISABLE(1)
@@ -443,8 +518,7 @@
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
amd_cpuid4(index, &eax, &ebx, &ecx);
- if (boot_cpu_data.x86 >= 0x10)
- amd_check_l3_disable(index, this_leaf);
+ amd_check_l3_disable(index, this_leaf);
} else {
cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
}
@@ -701,6 +775,7 @@
for (i = 0; i < num_cache_leaves; i++)
cache_remove_shared_cpu_map(cpu, i);
+ kfree(per_cpu(ici_cpuid4_info, cpu)->l3);
kfree(per_cpu(ici_cpuid4_info, cpu));
per_cpu(ici_cpuid4_info, cpu) = NULL;
}
@@ -985,7 +1060,7 @@
this_leaf = CPUID4_INFO_IDX(cpu, i);
- if (this_leaf->can_disable)
+ if (this_leaf->l3 && this_leaf->l3->can_disable)
ktype_cache.default_attrs = default_l3_attrs;
else
ktype_cache.default_attrs = default_attrs;
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 8a6f0af..7a355dd 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -539,7 +539,7 @@
struct mce m;
int i;
- __get_cpu_var(mce_poll_count)++;
+ percpu_inc(mce_poll_count);
mce_setup(&m);
@@ -934,7 +934,7 @@
atomic_inc(&mce_entry);
- __get_cpu_var(mce_exception_count)++;
+ percpu_inc(mce_exception_count);
if (notify_die(DIE_NMI, "machine check", regs, error_code,
18, SIGKILL) == NOTIFY_STOP)
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
new file mode 100644
index 0000000..16f41bb
--- /dev/null
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -0,0 +1,55 @@
+/*
+ * HyperV Detection code.
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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; version 2 of the License.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <asm/processor.h>
+#include <asm/hypervisor.h>
+#include <asm/hyperv.h>
+#include <asm/mshyperv.h>
+
+struct ms_hyperv_info ms_hyperv;
+
+static bool __init ms_hyperv_platform(void)
+{
+ u32 eax;
+ u32 hyp_signature[3];
+
+ if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
+ return false;
+
+ cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
+ &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
+
+ return eax >= HYPERV_CPUID_MIN &&
+ eax <= HYPERV_CPUID_MAX &&
+ !memcmp("Microsoft Hv", hyp_signature, 12);
+}
+
+static void __init ms_hyperv_init_platform(void)
+{
+ /*
+ * Extract the features and hints
+ */
+ ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
+ ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
+
+ printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
+ ms_hyperv.features, ms_hyperv.hints);
+}
+
+const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
+ .name = "Microsoft HyperV",
+ .detect = ms_hyperv_platform,
+ .init_platform = ms_hyperv_init_platform,
+};
+EXPORT_SYMBOL(x86_hyper_ms_hyperv);
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index 424fc8d..ae85d69 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -465,15 +465,21 @@
return rc;
}
-static inline void p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
+static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
{
- unsigned long dummy;
+ int overflow = 0;
+ u32 low, high;
- rdmsrl(hwc->config_base + hwc->idx, dummy);
- if (dummy & P4_CCCR_OVF) {
+ rdmsr(hwc->config_base + hwc->idx, low, high);
+
+ /* we need to check high bit for unflagged overflows */
+ if ((low & P4_CCCR_OVF) || !(high & (1 << 31))) {
+ overflow = 1;
(void)checking_wrmsrl(hwc->config_base + hwc->idx,
- ((u64)dummy) & ~P4_CCCR_OVF);
+ ((u64)low) & ~P4_CCCR_OVF);
}
+
+ return overflow;
}
static inline void p4_pmu_disable_event(struct perf_event *event)
@@ -584,21 +590,15 @@
WARN_ON_ONCE(hwc->idx != idx);
- /*
- * FIXME: Redundant call, actually not needed
- * but just to check if we're screwed
- */
- p4_pmu_clear_cccr_ovf(hwc);
+ /* it might be unflagged overflow */
+ handled = p4_pmu_clear_cccr_ovf(hwc);
val = x86_perf_event_update(event);
- if (val & (1ULL << (x86_pmu.cntval_bits - 1)))
+ if (!handled && (val & (1ULL << (x86_pmu.cntval_bits - 1))))
continue;
- /*
- * event overflow
- */
- handled = 1;
- data.period = event->hw.last_period;
+ /* event overflow for sure */
+ data.period = event->hw.last_period;
if (!x86_perf_event_set_period(event))
continue;
@@ -670,7 +670,7 @@
/*
* ESCR address hashing is tricky, ESCRs are not sequential
- * in memory but all starts from MSR_P4_BSU_ESCR0 (0x03e0) and
+ * in memory but all starts from MSR_P4_BSU_ESCR0 (0x03a0) and
* the metric between any ESCRs is laid in range [0xa0,0xe1]
*
* so we make ~70% filled hashtable
@@ -735,8 +735,9 @@
{
unsigned int idx = P4_ESCR_MSR_IDX(addr);
- if (unlikely(idx >= P4_ESCR_MSR_TABLE_SIZE ||
- !p4_escr_table[idx])) {
+ if (unlikely(idx >= P4_ESCR_MSR_TABLE_SIZE ||
+ !p4_escr_table[idx] ||
+ p4_escr_table[idx] != addr)) {
WARN_ONCE(1, "P4 PMU: Wrong address passed: %x\n", addr);
return -1;
}
@@ -762,7 +763,7 @@
{
unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
unsigned long escr_mask[BITS_TO_LONGS(P4_ESCR_MSR_TABLE_SIZE)];
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
struct hw_perf_event *hwc;
struct p4_event_bind *bind;
unsigned int i, thread, num;
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index dfdb4db..b9d1ff5 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -24,8 +24,8 @@
#include <linux/dmi.h>
#include <linux/module.h>
#include <asm/div64.h>
-#include <asm/vmware.h>
#include <asm/x86_init.h>
+#include <asm/hypervisor.h>
#define CPUID_VMWARE_INFO_LEAF 0x40000000
#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
@@ -65,7 +65,7 @@
return tsc_hz;
}
-void __init vmware_platform_setup(void)
+static void __init vmware_platform_setup(void)
{
uint32_t eax, ebx, ecx, edx;
@@ -83,26 +83,22 @@
* serial key should be enough, as this will always have a VMware
* specific string when running under VMware hypervisor.
*/
-int vmware_platform(void)
+static bool __init vmware_platform(void)
{
if (cpu_has_hypervisor) {
- unsigned int eax, ebx, ecx, edx;
- char hyper_vendor_id[13];
+ unsigned int eax;
+ unsigned int hyper_vendor_id[3];
- cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &ebx, &ecx, &edx);
- memcpy(hyper_vendor_id + 0, &ebx, 4);
- memcpy(hyper_vendor_id + 4, &ecx, 4);
- memcpy(hyper_vendor_id + 8, &edx, 4);
- hyper_vendor_id[12] = '\0';
- if (!strcmp(hyper_vendor_id, "VMwareVMware"))
- return 1;
+ cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &hyper_vendor_id[0],
+ &hyper_vendor_id[1], &hyper_vendor_id[2]);
+ if (!memcmp(hyper_vendor_id, "VMwareVMware", 12))
+ return true;
} else if (dmi_available && dmi_name_in_serial("VMware") &&
__vmware_platform())
- return 1;
+ return true;
- return 0;
+ return false;
}
-EXPORT_SYMBOL(vmware_platform);
/*
* VMware hypervisor takes care of exporting a reliable TSC to the guest.
@@ -116,8 +112,16 @@
* so that the kernel could just trust the hypervisor with providing a
* reliable virtual TSC that is suitable for timekeeping.
*/
-void __cpuinit vmware_set_feature_bits(struct cpuinfo_x86 *c)
+static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c)
{
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE);
}
+
+const __refconst struct hypervisor_x86 x86_hyper_vmware = {
+ .name = "VMware",
+ .detect = vmware_platform,
+ .set_cpu_features = vmware_set_cpu_features,
+ .init_platform = vmware_platform_setup,
+};
+EXPORT_SYMBOL(x86_hyper_vmware);
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 44a8e0d..cd49141 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -53,6 +53,7 @@
#include <asm/processor-flags.h>
#include <asm/ftrace.h>
#include <asm/irq_vectors.h>
+#include <asm/cpufeature.h>
/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
#include <linux/elf-em.h>
@@ -905,7 +906,25 @@
RING0_INT_FRAME
pushl $0
CFI_ADJUST_CFA_OFFSET 4
+#ifdef CONFIG_X86_INVD_BUG
+ /* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */
+661: pushl $do_general_protection
+662:
+.section .altinstructions,"a"
+ .balign 4
+ .long 661b
+ .long 663f
+ .byte X86_FEATURE_XMM
+ .byte 662b-661b
+ .byte 664f-663f
+.previous
+.section .altinstr_replacement,"ax"
+663: pushl $do_simd_coprocessor_error
+664:
+.previous
+#else
pushl $do_simd_coprocessor_error
+#endif
CFI_ADJUST_CFA_OFFSET 4
jmp error_code
CFI_ENDPROC
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 54c31c2..86cef6b 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -102,14 +102,37 @@
mxcsr_feature_mask_init();
/* clean state in init */
- if (cpu_has_xsave)
- current_thread_info()->status = TS_XSAVE;
- else
- current_thread_info()->status = 0;
+ current_thread_info()->status = 0;
clear_used_math();
}
#endif /* CONFIG_X86_64 */
+static void fpu_finit(struct fpu *fpu)
+{
+#ifdef CONFIG_X86_32
+ if (!HAVE_HWFP) {
+ finit_soft_fpu(&fpu->state->soft);
+ return;
+ }
+#endif
+
+ if (cpu_has_fxsr) {
+ struct i387_fxsave_struct *fx = &fpu->state->fxsave;
+
+ memset(fx, 0, xstate_size);
+ fx->cwd = 0x37f;
+ if (cpu_has_xmm)
+ fx->mxcsr = MXCSR_DEFAULT;
+ } else {
+ struct i387_fsave_struct *fp = &fpu->state->fsave;
+ memset(fp, 0, xstate_size);
+ fp->cwd = 0xffff037fu;
+ fp->swd = 0xffff0000u;
+ fp->twd = 0xffffffffu;
+ fp->fos = 0xffff0000u;
+ }
+}
+
/*
* The _current_ task is using the FPU for the first time
* so initialize it and set the mxcsr to its default
@@ -118,6 +141,8 @@
*/
int init_fpu(struct task_struct *tsk)
{
+ int ret;
+
if (tsk_used_math(tsk)) {
if (HAVE_HWFP && tsk == current)
unlazy_fpu(tsk);
@@ -127,40 +152,12 @@
/*
* Memory allocation at the first usage of the FPU and other state.
*/
- if (!tsk->thread.xstate) {
- tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
- GFP_KERNEL);
- if (!tsk->thread.xstate)
- return -ENOMEM;
- }
+ ret = fpu_alloc(&tsk->thread.fpu);
+ if (ret)
+ return ret;
-#ifdef CONFIG_X86_32
- if (!HAVE_HWFP) {
- memset(tsk->thread.xstate, 0, xstate_size);
- finit_task(tsk);
- set_stopped_child_used_math(tsk);
- return 0;
- }
-#endif
+ fpu_finit(&tsk->thread.fpu);
- if (cpu_has_fxsr) {
- struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave;
-
- memset(fx, 0, xstate_size);
- fx->cwd = 0x37f;
- if (cpu_has_xmm)
- fx->mxcsr = MXCSR_DEFAULT;
- } else {
- struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave;
- memset(fp, 0, xstate_size);
- fp->cwd = 0xffff037fu;
- fp->swd = 0xffff0000u;
- fp->twd = 0xffffffffu;
- fp->fos = 0xffff0000u;
- }
- /*
- * Only the device not available exception or ptrace can call init_fpu.
- */
set_stopped_child_used_math(tsk);
return 0;
}
@@ -194,7 +191,7 @@
return ret;
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &target->thread.xstate->fxsave, 0, -1);
+ &target->thread.fpu.state->fxsave, 0, -1);
}
int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
@@ -211,19 +208,19 @@
return ret;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &target->thread.xstate->fxsave, 0, -1);
+ &target->thread.fpu.state->fxsave, 0, -1);
/*
* mxcsr reserved bits must be masked to zero for security reasons.
*/
- target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
+ target->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
/*
* update the header bits in the xsave header, indicating the
* presence of FP and SSE state.
*/
if (cpu_has_xsave)
- target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE;
+ target->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE;
return ret;
}
@@ -246,14 +243,14 @@
* memory layout in the thread struct, so that we can copy the entire
* xstateregs to the user using one user_regset_copyout().
*/
- memcpy(&target->thread.xstate->fxsave.sw_reserved,
+ memcpy(&target->thread.fpu.state->fxsave.sw_reserved,
xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes));
/*
* Copy the xstate memory layout.
*/
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &target->thread.xstate->xsave, 0, -1);
+ &target->thread.fpu.state->xsave, 0, -1);
return ret;
}
@@ -272,14 +269,14 @@
return ret;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &target->thread.xstate->xsave, 0, -1);
+ &target->thread.fpu.state->xsave, 0, -1);
/*
* mxcsr reserved bits must be masked to zero for security reasons.
*/
- target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
+ target->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
- xsave_hdr = &target->thread.xstate->xsave.xsave_hdr;
+ xsave_hdr = &target->thread.fpu.state->xsave.xsave_hdr;
xsave_hdr->xstate_bv &= pcntxt_mask;
/*
@@ -365,7 +362,7 @@
static void
convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
{
- struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave;
+ struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave;
struct _fpreg *to = (struct _fpreg *) &env->st_space[0];
struct _fpxreg *from = (struct _fpxreg *) &fxsave->st_space[0];
int i;
@@ -405,7 +402,7 @@
const struct user_i387_ia32_struct *env)
{
- struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave;
+ struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave;
struct _fpreg *from = (struct _fpreg *) &env->st_space[0];
struct _fpxreg *to = (struct _fpxreg *) &fxsave->st_space[0];
int i;
@@ -445,7 +442,7 @@
if (!cpu_has_fxsr) {
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &target->thread.xstate->fsave, 0,
+ &target->thread.fpu.state->fsave, 0,
-1);
}
@@ -475,7 +472,7 @@
if (!cpu_has_fxsr) {
return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &target->thread.xstate->fsave, 0, -1);
+ &target->thread.fpu.state->fsave, 0, -1);
}
if (pos > 0 || count < sizeof(env))
@@ -490,7 +487,7 @@
* presence of FP.
*/
if (cpu_has_xsave)
- target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FP;
+ target->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FP;
return ret;
}
@@ -501,7 +498,7 @@
static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf)
{
struct task_struct *tsk = current;
- struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave;
+ struct i387_fsave_struct *fp = &tsk->thread.fpu.state->fsave;
fp->status = fp->swd;
if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct)))
@@ -512,7 +509,7 @@
static int save_i387_fxsave(struct _fpstate_ia32 __user *buf)
{
struct task_struct *tsk = current;
- struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave;
+ struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave;
struct user_i387_ia32_struct env;
int err = 0;
@@ -547,7 +544,7 @@
* header as well as change any contents in the memory layout.
* xrestore as part of sigreturn will capture all the changes.
*/
- tsk->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE;
+ tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE;
if (save_i387_fxsave(fx) < 0)
return -1;
@@ -599,7 +596,7 @@
{
struct task_struct *tsk = current;
- return __copy_from_user(&tsk->thread.xstate->fsave, buf,
+ return __copy_from_user(&tsk->thread.fpu.state->fsave, buf,
sizeof(struct i387_fsave_struct));
}
@@ -610,10 +607,10 @@
struct user_i387_ia32_struct env;
int err;
- err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0],
+ err = __copy_from_user(&tsk->thread.fpu.state->fxsave, &buf->_fxsr_env[0],
size);
/* mxcsr reserved bits must be masked to zero for security reasons */
- tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask;
+ tsk->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
if (err || __copy_from_user(&env, buf, sizeof(env)))
return 1;
convert_to_fxsr(tsk, &env);
@@ -629,7 +626,7 @@
struct i387_fxsave_struct __user *fx =
(struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0];
struct xsave_hdr_struct *xsave_hdr =
- ¤t->thread.xstate->xsave.xsave_hdr;
+ ¤t->thread.fpu.state->xsave.xsave_hdr;
u64 mask;
int err;
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index 23c1679..2dfd315 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -16,7 +16,7 @@
#include <asm/hpet.h>
#include <asm/smp.h>
-DEFINE_SPINLOCK(i8253_lock);
+DEFINE_RAW_SPINLOCK(i8253_lock);
EXPORT_SYMBOL(i8253_lock);
/*
@@ -33,7 +33,7 @@
static void init_pit_timer(enum clock_event_mode mode,
struct clock_event_device *evt)
{
- spin_lock(&i8253_lock);
+ raw_spin_lock(&i8253_lock);
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
@@ -62,7 +62,7 @@
/* Nothing to do here */
break;
}
- spin_unlock(&i8253_lock);
+ raw_spin_unlock(&i8253_lock);
}
/*
@@ -72,10 +72,10 @@
*/
static int pit_next_event(unsigned long delta, struct clock_event_device *evt)
{
- spin_lock(&i8253_lock);
+ raw_spin_lock(&i8253_lock);
outb_pit(delta & 0xff , PIT_CH0); /* LSB */
outb_pit(delta >> 8 , PIT_CH0); /* MSB */
- spin_unlock(&i8253_lock);
+ raw_spin_unlock(&i8253_lock);
return 0;
}
@@ -130,7 +130,7 @@
int count;
u32 jifs;
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
/*
* Although our caller may have the read side of xtime_lock,
* this is now a seqlock, and we are cheating in this routine
@@ -176,7 +176,7 @@
old_count = count;
old_jifs = jifs;
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
count = (LATCH - 1) - count;
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 0ed2d30..990ae7c 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -60,7 +60,7 @@
outb(0, 0xF0);
if (ignore_fpu_irq || !boot_cpu_data.hard_math)
return IRQ_NONE;
- math_error((void __user *)get_irq_regs()->ip);
+ math_error(get_irq_regs(), 0, 16);
return IRQ_HANDLED;
}
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index f2f56c0..345a4b1 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -542,20 +542,6 @@
struct kprobe_ctlblk *kcb;
addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
- if (*addr != BREAKPOINT_INSTRUCTION) {
- /*
- * The breakpoint instruction was removed right
- * after we hit it. Another cpu has removed
- * either a probepoint or a debugger breakpoint
- * at this address. In either case, no further
- * handling of this interrupt is appropriate.
- * Back up over the (now missing) int3 and run
- * the original instruction.
- */
- regs->ip = (unsigned long)addr;
- return 1;
- }
-
/*
* We don't want to be preempted for the entire
* duration of kprobe processing. We conditionally
@@ -587,6 +573,19 @@
setup_singlestep(p, regs, kcb, 0);
return 1;
}
+ } else if (*addr != BREAKPOINT_INSTRUCTION) {
+ /*
+ * The breakpoint instruction was removed right
+ * after we hit it. Another cpu has removed
+ * either a probepoint or a debugger breakpoint
+ * at this address. In either case, no further
+ * handling of this interrupt is appropriate.
+ * Back up over the (now missing) int3 and run
+ * the original instruction.
+ */
+ regs->ip = (unsigned long)addr;
+ preempt_enable_no_resched();
+ return 1;
} else if (kprobe_running()) {
p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index cceb5bc..2cd8c54 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -201,9 +201,9 @@
return error;
}
-static int microcode_open(struct inode *unused1, struct file *unused2)
+static int microcode_open(struct inode *inode, struct file *file)
{
- return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+ return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM;
}
static ssize_t microcode_write(struct file *file, const char __user *buf,
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index 85a343e..3561702 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -343,10 +343,11 @@
int (*get_ucode_data)(void *, const void *, size_t))
{
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- u8 *ucode_ptr = data, *new_mc = NULL, *mc;
+ u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
int new_rev = uci->cpu_sig.rev;
unsigned int leftover = size;
enum ucode_state state = UCODE_OK;
+ unsigned int curr_mc_size = 0;
while (leftover) {
struct microcode_header_intel mc_header;
@@ -361,9 +362,15 @@
break;
}
- mc = vmalloc(mc_size);
- if (!mc)
- break;
+ /* For performance reasons, reuse mc area when possible */
+ if (!mc || mc_size > curr_mc_size) {
+ if (mc)
+ vfree(mc);
+ mc = vmalloc(mc_size);
+ if (!mc)
+ break;
+ curr_mc_size = mc_size;
+ }
if (get_ucode_data(mc, ucode_ptr, mc_size) ||
microcode_sanity_check(mc) < 0) {
@@ -376,13 +383,16 @@
vfree(new_mc);
new_rev = mc_header.rev;
new_mc = mc;
- } else
- vfree(mc);
+ mc = NULL; /* trigger new vmalloc */
+ }
ucode_ptr += mc_size;
leftover -= mc_size;
}
+ if (mc)
+ vfree(mc);
+
if (leftover) {
if (new_mc)
vfree(new_mc);
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index e81030f..5ae5d24 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -115,21 +115,6 @@
printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
}
-static int bad_ioapic(unsigned long address)
-{
- if (nr_ioapics >= MAX_IO_APICS) {
- printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
- "(found %d)\n", MAX_IO_APICS, nr_ioapics);
- panic("Recompile kernel with bigger MAX_IO_APICS!\n");
- }
- if (!address) {
- printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
- " found in table, skipping!\n");
- return 1;
- }
- return 0;
-}
-
static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
if (!(m->flags & MPC_APIC_USABLE))
@@ -138,15 +123,7 @@
printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
m->apicid, m->apicver, m->apicaddr);
- if (bad_ioapic(m->apicaddr))
- return;
-
- mp_ioapics[nr_ioapics].apicaddr = m->apicaddr;
- mp_ioapics[nr_ioapics].apicid = m->apicid;
- mp_ioapics[nr_ioapics].type = m->type;
- mp_ioapics[nr_ioapics].apicver = m->apicver;
- mp_ioapics[nr_ioapics].flags = m->flags;
- nr_ioapics++;
+ mp_register_ioapic(m->apicid, m->apicaddr, gsi_end + 1);
}
static void print_MP_intsrc_info(struct mpc_intsrc *m)
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index 0aad867..e796448 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -237,4 +237,9 @@
x86_init.pci.fixup_irqs = x86_init_noop;
legacy_pic = &null_legacy_pic;
+
+ /* Avoid searching for BIOS MP tables */
+ x86_init.mpparse.find_smp_config = x86_init_noop;
+ x86_init.mpparse.get_smp_config = x86_init_uint_noop;
+
}
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index eccdb57..e7e3521 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -31,24 +31,22 @@
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
+ int ret;
+
*dst = *src;
- if (src->thread.xstate) {
- dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
- GFP_KERNEL);
- if (!dst->thread.xstate)
- return -ENOMEM;
- WARN_ON((unsigned long)dst->thread.xstate & 15);
- memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
+ if (fpu_allocated(&src->thread.fpu)) {
+ memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu));
+ ret = fpu_alloc(&dst->thread.fpu);
+ if (ret)
+ return ret;
+ fpu_copy(&dst->thread.fpu, &src->thread.fpu);
}
return 0;
}
void free_thread_xstate(struct task_struct *tsk)
{
- if (tsk->thread.xstate) {
- kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
- tsk->thread.xstate = NULL;
- }
+ fpu_free(&tsk->thread.fpu);
}
void free_thread_info(struct thread_info *ti)
@@ -548,11 +546,13 @@
* check OSVW bit for CPUs that are not affected
* by erratum #400
*/
- rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val);
- if (val >= 2) {
- rdmsrl(MSR_AMD64_OSVW_STATUS, val);
- if (!(val & BIT(1)))
- goto no_c1e_idle;
+ if (cpu_has(c, X86_FEATURE_OSVW)) {
+ rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val);
+ if (val >= 2) {
+ rdmsrl(MSR_AMD64_OSVW_STATUS, val);
+ if (!(val & BIT(1)))
+ goto no_c1e_idle;
+ }
}
return 1;
}
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 75090c5..8d12878 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -309,7 +309,7 @@
/* we're going to use this soon, after a few expensive things */
if (preload_fpu)
- prefetch(next->xstate);
+ prefetch(next->fpu.state);
/*
* Reload esp0.
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 50cc84a..3c2422a 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -388,7 +388,7 @@
/* we're going to use this soon, after a few expensive things */
if (preload_fpu)
- prefetch(next->xstate);
+ prefetch(next->fpu.state);
/*
* Reload esp0, LDT and the page table pointer:
diff --git a/arch/x86/kernel/sfi.c b/arch/x86/kernel/sfi.c
index 34e0993..7ded578 100644
--- a/arch/x86/kernel/sfi.c
+++ b/arch/x86/kernel/sfi.c
@@ -81,7 +81,6 @@
#endif /* CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_IO_APIC
-static u32 gsi_base;
static int __init sfi_parse_ioapic(struct sfi_table_header *table)
{
@@ -94,8 +93,7 @@
pentry = (struct sfi_apic_table_entry *)sb->pentry;
for (i = 0; i < num; i++) {
- mp_register_ioapic(i, pentry->phys_addr, gsi_base);
- gsi_base += io_apic_get_redir_entries(i);
+ mp_register_ioapic(i, pentry->phys_addr, gsi_end + 1);
pentry++;
}
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 86c9f91..cc2c604 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -175,6 +175,9 @@
struct tboot_mac_region *mr;
phys_addr_t end = start + size;
+ if (tboot->num_mac_regions >= MAX_TB_MAC_REGIONS)
+ panic("tboot: Too many MAC regions\n");
+
if (start && size) {
mr = &tboot->mac_regions[tboot->num_mac_regions++];
mr->start = round_down(start, PAGE_SIZE);
@@ -184,18 +187,17 @@
static int tboot_setup_sleep(void)
{
+ int i;
+
tboot->num_mac_regions = 0;
- /* S3 resume code */
- add_mac_region(acpi_wakeup_address, WAKEUP_SIZE);
+ for (i = 0; i < e820.nr_map; i++) {
+ if ((e820.map[i].type != E820_RAM)
+ && (e820.map[i].type != E820_RESERVED_KERN))
+ continue;
-#ifdef CONFIG_X86_TRAMPOLINE
- /* AP trampoline code */
- add_mac_region(virt_to_phys(trampoline_base), TRAMPOLINE_SIZE);
-#endif
-
- /* kernel code + data + bss */
- add_mac_region(virt_to_phys(_text), _end - _text);
+ add_mac_region(e820.map[i].addr, e820.map[i].size);
+ }
tboot->acpi_sinfo.kernel_s3_resume_vector = acpi_wakeup_address;
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c
index 17b03dd..7fea555 100644
--- a/arch/x86/kernel/tlb_uv.c
+++ b/arch/x86/kernel/tlb_uv.c
@@ -1,7 +1,7 @@
/*
* SGI UltraViolet TLB flush routines.
*
- * (c) 2008 Cliff Wickman <cpw@sgi.com>, SGI.
+ * (c) 2008-2010 Cliff Wickman <cpw@sgi.com>, SGI.
*
* This code is released under the GNU General Public License version 2 or
* later.
@@ -20,42 +20,67 @@
#include <asm/idle.h>
#include <asm/tsc.h>
#include <asm/irq_vectors.h>
+#include <asm/timer.h>
-static struct bau_control **uv_bau_table_bases __read_mostly;
-static int uv_bau_retry_limit __read_mostly;
+struct msg_desc {
+ struct bau_payload_queue_entry *msg;
+ int msg_slot;
+ int sw_ack_slot;
+ struct bau_payload_queue_entry *va_queue_first;
+ struct bau_payload_queue_entry *va_queue_last;
+};
+
+#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL
+
+static int uv_bau_max_concurrent __read_mostly;
+
+static int nobau;
+static int __init setup_nobau(char *arg)
+{
+ nobau = 1;
+ return 0;
+}
+early_param("nobau", setup_nobau);
/* base pnode in this partition */
-static int uv_partition_base_pnode __read_mostly;
-
-static unsigned long uv_mmask __read_mostly;
+static int uv_partition_base_pnode __read_mostly;
+/* position of pnode (which is nasid>>1): */
+static int uv_nshift __read_mostly;
+static unsigned long uv_mmask __read_mostly;
static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
static DEFINE_PER_CPU(struct bau_control, bau_control);
+static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask);
+
+struct reset_args {
+ int sender;
+};
/*
- * Determine the first node on a blade.
+ * Determine the first node on a uvhub. 'Nodes' are used for kernel
+ * memory allocation.
*/
-static int __init blade_to_first_node(int blade)
+static int __init uvhub_to_first_node(int uvhub)
{
int node, b;
for_each_online_node(node) {
b = uv_node_to_blade_id(node);
- if (blade == b)
+ if (uvhub == b)
return node;
}
- return -1; /* shouldn't happen */
+ return -1;
}
/*
- * Determine the apicid of the first cpu on a blade.
+ * Determine the apicid of the first cpu on a uvhub.
*/
-static int __init blade_to_first_apicid(int blade)
+static int __init uvhub_to_first_apicid(int uvhub)
{
int cpu;
for_each_present_cpu(cpu)
- if (blade == uv_cpu_to_blade_id(cpu))
+ if (uvhub == uv_cpu_to_blade_id(cpu))
return per_cpu(x86_cpu_to_apicid, cpu);
return -1;
}
@@ -68,195 +93,459 @@
* clear of the Timeout bit (as well) will free the resource. No reply will
* be sent (the hardware will only do one reply per message).
*/
-static void uv_reply_to_message(int resource,
- struct bau_payload_queue_entry *msg,
- struct bau_msg_status *msp)
+static inline void uv_reply_to_message(struct msg_desc *mdp,
+ struct bau_control *bcp)
{
unsigned long dw;
+ struct bau_payload_queue_entry *msg;
- dw = (1 << (resource + UV_SW_ACK_NPENDING)) | (1 << resource);
+ msg = mdp->msg;
+ if (!msg->canceled) {
+ dw = (msg->sw_ack_vector << UV_SW_ACK_NPENDING) |
+ msg->sw_ack_vector;
+ uv_write_local_mmr(
+ UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, dw);
+ }
msg->replied_to = 1;
msg->sw_ack_vector = 0;
- if (msp)
- msp->seen_by.bits = 0;
- uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, dw);
+}
+
+/*
+ * Process the receipt of a RETRY message
+ */
+static inline void uv_bau_process_retry_msg(struct msg_desc *mdp,
+ struct bau_control *bcp)
+{
+ int i;
+ int cancel_count = 0;
+ int slot2;
+ unsigned long msg_res;
+ unsigned long mmr = 0;
+ struct bau_payload_queue_entry *msg;
+ struct bau_payload_queue_entry *msg2;
+ struct ptc_stats *stat;
+
+ msg = mdp->msg;
+ stat = &per_cpu(ptcstats, bcp->cpu);
+ stat->d_retries++;
+ /*
+ * cancel any message from msg+1 to the retry itself
+ */
+ for (msg2 = msg+1, i = 0; i < DEST_Q_SIZE; msg2++, i++) {
+ if (msg2 > mdp->va_queue_last)
+ msg2 = mdp->va_queue_first;
+ if (msg2 == msg)
+ break;
+
+ /* same conditions for cancellation as uv_do_reset */
+ if ((msg2->replied_to == 0) && (msg2->canceled == 0) &&
+ (msg2->sw_ack_vector) && ((msg2->sw_ack_vector &
+ msg->sw_ack_vector) == 0) &&
+ (msg2->sending_cpu == msg->sending_cpu) &&
+ (msg2->msg_type != MSG_NOOP)) {
+ slot2 = msg2 - mdp->va_queue_first;
+ mmr = uv_read_local_mmr
+ (UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
+ msg_res = ((msg2->sw_ack_vector << 8) |
+ msg2->sw_ack_vector);
+ /*
+ * This is a message retry; clear the resources held
+ * by the previous message only if they timed out.
+ * If it has not timed out we have an unexpected
+ * situation to report.
+ */
+ if (mmr & (msg_res << 8)) {
+ /*
+ * is the resource timed out?
+ * make everyone ignore the cancelled message.
+ */
+ msg2->canceled = 1;
+ stat->d_canceled++;
+ cancel_count++;
+ uv_write_local_mmr(
+ UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS,
+ (msg_res << 8) | msg_res);
+ } else
+ printk(KERN_INFO "note bau retry: no effect\n");
+ }
+ }
+ if (!cancel_count)
+ stat->d_nocanceled++;
}
/*
* Do all the things a cpu should do for a TLB shootdown message.
* Other cpu's may come here at the same time for this message.
*/
-static void uv_bau_process_message(struct bau_payload_queue_entry *msg,
- int msg_slot, int sw_ack_slot)
+static void uv_bau_process_message(struct msg_desc *mdp,
+ struct bau_control *bcp)
{
- unsigned long this_cpu_mask;
- struct bau_msg_status *msp;
- int cpu;
+ int msg_ack_count;
+ short socket_ack_count = 0;
+ struct ptc_stats *stat;
+ struct bau_payload_queue_entry *msg;
+ struct bau_control *smaster = bcp->socket_master;
- msp = __get_cpu_var(bau_control).msg_statuses + msg_slot;
- cpu = uv_blade_processor_id();
- msg->number_of_cpus =
- uv_blade_nr_online_cpus(uv_node_to_blade_id(numa_node_id()));
- this_cpu_mask = 1UL << cpu;
- if (msp->seen_by.bits & this_cpu_mask)
- return;
- atomic_or_long(&msp->seen_by.bits, this_cpu_mask);
-
- if (msg->replied_to == 1)
- return;
-
+ /*
+ * This must be a normal message, or retry of a normal message
+ */
+ msg = mdp->msg;
+ stat = &per_cpu(ptcstats, bcp->cpu);
if (msg->address == TLB_FLUSH_ALL) {
local_flush_tlb();
- __get_cpu_var(ptcstats).alltlb++;
+ stat->d_alltlb++;
} else {
__flush_tlb_one(msg->address);
- __get_cpu_var(ptcstats).onetlb++;
+ stat->d_onetlb++;
}
+ stat->d_requestee++;
- __get_cpu_var(ptcstats).requestee++;
+ /*
+ * One cpu on each uvhub has the additional job on a RETRY
+ * of releasing the resource held by the message that is
+ * being retried. That message is identified by sending
+ * cpu number.
+ */
+ if (msg->msg_type == MSG_RETRY && bcp == bcp->uvhub_master)
+ uv_bau_process_retry_msg(mdp, bcp);
- atomic_inc_short(&msg->acknowledge_count);
- if (msg->number_of_cpus == msg->acknowledge_count)
- uv_reply_to_message(sw_ack_slot, msg, msp);
-}
+ /*
+ * This is a sw_ack message, so we have to reply to it.
+ * Count each responding cpu on the socket. This avoids
+ * pinging the count's cache line back and forth between
+ * the sockets.
+ */
+ socket_ack_count = atomic_add_short_return(1, (struct atomic_short *)
+ &smaster->socket_acknowledge_count[mdp->msg_slot]);
+ if (socket_ack_count == bcp->cpus_in_socket) {
+ /*
+ * Both sockets dump their completed count total into
+ * the message's count.
+ */
+ smaster->socket_acknowledge_count[mdp->msg_slot] = 0;
+ msg_ack_count = atomic_add_short_return(socket_ack_count,
+ (struct atomic_short *)&msg->acknowledge_count);
-/*
- * Examine the payload queue on one distribution node to see
- * which messages have not been seen, and which cpu(s) have not seen them.
- *
- * Returns the number of cpu's that have not responded.
- */
-static int uv_examine_destination(struct bau_control *bau_tablesp, int sender)
-{
- struct bau_payload_queue_entry *msg;
- struct bau_msg_status *msp;
- int count = 0;
- int i;
- int j;
-
- for (msg = bau_tablesp->va_queue_first, i = 0; i < DEST_Q_SIZE;
- msg++, i++) {
- if ((msg->sending_cpu == sender) && (!msg->replied_to)) {
- msp = bau_tablesp->msg_statuses + i;
- printk(KERN_DEBUG
- "blade %d: address:%#lx %d of %d, not cpu(s): ",
- i, msg->address, msg->acknowledge_count,
- msg->number_of_cpus);
- for (j = 0; j < msg->number_of_cpus; j++) {
- if (!((1L << j) & msp->seen_by.bits)) {
- count++;
- printk("%d ", j);
- }
- }
- printk("\n");
+ if (msg_ack_count == bcp->cpus_in_uvhub) {
+ /*
+ * All cpus in uvhub saw it; reply
+ */
+ uv_reply_to_message(mdp, bcp);
}
}
- return count;
+
+ return;
}
/*
- * Examine the payload queue on all the distribution nodes to see
- * which messages have not been seen, and which cpu(s) have not seen them.
- *
- * Returns the number of cpu's that have not responded.
+ * Determine the first cpu on a uvhub.
*/
-static int uv_examine_destinations(struct bau_target_nodemask *distribution)
+static int uvhub_to_first_cpu(int uvhub)
{
- int sender;
- int i;
- int count = 0;
-
- sender = smp_processor_id();
- for (i = 0; i < sizeof(struct bau_target_nodemask) * BITSPERBYTE; i++) {
- if (!bau_node_isset(i, distribution))
- continue;
- count += uv_examine_destination(uv_bau_table_bases[i], sender);
- }
- return count;
+ int cpu;
+ for_each_present_cpu(cpu)
+ if (uvhub == uv_cpu_to_blade_id(cpu))
+ return cpu;
+ return -1;
}
/*
- * wait for completion of a broadcast message
+ * Last resort when we get a large number of destination timeouts is
+ * to clear resources held by a given cpu.
+ * Do this with IPI so that all messages in the BAU message queue
+ * can be identified by their nonzero sw_ack_vector field.
*
- * return COMPLETE, RETRY or GIVEUP
+ * This is entered for a single cpu on the uvhub.
+ * The sender want's this uvhub to free a specific message's
+ * sw_ack resources.
+ */
+static void
+uv_do_reset(void *ptr)
+{
+ int i;
+ int slot;
+ int count = 0;
+ unsigned long mmr;
+ unsigned long msg_res;
+ struct bau_control *bcp;
+ struct reset_args *rap;
+ struct bau_payload_queue_entry *msg;
+ struct ptc_stats *stat;
+
+ bcp = &per_cpu(bau_control, smp_processor_id());
+ rap = (struct reset_args *)ptr;
+ stat = &per_cpu(ptcstats, bcp->cpu);
+ stat->d_resets++;
+
+ /*
+ * We're looking for the given sender, and
+ * will free its sw_ack resource.
+ * If all cpu's finally responded after the timeout, its
+ * message 'replied_to' was set.
+ */
+ for (msg = bcp->va_queue_first, i = 0; i < DEST_Q_SIZE; msg++, i++) {
+ /* uv_do_reset: same conditions for cancellation as
+ uv_bau_process_retry_msg() */
+ if ((msg->replied_to == 0) &&
+ (msg->canceled == 0) &&
+ (msg->sending_cpu == rap->sender) &&
+ (msg->sw_ack_vector) &&
+ (msg->msg_type != MSG_NOOP)) {
+ /*
+ * make everyone else ignore this message
+ */
+ msg->canceled = 1;
+ slot = msg - bcp->va_queue_first;
+ count++;
+ /*
+ * only reset the resource if it is still pending
+ */
+ mmr = uv_read_local_mmr
+ (UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
+ msg_res = ((msg->sw_ack_vector << 8) |
+ msg->sw_ack_vector);
+ if (mmr & msg_res) {
+ stat->d_rcanceled++;
+ uv_write_local_mmr(
+ UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS,
+ msg_res);
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Use IPI to get all target uvhubs to release resources held by
+ * a given sending cpu number.
+ */
+static void uv_reset_with_ipi(struct bau_target_uvhubmask *distribution,
+ int sender)
+{
+ int uvhub;
+ int cpu;
+ cpumask_t mask;
+ struct reset_args reset_args;
+
+ reset_args.sender = sender;
+
+ cpus_clear(mask);
+ /* find a single cpu for each uvhub in this distribution mask */
+ for (uvhub = 0;
+ uvhub < sizeof(struct bau_target_uvhubmask) * BITSPERBYTE;
+ uvhub++) {
+ if (!bau_uvhub_isset(uvhub, distribution))
+ continue;
+ /* find a cpu for this uvhub */
+ cpu = uvhub_to_first_cpu(uvhub);
+ cpu_set(cpu, mask);
+ }
+ /* IPI all cpus; Preemption is already disabled */
+ smp_call_function_many(&mask, uv_do_reset, (void *)&reset_args, 1);
+ return;
+}
+
+static inline unsigned long
+cycles_2_us(unsigned long long cyc)
+{
+ unsigned long long ns;
+ unsigned long us;
+ ns = (cyc * per_cpu(cyc2ns, smp_processor_id()))
+ >> CYC2NS_SCALE_FACTOR;
+ us = ns / 1000;
+ return us;
+}
+
+/*
+ * wait for all cpus on this hub to finish their sends and go quiet
+ * leaves uvhub_quiesce set so that no new broadcasts are started by
+ * bau_flush_send_and_wait()
+ */
+static inline void
+quiesce_local_uvhub(struct bau_control *hmaster)
+{
+ atomic_add_short_return(1, (struct atomic_short *)
+ &hmaster->uvhub_quiesce);
+}
+
+/*
+ * mark this quiet-requestor as done
+ */
+static inline void
+end_uvhub_quiesce(struct bau_control *hmaster)
+{
+ atomic_add_short_return(-1, (struct atomic_short *)
+ &hmaster->uvhub_quiesce);
+}
+
+/*
+ * Wait for completion of a broadcast software ack message
+ * return COMPLETE, RETRY(PLUGGED or TIMEOUT) or GIVEUP
*/
static int uv_wait_completion(struct bau_desc *bau_desc,
- unsigned long mmr_offset, int right_shift)
+ unsigned long mmr_offset, int right_shift, int this_cpu,
+ struct bau_control *bcp, struct bau_control *smaster, long try)
{
- int exams = 0;
- long destination_timeouts = 0;
- long source_timeouts = 0;
+ int relaxes = 0;
unsigned long descriptor_status;
+ unsigned long mmr;
+ unsigned long mask;
+ cycles_t ttime;
+ cycles_t timeout_time;
+ struct ptc_stats *stat = &per_cpu(ptcstats, this_cpu);
+ struct bau_control *hmaster;
+ hmaster = bcp->uvhub_master;
+ timeout_time = get_cycles() + bcp->timeout_interval;
+
+ /* spin on the status MMR, waiting for it to go idle */
while ((descriptor_status = (((unsigned long)
uv_read_local_mmr(mmr_offset) >>
right_shift) & UV_ACT_STATUS_MASK)) !=
DESC_STATUS_IDLE) {
- if (descriptor_status == DESC_STATUS_SOURCE_TIMEOUT) {
- source_timeouts++;
- if (source_timeouts > SOURCE_TIMEOUT_LIMIT)
- source_timeouts = 0;
- __get_cpu_var(ptcstats).s_retry++;
- return FLUSH_RETRY;
- }
/*
- * spin here looking for progress at the destinations
+ * Our software ack messages may be blocked because there are
+ * no swack resources available. As long as none of them
+ * has timed out hardware will NACK our message and its
+ * state will stay IDLE.
*/
- if (descriptor_status == DESC_STATUS_DESTINATION_TIMEOUT) {
- destination_timeouts++;
- if (destination_timeouts > DESTINATION_TIMEOUT_LIMIT) {
- /*
- * returns number of cpus not responding
- */
- if (uv_examine_destinations
- (&bau_desc->distribution) == 0) {
- __get_cpu_var(ptcstats).d_retry++;
- return FLUSH_RETRY;
- }
- exams++;
- if (exams >= uv_bau_retry_limit) {
- printk(KERN_DEBUG
- "uv_flush_tlb_others");
- printk("giving up on cpu %d\n",
- smp_processor_id());
+ if (descriptor_status == DESC_STATUS_SOURCE_TIMEOUT) {
+ stat->s_stimeout++;
+ return FLUSH_GIVEUP;
+ } else if (descriptor_status ==
+ DESC_STATUS_DESTINATION_TIMEOUT) {
+ stat->s_dtimeout++;
+ ttime = get_cycles();
+
+ /*
+ * Our retries may be blocked by all destination
+ * swack resources being consumed, and a timeout
+ * pending. In that case hardware returns the
+ * ERROR that looks like a destination timeout.
+ */
+ if (cycles_2_us(ttime - bcp->send_message) < BIOS_TO) {
+ bcp->conseccompletes = 0;
+ return FLUSH_RETRY_PLUGGED;
+ }
+
+ bcp->conseccompletes = 0;
+ return FLUSH_RETRY_TIMEOUT;
+ } else {
+ /*
+ * descriptor_status is still BUSY
+ */
+ cpu_relax();
+ relaxes++;
+ if (relaxes >= 10000) {
+ relaxes = 0;
+ if (get_cycles() > timeout_time) {
+ quiesce_local_uvhub(hmaster);
+
+ /* single-thread the register change */
+ spin_lock(&hmaster->masks_lock);
+ mmr = uv_read_local_mmr(mmr_offset);
+ mask = 0UL;
+ mask |= (3UL < right_shift);
+ mask = ~mask;
+ mmr &= mask;
+ uv_write_local_mmr(mmr_offset, mmr);
+ spin_unlock(&hmaster->masks_lock);
+ end_uvhub_quiesce(hmaster);
+ stat->s_busy++;
return FLUSH_GIVEUP;
}
- /*
- * delays can hang the simulator
- udelay(1000);
- */
- destination_timeouts = 0;
}
}
- cpu_relax();
}
+ bcp->conseccompletes++;
return FLUSH_COMPLETE;
}
+static inline cycles_t
+sec_2_cycles(unsigned long sec)
+{
+ unsigned long ns;
+ cycles_t cyc;
+
+ ns = sec * 1000000000;
+ cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id()));
+ return cyc;
+}
+
+/*
+ * conditionally add 1 to *v, unless *v is >= u
+ * return 0 if we cannot add 1 to *v because it is >= u
+ * return 1 if we can add 1 to *v because it is < u
+ * the add is atomic
+ *
+ * This is close to atomic_add_unless(), but this allows the 'u' value
+ * to be lowered below the current 'v'. atomic_add_unless can only stop
+ * on equal.
+ */
+static inline int atomic_inc_unless_ge(spinlock_t *lock, atomic_t *v, int u)
+{
+ spin_lock(lock);
+ if (atomic_read(v) >= u) {
+ spin_unlock(lock);
+ return 0;
+ }
+ atomic_inc(v);
+ spin_unlock(lock);
+ return 1;
+}
+
/**
* uv_flush_send_and_wait
*
- * Send a broadcast and wait for a broadcast message to complete.
+ * Send a broadcast and wait for it to complete.
*
- * The flush_mask contains the cpus the broadcast was sent to.
+ * The flush_mask contains the cpus the broadcast is to be sent to, plus
+ * cpus that are on the local uvhub.
*
- * Returns NULL if all remote flushing was done. The mask is zeroed.
+ * Returns NULL if all flushing represented in the mask was done. The mask
+ * is zeroed.
* Returns @flush_mask if some remote flushing remains to be done. The
- * mask will have some bits still set.
+ * mask will have some bits still set, representing any cpus on the local
+ * uvhub (not current cpu) and any on remote uvhubs if the broadcast failed.
*/
-const struct cpumask *uv_flush_send_and_wait(int cpu, int this_pnode,
- struct bau_desc *bau_desc,
- struct cpumask *flush_mask)
+const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc,
+ struct cpumask *flush_mask,
+ struct bau_control *bcp)
{
- int completion_status = 0;
int right_shift;
- int tries = 0;
- int pnode;
+ int uvhub;
int bit;
+ int completion_status = 0;
+ int seq_number = 0;
+ long try = 0;
+ int cpu = bcp->uvhub_cpu;
+ int this_cpu = bcp->cpu;
+ int this_uvhub = bcp->uvhub;
unsigned long mmr_offset;
unsigned long index;
cycles_t time1;
cycles_t time2;
+ struct ptc_stats *stat = &per_cpu(ptcstats, bcp->cpu);
+ struct bau_control *smaster = bcp->socket_master;
+ struct bau_control *hmaster = bcp->uvhub_master;
+
+ /*
+ * Spin here while there are hmaster->max_concurrent or more active
+ * descriptors. This is the per-uvhub 'throttle'.
+ */
+ if (!atomic_inc_unless_ge(&hmaster->uvhub_lock,
+ &hmaster->active_descriptor_count,
+ hmaster->max_concurrent)) {
+ stat->s_throttles++;
+ do {
+ cpu_relax();
+ } while (!atomic_inc_unless_ge(&hmaster->uvhub_lock,
+ &hmaster->active_descriptor_count,
+ hmaster->max_concurrent));
+ }
+
+ while (hmaster->uvhub_quiesce)
+ cpu_relax();
if (cpu < UV_CPUS_PER_ACT_STATUS) {
mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0;
@@ -268,24 +557,108 @@
}
time1 = get_cycles();
do {
- tries++;
+ /*
+ * Every message from any given cpu gets a unique message
+ * sequence number. But retries use that same number.
+ * Our message may have timed out at the destination because
+ * all sw-ack resources are in use and there is a timeout
+ * pending there. In that case, our last send never got
+ * placed into the queue and we need to persist until it
+ * does.
+ *
+ * Make any retry a type MSG_RETRY so that the destination will
+ * free any resource held by a previous message from this cpu.
+ */
+ if (try == 0) {
+ /* use message type set by the caller the first time */
+ seq_number = bcp->message_number++;
+ } else {
+ /* use RETRY type on all the rest; same sequence */
+ bau_desc->header.msg_type = MSG_RETRY;
+ stat->s_retry_messages++;
+ }
+ bau_desc->header.sequence = seq_number;
index = (1UL << UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT) |
- cpu;
- uv_write_local_mmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index);
- completion_status = uv_wait_completion(bau_desc, mmr_offset,
- right_shift);
- } while (completion_status == FLUSH_RETRY);
- time2 = get_cycles();
- __get_cpu_var(ptcstats).sflush += (time2 - time1);
- if (tries > 1)
- __get_cpu_var(ptcstats).retriesok++;
+ bcp->uvhub_cpu;
+ bcp->send_message = get_cycles();
- if (completion_status == FLUSH_GIVEUP) {
+ uv_write_local_mmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index);
+
+ try++;
+ completion_status = uv_wait_completion(bau_desc, mmr_offset,
+ right_shift, this_cpu, bcp, smaster, try);
+
+ if (completion_status == FLUSH_RETRY_PLUGGED) {
+ /*
+ * Our retries may be blocked by all destination swack
+ * resources being consumed, and a timeout pending. In
+ * that case hardware immediately returns the ERROR
+ * that looks like a destination timeout.
+ */
+ udelay(TIMEOUT_DELAY);
+ bcp->plugged_tries++;
+ if (bcp->plugged_tries >= PLUGSB4RESET) {
+ bcp->plugged_tries = 0;
+ quiesce_local_uvhub(hmaster);
+ spin_lock(&hmaster->queue_lock);
+ uv_reset_with_ipi(&bau_desc->distribution,
+ this_cpu);
+ spin_unlock(&hmaster->queue_lock);
+ end_uvhub_quiesce(hmaster);
+ bcp->ipi_attempts++;
+ stat->s_resets_plug++;
+ }
+ } else if (completion_status == FLUSH_RETRY_TIMEOUT) {
+ hmaster->max_concurrent = 1;
+ bcp->timeout_tries++;
+ udelay(TIMEOUT_DELAY);
+ if (bcp->timeout_tries >= TIMEOUTSB4RESET) {
+ bcp->timeout_tries = 0;
+ quiesce_local_uvhub(hmaster);
+ spin_lock(&hmaster->queue_lock);
+ uv_reset_with_ipi(&bau_desc->distribution,
+ this_cpu);
+ spin_unlock(&hmaster->queue_lock);
+ end_uvhub_quiesce(hmaster);
+ bcp->ipi_attempts++;
+ stat->s_resets_timeout++;
+ }
+ }
+ if (bcp->ipi_attempts >= 3) {
+ bcp->ipi_attempts = 0;
+ completion_status = FLUSH_GIVEUP;
+ break;
+ }
+ cpu_relax();
+ } while ((completion_status == FLUSH_RETRY_PLUGGED) ||
+ (completion_status == FLUSH_RETRY_TIMEOUT));
+ time2 = get_cycles();
+
+ if ((completion_status == FLUSH_COMPLETE) && (bcp->conseccompletes > 5)
+ && (hmaster->max_concurrent < hmaster->max_concurrent_constant))
+ hmaster->max_concurrent++;
+
+ /*
+ * hold any cpu not timing out here; no other cpu currently held by
+ * the 'throttle' should enter the activation code
+ */
+ while (hmaster->uvhub_quiesce)
+ cpu_relax();
+ atomic_dec(&hmaster->active_descriptor_count);
+
+ /* guard against cycles wrap */
+ if (time2 > time1)
+ stat->s_time += (time2 - time1);
+ else
+ stat->s_requestor--; /* don't count this one */
+ if (completion_status == FLUSH_COMPLETE && try > 1)
+ stat->s_retriesok++;
+ else if (completion_status == FLUSH_GIVEUP) {
/*
* Cause the caller to do an IPI-style TLB shootdown on
- * the cpu's, all of which are still in the mask.
+ * the target cpu's, all of which are still in the mask.
*/
- __get_cpu_var(ptcstats).ptc_i++;
+ stat->s_giveup++;
return flush_mask;
}
@@ -294,18 +667,17 @@
* use the IPI method of shootdown on them.
*/
for_each_cpu(bit, flush_mask) {
- pnode = uv_cpu_to_pnode(bit);
- if (pnode == this_pnode)
+ uvhub = uv_cpu_to_blade_id(bit);
+ if (uvhub == this_uvhub)
continue;
cpumask_clear_cpu(bit, flush_mask);
}
if (!cpumask_empty(flush_mask))
return flush_mask;
+
return NULL;
}
-static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask);
-
/**
* uv_flush_tlb_others - globally purge translation cache of a virtual
* address or all TLB's
@@ -322,8 +694,8 @@
* The caller has derived the cpumask from the mm_struct. This function
* is called only if there are bits set in the mask. (e.g. flush_tlb_page())
*
- * The cpumask is converted into a nodemask of the nodes containing
- * the cpus.
+ * The cpumask is converted into a uvhubmask of the uvhubs containing
+ * those cpus.
*
* Note that this function should be called with preemption disabled.
*
@@ -335,52 +707,82 @@
struct mm_struct *mm,
unsigned long va, unsigned int cpu)
{
- struct cpumask *flush_mask = __get_cpu_var(uv_flush_tlb_mask);
- int i;
- int bit;
- int pnode;
- int uv_cpu;
- int this_pnode;
+ int remotes;
+ int tcpu;
+ int uvhub;
int locals = 0;
struct bau_desc *bau_desc;
+ struct cpumask *flush_mask;
+ struct ptc_stats *stat;
+ struct bau_control *bcp;
+ if (nobau)
+ return cpumask;
+
+ bcp = &per_cpu(bau_control, cpu);
+ /*
+ * Each sending cpu has a per-cpu mask which it fills from the caller's
+ * cpu mask. Only remote cpus are converted to uvhubs and copied.
+ */
+ flush_mask = (struct cpumask *)per_cpu(uv_flush_tlb_mask, cpu);
+ /*
+ * copy cpumask to flush_mask, removing current cpu
+ * (current cpu should already have been flushed by the caller and
+ * should never be returned if we return flush_mask)
+ */
cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu));
+ if (cpu_isset(cpu, *cpumask))
+ locals++; /* current cpu was targeted */
- uv_cpu = uv_blade_processor_id();
- this_pnode = uv_hub_info->pnode;
- bau_desc = __get_cpu_var(bau_control).descriptor_base;
- bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu;
+ bau_desc = bcp->descriptor_base;
+ bau_desc += UV_ITEMS_PER_DESCRIPTOR * bcp->uvhub_cpu;
- bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
-
- i = 0;
- for_each_cpu(bit, flush_mask) {
- pnode = uv_cpu_to_pnode(bit);
- BUG_ON(pnode > (UV_DISTRIBUTION_SIZE - 1));
- if (pnode == this_pnode) {
+ bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
+ remotes = 0;
+ for_each_cpu(tcpu, flush_mask) {
+ uvhub = uv_cpu_to_blade_id(tcpu);
+ if (uvhub == bcp->uvhub) {
locals++;
continue;
}
- bau_node_set(pnode - uv_partition_base_pnode,
- &bau_desc->distribution);
- i++;
+ bau_uvhub_set(uvhub, &bau_desc->distribution);
+ remotes++;
}
- if (i == 0) {
+ if (remotes == 0) {
/*
- * no off_node flushing; return status for local node
+ * No off_hub flushing; return status for local hub.
+ * Return the caller's mask if all were local (the current
+ * cpu may be in that mask).
*/
if (locals)
- return flush_mask;
+ return cpumask;
else
return NULL;
}
- __get_cpu_var(ptcstats).requestor++;
- __get_cpu_var(ptcstats).ntargeted += i;
+ stat = &per_cpu(ptcstats, cpu);
+ stat->s_requestor++;
+ stat->s_ntargcpu += remotes;
+ remotes = bau_uvhub_weight(&bau_desc->distribution);
+ stat->s_ntarguvhub += remotes;
+ if (remotes >= 16)
+ stat->s_ntarguvhub16++;
+ else if (remotes >= 8)
+ stat->s_ntarguvhub8++;
+ else if (remotes >= 4)
+ stat->s_ntarguvhub4++;
+ else if (remotes >= 2)
+ stat->s_ntarguvhub2++;
+ else
+ stat->s_ntarguvhub1++;
bau_desc->payload.address = va;
bau_desc->payload.sending_cpu = cpu;
- return uv_flush_send_and_wait(uv_cpu, this_pnode, bau_desc, flush_mask);
+ /*
+ * uv_flush_send_and_wait returns null if all cpu's were messaged, or
+ * the adjusted flush_mask if any cpu's were not messaged.
+ */
+ return uv_flush_send_and_wait(bau_desc, flush_mask, bcp);
}
/*
@@ -389,87 +791,70 @@
*
* We received a broadcast assist message.
*
- * Interrupts may have been disabled; this interrupt could represent
+ * Interrupts are disabled; this interrupt could represent
* the receipt of several messages.
*
- * All cores/threads on this node get this interrupt.
- * The last one to see it does the s/w ack.
+ * All cores/threads on this hub get this interrupt.
+ * The last one to see it does the software ack.
* (the resource will not be freed until noninterruptable cpus see this
- * interrupt; hardware will timeout the s/w ack and reply ERROR)
+ * interrupt; hardware may timeout the s/w ack and reply ERROR)
*/
void uv_bau_message_interrupt(struct pt_regs *regs)
{
- struct bau_payload_queue_entry *va_queue_first;
- struct bau_payload_queue_entry *va_queue_last;
- struct bau_payload_queue_entry *msg;
- struct pt_regs *old_regs = set_irq_regs(regs);
- cycles_t time1;
- cycles_t time2;
- int msg_slot;
- int sw_ack_slot;
- int fw;
int count = 0;
- unsigned long local_pnode;
+ cycles_t time_start;
+ struct bau_payload_queue_entry *msg;
+ struct bau_control *bcp;
+ struct ptc_stats *stat;
+ struct msg_desc msgdesc;
- ack_APIC_irq();
- exit_idle();
- irq_enter();
-
- time1 = get_cycles();
-
- local_pnode = uv_blade_to_pnode(uv_numa_blade_id());
-
- va_queue_first = __get_cpu_var(bau_control).va_queue_first;
- va_queue_last = __get_cpu_var(bau_control).va_queue_last;
-
- msg = __get_cpu_var(bau_control).bau_msg_head;
+ time_start = get_cycles();
+ bcp = &per_cpu(bau_control, smp_processor_id());
+ stat = &per_cpu(ptcstats, smp_processor_id());
+ msgdesc.va_queue_first = bcp->va_queue_first;
+ msgdesc.va_queue_last = bcp->va_queue_last;
+ msg = bcp->bau_msg_head;
while (msg->sw_ack_vector) {
count++;
- fw = msg->sw_ack_vector;
- msg_slot = msg - va_queue_first;
- sw_ack_slot = ffs(fw) - 1;
-
- uv_bau_process_message(msg, msg_slot, sw_ack_slot);
-
+ msgdesc.msg_slot = msg - msgdesc.va_queue_first;
+ msgdesc.sw_ack_slot = ffs(msg->sw_ack_vector) - 1;
+ msgdesc.msg = msg;
+ uv_bau_process_message(&msgdesc, bcp);
msg++;
- if (msg > va_queue_last)
- msg = va_queue_first;
- __get_cpu_var(bau_control).bau_msg_head = msg;
+ if (msg > msgdesc.va_queue_last)
+ msg = msgdesc.va_queue_first;
+ bcp->bau_msg_head = msg;
}
+ stat->d_time += (get_cycles() - time_start);
if (!count)
- __get_cpu_var(ptcstats).nomsg++;
+ stat->d_nomsg++;
else if (count > 1)
- __get_cpu_var(ptcstats).multmsg++;
-
- time2 = get_cycles();
- __get_cpu_var(ptcstats).dflush += (time2 - time1);
-
- irq_exit();
- set_irq_regs(old_regs);
+ stat->d_multmsg++;
+ ack_APIC_irq();
}
/*
* uv_enable_timeouts
*
- * Each target blade (i.e. blades that have cpu's) needs to have
+ * Each target uvhub (i.e. a uvhub that has no cpu's) needs to have
* shootdown message timeouts enabled. The timeout does not cause
* an interrupt, but causes an error message to be returned to
* the sender.
*/
static void uv_enable_timeouts(void)
{
- int blade;
- int nblades;
+ int uvhub;
+ int nuvhubs;
int pnode;
unsigned long mmr_image;
- nblades = uv_num_possible_blades();
+ nuvhubs = uv_num_possible_blades();
- for (blade = 0; blade < nblades; blade++) {
- if (!uv_blade_nr_possible_cpus(blade))
+ for (uvhub = 0; uvhub < nuvhubs; uvhub++) {
+ if (!uv_blade_nr_possible_cpus(uvhub))
continue;
- pnode = uv_blade_to_pnode(blade);
+ pnode = uv_blade_to_pnode(uvhub);
mmr_image =
uv_read_global_mmr64(pnode, UVH_LB_BAU_MISC_CONTROL);
/*
@@ -479,16 +864,16 @@
* To program the period, the SOFT_ACK_MODE must be off.
*/
mmr_image &= ~((unsigned long)1 <<
- UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT);
+ UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT);
uv_write_global_mmr64
(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
/*
* Set the 4-bit period.
*/
mmr_image &= ~((unsigned long)0xf <<
- UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT);
+ UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT);
mmr_image |= (UV_INTD_SOFT_ACK_TIMEOUT_PERIOD <<
- UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT);
+ UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT);
uv_write_global_mmr64
(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
/*
@@ -497,7 +882,7 @@
* indicated in bits 2:0 (7 causes all of them to timeout).
*/
mmr_image |= ((unsigned long)1 <<
- UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT);
+ UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT);
uv_write_global_mmr64
(pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image);
}
@@ -522,9 +907,20 @@
{
}
+static inline unsigned long long
+millisec_2_cycles(unsigned long millisec)
+{
+ unsigned long ns;
+ unsigned long long cyc;
+
+ ns = millisec * 1000;
+ cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id()));
+ return cyc;
+}
+
/*
- * Display the statistics thru /proc
- * data points to the cpu number
+ * Display the statistics thru /proc.
+ * 'data' points to the cpu number
*/
static int uv_ptc_seq_show(struct seq_file *file, void *data)
{
@@ -535,78 +931,155 @@
if (!cpu) {
seq_printf(file,
- "# cpu requestor requestee one all sretry dretry ptc_i ");
+ "# cpu sent stime numuvhubs numuvhubs16 numuvhubs8 ");
seq_printf(file,
- "sw_ack sflush dflush sok dnomsg dmult starget\n");
+ "numuvhubs4 numuvhubs2 numuvhubs1 numcpus dto ");
+ seq_printf(file,
+ "retries rok resetp resett giveup sto bz throt ");
+ seq_printf(file,
+ "sw_ack recv rtime all ");
+ seq_printf(file,
+ "one mult none retry canc nocan reset rcan\n");
}
if (cpu < num_possible_cpus() && cpu_online(cpu)) {
stat = &per_cpu(ptcstats, cpu);
- seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld ",
- cpu, stat->requestor,
- stat->requestee, stat->onetlb, stat->alltlb,
- stat->s_retry, stat->d_retry, stat->ptc_i);
- seq_printf(file, "%lx %ld %ld %ld %ld %ld %ld\n",
+ /* source side statistics */
+ seq_printf(file,
+ "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
+ cpu, stat->s_requestor, cycles_2_us(stat->s_time),
+ stat->s_ntarguvhub, stat->s_ntarguvhub16,
+ stat->s_ntarguvhub8, stat->s_ntarguvhub4,
+ stat->s_ntarguvhub2, stat->s_ntarguvhub1,
+ stat->s_ntargcpu, stat->s_dtimeout);
+ seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld ",
+ stat->s_retry_messages, stat->s_retriesok,
+ stat->s_resets_plug, stat->s_resets_timeout,
+ stat->s_giveup, stat->s_stimeout,
+ stat->s_busy, stat->s_throttles);
+ /* destination side statistics */
+ seq_printf(file,
+ "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n",
uv_read_global_mmr64(uv_cpu_to_pnode(cpu),
UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE),
- stat->sflush, stat->dflush,
- stat->retriesok, stat->nomsg,
- stat->multmsg, stat->ntargeted);
+ stat->d_requestee, cycles_2_us(stat->d_time),
+ stat->d_alltlb, stat->d_onetlb, stat->d_multmsg,
+ stat->d_nomsg, stat->d_retries, stat->d_canceled,
+ stat->d_nocanceled, stat->d_resets,
+ stat->d_rcanceled);
}
return 0;
}
/*
+ * -1: resetf the statistics
* 0: display meaning of the statistics
- * >0: retry limit
+ * >0: maximum concurrent active descriptors per uvhub (throttle)
*/
static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user,
size_t count, loff_t *data)
{
- long newmode;
+ int cpu;
+ long input_arg;
char optstr[64];
+ struct ptc_stats *stat;
+ struct bau_control *bcp;
if (count == 0 || count > sizeof(optstr))
return -EINVAL;
if (copy_from_user(optstr, user, count))
return -EFAULT;
optstr[count - 1] = '\0';
- if (strict_strtoul(optstr, 10, &newmode) < 0) {
+ if (strict_strtol(optstr, 10, &input_arg) < 0) {
printk(KERN_DEBUG "%s is invalid\n", optstr);
return -EINVAL;
}
- if (newmode == 0) {
+ if (input_arg == 0) {
printk(KERN_DEBUG "# cpu: cpu number\n");
+ printk(KERN_DEBUG "Sender statistics:\n");
printk(KERN_DEBUG
- "requestor: times this cpu was the flush requestor\n");
+ "sent: number of shootdown messages sent\n");
printk(KERN_DEBUG
- "requestee: times this cpu was requested to flush its TLBs\n");
+ "stime: time spent sending messages\n");
printk(KERN_DEBUG
- "one: times requested to flush a single address\n");
+ "numuvhubs: number of hubs targeted with shootdown\n");
printk(KERN_DEBUG
- "all: times requested to flush all TLB's\n");
+ "numuvhubs16: number times 16 or more hubs targeted\n");
printk(KERN_DEBUG
- "sretry: number of retries of source-side timeouts\n");
+ "numuvhubs8: number times 8 or more hubs targeted\n");
printk(KERN_DEBUG
- "dretry: number of retries of destination-side timeouts\n");
+ "numuvhubs4: number times 4 or more hubs targeted\n");
printk(KERN_DEBUG
- "ptc_i: times UV fell through to IPI-style flushes\n");
+ "numuvhubs2: number times 2 or more hubs targeted\n");
printk(KERN_DEBUG
- "sw_ack: image of UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE\n");
+ "numuvhubs1: number times 1 hub targeted\n");
printk(KERN_DEBUG
- "sflush_us: cycles spent in uv_flush_tlb_others()\n");
+ "numcpus: number of cpus targeted with shootdown\n");
printk(KERN_DEBUG
- "dflush_us: cycles spent in handling flush requests\n");
- printk(KERN_DEBUG "sok: successes on retry\n");
- printk(KERN_DEBUG "dnomsg: interrupts with no message\n");
+ "dto: number of destination timeouts\n");
printk(KERN_DEBUG
- "dmult: interrupts with multiple messages\n");
- printk(KERN_DEBUG "starget: nodes targeted\n");
+ "retries: destination timeout retries sent\n");
+ printk(KERN_DEBUG
+ "rok: : destination timeouts successfully retried\n");
+ printk(KERN_DEBUG
+ "resetp: ipi-style resource resets for plugs\n");
+ printk(KERN_DEBUG
+ "resett: ipi-style resource resets for timeouts\n");
+ printk(KERN_DEBUG
+ "giveup: fall-backs to ipi-style shootdowns\n");
+ printk(KERN_DEBUG
+ "sto: number of source timeouts\n");
+ printk(KERN_DEBUG
+ "bz: number of stay-busy's\n");
+ printk(KERN_DEBUG
+ "throt: number times spun in throttle\n");
+ printk(KERN_DEBUG "Destination side statistics:\n");
+ printk(KERN_DEBUG
+ "sw_ack: image of UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE\n");
+ printk(KERN_DEBUG
+ "recv: shootdown messages received\n");
+ printk(KERN_DEBUG
+ "rtime: time spent processing messages\n");
+ printk(KERN_DEBUG
+ "all: shootdown all-tlb messages\n");
+ printk(KERN_DEBUG
+ "one: shootdown one-tlb messages\n");
+ printk(KERN_DEBUG
+ "mult: interrupts that found multiple messages\n");
+ printk(KERN_DEBUG
+ "none: interrupts that found no messages\n");
+ printk(KERN_DEBUG
+ "retry: number of retry messages processed\n");
+ printk(KERN_DEBUG
+ "canc: number messages canceled by retries\n");
+ printk(KERN_DEBUG
+ "nocan: number retries that found nothing to cancel\n");
+ printk(KERN_DEBUG
+ "reset: number of ipi-style reset requests processed\n");
+ printk(KERN_DEBUG
+ "rcan: number messages canceled by reset requests\n");
+ } else if (input_arg == -1) {
+ for_each_present_cpu(cpu) {
+ stat = &per_cpu(ptcstats, cpu);
+ memset(stat, 0, sizeof(struct ptc_stats));
+ }
} else {
- uv_bau_retry_limit = newmode;
- printk(KERN_DEBUG "timeout retry limit:%d\n",
- uv_bau_retry_limit);
+ uv_bau_max_concurrent = input_arg;
+ bcp = &per_cpu(bau_control, smp_processor_id());
+ if (uv_bau_max_concurrent < 1 ||
+ uv_bau_max_concurrent > bcp->cpus_in_uvhub) {
+ printk(KERN_DEBUG
+ "Error: BAU max concurrent %d; %d is invalid\n",
+ bcp->max_concurrent, uv_bau_max_concurrent);
+ return -EINVAL;
+ }
+ printk(KERN_DEBUG "Set BAU max concurrent:%d\n",
+ uv_bau_max_concurrent);
+ for_each_present_cpu(cpu) {
+ bcp = &per_cpu(bau_control, cpu);
+ bcp->max_concurrent = uv_bau_max_concurrent;
+ }
}
return count;
@@ -650,79 +1123,30 @@
}
/*
- * begin the initialization of the per-blade control structures
- */
-static struct bau_control * __init uv_table_bases_init(int blade, int node)
-{
- int i;
- struct bau_msg_status *msp;
- struct bau_control *bau_tabp;
-
- bau_tabp =
- kmalloc_node(sizeof(struct bau_control), GFP_KERNEL, node);
- BUG_ON(!bau_tabp);
-
- bau_tabp->msg_statuses =
- kmalloc_node(sizeof(struct bau_msg_status) *
- DEST_Q_SIZE, GFP_KERNEL, node);
- BUG_ON(!bau_tabp->msg_statuses);
-
- for (i = 0, msp = bau_tabp->msg_statuses; i < DEST_Q_SIZE; i++, msp++)
- bau_cpubits_clear(&msp->seen_by, (int)
- uv_blade_nr_possible_cpus(blade));
-
- uv_bau_table_bases[blade] = bau_tabp;
-
- return bau_tabp;
-}
-
-/*
- * finish the initialization of the per-blade control structures
- */
-static void __init
-uv_table_bases_finish(int blade,
- struct bau_control *bau_tablesp,
- struct bau_desc *adp)
-{
- struct bau_control *bcp;
- int cpu;
-
- for_each_present_cpu(cpu) {
- if (blade != uv_cpu_to_blade_id(cpu))
- continue;
-
- bcp = (struct bau_control *)&per_cpu(bau_control, cpu);
- bcp->bau_msg_head = bau_tablesp->va_queue_first;
- bcp->va_queue_first = bau_tablesp->va_queue_first;
- bcp->va_queue_last = bau_tablesp->va_queue_last;
- bcp->msg_statuses = bau_tablesp->msg_statuses;
- bcp->descriptor_base = adp;
- }
-}
-
-/*
* initialize the sending side's sending buffers
*/
-static struct bau_desc * __init
+static void
uv_activation_descriptor_init(int node, int pnode)
{
int i;
+ int cpu;
unsigned long pa;
unsigned long m;
unsigned long n;
- struct bau_desc *adp;
- struct bau_desc *ad2;
+ struct bau_desc *bau_desc;
+ struct bau_desc *bd2;
+ struct bau_control *bcp;
/*
* each bau_desc is 64 bytes; there are 8 (UV_ITEMS_PER_DESCRIPTOR)
- * per cpu; and up to 32 (UV_ADP_SIZE) cpu's per blade
+ * per cpu; and up to 32 (UV_ADP_SIZE) cpu's per uvhub
*/
- adp = (struct bau_desc *)kmalloc_node(sizeof(struct bau_desc)*
+ bau_desc = (struct bau_desc *)kmalloc_node(sizeof(struct bau_desc)*
UV_ADP_SIZE*UV_ITEMS_PER_DESCRIPTOR, GFP_KERNEL, node);
- BUG_ON(!adp);
+ BUG_ON(!bau_desc);
- pa = uv_gpa(adp); /* need the real nasid*/
- n = uv_gpa_to_pnode(pa);
+ pa = uv_gpa(bau_desc); /* need the real nasid*/
+ n = pa >> uv_nshift;
m = pa & uv_mmask;
uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE,
@@ -731,96 +1155,188 @@
/*
* initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
* cpu even though we only use the first one; one descriptor can
- * describe a broadcast to 256 nodes.
+ * describe a broadcast to 256 uv hubs.
*/
- for (i = 0, ad2 = adp; i < (UV_ADP_SIZE*UV_ITEMS_PER_DESCRIPTOR);
- i++, ad2++) {
- memset(ad2, 0, sizeof(struct bau_desc));
- ad2->header.sw_ack_flag = 1;
+ for (i = 0, bd2 = bau_desc; i < (UV_ADP_SIZE*UV_ITEMS_PER_DESCRIPTOR);
+ i++, bd2++) {
+ memset(bd2, 0, sizeof(struct bau_desc));
+ bd2->header.sw_ack_flag = 1;
/*
- * base_dest_nodeid is the first node in the partition, so
- * the bit map will indicate partition-relative node numbers.
- * note that base_dest_nodeid is actually a nasid.
+ * base_dest_nodeid is the nasid (pnode<<1) of the first uvhub
+ * in the partition. The bit map will indicate uvhub numbers,
+ * which are 0-N in a partition. Pnodes are unique system-wide.
*/
- ad2->header.base_dest_nodeid = uv_partition_base_pnode << 1;
- ad2->header.dest_subnodeid = 0x10; /* the LB */
- ad2->header.command = UV_NET_ENDPOINT_INTD;
- ad2->header.int_both = 1;
+ bd2->header.base_dest_nodeid = uv_partition_base_pnode << 1;
+ bd2->header.dest_subnodeid = 0x10; /* the LB */
+ bd2->header.command = UV_NET_ENDPOINT_INTD;
+ bd2->header.int_both = 1;
/*
* all others need to be set to zero:
* fairness chaining multilevel count replied_to
*/
}
- return adp;
+ for_each_present_cpu(cpu) {
+ if (pnode != uv_blade_to_pnode(uv_cpu_to_blade_id(cpu)))
+ continue;
+ bcp = &per_cpu(bau_control, cpu);
+ bcp->descriptor_base = bau_desc;
+ }
}
/*
* initialize the destination side's receiving buffers
+ * entered for each uvhub in the partition
+ * - node is first node (kernel memory notion) on the uvhub
+ * - pnode is the uvhub's physical identifier
*/
-static struct bau_payload_queue_entry * __init
-uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp)
+static void
+uv_payload_queue_init(int node, int pnode)
{
- struct bau_payload_queue_entry *pqp;
- unsigned long pa;
int pn;
+ int cpu;
char *cp;
+ unsigned long pa;
+ struct bau_payload_queue_entry *pqp;
+ struct bau_payload_queue_entry *pqp_malloc;
+ struct bau_control *bcp;
pqp = (struct bau_payload_queue_entry *) kmalloc_node(
(DEST_Q_SIZE + 1) * sizeof(struct bau_payload_queue_entry),
GFP_KERNEL, node);
BUG_ON(!pqp);
+ pqp_malloc = pqp;
cp = (char *)pqp + 31;
pqp = (struct bau_payload_queue_entry *)(((unsigned long)cp >> 5) << 5);
- bau_tablesp->va_queue_first = pqp;
+
+ for_each_present_cpu(cpu) {
+ if (pnode != uv_cpu_to_pnode(cpu))
+ continue;
+ /* for every cpu on this pnode: */
+ bcp = &per_cpu(bau_control, cpu);
+ bcp->va_queue_first = pqp;
+ bcp->bau_msg_head = pqp;
+ bcp->va_queue_last = pqp + (DEST_Q_SIZE - 1);
+ }
/*
* need the pnode of where the memory was really allocated
*/
pa = uv_gpa(pqp);
- pn = uv_gpa_to_pnode(pa);
+ pn = pa >> uv_nshift;
uv_write_global_mmr64(pnode,
UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST,
((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) |
uv_physnodeaddr(pqp));
uv_write_global_mmr64(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL,
uv_physnodeaddr(pqp));
- bau_tablesp->va_queue_last = pqp + (DEST_Q_SIZE - 1);
uv_write_global_mmr64(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST,
(unsigned long)
- uv_physnodeaddr(bau_tablesp->va_queue_last));
+ uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1)));
+ /* in effect, all msg_type's are set to MSG_NOOP */
memset(pqp, 0, sizeof(struct bau_payload_queue_entry) * DEST_Q_SIZE);
-
- return pqp;
}
/*
- * Initialization of each UV blade's structures
+ * Initialization of each UV hub's structures
*/
-static int __init uv_init_blade(int blade)
+static void __init uv_init_uvhub(int uvhub, int vector)
{
int node;
int pnode;
- unsigned long pa;
unsigned long apicid;
- struct bau_desc *adp;
- struct bau_payload_queue_entry *pqp;
- struct bau_control *bau_tablesp;
- node = blade_to_first_node(blade);
- bau_tablesp = uv_table_bases_init(blade, node);
- pnode = uv_blade_to_pnode(blade);
- adp = uv_activation_descriptor_init(node, pnode);
- pqp = uv_payload_queue_init(node, pnode, bau_tablesp);
- uv_table_bases_finish(blade, bau_tablesp, adp);
+ node = uvhub_to_first_node(uvhub);
+ pnode = uv_blade_to_pnode(uvhub);
+ uv_activation_descriptor_init(node, pnode);
+ uv_payload_queue_init(node, pnode);
/*
* the below initialization can't be in firmware because the
* messaging IRQ will be determined by the OS
*/
- apicid = blade_to_first_apicid(blade);
- pa = uv_read_global_mmr64(pnode, UVH_BAU_DATA_CONFIG);
+ apicid = uvhub_to_first_apicid(uvhub);
uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
- ((apicid << 32) | UV_BAU_MESSAGE));
- return 0;
+ ((apicid << 32) | vector));
+}
+
+/*
+ * initialize the bau_control structure for each cpu
+ */
+static void uv_init_per_cpu(int nuvhubs)
+{
+ int i, j, k;
+ int cpu;
+ int pnode;
+ int uvhub;
+ short socket = 0;
+ struct bau_control *bcp;
+ struct uvhub_desc *bdp;
+ struct socket_desc *sdp;
+ struct bau_control *hmaster = NULL;
+ struct bau_control *smaster = NULL;
+ struct socket_desc {
+ short num_cpus;
+ short cpu_number[16];
+ };
+ struct uvhub_desc {
+ short num_sockets;
+ short num_cpus;
+ short uvhub;
+ short pnode;
+ struct socket_desc socket[2];
+ };
+ struct uvhub_desc *uvhub_descs;
+
+ uvhub_descs = (struct uvhub_desc *)
+ kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL);
+ memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc));
+ for_each_present_cpu(cpu) {
+ bcp = &per_cpu(bau_control, cpu);
+ memset(bcp, 0, sizeof(struct bau_control));
+ spin_lock_init(&bcp->masks_lock);
+ bcp->max_concurrent = uv_bau_max_concurrent;
+ pnode = uv_cpu_hub_info(cpu)->pnode;
+ uvhub = uv_cpu_hub_info(cpu)->numa_blade_id;
+ bdp = &uvhub_descs[uvhub];
+ bdp->num_cpus++;
+ bdp->uvhub = uvhub;
+ bdp->pnode = pnode;
+ /* time interval to catch a hardware stay-busy bug */
+ bcp->timeout_interval = millisec_2_cycles(3);
+ /* kludge: assume uv_hub.h is constant */
+ socket = (cpu_physical_id(cpu)>>5)&1;
+ if (socket >= bdp->num_sockets)
+ bdp->num_sockets = socket+1;
+ sdp = &bdp->socket[socket];
+ sdp->cpu_number[sdp->num_cpus] = cpu;
+ sdp->num_cpus++;
+ }
+ socket = 0;
+ for_each_possible_blade(uvhub) {
+ bdp = &uvhub_descs[uvhub];
+ for (i = 0; i < bdp->num_sockets; i++) {
+ sdp = &bdp->socket[i];
+ for (j = 0; j < sdp->num_cpus; j++) {
+ cpu = sdp->cpu_number[j];
+ bcp = &per_cpu(bau_control, cpu);
+ bcp->cpu = cpu;
+ if (j == 0) {
+ smaster = bcp;
+ if (i == 0)
+ hmaster = bcp;
+ }
+ bcp->cpus_in_uvhub = bdp->num_cpus;
+ bcp->cpus_in_socket = sdp->num_cpus;
+ bcp->socket_master = smaster;
+ bcp->uvhub_master = hmaster;
+ for (k = 0; k < DEST_Q_SIZE; k++)
+ bcp->socket_acknowledge_count[k] = 0;
+ bcp->uvhub_cpu =
+ uv_cpu_hub_info(cpu)->blade_processor_id;
+ }
+ socket++;
+ }
+ }
+ kfree(uvhub_descs);
}
/*
@@ -828,38 +1344,54 @@
*/
static int __init uv_bau_init(void)
{
- int blade;
- int nblades;
+ int uvhub;
+ int pnode;
+ int nuvhubs;
int cur_cpu;
+ int vector;
+ unsigned long mmr;
if (!is_uv_system())
return 0;
+ if (nobau)
+ return 0;
+
for_each_possible_cpu(cur_cpu)
zalloc_cpumask_var_node(&per_cpu(uv_flush_tlb_mask, cur_cpu),
GFP_KERNEL, cpu_to_node(cur_cpu));
- uv_bau_retry_limit = 1;
+ uv_bau_max_concurrent = MAX_BAU_CONCURRENT;
+ uv_nshift = uv_hub_info->m_val;
uv_mmask = (1UL << uv_hub_info->m_val) - 1;
- nblades = uv_num_possible_blades();
+ nuvhubs = uv_num_possible_blades();
- uv_bau_table_bases = (struct bau_control **)
- kmalloc(nblades * sizeof(struct bau_control *), GFP_KERNEL);
- BUG_ON(!uv_bau_table_bases);
+ uv_init_per_cpu(nuvhubs);
uv_partition_base_pnode = 0x7fffffff;
- for (blade = 0; blade < nblades; blade++)
- if (uv_blade_nr_possible_cpus(blade) &&
- (uv_blade_to_pnode(blade) < uv_partition_base_pnode))
- uv_partition_base_pnode = uv_blade_to_pnode(blade);
- for (blade = 0; blade < nblades; blade++)
- if (uv_blade_nr_possible_cpus(blade))
- uv_init_blade(blade);
+ for (uvhub = 0; uvhub < nuvhubs; uvhub++)
+ if (uv_blade_nr_possible_cpus(uvhub) &&
+ (uv_blade_to_pnode(uvhub) < uv_partition_base_pnode))
+ uv_partition_base_pnode = uv_blade_to_pnode(uvhub);
- alloc_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1);
+ vector = UV_BAU_MESSAGE;
+ for_each_possible_blade(uvhub)
+ if (uv_blade_nr_possible_cpus(uvhub))
+ uv_init_uvhub(uvhub, vector);
+
uv_enable_timeouts();
+ alloc_intr_gate(vector, uv_bau_message_intr1);
+
+ for_each_possible_blade(uvhub) {
+ pnode = uv_blade_to_pnode(uvhub);
+ /* INIT the bau */
+ uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL,
+ ((unsigned long)1 << 63));
+ mmr = 1; /* should be 1 to broadcast to both sockets */
+ uv_write_global_mmr64(pnode, UVH_BAU_DATA_BROADCAST, mmr);
+ }
return 0;
}
-__initcall(uv_bau_init);
-__initcall(uv_ptc_init);
+core_initcall(uv_bau_init);
+core_initcall(uv_ptc_init);
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 36f1bd9..02cfb9b 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -108,15 +108,6 @@
dec_preempt_count();
}
-#ifdef CONFIG_X86_32
-static inline void
-die_if_kernel(const char *str, struct pt_regs *regs, long err)
-{
- if (!user_mode_vm(regs))
- die(str, regs, err);
-}
-#endif
-
static void __kprobes
do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
long error_code, siginfo_t *info)
@@ -585,55 +576,67 @@
return;
}
-#ifdef CONFIG_X86_64
-static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
-{
- if (fixup_exception(regs))
- return 1;
-
- notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
- /* Illegal floating point operation in the kernel */
- current->thread.trap_no = trapnr;
- die(str, regs, 0);
- return 0;
-}
-#endif
-
/*
* Note that we play around with the 'TS' bit in an attempt to get
* the correct behaviour even in the presence of the asynchronous
* IRQ13 behaviour
*/
-void math_error(void __user *ip)
+void math_error(struct pt_regs *regs, int error_code, int trapnr)
{
- struct task_struct *task;
+ struct task_struct *task = current;
siginfo_t info;
- unsigned short cwd, swd, err;
+ unsigned short err;
+ char *str = (trapnr == 16) ? "fpu exception" : "simd exception";
+
+ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)
+ return;
+ conditional_sti(regs);
+
+ if (!user_mode_vm(regs))
+ {
+ if (!fixup_exception(regs)) {
+ task->thread.error_code = error_code;
+ task->thread.trap_no = trapnr;
+ die(str, regs, error_code);
+ }
+ return;
+ }
/*
* Save the info for the exception handler and clear the error.
*/
- task = current;
save_init_fpu(task);
- task->thread.trap_no = 16;
- task->thread.error_code = 0;
+ task->thread.trap_no = trapnr;
+ task->thread.error_code = error_code;
info.si_signo = SIGFPE;
info.si_errno = 0;
- info.si_addr = ip;
- /*
- * (~cwd & swd) will mask out exceptions that are not set to unmasked
- * status. 0x3f is the exception bits in these regs, 0x200 is the
- * C1 reg you need in case of a stack fault, 0x040 is the stack
- * fault bit. We should only be taking one exception at a time,
- * so if this combination doesn't produce any single exception,
- * then we have a bad program that isn't synchronizing its FPU usage
- * and it will suffer the consequences since we won't be able to
- * fully reproduce the context of the exception
- */
- cwd = get_fpu_cwd(task);
- swd = get_fpu_swd(task);
+ info.si_addr = (void __user *)regs->ip;
+ if (trapnr == 16) {
+ unsigned short cwd, swd;
+ /*
+ * (~cwd & swd) will mask out exceptions that are not set to unmasked
+ * status. 0x3f is the exception bits in these regs, 0x200 is the
+ * C1 reg you need in case of a stack fault, 0x040 is the stack
+ * fault bit. We should only be taking one exception at a time,
+ * so if this combination doesn't produce any single exception,
+ * then we have a bad program that isn't synchronizing its FPU usage
+ * and it will suffer the consequences since we won't be able to
+ * fully reproduce the context of the exception
+ */
+ cwd = get_fpu_cwd(task);
+ swd = get_fpu_swd(task);
- err = swd & ~cwd;
+ err = swd & ~cwd;
+ } else {
+ /*
+ * The SIMD FPU exceptions are handled a little differently, as there
+ * is only a single status/control register. Thus, to determine which
+ * unmasked exception was caught we must mask the exception mask bits
+ * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+ */
+ unsigned short mxcsr = get_fpu_mxcsr(task);
+ err = ~(mxcsr >> 7) & mxcsr;
+ }
if (err & 0x001) { /* Invalid op */
/*
@@ -662,97 +665,17 @@
dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
{
- conditional_sti(regs);
-
#ifdef CONFIG_X86_32
ignore_fpu_irq = 1;
-#else
- if (!user_mode(regs) &&
- kernel_math_error(regs, "kernel x87 math error", 16))
- return;
#endif
- math_error((void __user *)regs->ip);
-}
-
-static void simd_math_error(void __user *ip)
-{
- struct task_struct *task;
- siginfo_t info;
- unsigned short mxcsr;
-
- /*
- * Save the info for the exception handler and clear the error.
- */
- task = current;
- save_init_fpu(task);
- task->thread.trap_no = 19;
- task->thread.error_code = 0;
- info.si_signo = SIGFPE;
- info.si_errno = 0;
- info.si_code = __SI_FAULT;
- info.si_addr = ip;
- /*
- * The SIMD FPU exceptions are handled a little differently, as there
- * is only a single status/control register. Thus, to determine which
- * unmasked exception was caught we must mask the exception mask bits
- * at 0x1f80, and then use these to mask the exception bits at 0x3f.
- */
- mxcsr = get_fpu_mxcsr(task);
- switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
- case 0x000:
- default:
- break;
- case 0x001: /* Invalid Op */
- info.si_code = FPE_FLTINV;
- break;
- case 0x002: /* Denormalize */
- case 0x010: /* Underflow */
- info.si_code = FPE_FLTUND;
- break;
- case 0x004: /* Zero Divide */
- info.si_code = FPE_FLTDIV;
- break;
- case 0x008: /* Overflow */
- info.si_code = FPE_FLTOVF;
- break;
- case 0x020: /* Precision */
- info.si_code = FPE_FLTRES;
- break;
- }
- force_sig_info(SIGFPE, &info, task);
+ math_error(regs, error_code, 16);
}
dotraplinkage void
do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
{
- conditional_sti(regs);
-
-#ifdef CONFIG_X86_32
- if (cpu_has_xmm) {
- /* Handle SIMD FPU exceptions on PIII+ processors. */
- ignore_fpu_irq = 1;
- simd_math_error((void __user *)regs->ip);
- return;
- }
- /*
- * Handle strange cache flush from user space exception
- * in all other cases. This is undocumented behaviour.
- */
- if (regs->flags & X86_VM_MASK) {
- handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
- return;
- }
- current->thread.trap_no = 19;
- current->thread.error_code = error_code;
- die_if_kernel("cache flush denied", regs, error_code);
- force_sig(SIGSEGV, current);
-#else
- if (!user_mode(regs) &&
- kernel_math_error(regs, "kernel simd math error", 19))
- return;
- simd_math_error((void __user *)regs->ip);
-#endif
+ math_error(regs, error_code, 19);
}
dotraplinkage void
diff --git a/arch/x86/kernel/uv_irq.c b/arch/x86/kernel/uv_irq.c
index 1d40336..1132129 100644
--- a/arch/x86/kernel/uv_irq.c
+++ b/arch/x86/kernel/uv_irq.c
@@ -44,7 +44,7 @@
ack_APIC_irq();
}
-struct irq_chip uv_irq_chip = {
+static struct irq_chip uv_irq_chip = {
.name = "UV-CORE",
.startup = uv_noop_ret,
.shutdown = uv_noop,
@@ -141,7 +141,7 @@
*/
static int
arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
- unsigned long mmr_offset, int restrict)
+ unsigned long mmr_offset, int limit)
{
const struct cpumask *eligible_cpu = cpumask_of(cpu);
struct irq_desc *desc = irq_to_desc(irq);
@@ -160,7 +160,7 @@
if (err != 0)
return err;
- if (restrict == UV_AFFINITY_CPU)
+ if (limit == UV_AFFINITY_CPU)
desc->status |= IRQ_NO_BALANCING;
else
desc->status |= IRQ_MOVE_PCNTXT;
@@ -214,7 +214,7 @@
unsigned long mmr_value;
struct uv_IO_APIC_route_entry *entry;
unsigned long mmr_offset;
- unsigned mmr_pnode;
+ int mmr_pnode;
if (set_desc_affinity(desc, mask, &dest))
return -1;
@@ -248,7 +248,7 @@
* interrupt is raised.
*/
int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
- unsigned long mmr_offset, int restrict)
+ unsigned long mmr_offset, int limit)
{
int irq, ret;
@@ -258,7 +258,7 @@
return -EBUSY;
ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset,
- restrict);
+ limit);
if (ret == irq)
uv_set_irq_2_mmr_info(irq, mmr_offset, mmr_blade);
else
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 693920b..1b950d1 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -54,7 +54,6 @@
EXPORT_SYMBOL(__memcpy);
EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(init_level4_pgt);
#ifndef CONFIG_PARAVIRT
EXPORT_SYMBOL(native_load_gs_index);
#endif
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 782c3a36..37e68fc 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -99,7 +99,7 @@
if (err)
return err;
- if (task_thread_info(tsk)->status & TS_XSAVE)
+ if (use_xsave())
err = xsave_user(buf);
else
err = fxsave_user(buf);
@@ -109,14 +109,14 @@
task_thread_info(tsk)->status &= ~TS_USEDFPU;
stts();
} else {
- if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
+ if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
xstate_size))
return -1;
}
clear_used_math(); /* trigger finit */
- if (task_thread_info(tsk)->status & TS_XSAVE) {
+ if (use_xsave()) {
struct _fpstate __user *fx = buf;
struct _xstate __user *x = buf;
u64 xstate_bv;
@@ -225,7 +225,7 @@
clts();
task_thread_info(current)->status |= TS_USEDFPU;
}
- if (task_thread_info(tsk)->status & TS_XSAVE)
+ if (use_xsave())
err = restore_user_xstate(buf);
else
err = fxrstor_checking((__force struct i387_fxsave_struct *)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 2ba5820..737361f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2067,7 +2067,7 @@
static int iret_interception(struct vcpu_svm *svm)
{
++svm->vcpu.stat.nmi_window_exits;
- svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET);
+ svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_IRET);
svm->vcpu.arch.hflags |= HF_IRET_MASK;
return 1;
}
@@ -2479,7 +2479,7 @@
svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
vcpu->arch.hflags |= HF_NMI_MASK;
- svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET);
+ svm->vmcb->control.intercept |= (1ULL << INTERCEPT_IRET);
++vcpu->stat.nmi_injections;
}
@@ -2539,10 +2539,10 @@
if (masked) {
svm->vcpu.arch.hflags |= HF_NMI_MASK;
- svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET);
+ svm->vmcb->control.intercept |= (1ULL << INTERCEPT_IRET);
} else {
svm->vcpu.arch.hflags &= ~HF_NMI_MASK;
- svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET);
+ svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_IRET);
}
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 32022a8..edca080 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2703,8 +2703,7 @@
return 0;
return !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
- (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS |
- GUEST_INTR_STATE_NMI));
+ (GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_NMI));
}
static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 73d854c..dd9bc8f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1713,6 +1713,7 @@
if (copy_from_user(cpuid_entries, entries,
cpuid->nent * sizeof(struct kvm_cpuid_entry)))
goto out_free;
+ vcpu_load(vcpu);
for (i = 0; i < cpuid->nent; i++) {
vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function;
vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax;
@@ -1730,6 +1731,7 @@
r = 0;
kvm_apic_set_version(vcpu);
kvm_x86_ops->cpuid_update(vcpu);
+ vcpu_put(vcpu);
out_free:
vfree(cpuid_entries);
@@ -1750,9 +1752,11 @@
if (copy_from_user(&vcpu->arch.cpuid_entries, entries,
cpuid->nent * sizeof(struct kvm_cpuid_entry2)))
goto out;
+ vcpu_load(vcpu);
vcpu->arch.cpuid_nent = cpuid->nent;
kvm_apic_set_version(vcpu);
kvm_x86_ops->cpuid_update(vcpu);
+ vcpu_put(vcpu);
return 0;
out:
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index cbaf8f2..f871e04 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -26,11 +26,12 @@
ifeq ($(CONFIG_X86_32),y)
obj-y += atomic64_32.o
+ lib-y += atomic64_cx8_32.o
lib-y += checksum_32.o
lib-y += strstr_32.o
lib-y += semaphore_32.o string_32.o
ifneq ($(CONFIG_X86_CMPXCHG64),y)
- lib-y += cmpxchg8b_emu.o
+ lib-y += cmpxchg8b_emu.o atomic64_386_32.o
endif
lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o
else
diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c
index 824fa0b..540179e 100644
--- a/arch/x86/lib/atomic64_32.c
+++ b/arch/x86/lib/atomic64_32.c
@@ -6,225 +6,54 @@
#include <asm/cmpxchg.h>
#include <asm/atomic.h>
-static noinline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new)
-{
- u32 low = new;
- u32 high = new >> 32;
+long long atomic64_read_cx8(long long, const atomic64_t *v);
+EXPORT_SYMBOL(atomic64_read_cx8);
+long long atomic64_set_cx8(long long, const atomic64_t *v);
+EXPORT_SYMBOL(atomic64_set_cx8);
+long long atomic64_xchg_cx8(long long, unsigned high);
+EXPORT_SYMBOL(atomic64_xchg_cx8);
+long long atomic64_add_return_cx8(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_add_return_cx8);
+long long atomic64_sub_return_cx8(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_sub_return_cx8);
+long long atomic64_inc_return_cx8(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_inc_return_cx8);
+long long atomic64_dec_return_cx8(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_dec_return_cx8);
+long long atomic64_dec_if_positive_cx8(atomic64_t *v);
+EXPORT_SYMBOL(atomic64_dec_if_positive_cx8);
+int atomic64_inc_not_zero_cx8(atomic64_t *v);
+EXPORT_SYMBOL(atomic64_inc_not_zero_cx8);
+int atomic64_add_unless_cx8(atomic64_t *v, long long a, long long u);
+EXPORT_SYMBOL(atomic64_add_unless_cx8);
- asm volatile(
- LOCK_PREFIX "cmpxchg8b %1\n"
- : "+A" (old), "+m" (*ptr)
- : "b" (low), "c" (high)
- );
- return old;
-}
-
-u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val)
-{
- return cmpxchg8b(&ptr->counter, old_val, new_val);
-}
-EXPORT_SYMBOL(atomic64_cmpxchg);
-
-/**
- * atomic64_xchg - xchg atomic64 variable
- * @ptr: pointer to type atomic64_t
- * @new_val: value to assign
- *
- * Atomically xchgs the value of @ptr to @new_val and returns
- * the old value.
- */
-u64 atomic64_xchg(atomic64_t *ptr, u64 new_val)
-{
- /*
- * Try first with a (possibly incorrect) assumption about
- * what we have there. We'll do two loops most likely,
- * but we'll get an ownership MESI transaction straight away
- * instead of a read transaction followed by a
- * flush-for-ownership transaction:
- */
- u64 old_val, real_val = 0;
-
- do {
- old_val = real_val;
-
- real_val = atomic64_cmpxchg(ptr, old_val, new_val);
-
- } while (real_val != old_val);
-
- return old_val;
-}
-EXPORT_SYMBOL(atomic64_xchg);
-
-/**
- * atomic64_set - set atomic64 variable
- * @ptr: pointer to type atomic64_t
- * @new_val: value to assign
- *
- * Atomically sets the value of @ptr to @new_val.
- */
-void atomic64_set(atomic64_t *ptr, u64 new_val)
-{
- atomic64_xchg(ptr, new_val);
-}
-EXPORT_SYMBOL(atomic64_set);
-
-/**
-EXPORT_SYMBOL(atomic64_read);
- * atomic64_add_return - add and return
- * @delta: integer value to add
- * @ptr: pointer to type atomic64_t
- *
- * Atomically adds @delta to @ptr and returns @delta + *@ptr
- */
-noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr)
-{
- /*
- * Try first with a (possibly incorrect) assumption about
- * what we have there. We'll do two loops most likely,
- * but we'll get an ownership MESI transaction straight away
- * instead of a read transaction followed by a
- * flush-for-ownership transaction:
- */
- u64 old_val, new_val, real_val = 0;
-
- do {
- old_val = real_val;
- new_val = old_val + delta;
-
- real_val = atomic64_cmpxchg(ptr, old_val, new_val);
-
- } while (real_val != old_val);
-
- return new_val;
-}
-EXPORT_SYMBOL(atomic64_add_return);
-
-u64 atomic64_sub_return(u64 delta, atomic64_t *ptr)
-{
- return atomic64_add_return(-delta, ptr);
-}
-EXPORT_SYMBOL(atomic64_sub_return);
-
-u64 atomic64_inc_return(atomic64_t *ptr)
-{
- return atomic64_add_return(1, ptr);
-}
-EXPORT_SYMBOL(atomic64_inc_return);
-
-u64 atomic64_dec_return(atomic64_t *ptr)
-{
- return atomic64_sub_return(1, ptr);
-}
-EXPORT_SYMBOL(atomic64_dec_return);
-
-/**
- * atomic64_add - add integer to atomic64 variable
- * @delta: integer value to add
- * @ptr: pointer to type atomic64_t
- *
- * Atomically adds @delta to @ptr.
- */
-void atomic64_add(u64 delta, atomic64_t *ptr)
-{
- atomic64_add_return(delta, ptr);
-}
-EXPORT_SYMBOL(atomic64_add);
-
-/**
- * atomic64_sub - subtract the atomic64 variable
- * @delta: integer value to subtract
- * @ptr: pointer to type atomic64_t
- *
- * Atomically subtracts @delta from @ptr.
- */
-void atomic64_sub(u64 delta, atomic64_t *ptr)
-{
- atomic64_add(-delta, ptr);
-}
-EXPORT_SYMBOL(atomic64_sub);
-
-/**
- * atomic64_sub_and_test - subtract value from variable and test result
- * @delta: integer value to subtract
- * @ptr: pointer to type atomic64_t
- *
- * Atomically subtracts @delta from @ptr and returns
- * true if the result is zero, or false for all
- * other cases.
- */
-int atomic64_sub_and_test(u64 delta, atomic64_t *ptr)
-{
- u64 new_val = atomic64_sub_return(delta, ptr);
-
- return new_val == 0;
-}
-EXPORT_SYMBOL(atomic64_sub_and_test);
-
-/**
- * atomic64_inc - increment atomic64 variable
- * @ptr: pointer to type atomic64_t
- *
- * Atomically increments @ptr by 1.
- */
-void atomic64_inc(atomic64_t *ptr)
-{
- atomic64_add(1, ptr);
-}
-EXPORT_SYMBOL(atomic64_inc);
-
-/**
- * atomic64_dec - decrement atomic64 variable
- * @ptr: pointer to type atomic64_t
- *
- * Atomically decrements @ptr by 1.
- */
-void atomic64_dec(atomic64_t *ptr)
-{
- atomic64_sub(1, ptr);
-}
-EXPORT_SYMBOL(atomic64_dec);
-
-/**
- * atomic64_dec_and_test - decrement and test
- * @ptr: pointer to type atomic64_t
- *
- * Atomically decrements @ptr by 1 and
- * returns true if the result is 0, or false for all other
- * cases.
- */
-int atomic64_dec_and_test(atomic64_t *ptr)
-{
- return atomic64_sub_and_test(1, ptr);
-}
-EXPORT_SYMBOL(atomic64_dec_and_test);
-
-/**
- * atomic64_inc_and_test - increment and test
- * @ptr: pointer to type atomic64_t
- *
- * Atomically increments @ptr by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-int atomic64_inc_and_test(atomic64_t *ptr)
-{
- return atomic64_sub_and_test(-1, ptr);
-}
-EXPORT_SYMBOL(atomic64_inc_and_test);
-
-/**
- * atomic64_add_negative - add and test if negative
- * @delta: integer value to add
- * @ptr: pointer to type atomic64_t
- *
- * Atomically adds @delta to @ptr and returns true
- * if the result is negative, or false when
- * result is greater than or equal to zero.
- */
-int atomic64_add_negative(u64 delta, atomic64_t *ptr)
-{
- s64 new_val = atomic64_add_return(delta, ptr);
-
- return new_val < 0;
-}
-EXPORT_SYMBOL(atomic64_add_negative);
+#ifndef CONFIG_X86_CMPXCHG64
+long long atomic64_read_386(long long, const atomic64_t *v);
+EXPORT_SYMBOL(atomic64_read_386);
+long long atomic64_set_386(long long, const atomic64_t *v);
+EXPORT_SYMBOL(atomic64_set_386);
+long long atomic64_xchg_386(long long, unsigned high);
+EXPORT_SYMBOL(atomic64_xchg_386);
+long long atomic64_add_return_386(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_add_return_386);
+long long atomic64_sub_return_386(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_sub_return_386);
+long long atomic64_inc_return_386(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_inc_return_386);
+long long atomic64_dec_return_386(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_dec_return_386);
+long long atomic64_add_386(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_add_386);
+long long atomic64_sub_386(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_sub_386);
+long long atomic64_inc_386(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_inc_386);
+long long atomic64_dec_386(long long a, atomic64_t *v);
+EXPORT_SYMBOL(atomic64_dec_386);
+long long atomic64_dec_if_positive_386(atomic64_t *v);
+EXPORT_SYMBOL(atomic64_dec_if_positive_386);
+int atomic64_inc_not_zero_386(atomic64_t *v);
+EXPORT_SYMBOL(atomic64_inc_not_zero_386);
+int atomic64_add_unless_386(atomic64_t *v, long long a, long long u);
+EXPORT_SYMBOL(atomic64_add_unless_386);
+#endif
diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S
new file mode 100644
index 0000000..4a5979a
--- /dev/null
+++ b/arch/x86/lib/atomic64_386_32.S
@@ -0,0 +1,174 @@
+/*
+ * atomic64_t for 386/486
+ *
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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.
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/dwarf2.h>
+
+/* if you want SMP support, implement these with real spinlocks */
+.macro LOCK reg
+ pushfl
+ CFI_ADJUST_CFA_OFFSET 4
+ cli
+.endm
+
+.macro UNLOCK reg
+ popfl
+ CFI_ADJUST_CFA_OFFSET -4
+.endm
+
+.macro BEGIN func reg
+$v = \reg
+
+ENTRY(atomic64_\func\()_386)
+ CFI_STARTPROC
+ LOCK $v
+
+.macro RETURN
+ UNLOCK $v
+ ret
+.endm
+
+.macro END_
+ CFI_ENDPROC
+ENDPROC(atomic64_\func\()_386)
+.purgem RETURN
+.purgem END_
+.purgem END
+.endm
+
+.macro END
+RETURN
+END_
+.endm
+.endm
+
+BEGIN read %ecx
+ movl ($v), %eax
+ movl 4($v), %edx
+END
+
+BEGIN set %esi
+ movl %ebx, ($v)
+ movl %ecx, 4($v)
+END
+
+BEGIN xchg %esi
+ movl ($v), %eax
+ movl 4($v), %edx
+ movl %ebx, ($v)
+ movl %ecx, 4($v)
+END
+
+BEGIN add %ecx
+ addl %eax, ($v)
+ adcl %edx, 4($v)
+END
+
+BEGIN add_return %ecx
+ addl ($v), %eax
+ adcl 4($v), %edx
+ movl %eax, ($v)
+ movl %edx, 4($v)
+END
+
+BEGIN sub %ecx
+ subl %eax, ($v)
+ sbbl %edx, 4($v)
+END
+
+BEGIN sub_return %ecx
+ negl %edx
+ negl %eax
+ sbbl $0, %edx
+ addl ($v), %eax
+ adcl 4($v), %edx
+ movl %eax, ($v)
+ movl %edx, 4($v)
+END
+
+BEGIN inc %esi
+ addl $1, ($v)
+ adcl $0, 4($v)
+END
+
+BEGIN inc_return %esi
+ movl ($v), %eax
+ movl 4($v), %edx
+ addl $1, %eax
+ adcl $0, %edx
+ movl %eax, ($v)
+ movl %edx, 4($v)
+END
+
+BEGIN dec %esi
+ subl $1, ($v)
+ sbbl $0, 4($v)
+END
+
+BEGIN dec_return %esi
+ movl ($v), %eax
+ movl 4($v), %edx
+ subl $1, %eax
+ sbbl $0, %edx
+ movl %eax, ($v)
+ movl %edx, 4($v)
+END
+
+BEGIN add_unless %ecx
+ addl %eax, %esi
+ adcl %edx, %edi
+ addl ($v), %eax
+ adcl 4($v), %edx
+ cmpl %eax, %esi
+ je 3f
+1:
+ movl %eax, ($v)
+ movl %edx, 4($v)
+ movl $1, %eax
+2:
+RETURN
+3:
+ cmpl %edx, %edi
+ jne 1b
+ xorl %eax, %eax
+ jmp 2b
+END_
+
+BEGIN inc_not_zero %esi
+ movl ($v), %eax
+ movl 4($v), %edx
+ testl %eax, %eax
+ je 3f
+1:
+ addl $1, %eax
+ adcl $0, %edx
+ movl %eax, ($v)
+ movl %edx, 4($v)
+ movl $1, %eax
+2:
+RETURN
+3:
+ testl %edx, %edx
+ jne 1b
+ jmp 2b
+END_
+
+BEGIN dec_if_positive %esi
+ movl ($v), %eax
+ movl 4($v), %edx
+ subl $1, %eax
+ sbbl $0, %edx
+ js 1f
+ movl %eax, ($v)
+ movl %edx, 4($v)
+1:
+END
diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S
new file mode 100644
index 0000000..71e080d
--- /dev/null
+++ b/arch/x86/lib/atomic64_cx8_32.S
@@ -0,0 +1,224 @@
+/*
+ * atomic64_t for 586+
+ *
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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.
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/dwarf2.h>
+
+.macro SAVE reg
+ pushl %\reg
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET \reg, 0
+.endm
+
+.macro RESTORE reg
+ popl %\reg
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE \reg
+.endm
+
+.macro read64 reg
+ movl %ebx, %eax
+ movl %ecx, %edx
+/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
+ LOCK_PREFIX
+ cmpxchg8b (\reg)
+.endm
+
+ENTRY(atomic64_read_cx8)
+ CFI_STARTPROC
+
+ read64 %ecx
+ ret
+ CFI_ENDPROC
+ENDPROC(atomic64_read_cx8)
+
+ENTRY(atomic64_set_cx8)
+ CFI_STARTPROC
+
+1:
+/* we don't need LOCK_PREFIX since aligned 64-bit writes
+ * are atomic on 586 and newer */
+ cmpxchg8b (%esi)
+ jne 1b
+
+ ret
+ CFI_ENDPROC
+ENDPROC(atomic64_set_cx8)
+
+ENTRY(atomic64_xchg_cx8)
+ CFI_STARTPROC
+
+ movl %ebx, %eax
+ movl %ecx, %edx
+1:
+ LOCK_PREFIX
+ cmpxchg8b (%esi)
+ jne 1b
+
+ ret
+ CFI_ENDPROC
+ENDPROC(atomic64_xchg_cx8)
+
+.macro addsub_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+ CFI_STARTPROC
+ SAVE ebp
+ SAVE ebx
+ SAVE esi
+ SAVE edi
+
+ movl %eax, %esi
+ movl %edx, %edi
+ movl %ecx, %ebp
+
+ read64 %ebp
+1:
+ movl %eax, %ebx
+ movl %edx, %ecx
+ \ins\()l %esi, %ebx
+ \insc\()l %edi, %ecx
+ LOCK_PREFIX
+ cmpxchg8b (%ebp)
+ jne 1b
+
+10:
+ movl %ebx, %eax
+ movl %ecx, %edx
+ RESTORE edi
+ RESTORE esi
+ RESTORE ebx
+ RESTORE ebp
+ ret
+ CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+addsub_return add add adc
+addsub_return sub sub sbb
+
+.macro incdec_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+ CFI_STARTPROC
+ SAVE ebx
+
+ read64 %esi
+1:
+ movl %eax, %ebx
+ movl %edx, %ecx
+ \ins\()l $1, %ebx
+ \insc\()l $0, %ecx
+ LOCK_PREFIX
+ cmpxchg8b (%esi)
+ jne 1b
+
+10:
+ movl %ebx, %eax
+ movl %ecx, %edx
+ RESTORE ebx
+ ret
+ CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+incdec_return inc add adc
+incdec_return dec sub sbb
+
+ENTRY(atomic64_dec_if_positive_cx8)
+ CFI_STARTPROC
+ SAVE ebx
+
+ read64 %esi
+1:
+ movl %eax, %ebx
+ movl %edx, %ecx
+ subl $1, %ebx
+ sbb $0, %ecx
+ js 2f
+ LOCK_PREFIX
+ cmpxchg8b (%esi)
+ jne 1b
+
+2:
+ movl %ebx, %eax
+ movl %ecx, %edx
+ RESTORE ebx
+ ret
+ CFI_ENDPROC
+ENDPROC(atomic64_dec_if_positive_cx8)
+
+ENTRY(atomic64_add_unless_cx8)
+ CFI_STARTPROC
+ SAVE ebp
+ SAVE ebx
+/* these just push these two parameters on the stack */
+ SAVE edi
+ SAVE esi
+
+ movl %ecx, %ebp
+ movl %eax, %esi
+ movl %edx, %edi
+
+ read64 %ebp
+1:
+ cmpl %eax, 0(%esp)
+ je 4f
+2:
+ movl %eax, %ebx
+ movl %edx, %ecx
+ addl %esi, %ebx
+ adcl %edi, %ecx
+ LOCK_PREFIX
+ cmpxchg8b (%ebp)
+ jne 1b
+
+ movl $1, %eax
+3:
+ addl $8, %esp
+ CFI_ADJUST_CFA_OFFSET -8
+ RESTORE ebx
+ RESTORE ebp
+ ret
+4:
+ cmpl %edx, 4(%esp)
+ jne 2b
+ xorl %eax, %eax
+ jmp 3b
+ CFI_ENDPROC
+ENDPROC(atomic64_add_unless_cx8)
+
+ENTRY(atomic64_inc_not_zero_cx8)
+ CFI_STARTPROC
+ SAVE ebx
+
+ read64 %esi
+1:
+ testl %eax, %eax
+ je 4f
+2:
+ movl %eax, %ebx
+ movl %edx, %ecx
+ addl $1, %ebx
+ adcl $0, %ecx
+ LOCK_PREFIX
+ cmpxchg8b (%esi)
+ jne 1b
+
+ movl $1, %eax
+3:
+ RESTORE ebx
+ ret
+4:
+ testl %edx, %edx
+ jne 2b
+ jmp 3b
+ CFI_ENDPROC
+ENDPROC(atomic64_inc_not_zero_cx8)
diff --git a/arch/x86/math-emu/fpu_aux.c b/arch/x86/math-emu/fpu_aux.c
index aa09870..dc8adad 100644
--- a/arch/x86/math-emu/fpu_aux.c
+++ b/arch/x86/math-emu/fpu_aux.c
@@ -30,10 +30,10 @@
}
/* Needs to be externally visible */
-void finit_task(struct task_struct *tsk)
+void finit_soft_fpu(struct i387_soft_struct *soft)
{
- struct i387_soft_struct *soft = &tsk->thread.xstate->soft;
struct address *oaddr, *iaddr;
+ memset(soft, 0, sizeof(*soft));
soft->cwd = 0x037f;
soft->swd = 0;
soft->ftop = 0; /* We don't keep top in the status word internally. */
@@ -52,7 +52,7 @@
void finit(void)
{
- finit_task(current);
+ finit_soft_fpu(¤t->thread.fpu.state->soft);
}
/*
diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c
index 5d87f58..7718541 100644
--- a/arch/x86/math-emu/fpu_entry.c
+++ b/arch/x86/math-emu/fpu_entry.c
@@ -681,7 +681,7 @@
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
- struct i387_soft_struct *s387 = &target->thread.xstate->soft;
+ struct i387_soft_struct *s387 = &target->thread.fpu.state->soft;
void *space = s387->st_space;
int ret;
int offset, other, i, tags, regnr, tag, newtop;
@@ -733,7 +733,7 @@
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
{
- struct i387_soft_struct *s387 = &target->thread.xstate->soft;
+ struct i387_soft_struct *s387 = &target->thread.fpu.state->soft;
const void *space = s387->st_space;
int ret;
int offset = (S387->ftop & 7) * 10, other = 80 - offset;
diff --git a/arch/x86/math-emu/fpu_system.h b/arch/x86/math-emu/fpu_system.h
index 50fa0ec..2c61441 100644
--- a/arch/x86/math-emu/fpu_system.h
+++ b/arch/x86/math-emu/fpu_system.h
@@ -31,7 +31,7 @@
#define SEG_EXPAND_DOWN(s) (((s).b & ((1 << 11) | (1 << 10))) \
== (1 << 10))
-#define I387 (current->thread.xstate)
+#define I387 (current->thread.fpu.state)
#define FPU_info (I387->soft.info)
#define FPU_CS (*(unsigned short *) &(FPU_info->regs->cs))
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 06630d2..a4c7683 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -6,6 +6,7 @@
CFLAGS_physaddr.o := $(nostackp)
CFLAGS_setup_nx.o := $(nostackp)
+obj-$(CONFIG_X86_PAT) += pat_rbtree.o
obj-$(CONFIG_SMP) += tlb.o
obj-$(CONFIG_X86_32) += pgtable_32.o iomap_32.o
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index edc8b95..bbe5502 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -30,6 +30,8 @@
#include <asm/pat.h>
#include <asm/io.h>
+#include "pat_internal.h"
+
#ifdef CONFIG_X86_PAT
int __read_mostly pat_enabled = 1;
@@ -53,19 +55,15 @@
#endif
-static int debug_enable;
+int pat_debug_enable;
static int __init pat_debug_setup(char *str)
{
- debug_enable = 1;
+ pat_debug_enable = 1;
return 0;
}
__setup("debugpat", pat_debug_setup);
-#define dprintk(fmt, arg...) \
- do { if (debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
-
-
static u64 __read_mostly boot_pat_state;
enum {
@@ -132,84 +130,7 @@
#undef PAT
-static char *cattr_name(unsigned long flags)
-{
- switch (flags & _PAGE_CACHE_MASK) {
- case _PAGE_CACHE_UC: return "uncached";
- case _PAGE_CACHE_UC_MINUS: return "uncached-minus";
- case _PAGE_CACHE_WB: return "write-back";
- case _PAGE_CACHE_WC: return "write-combining";
- default: return "broken";
- }
-}
-
-/*
- * The global memtype list keeps track of memory type for specific
- * physical memory areas. Conflicting memory types in different
- * mappings can cause CPU cache corruption. To avoid this we keep track.
- *
- * The list is sorted based on starting address and can contain multiple
- * entries for each address (this allows reference counting for overlapping
- * areas). All the aliases have the same cache attributes of course.
- * Zero attributes are represented as holes.
- *
- * The data structure is a list that is also organized as an rbtree
- * sorted on the start address of memtype range.
- *
- * memtype_lock protects both the linear list and rbtree.
- */
-
-struct memtype {
- u64 start;
- u64 end;
- unsigned long type;
- struct list_head nd;
- struct rb_node rb;
-};
-
-static struct rb_root memtype_rbroot = RB_ROOT;
-static LIST_HEAD(memtype_list);
-static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */
-
-static struct memtype *memtype_rb_search(struct rb_root *root, u64 start)
-{
- struct rb_node *node = root->rb_node;
- struct memtype *last_lower = NULL;
-
- while (node) {
- struct memtype *data = container_of(node, struct memtype, rb);
-
- if (data->start < start) {
- last_lower = data;
- node = node->rb_right;
- } else if (data->start > start) {
- node = node->rb_left;
- } else
- return data;
- }
-
- /* Will return NULL if there is no entry with its start <= start */
- return last_lower;
-}
-
-static void memtype_rb_insert(struct rb_root *root, struct memtype *data)
-{
- struct rb_node **new = &(root->rb_node);
- struct rb_node *parent = NULL;
-
- while (*new) {
- struct memtype *this = container_of(*new, struct memtype, rb);
-
- parent = *new;
- if (data->start <= this->start)
- new = &((*new)->rb_left);
- else if (data->start > this->start)
- new = &((*new)->rb_right);
- }
-
- rb_link_node(&data->rb, parent, new);
- rb_insert_color(&data->rb, root);
-}
+static DEFINE_SPINLOCK(memtype_lock); /* protects memtype accesses */
/*
* Does intersection of PAT memory type and MTRR memory type and returns
@@ -237,33 +158,6 @@
return req_type;
}
-static int
-chk_conflict(struct memtype *new, struct memtype *entry, unsigned long *type)
-{
- if (new->type != entry->type) {
- if (type) {
- new->type = entry->type;
- *type = entry->type;
- } else
- goto conflict;
- }
-
- /* check overlaps with more than one entry in the list */
- list_for_each_entry_continue(entry, &memtype_list, nd) {
- if (new->end <= entry->start)
- break;
- else if (new->type != entry->type)
- goto conflict;
- }
- return 0;
-
- conflict:
- printk(KERN_INFO "%s:%d conflicting memory types "
- "%Lx-%Lx %s<->%s\n", current->comm, current->pid, new->start,
- new->end, cattr_name(new->type), cattr_name(entry->type));
- return -EBUSY;
-}
-
static int pat_pagerange_is_ram(unsigned long start, unsigned long end)
{
int ram_page = 0, not_rampage = 0;
@@ -296,8 +190,6 @@
* Here we do two pass:
* - Find the memtype of all the pages in the range, look for any conflicts
* - In case of no conflicts, set the new memtype for pages in the range
- *
- * Caller must hold memtype_lock for atomicity.
*/
static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type,
unsigned long *new_type)
@@ -364,9 +256,8 @@
int reserve_memtype(u64 start, u64 end, unsigned long req_type,
unsigned long *new_type)
{
- struct memtype *new, *entry;
+ struct memtype *new;
unsigned long actual_type;
- struct list_head *where;
int is_range_ram;
int err = 0;
@@ -404,9 +295,7 @@
is_range_ram = pat_pagerange_is_ram(start, end);
if (is_range_ram == 1) {
- spin_lock(&memtype_lock);
err = reserve_ram_pages_type(start, end, req_type, new_type);
- spin_unlock(&memtype_lock);
return err;
} else if (is_range_ram < 0) {
@@ -423,42 +312,7 @@
spin_lock(&memtype_lock);
- /* Search for existing mapping that overlaps the current range */
- where = NULL;
- list_for_each_entry(entry, &memtype_list, nd) {
- if (end <= entry->start) {
- where = entry->nd.prev;
- break;
- } else if (start <= entry->start) { /* end > entry->start */
- err = chk_conflict(new, entry, new_type);
- if (!err) {
- dprintk("Overlap at 0x%Lx-0x%Lx\n",
- entry->start, entry->end);
- where = entry->nd.prev;
- }
- break;
- } else if (start < entry->end) { /* start > entry->start */
- err = chk_conflict(new, entry, new_type);
- if (!err) {
- dprintk("Overlap at 0x%Lx-0x%Lx\n",
- entry->start, entry->end);
-
- /*
- * Move to right position in the linked
- * list to add this new entry
- */
- list_for_each_entry_continue(entry,
- &memtype_list, nd) {
- if (start <= entry->start) {
- where = entry->nd.prev;
- break;
- }
- }
- }
- break;
- }
- }
-
+ err = rbt_memtype_check_insert(new, new_type);
if (err) {
printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
"track %s, req %s\n",
@@ -469,13 +323,6 @@
return err;
}
- if (where)
- list_add(&new->nd, where);
- else
- list_add_tail(&new->nd, &memtype_list);
-
- memtype_rb_insert(&memtype_rbroot, new);
-
spin_unlock(&memtype_lock);
dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
@@ -487,7 +334,6 @@
int free_memtype(u64 start, u64 end)
{
- struct memtype *entry, *saved_entry;
int err = -EINVAL;
int is_range_ram;
@@ -501,9 +347,7 @@
is_range_ram = pat_pagerange_is_ram(start, end);
if (is_range_ram == 1) {
- spin_lock(&memtype_lock);
err = free_ram_pages_type(start, end);
- spin_unlock(&memtype_lock);
return err;
} else if (is_range_ram < 0) {
@@ -511,46 +355,7 @@
}
spin_lock(&memtype_lock);
-
- entry = memtype_rb_search(&memtype_rbroot, start);
- if (unlikely(entry == NULL))
- goto unlock_ret;
-
- /*
- * Saved entry points to an entry with start same or less than what
- * we searched for. Now go through the list in both directions to look
- * for the entry that matches with both start and end, with list stored
- * in sorted start address
- */
- saved_entry = entry;
- list_for_each_entry_from(entry, &memtype_list, nd) {
- if (entry->start == start && entry->end == end) {
- rb_erase(&entry->rb, &memtype_rbroot);
- list_del(&entry->nd);
- kfree(entry);
- err = 0;
- break;
- } else if (entry->start > start) {
- break;
- }
- }
-
- if (!err)
- goto unlock_ret;
-
- entry = saved_entry;
- list_for_each_entry_reverse(entry, &memtype_list, nd) {
- if (entry->start == start && entry->end == end) {
- rb_erase(&entry->rb, &memtype_rbroot);
- list_del(&entry->nd);
- kfree(entry);
- err = 0;
- break;
- } else if (entry->start < start) {
- break;
- }
- }
-unlock_ret:
+ err = rbt_memtype_erase(start, end);
spin_unlock(&memtype_lock);
if (err) {
@@ -583,10 +388,8 @@
if (pat_pagerange_is_ram(paddr, paddr + PAGE_SIZE)) {
struct page *page;
- spin_lock(&memtype_lock);
page = pfn_to_page(paddr >> PAGE_SHIFT);
rettype = get_page_memtype(page);
- spin_unlock(&memtype_lock);
/*
* -1 from get_page_memtype() implies RAM page is in its
* default state and not reserved, and hence of type WB
@@ -599,7 +402,7 @@
spin_lock(&memtype_lock);
- entry = memtype_rb_search(&memtype_rbroot, paddr);
+ entry = rbt_memtype_lookup(paddr);
if (entry != NULL)
rettype = entry->type;
else
@@ -936,29 +739,25 @@
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
-/* get Nth element of the linked list */
static struct memtype *memtype_get_idx(loff_t pos)
{
- struct memtype *list_node, *print_entry;
- int i = 1;
+ struct memtype *print_entry;
+ int ret;
- print_entry = kmalloc(sizeof(struct memtype), GFP_KERNEL);
+ print_entry = kzalloc(sizeof(struct memtype), GFP_KERNEL);
if (!print_entry)
return NULL;
spin_lock(&memtype_lock);
- list_for_each_entry(list_node, &memtype_list, nd) {
- if (pos == i) {
- *print_entry = *list_node;
- spin_unlock(&memtype_lock);
- return print_entry;
- }
- ++i;
- }
+ ret = rbt_memtype_copy_nth_element(print_entry, pos);
spin_unlock(&memtype_lock);
- kfree(print_entry);
- return NULL;
+ if (!ret) {
+ return print_entry;
+ } else {
+ kfree(print_entry);
+ return NULL;
+ }
}
static void *memtype_seq_start(struct seq_file *seq, loff_t *pos)
diff --git a/arch/x86/mm/pat_internal.h b/arch/x86/mm/pat_internal.h
new file mode 100644
index 0000000..4f39eef
--- /dev/null
+++ b/arch/x86/mm/pat_internal.h
@@ -0,0 +1,46 @@
+#ifndef __PAT_INTERNAL_H_
+#define __PAT_INTERNAL_H_
+
+extern int pat_debug_enable;
+
+#define dprintk(fmt, arg...) \
+ do { if (pat_debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
+
+struct memtype {
+ u64 start;
+ u64 end;
+ u64 subtree_max_end;
+ unsigned long type;
+ struct rb_node rb;
+};
+
+static inline char *cattr_name(unsigned long flags)
+{
+ switch (flags & _PAGE_CACHE_MASK) {
+ case _PAGE_CACHE_UC: return "uncached";
+ case _PAGE_CACHE_UC_MINUS: return "uncached-minus";
+ case _PAGE_CACHE_WB: return "write-back";
+ case _PAGE_CACHE_WC: return "write-combining";
+ default: return "broken";
+ }
+}
+
+#ifdef CONFIG_X86_PAT
+extern int rbt_memtype_check_insert(struct memtype *new,
+ unsigned long *new_type);
+extern int rbt_memtype_erase(u64 start, u64 end);
+extern struct memtype *rbt_memtype_lookup(u64 addr);
+extern int rbt_memtype_copy_nth_element(struct memtype *out, loff_t pos);
+#else
+static inline int rbt_memtype_check_insert(struct memtype *new,
+ unsigned long *new_type)
+{ return 0; }
+static inline int rbt_memtype_erase(u64 start, u64 end)
+{ return 0; }
+static inline struct memtype *rbt_memtype_lookup(u64 addr)
+{ return NULL; }
+static inline int rbt_memtype_copy_nth_element(struct memtype *out, loff_t pos)
+{ return 0; }
+#endif
+
+#endif /* __PAT_INTERNAL_H_ */
diff --git a/arch/x86/mm/pat_rbtree.c b/arch/x86/mm/pat_rbtree.c
new file mode 100644
index 0000000..07de4cb
--- /dev/null
+++ b/arch/x86/mm/pat_rbtree.c
@@ -0,0 +1,273 @@
+/*
+ * Handle caching attributes in page tables (PAT)
+ *
+ * Authors: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ * Suresh B Siddha <suresh.b.siddha@intel.com>
+ *
+ * Interval tree (augmented rbtree) used to store the PAT memory type
+ * reservations.
+ */
+
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rbtree.h>
+#include <linux/sched.h>
+#include <linux/gfp.h>
+
+#include <asm/pgtable.h>
+#include <asm/pat.h>
+
+#include "pat_internal.h"
+
+/*
+ * The memtype tree keeps track of memory type for specific
+ * physical memory areas. Without proper tracking, conflicting memory
+ * types in different mappings can cause CPU cache corruption.
+ *
+ * The tree is an interval tree (augmented rbtree) with tree ordered
+ * on starting address. Tree can contain multiple entries for
+ * different regions which overlap. All the aliases have the same
+ * cache attributes of course.
+ *
+ * memtype_lock protects the rbtree.
+ */
+
+static void memtype_rb_augment_cb(struct rb_node *node);
+static struct rb_root memtype_rbroot = RB_AUGMENT_ROOT(&memtype_rb_augment_cb);
+
+static int is_node_overlap(struct memtype *node, u64 start, u64 end)
+{
+ if (node->start >= end || node->end <= start)
+ return 0;
+
+ return 1;
+}
+
+static u64 get_subtree_max_end(struct rb_node *node)
+{
+ u64 ret = 0;
+ if (node) {
+ struct memtype *data = container_of(node, struct memtype, rb);
+ ret = data->subtree_max_end;
+ }
+ return ret;
+}
+
+/* Update 'subtree_max_end' for a node, based on node and its children */
+static void update_node_max_end(struct rb_node *node)
+{
+ struct memtype *data;
+ u64 max_end, child_max_end;
+
+ if (!node)
+ return;
+
+ data = container_of(node, struct memtype, rb);
+ max_end = data->end;
+
+ child_max_end = get_subtree_max_end(node->rb_right);
+ if (child_max_end > max_end)
+ max_end = child_max_end;
+
+ child_max_end = get_subtree_max_end(node->rb_left);
+ if (child_max_end > max_end)
+ max_end = child_max_end;
+
+ data->subtree_max_end = max_end;
+}
+
+/* Update 'subtree_max_end' for a node and all its ancestors */
+static void update_path_max_end(struct rb_node *node)
+{
+ u64 old_max_end, new_max_end;
+
+ while (node) {
+ struct memtype *data = container_of(node, struct memtype, rb);
+
+ old_max_end = data->subtree_max_end;
+ update_node_max_end(node);
+ new_max_end = data->subtree_max_end;
+
+ if (new_max_end == old_max_end)
+ break;
+
+ node = rb_parent(node);
+ }
+}
+
+/* Find the first (lowest start addr) overlapping range from rb tree */
+static struct memtype *memtype_rb_lowest_match(struct rb_root *root,
+ u64 start, u64 end)
+{
+ struct rb_node *node = root->rb_node;
+ struct memtype *last_lower = NULL;
+
+ while (node) {
+ struct memtype *data = container_of(node, struct memtype, rb);
+
+ if (get_subtree_max_end(node->rb_left) > start) {
+ /* Lowest overlap if any must be on left side */
+ node = node->rb_left;
+ } else if (is_node_overlap(data, start, end)) {
+ last_lower = data;
+ break;
+ } else if (start >= data->start) {
+ /* Lowest overlap if any must be on right side */
+ node = node->rb_right;
+ } else {
+ break;
+ }
+ }
+ return last_lower; /* Returns NULL if there is no overlap */
+}
+
+static struct memtype *memtype_rb_exact_match(struct rb_root *root,
+ u64 start, u64 end)
+{
+ struct memtype *match;
+
+ match = memtype_rb_lowest_match(root, start, end);
+ while (match != NULL && match->start < end) {
+ struct rb_node *node;
+
+ if (match->start == start && match->end == end)
+ return match;
+
+ node = rb_next(&match->rb);
+ if (node)
+ match = container_of(node, struct memtype, rb);
+ else
+ match = NULL;
+ }
+
+ return NULL; /* Returns NULL if there is no exact match */
+}
+
+static int memtype_rb_check_conflict(struct rb_root *root,
+ u64 start, u64 end,
+ unsigned long reqtype, unsigned long *newtype)
+{
+ struct rb_node *node;
+ struct memtype *match;
+ int found_type = reqtype;
+
+ match = memtype_rb_lowest_match(&memtype_rbroot, start, end);
+ if (match == NULL)
+ goto success;
+
+ if (match->type != found_type && newtype == NULL)
+ goto failure;
+
+ dprintk("Overlap at 0x%Lx-0x%Lx\n", match->start, match->end);
+ found_type = match->type;
+
+ node = rb_next(&match->rb);
+ while (node) {
+ match = container_of(node, struct memtype, rb);
+
+ if (match->start >= end) /* Checked all possible matches */
+ goto success;
+
+ if (is_node_overlap(match, start, end) &&
+ match->type != found_type) {
+ goto failure;
+ }
+
+ node = rb_next(&match->rb);
+ }
+success:
+ if (newtype)
+ *newtype = found_type;
+
+ return 0;
+
+failure:
+ printk(KERN_INFO "%s:%d conflicting memory types "
+ "%Lx-%Lx %s<->%s\n", current->comm, current->pid, start,
+ end, cattr_name(found_type), cattr_name(match->type));
+ return -EBUSY;
+}
+
+static void memtype_rb_augment_cb(struct rb_node *node)
+{
+ if (node)
+ update_path_max_end(node);
+}
+
+static void memtype_rb_insert(struct rb_root *root, struct memtype *newdata)
+{
+ struct rb_node **node = &(root->rb_node);
+ struct rb_node *parent = NULL;
+
+ while (*node) {
+ struct memtype *data = container_of(*node, struct memtype, rb);
+
+ parent = *node;
+ if (newdata->start <= data->start)
+ node = &((*node)->rb_left);
+ else if (newdata->start > data->start)
+ node = &((*node)->rb_right);
+ }
+
+ rb_link_node(&newdata->rb, parent, node);
+ rb_insert_color(&newdata->rb, root);
+}
+
+int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type)
+{
+ int err = 0;
+
+ err = memtype_rb_check_conflict(&memtype_rbroot, new->start, new->end,
+ new->type, ret_type);
+
+ if (!err) {
+ if (ret_type)
+ new->type = *ret_type;
+
+ memtype_rb_insert(&memtype_rbroot, new);
+ }
+ return err;
+}
+
+int rbt_memtype_erase(u64 start, u64 end)
+{
+ struct memtype *data;
+
+ data = memtype_rb_exact_match(&memtype_rbroot, start, end);
+ if (!data)
+ return -EINVAL;
+
+ rb_erase(&data->rb, &memtype_rbroot);
+ return 0;
+}
+
+struct memtype *rbt_memtype_lookup(u64 addr)
+{
+ struct memtype *data;
+ data = memtype_rb_lowest_match(&memtype_rbroot, addr, addr + PAGE_SIZE);
+ return data;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+int rbt_memtype_copy_nth_element(struct memtype *out, loff_t pos)
+{
+ struct rb_node *node;
+ int i = 1;
+
+ node = rb_first(&memtype_rbroot);
+ while (node && pos != i) {
+ node = rb_next(node);
+ i++;
+ }
+
+ if (node) { /* pos == i */
+ struct memtype *this = container_of(node, struct memtype, rb);
+ *out = *this;
+ return 0;
+ } else {
+ return 1;
+ }
+}
+#endif
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index 28c6876..f9897f7 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -363,6 +363,54 @@
for (i = 0; i < MAX_NUMNODES; i++)
cutoff_node(i, start, end);
+ /*
+ * Join together blocks on the same node, holes between
+ * which don't overlap with memory on other nodes.
+ */
+ for (i = 0; i < num_node_memblks; ++i) {
+ int j, k;
+
+ for (j = i + 1; j < num_node_memblks; ++j) {
+ unsigned long start, end;
+
+ if (memblk_nodeid[i] != memblk_nodeid[j])
+ continue;
+ start = min(node_memblk_range[i].end,
+ node_memblk_range[j].end);
+ end = max(node_memblk_range[i].start,
+ node_memblk_range[j].start);
+ for (k = 0; k < num_node_memblks; ++k) {
+ if (memblk_nodeid[i] == memblk_nodeid[k])
+ continue;
+ if (start < node_memblk_range[k].end &&
+ end > node_memblk_range[k].start)
+ break;
+ }
+ if (k < num_node_memblks)
+ continue;
+ start = min(node_memblk_range[i].start,
+ node_memblk_range[j].start);
+ end = max(node_memblk_range[i].end,
+ node_memblk_range[j].end);
+ printk(KERN_INFO "SRAT: Node %d "
+ "[%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
+ memblk_nodeid[i],
+ node_memblk_range[i].start,
+ node_memblk_range[i].end,
+ node_memblk_range[j].start,
+ node_memblk_range[j].end,
+ start, end);
+ node_memblk_range[i].start = start;
+ node_memblk_range[i].end = end;
+ k = --num_node_memblks - j;
+ memmove(memblk_nodeid + j, memblk_nodeid + j+1,
+ k * sizeof(*memblk_nodeid));
+ memmove(node_memblk_range + j, node_memblk_range + j+1,
+ k * sizeof(*node_memblk_range));
+ --j;
+ }
+ }
+
memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
memblk_nodeid);
if (memnode_shift < 0) {
@@ -461,7 +509,8 @@
* node, it must now point to the fake node ID.
*/
for (j = 0; j < MAX_LOCAL_APIC; j++)
- if (apicid_to_node[j] == nid)
+ if (apicid_to_node[j] == nid &&
+ fake_apicid_to_node[j] == NUMA_NO_NODE)
fake_apicid_to_node[j] = i;
}
for (i = 0; i < num_nodes; i++)
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
index 2c505ee..b28d2f1 100644
--- a/arch/x86/oprofile/nmi_int.c
+++ b/arch/x86/oprofile/nmi_int.c
@@ -31,8 +31,9 @@
static DEFINE_PER_CPU(struct op_msrs, cpu_msrs);
static DEFINE_PER_CPU(unsigned long, saved_lvtpc);
-/* 0 == registered but off, 1 == registered and on */
-static int nmi_enabled = 0;
+/* must be protected with get_online_cpus()/put_online_cpus(): */
+static int nmi_enabled;
+static int ctr_running;
struct op_counter_config counter_config[OP_MAX_COUNTER];
@@ -61,12 +62,16 @@
{
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
- int cpu = smp_processor_id();
switch (val) {
case DIE_NMI:
case DIE_NMI_IPI:
- model->check_ctrs(args->regs, &per_cpu(cpu_msrs, cpu));
+ if (ctr_running)
+ model->check_ctrs(args->regs, &__get_cpu_var(cpu_msrs));
+ else if (!nmi_enabled)
+ break;
+ else
+ model->stop(&__get_cpu_var(cpu_msrs));
ret = NOTIFY_STOP;
break;
default:
@@ -95,24 +100,36 @@
static void nmi_cpu_start(void *dummy)
{
struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
- model->start(msrs);
+ if (!msrs->controls)
+ WARN_ON_ONCE(1);
+ else
+ model->start(msrs);
}
static int nmi_start(void)
{
+ get_online_cpus();
on_each_cpu(nmi_cpu_start, NULL, 1);
+ ctr_running = 1;
+ put_online_cpus();
return 0;
}
static void nmi_cpu_stop(void *dummy)
{
struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs);
- model->stop(msrs);
+ if (!msrs->controls)
+ WARN_ON_ONCE(1);
+ else
+ model->stop(msrs);
}
static void nmi_stop(void)
{
+ get_online_cpus();
on_each_cpu(nmi_cpu_stop, NULL, 1);
+ ctr_running = 0;
+ put_online_cpus();
}
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
@@ -252,7 +269,10 @@
if (nmi_multiplex_on() < 0)
return -EINVAL; /* not necessary */
- on_each_cpu(nmi_cpu_switch, NULL, 1);
+ get_online_cpus();
+ if (ctr_running)
+ on_each_cpu(nmi_cpu_switch, NULL, 1);
+ put_online_cpus();
return 0;
}
@@ -295,6 +315,7 @@
kfree(per_cpu(cpu_msrs, i).controls);
per_cpu(cpu_msrs, i).controls = NULL;
}
+ nmi_shutdown_mux();
}
static int allocate_msrs(void)
@@ -307,14 +328,21 @@
per_cpu(cpu_msrs, i).counters = kzalloc(counters_size,
GFP_KERNEL);
if (!per_cpu(cpu_msrs, i).counters)
- return 0;
+ goto fail;
per_cpu(cpu_msrs, i).controls = kzalloc(controls_size,
GFP_KERNEL);
if (!per_cpu(cpu_msrs, i).controls)
- return 0;
+ goto fail;
}
+ if (!nmi_setup_mux())
+ goto fail;
+
return 1;
+
+fail:
+ free_msrs();
+ return 0;
}
static void nmi_cpu_setup(void *dummy)
@@ -336,49 +364,6 @@
.priority = 2
};
-static int nmi_setup(void)
-{
- int err = 0;
- int cpu;
-
- if (!allocate_msrs())
- err = -ENOMEM;
- else if (!nmi_setup_mux())
- err = -ENOMEM;
- else
- err = register_die_notifier(&profile_exceptions_nb);
-
- if (err) {
- free_msrs();
- nmi_shutdown_mux();
- return err;
- }
-
- /* We need to serialize save and setup for HT because the subset
- * of msrs are distinct for save and setup operations
- */
-
- /* Assume saved/restored counters are the same on all CPUs */
- model->fill_in_addresses(&per_cpu(cpu_msrs, 0));
- for_each_possible_cpu(cpu) {
- if (!cpu)
- continue;
-
- memcpy(per_cpu(cpu_msrs, cpu).counters,
- per_cpu(cpu_msrs, 0).counters,
- sizeof(struct op_msr) * model->num_counters);
-
- memcpy(per_cpu(cpu_msrs, cpu).controls,
- per_cpu(cpu_msrs, 0).controls,
- sizeof(struct op_msr) * model->num_controls);
-
- mux_clone(cpu);
- }
- on_each_cpu(nmi_cpu_setup, NULL, 1);
- nmi_enabled = 1;
- return 0;
-}
-
static void nmi_cpu_restore_registers(struct op_msrs *msrs)
{
struct op_msr *counters = msrs->counters;
@@ -412,20 +397,24 @@
apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu));
apic_write(APIC_LVTERR, v);
nmi_cpu_restore_registers(msrs);
+ if (model->cpu_down)
+ model->cpu_down();
}
-static void nmi_shutdown(void)
+static void nmi_cpu_up(void *dummy)
{
- struct op_msrs *msrs;
+ if (nmi_enabled)
+ nmi_cpu_setup(dummy);
+ if (ctr_running)
+ nmi_cpu_start(dummy);
+}
- nmi_enabled = 0;
- on_each_cpu(nmi_cpu_shutdown, NULL, 1);
- unregister_die_notifier(&profile_exceptions_nb);
- nmi_shutdown_mux();
- msrs = &get_cpu_var(cpu_msrs);
- model->shutdown(msrs);
- free_msrs();
- put_cpu_var(cpu_msrs);
+static void nmi_cpu_down(void *dummy)
+{
+ if (ctr_running)
+ nmi_cpu_stop(dummy);
+ if (nmi_enabled)
+ nmi_cpu_shutdown(dummy);
}
static int nmi_create_files(struct super_block *sb, struct dentry *root)
@@ -457,7 +446,6 @@
return 0;
}
-#ifdef CONFIG_SMP
static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action,
void *data)
{
@@ -465,10 +453,10 @@
switch (action) {
case CPU_DOWN_FAILED:
case CPU_ONLINE:
- smp_call_function_single(cpu, nmi_cpu_start, NULL, 0);
+ smp_call_function_single(cpu, nmi_cpu_up, NULL, 0);
break;
case CPU_DOWN_PREPARE:
- smp_call_function_single(cpu, nmi_cpu_stop, NULL, 1);
+ smp_call_function_single(cpu, nmi_cpu_down, NULL, 1);
break;
}
return NOTIFY_DONE;
@@ -477,7 +465,75 @@
static struct notifier_block oprofile_cpu_nb = {
.notifier_call = oprofile_cpu_notifier
};
-#endif
+
+static int nmi_setup(void)
+{
+ int err = 0;
+ int cpu;
+
+ if (!allocate_msrs())
+ return -ENOMEM;
+
+ /* We need to serialize save and setup for HT because the subset
+ * of msrs are distinct for save and setup operations
+ */
+
+ /* Assume saved/restored counters are the same on all CPUs */
+ err = model->fill_in_addresses(&per_cpu(cpu_msrs, 0));
+ if (err)
+ goto fail;
+
+ for_each_possible_cpu(cpu) {
+ if (!cpu)
+ continue;
+
+ memcpy(per_cpu(cpu_msrs, cpu).counters,
+ per_cpu(cpu_msrs, 0).counters,
+ sizeof(struct op_msr) * model->num_counters);
+
+ memcpy(per_cpu(cpu_msrs, cpu).controls,
+ per_cpu(cpu_msrs, 0).controls,
+ sizeof(struct op_msr) * model->num_controls);
+
+ mux_clone(cpu);
+ }
+
+ nmi_enabled = 0;
+ ctr_running = 0;
+ barrier();
+ err = register_die_notifier(&profile_exceptions_nb);
+ if (err)
+ goto fail;
+
+ get_online_cpus();
+ register_cpu_notifier(&oprofile_cpu_nb);
+ on_each_cpu(nmi_cpu_setup, NULL, 1);
+ nmi_enabled = 1;
+ put_online_cpus();
+
+ return 0;
+fail:
+ free_msrs();
+ return err;
+}
+
+static void nmi_shutdown(void)
+{
+ struct op_msrs *msrs;
+
+ get_online_cpus();
+ unregister_cpu_notifier(&oprofile_cpu_nb);
+ on_each_cpu(nmi_cpu_shutdown, NULL, 1);
+ nmi_enabled = 0;
+ ctr_running = 0;
+ put_online_cpus();
+ barrier();
+ unregister_die_notifier(&profile_exceptions_nb);
+ msrs = &get_cpu_var(cpu_msrs);
+ model->shutdown(msrs);
+ free_msrs();
+ put_cpu_var(cpu_msrs);
+}
#ifdef CONFIG_PM
@@ -687,9 +743,6 @@
return -ENODEV;
}
-#ifdef CONFIG_SMP
- register_cpu_notifier(&oprofile_cpu_nb);
-#endif
/* default values, can be overwritten by model */
ops->create_files = nmi_create_files;
ops->setup = nmi_setup;
@@ -716,12 +769,6 @@
void op_nmi_exit(void)
{
- if (using_nmi) {
+ if (using_nmi)
exit_sysfs();
-#ifdef CONFIG_SMP
- unregister_cpu_notifier(&oprofile_cpu_nb);
-#endif
- }
- if (model->exit)
- model->exit();
}
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index 090cbbe..b67a6b5 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -30,13 +30,10 @@
#include "op_counter.h"
#define NUM_COUNTERS 4
-#define NUM_CONTROLS 4
#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
#define NUM_VIRT_COUNTERS 32
-#define NUM_VIRT_CONTROLS 32
#else
#define NUM_VIRT_COUNTERS NUM_COUNTERS
-#define NUM_VIRT_CONTROLS NUM_CONTROLS
#endif
#define OP_EVENT_MASK 0x0FFF
@@ -105,102 +102,6 @@
return ibs_caps;
}
-#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
-
-static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
- struct op_msrs const * const msrs)
-{
- u64 val;
- int i;
-
- /* enable active counters */
- for (i = 0; i < NUM_COUNTERS; ++i) {
- int virt = op_x86_phys_to_virt(i);
- if (!reset_value[virt])
- continue;
- rdmsrl(msrs->controls[i].addr, val);
- val &= model->reserved;
- val |= op_x86_get_ctrl(model, &counter_config[virt]);
- wrmsrl(msrs->controls[i].addr, val);
- }
-}
-
-#endif
-
-/* functions for op_amd_spec */
-
-static void op_amd_fill_in_addresses(struct op_msrs * const msrs)
-{
- int i;
-
- for (i = 0; i < NUM_COUNTERS; i++) {
- if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
- msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
- }
-
- for (i = 0; i < NUM_CONTROLS; i++) {
- if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
- msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
- }
-}
-
-static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
- struct op_msrs const * const msrs)
-{
- u64 val;
- int i;
-
- /* setup reset_value */
- for (i = 0; i < NUM_VIRT_COUNTERS; ++i) {
- if (counter_config[i].enabled
- && msrs->counters[op_x86_virt_to_phys(i)].addr)
- reset_value[i] = counter_config[i].count;
- else
- reset_value[i] = 0;
- }
-
- /* clear all counters */
- for (i = 0; i < NUM_CONTROLS; ++i) {
- if (unlikely(!msrs->controls[i].addr)) {
- if (counter_config[i].enabled && !smp_processor_id())
- /*
- * counter is reserved, this is on all
- * cpus, so report only for cpu #0
- */
- op_x86_warn_reserved(i);
- continue;
- }
- rdmsrl(msrs->controls[i].addr, val);
- if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
- op_x86_warn_in_use(i);
- val &= model->reserved;
- wrmsrl(msrs->controls[i].addr, val);
- }
-
- /* avoid a false detection of ctr overflows in NMI handler */
- for (i = 0; i < NUM_COUNTERS; ++i) {
- if (unlikely(!msrs->counters[i].addr))
- continue;
- wrmsrl(msrs->counters[i].addr, -1LL);
- }
-
- /* enable active counters */
- for (i = 0; i < NUM_COUNTERS; ++i) {
- int virt = op_x86_phys_to_virt(i);
- if (!reset_value[virt])
- continue;
-
- /* setup counter registers */
- wrmsrl(msrs->counters[i].addr, -(u64)reset_value[virt]);
-
- /* setup control registers */
- rdmsrl(msrs->controls[i].addr, val);
- val &= model->reserved;
- val |= op_x86_get_ctrl(model, &counter_config[virt]);
- wrmsrl(msrs->controls[i].addr, val);
- }
-}
-
/*
* 16-bit Linear Feedback Shift Register (LFSR)
*
@@ -365,6 +266,125 @@
wrmsrl(MSR_AMD64_IBSOPCTL, 0);
}
+#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
+
+static void op_mux_switch_ctrl(struct op_x86_model_spec const *model,
+ struct op_msrs const * const msrs)
+{
+ u64 val;
+ int i;
+
+ /* enable active counters */
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+ int virt = op_x86_phys_to_virt(i);
+ if (!reset_value[virt])
+ continue;
+ rdmsrl(msrs->controls[i].addr, val);
+ val &= model->reserved;
+ val |= op_x86_get_ctrl(model, &counter_config[virt]);
+ wrmsrl(msrs->controls[i].addr, val);
+ }
+}
+
+#endif
+
+/* functions for op_amd_spec */
+
+static void op_amd_shutdown(struct op_msrs const * const msrs)
+{
+ int i;
+
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+ if (!msrs->counters[i].addr)
+ continue;
+ release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+ release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+ }
+}
+
+static int op_amd_fill_in_addresses(struct op_msrs * const msrs)
+{
+ int i;
+
+ for (i = 0; i < NUM_COUNTERS; i++) {
+ if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
+ goto fail;
+ if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) {
+ release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+ goto fail;
+ }
+ /* both registers must be reserved */
+ msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
+ msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+ continue;
+ fail:
+ if (!counter_config[i].enabled)
+ continue;
+ op_x86_warn_reserved(i);
+ op_amd_shutdown(msrs);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static void op_amd_setup_ctrs(struct op_x86_model_spec const *model,
+ struct op_msrs const * const msrs)
+{
+ u64 val;
+ int i;
+
+ /* setup reset_value */
+ for (i = 0; i < NUM_VIRT_COUNTERS; ++i) {
+ if (counter_config[i].enabled
+ && msrs->counters[op_x86_virt_to_phys(i)].addr)
+ reset_value[i] = counter_config[i].count;
+ else
+ reset_value[i] = 0;
+ }
+
+ /* clear all counters */
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+ if (!msrs->controls[i].addr)
+ continue;
+ rdmsrl(msrs->controls[i].addr, val);
+ if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
+ op_x86_warn_in_use(i);
+ val &= model->reserved;
+ wrmsrl(msrs->controls[i].addr, val);
+ /*
+ * avoid a false detection of ctr overflows in NMI
+ * handler
+ */
+ wrmsrl(msrs->counters[i].addr, -1LL);
+ }
+
+ /* enable active counters */
+ for (i = 0; i < NUM_COUNTERS; ++i) {
+ int virt = op_x86_phys_to_virt(i);
+ if (!reset_value[virt])
+ continue;
+
+ /* setup counter registers */
+ wrmsrl(msrs->counters[i].addr, -(u64)reset_value[virt]);
+
+ /* setup control registers */
+ rdmsrl(msrs->controls[i].addr, val);
+ val &= model->reserved;
+ val |= op_x86_get_ctrl(model, &counter_config[virt]);
+ wrmsrl(msrs->controls[i].addr, val);
+ }
+
+ if (ibs_caps)
+ setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
+}
+
+static void op_amd_cpu_shutdown(void)
+{
+ if (ibs_caps)
+ setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
+}
+
static int op_amd_check_ctrs(struct pt_regs * const regs,
struct op_msrs const * const msrs)
{
@@ -425,42 +445,16 @@
op_amd_stop_ibs();
}
-static void op_amd_shutdown(struct op_msrs const * const msrs)
-{
- int i;
-
- for (i = 0; i < NUM_COUNTERS; ++i) {
- if (msrs->counters[i].addr)
- release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
- }
- for (i = 0; i < NUM_CONTROLS; ++i) {
- if (msrs->controls[i].addr)
- release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
- }
-}
-
-static u8 ibs_eilvt_off;
-
-static inline void apic_init_ibs_nmi_per_cpu(void *arg)
-{
- ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0);
-}
-
-static inline void apic_clear_ibs_nmi_per_cpu(void *arg)
-{
- setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
-}
-
-static int init_ibs_nmi(void)
+static int __init_ibs_nmi(void)
{
#define IBSCTL_LVTOFFSETVAL (1 << 8)
#define IBSCTL 0x1cc
struct pci_dev *cpu_cfg;
int nodes;
u32 value = 0;
+ u8 ibs_eilvt_off;
- /* per CPU setup */
- on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1);
+ ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1);
nodes = 0;
cpu_cfg = NULL;
@@ -490,22 +484,15 @@
return 0;
}
-/* uninitialize the APIC for the IBS interrupts if needed */
-static void clear_ibs_nmi(void)
-{
- if (ibs_caps)
- on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);
-}
-
/* initialize the APIC for the IBS interrupts if available */
-static void ibs_init(void)
+static void init_ibs(void)
{
ibs_caps = get_ibs_caps();
if (!ibs_caps)
return;
- if (init_ibs_nmi()) {
+ if (__init_ibs_nmi()) {
ibs_caps = 0;
return;
}
@@ -514,14 +501,6 @@
(unsigned)ibs_caps);
}
-static void ibs_exit(void)
-{
- if (!ibs_caps)
- return;
-
- clear_ibs_nmi();
-}
-
static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
static int setup_ibs_files(struct super_block *sb, struct dentry *root)
@@ -570,27 +549,22 @@
static int op_amd_init(struct oprofile_operations *ops)
{
- ibs_init();
+ init_ibs();
create_arch_files = ops->create_files;
ops->create_files = setup_ibs_files;
return 0;
}
-static void op_amd_exit(void)
-{
- ibs_exit();
-}
-
struct op_x86_model_spec op_amd_spec = {
.num_counters = NUM_COUNTERS,
- .num_controls = NUM_CONTROLS,
+ .num_controls = NUM_COUNTERS,
.num_virt_counters = NUM_VIRT_COUNTERS,
.reserved = MSR_AMD_EVENTSEL_RESERVED,
.event_mask = OP_EVENT_MASK,
.init = op_amd_init,
- .exit = op_amd_exit,
.fill_in_addresses = &op_amd_fill_in_addresses,
.setup_ctrs = &op_amd_setup_ctrs,
+ .cpu_down = &op_amd_cpu_shutdown,
.check_ctrs = &op_amd_check_ctrs,
.start = &op_amd_start,
.stop = &op_amd_stop,
diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c
index e6a160a..182558d 100644
--- a/arch/x86/oprofile/op_model_p4.c
+++ b/arch/x86/oprofile/op_model_p4.c
@@ -385,8 +385,26 @@
static unsigned long reset_value[NUM_COUNTERS_NON_HT];
+static void p4_shutdown(struct op_msrs const * const msrs)
+{
+ int i;
-static void p4_fill_in_addresses(struct op_msrs * const msrs)
+ for (i = 0; i < num_counters; ++i) {
+ if (msrs->counters[i].addr)
+ release_perfctr_nmi(msrs->counters[i].addr);
+ }
+ /*
+ * some of the control registers are specially reserved in
+ * conjunction with the counter registers (hence the starting offset).
+ * This saves a few bits.
+ */
+ for (i = num_counters; i < num_controls; ++i) {
+ if (msrs->controls[i].addr)
+ release_evntsel_nmi(msrs->controls[i].addr);
+ }
+}
+
+static int p4_fill_in_addresses(struct op_msrs * const msrs)
{
unsigned int i;
unsigned int addr, cccraddr, stag;
@@ -468,6 +486,18 @@
msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
}
}
+
+ for (i = 0; i < num_counters; ++i) {
+ if (!counter_config[i].enabled)
+ continue;
+ if (msrs->controls[i].addr)
+ continue;
+ op_x86_warn_reserved(i);
+ p4_shutdown(msrs);
+ return -EBUSY;
+ }
+
+ return 0;
}
@@ -668,26 +698,6 @@
}
}
-static void p4_shutdown(struct op_msrs const * const msrs)
-{
- int i;
-
- for (i = 0; i < num_counters; ++i) {
- if (msrs->counters[i].addr)
- release_perfctr_nmi(msrs->counters[i].addr);
- }
- /*
- * some of the control registers are specially reserved in
- * conjunction with the counter registers (hence the starting offset).
- * This saves a few bits.
- */
- for (i = num_counters; i < num_controls; ++i) {
- if (msrs->controls[i].addr)
- release_evntsel_nmi(msrs->controls[i].addr);
- }
-}
-
-
#ifdef CONFIG_SMP
struct op_x86_model_spec op_p4_ht2_spec = {
.num_counters = NUM_COUNTERS_HT2,
diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c
index c8abc4d..d769cda 100644
--- a/arch/x86/oprofile/op_model_ppro.c
+++ b/arch/x86/oprofile/op_model_ppro.c
@@ -30,19 +30,46 @@
static u64 *reset_value;
-static void ppro_fill_in_addresses(struct op_msrs * const msrs)
+static void ppro_shutdown(struct op_msrs const * const msrs)
+{
+ int i;
+
+ for (i = 0; i < num_counters; ++i) {
+ if (!msrs->counters[i].addr)
+ continue;
+ release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
+ release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
+ }
+ if (reset_value) {
+ kfree(reset_value);
+ reset_value = NULL;
+ }
+}
+
+static int ppro_fill_in_addresses(struct op_msrs * const msrs)
{
int i;
for (i = 0; i < num_counters; i++) {
- if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
- msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+ if (!reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
+ goto fail;
+ if (!reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i)) {
+ release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
+ goto fail;
+ }
+ /* both registers must be reserved */
+ msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+ msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+ continue;
+ fail:
+ if (!counter_config[i].enabled)
+ continue;
+ op_x86_warn_reserved(i);
+ ppro_shutdown(msrs);
+ return -EBUSY;
}
- for (i = 0; i < num_counters; i++) {
- if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
- msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
- }
+ return 0;
}
@@ -78,26 +105,17 @@
/* clear all counters */
for (i = 0; i < num_counters; ++i) {
- if (unlikely(!msrs->controls[i].addr)) {
- if (counter_config[i].enabled && !smp_processor_id())
- /*
- * counter is reserved, this is on all
- * cpus, so report only for cpu #0
- */
- op_x86_warn_reserved(i);
+ if (!msrs->controls[i].addr)
continue;
- }
rdmsrl(msrs->controls[i].addr, val);
if (val & ARCH_PERFMON_EVENTSEL_ENABLE)
op_x86_warn_in_use(i);
val &= model->reserved;
wrmsrl(msrs->controls[i].addr, val);
- }
-
- /* avoid a false detection of ctr overflows in NMI handler */
- for (i = 0; i < num_counters; ++i) {
- if (unlikely(!msrs->counters[i].addr))
- continue;
+ /*
+ * avoid a false detection of ctr overflows in NMI *
+ * handler
+ */
wrmsrl(msrs->counters[i].addr, -1LL);
}
@@ -189,25 +207,6 @@
}
}
-static void ppro_shutdown(struct op_msrs const * const msrs)
-{
- int i;
-
- for (i = 0; i < num_counters; ++i) {
- if (msrs->counters[i].addr)
- release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
- }
- for (i = 0; i < num_counters; ++i) {
- if (msrs->controls[i].addr)
- release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
- }
- if (reset_value) {
- kfree(reset_value);
- reset_value = NULL;
- }
-}
-
-
struct op_x86_model_spec op_ppro_spec = {
.num_counters = 2,
.num_controls = 2,
diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h
index ff82a75..89017fa 100644
--- a/arch/x86/oprofile/op_x86_model.h
+++ b/arch/x86/oprofile/op_x86_model.h
@@ -40,10 +40,10 @@
u64 reserved;
u16 event_mask;
int (*init)(struct oprofile_operations *ops);
- void (*exit)(void);
- void (*fill_in_addresses)(struct op_msrs * const msrs);
+ int (*fill_in_addresses)(struct op_msrs * const msrs);
void (*setup_ctrs)(struct op_x86_model_spec const *model,
struct op_msrs const * const msrs);
+ void (*cpu_down)(void);
int (*check_ctrs)(struct pt_regs * const regs,
struct op_msrs const * const msrs);
void (*start)(struct op_msrs const * const msrs);
diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c
index 8bf2fcb..7ef3a27 100644
--- a/arch/x86/pci/mrst.c
+++ b/arch/x86/pci/mrst.c
@@ -109,7 +109,7 @@
decode++;
decode = ~(decode - 1);
} else {
- decode = ~0;
+ decode = 0;
}
/*
@@ -247,6 +247,10 @@
u32 size;
int i;
+ /* Must have extended configuration space */
+ if (dev->cfg_size < PCIE_CAP_OFFSET + 4)
+ return;
+
/* Fixup the BAR sizes for fixed BAR devices and make them unmoveable */
offset = fixed_bar_cap(dev->bus, dev->devfn);
if (!offset || PCI_DEVFN(2, 0) == dev->devfn ||
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h
index 22d6dde..a96a061 100644
--- a/arch/xtensa/include/asm/atomic.h
+++ b/arch/xtensa/include/asm/atomic.h
@@ -46,7 +46,7 @@
*
* Atomically reads the value of @v.
*/
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
/**
* atomic_set - set atomic variable
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 5fe03de..2cc682b 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -286,16 +286,16 @@
static struct cgroup_subsys_state *
blkiocg_create(struct cgroup_subsys *subsys, struct cgroup *cgroup)
{
- struct blkio_cgroup *blkcg, *parent_blkcg;
+ struct blkio_cgroup *blkcg;
+ struct cgroup *parent = cgroup->parent;
- if (!cgroup->parent) {
+ if (!parent) {
blkcg = &blkio_root_cgroup;
goto done;
}
/* Currently we do not support hierarchy deeper than two level (0,1) */
- parent_blkcg = cgroup_to_blkio_cgroup(cgroup->parent);
- if (css_depth(&parent_blkcg->css) > 0)
+ if (parent != cgroup->top_cgroup)
return ERR_PTR(-EINVAL);
blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 838834b..5f127cf 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -3694,8 +3694,10 @@
* to make sure that cfq_put_cfqg() does not try to kfree root group
*/
atomic_set(&cfqg->ref, 1);
+ rcu_read_lock();
blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd,
0);
+ rcu_read_unlock();
#endif
/*
* Not strictly needed (since RB_ROOT just clears the node and we
diff --git a/drivers/Makefile b/drivers/Makefile
index 34f1e10..f42a030 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -17,6 +17,7 @@
obj-$(CONFIG_PNP) += pnp/
obj-$(CONFIG_ARM_AMBA) += amba/
+obj-$(CONFIG_VIRTIO) += virtio/
obj-$(CONFIG_XEN) += xen/
# regulators early, since some subsystems rely on them to initialize
@@ -108,7 +109,6 @@
obj-$(CONFIG_OF) += of/
obj-$(CONFIG_SSB) += ssb/
obj-$(CONFIG_VHOST_NET) += vhost/
-obj-$(CONFIG_VIRTIO) += virtio/
obj-$(CONFIG_VLYNQ) += vlynq/
obj-$(CONFIG_STAGING) += staging/
obj-y += platform/
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 19dacfd..6212213 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -31,7 +31,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#define ACPI_PROCESSOR_AGGREGATOR_CLASS "processor_aggregator"
+#define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad"
#define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator"
#define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80
static DEFINE_MUTEX(isolated_cpus_lock);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 37132dc..743576b 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -527,7 +527,7 @@
if (!event_is_open)
return 0;
- event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
+ event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
if (!event)
return -ENOMEM;
diff --git a/drivers/acpi/hest.c b/drivers/acpi/hest.c
index 4bb18c9..1c527a1 100644
--- a/drivers/acpi/hest.c
+++ b/drivers/acpi/hest.c
@@ -123,6 +123,10 @@
{
acpi_status status = AE_NOT_FOUND;
struct acpi_table_header *hest = NULL;
+
+ if (acpi_disabled)
+ return 0;
+
status = acpi_get_table(ACPI_SIG_HEST, 1, &hest);
if (ACPI_SUCCESS(status)) {
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index b0a71ec..e4804fb 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -401,11 +401,13 @@
* driver reported one, then use it. Exit in any case.
*/
if (gsi < 0) {
+ u32 dev_gsi;
dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));
/* Interrupt Line values above 0xF are forbidden */
- if (dev->irq > 0 && (dev->irq <= 0xF)) {
- printk(" - using IRQ %d\n", dev->irq);
- acpi_register_gsi(&dev->dev, dev->irq,
+ if (dev->irq > 0 && (dev->irq <= 0xF) &&
+ (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
+ printk(" - using ISA IRQ %d\n", dev->irq);
+ acpi_register_gsi(&dev->dev, dev_gsi,
ACPI_LEVEL_SENSITIVE,
ACPI_ACTIVE_LOW);
return 0;
diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c
index e8c32a4..66f6729 100644
--- a/drivers/acpi/power_meter.c
+++ b/drivers/acpi/power_meter.c
@@ -35,7 +35,7 @@
#define ACPI_POWER_METER_NAME "power_meter"
ACPI_MODULE_NAME(ACPI_POWER_METER_NAME);
#define ACPI_POWER_METER_DEVICE_NAME "Power Meter"
-#define ACPI_POWER_METER_CLASS "power_meter_resource"
+#define ACPI_POWER_METER_CLASS "pwr_meter_resource"
#define NUM_SENSORS 17
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index 36704b8..f8be23b 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -18,7 +18,7 @@
#define PREFIX "ACPI: "
-#define ACPI_SMB_HC_CLASS "smbus_host_controller"
+#define ACPI_SMB_HC_CLASS "smbus_host_ctl"
#define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC"
struct acpi_smb_hc {
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index f74834a..baa76bb 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -450,6 +450,38 @@
},
},
{
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Lenovo ThinkPad T410",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Lenovo ThinkPad T510",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Lenovo ThinkPad W510",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Lenovo ThinkPad X201[s]",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"),
+ },
+ },
+ {
.callback = init_old_suspend_ordering,
.ident = "Panasonic CF51-2L",
.matches = {
@@ -458,6 +490,30 @@
DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
},
},
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Dell Studio 1558",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1558"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Dell Studio 1557",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"),
+ },
+ },
+ {
+ .callback = init_set_sci_en_on_resume,
+ .ident = "Dell Studio 1555",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1555"),
+ },
+ },
{},
};
#endif /* CONFIG_SUSPEND */
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c
index 8ad4ffe..6e6b6a1 100644
--- a/drivers/base/iommu.c
+++ b/drivers/base/iommu.c
@@ -80,20 +80,6 @@
}
EXPORT_SYMBOL_GPL(iommu_detach_device);
-int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
- phys_addr_t paddr, size_t size, int prot)
-{
- return iommu_ops->map(domain, iova, paddr, size, prot);
-}
-EXPORT_SYMBOL_GPL(iommu_map_range);
-
-void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
- size_t size)
-{
- iommu_ops->unmap(domain, iova, size);
-}
-EXPORT_SYMBOL_GPL(iommu_unmap_range);
-
phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long iova)
{
@@ -107,3 +93,32 @@
return iommu_ops->domain_has_cap(domain, cap);
}
EXPORT_SYMBOL_GPL(iommu_domain_has_cap);
+
+int iommu_map(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, int gfp_order, int prot)
+{
+ unsigned long invalid_mask;
+ size_t size;
+
+ size = 0x1000UL << gfp_order;
+ invalid_mask = size - 1;
+
+ BUG_ON((iova | paddr) & invalid_mask);
+
+ return iommu_ops->map(domain, iova, paddr, gfp_order, prot);
+}
+EXPORT_SYMBOL_GPL(iommu_map);
+
+int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order)
+{
+ unsigned long invalid_mask;
+ size_t size;
+
+ size = 0x1000UL << gfp_order;
+ invalid_mask = size - 1;
+
+ BUG_ON(iova & invalid_mask);
+
+ return iommu_ops->unmap(domain, iova, gfp_order);
+}
+EXPORT_SYMBOL_GPL(iommu_unmap);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 4b4b565..c5fbe19 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -187,7 +187,7 @@
* released.
*/
int platform_device_add_resources(struct platform_device *pdev,
- struct resource *res, unsigned int num)
+ const struct resource *res, unsigned int num)
{
struct resource *r;
@@ -367,7 +367,7 @@
*/
struct platform_device *platform_device_register_simple(const char *name,
int id,
- struct resource *res,
+ const struct resource *res,
unsigned int num)
{
struct platform_device *pdev;
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 0182a22..832798a 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -66,6 +66,7 @@
#include <linux/blkdev.h>
#include <linux/elevator.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
@@ -1696,34 +1697,18 @@
return get_disk(unit[drive].gendisk);
}
-static int __init amiga_floppy_init(void)
+static int __init amiga_floppy_probe(struct platform_device *pdev)
{
int i, ret;
- if (!MACH_IS_AMIGA)
- return -ENODEV;
-
- if (!AMIGAHW_PRESENT(AMI_FLOPPY))
- return -ENODEV;
-
if (register_blkdev(FLOPPY_MAJOR,"fd"))
return -EBUSY;
- /*
- * We request DSKPTR, DSKLEN and DSKDATA only, because the other
- * floppy registers are too spreaded over the custom register space
- */
- ret = -EBUSY;
- if (!request_mem_region(CUSTOM_PHYSADDR+0x20, 8, "amiflop [Paula]")) {
- printk("fd: cannot get floppy registers\n");
- goto out_blkdev;
- }
-
ret = -ENOMEM;
if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) ==
NULL) {
printk("fd: cannot get chip mem buffer\n");
- goto out_memregion;
+ goto out_blkdev;
}
ret = -EBUSY;
@@ -1792,18 +1777,13 @@
free_irq(IRQ_AMIGA_DSKBLK, NULL);
out_irq:
amiga_chip_free(raw_buf);
-out_memregion:
- release_mem_region(CUSTOM_PHYSADDR+0x20, 8);
out_blkdev:
unregister_blkdev(FLOPPY_MAJOR,"fd");
return ret;
}
-module_init(amiga_floppy_init);
-#ifdef MODULE
-
#if 0 /* not safe to unload */
-void cleanup_module(void)
+static int __exit amiga_floppy_remove(struct platform_device *pdev)
{
int i;
@@ -1820,12 +1800,25 @@
custom.dmacon = DMAF_DISK; /* disable DMA */
amiga_chip_free(raw_buf);
blk_cleanup_queue(floppy_queue);
- release_mem_region(CUSTOM_PHYSADDR+0x20, 8);
unregister_blkdev(FLOPPY_MAJOR, "fd");
}
#endif
-#else
+static struct platform_driver amiga_floppy_driver = {
+ .driver = {
+ .name = "amiga-floppy",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init amiga_floppy_init(void)
+{
+ return platform_driver_probe(&amiga_floppy_driver, amiga_floppy_probe);
+}
+
+module_init(amiga_floppy_init);
+
+#ifndef MODULE
static int __init amiga_floppy_setup (char *str)
{
int n;
@@ -1840,3 +1833,5 @@
__setup("floppy=", amiga_floppy_setup);
#endif
+
+MODULE_ALIAS("platform:amiga-floppy");
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 44bf6d1..d48a1df 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -235,7 +235,7 @@
if (unlikely(error)) {
what = (bio_data_dir(bio) == WRITE)
? write_completed_with_error
- : (bio_rw(bio) == READA)
+ : (bio_rw(bio) == READ)
? read_completed_with_error
: read_ahead_completed_with_error;
} else
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index 034e6df..81c78b3 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -164,12 +164,12 @@
unsigned long t, flags;
int i;
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
t = jiffies * 11932;
outb_p(0, 0x43);
i = inb_p(0x40);
i |= inb(0x40) << 8;
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
return(t - i);
}
#endif
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 8dfd247..78a62eb 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -627,7 +627,6 @@
char data;
int char_count;
int save_cnt;
- int len;
/* determine the channel and change to that context */
channel = (u_short) (base_addr[CyLICR] >> 2);
@@ -1528,7 +1527,6 @@
cy_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- unsigned long val;
struct cyclades_port *info = tty->driver_data;
int ret_val = 0;
void __user *argp = (void __user *)arg;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 6da962c..d71f0fc 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1875,6 +1875,7 @@
*/
if (filp->f_op == &hung_up_tty_fops)
filp->f_op = &tty_fops;
+ unlock_kernel();
goto retry_open;
}
unlock_kernel();
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 75d293e..063b218 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -662,32 +662,20 @@
return sprintf(buf, "%u\n", policy->cpuinfo.max_freq);
}
-#define define_one_ro(_name) \
-static struct freq_attr _name = \
-__ATTR(_name, 0444, show_##_name, NULL)
-
-#define define_one_ro0400(_name) \
-static struct freq_attr _name = \
-__ATTR(_name, 0400, show_##_name, NULL)
-
-#define define_one_rw(_name) \
-static struct freq_attr _name = \
-__ATTR(_name, 0644, show_##_name, store_##_name)
-
-define_one_ro0400(cpuinfo_cur_freq);
-define_one_ro(cpuinfo_min_freq);
-define_one_ro(cpuinfo_max_freq);
-define_one_ro(cpuinfo_transition_latency);
-define_one_ro(scaling_available_governors);
-define_one_ro(scaling_driver);
-define_one_ro(scaling_cur_freq);
-define_one_ro(bios_limit);
-define_one_ro(related_cpus);
-define_one_ro(affected_cpus);
-define_one_rw(scaling_min_freq);
-define_one_rw(scaling_max_freq);
-define_one_rw(scaling_governor);
-define_one_rw(scaling_setspeed);
+cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400);
+cpufreq_freq_attr_ro(cpuinfo_min_freq);
+cpufreq_freq_attr_ro(cpuinfo_max_freq);
+cpufreq_freq_attr_ro(cpuinfo_transition_latency);
+cpufreq_freq_attr_ro(scaling_available_governors);
+cpufreq_freq_attr_ro(scaling_driver);
+cpufreq_freq_attr_ro(scaling_cur_freq);
+cpufreq_freq_attr_ro(bios_limit);
+cpufreq_freq_attr_ro(related_cpus);
+cpufreq_freq_attr_ro(affected_cpus);
+cpufreq_freq_attr_rw(scaling_min_freq);
+cpufreq_freq_attr_rw(scaling_max_freq);
+cpufreq_freq_attr_rw(scaling_governor);
+cpufreq_freq_attr_rw(scaling_setspeed);
static struct attribute *default_attrs[] = {
&cpuinfo_min_freq.attr,
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 3a14787..526bfbf 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -178,12 +178,8 @@
return sprintf(buf, "%u\n", min_sampling_rate);
}
-#define define_one_ro(_name) \
-static struct global_attr _name = \
-__ATTR(_name, 0444, show_##_name, NULL)
-
-define_one_ro(sampling_rate_max);
-define_one_ro(sampling_rate_min);
+define_one_global_ro(sampling_rate_max);
+define_one_global_ro(sampling_rate_min);
/* cpufreq_conservative Governor Tunables */
#define show_one(file_name, object) \
@@ -221,12 +217,8 @@
show_one_old(sampling_rate_min);
show_one_old(sampling_rate_max);
-#define define_one_ro_old(object, _name) \
-static struct freq_attr object = \
-__ATTR(_name, 0444, show_##_name##_old, NULL)
-
-define_one_ro_old(sampling_rate_min_old, sampling_rate_min);
-define_one_ro_old(sampling_rate_max_old, sampling_rate_max);
+cpufreq_freq_attr_ro_old(sampling_rate_min);
+cpufreq_freq_attr_ro_old(sampling_rate_max);
/*** delete after deprecation time ***/
@@ -364,16 +356,12 @@
return count;
}
-#define define_one_rw(_name) \
-static struct global_attr _name = \
-__ATTR(_name, 0644, show_##_name, store_##_name)
-
-define_one_rw(sampling_rate);
-define_one_rw(sampling_down_factor);
-define_one_rw(up_threshold);
-define_one_rw(down_threshold);
-define_one_rw(ignore_nice_load);
-define_one_rw(freq_step);
+define_one_global_rw(sampling_rate);
+define_one_global_rw(sampling_down_factor);
+define_one_global_rw(up_threshold);
+define_one_global_rw(down_threshold);
+define_one_global_rw(ignore_nice_load);
+define_one_global_rw(freq_step);
static struct attribute *dbs_attributes[] = {
&sampling_rate_max.attr,
@@ -409,16 +397,12 @@
write_one_old(ignore_nice_load);
write_one_old(freq_step);
-#define define_one_rw_old(object, _name) \
-static struct freq_attr object = \
-__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old)
-
-define_one_rw_old(sampling_rate_old, sampling_rate);
-define_one_rw_old(sampling_down_factor_old, sampling_down_factor);
-define_one_rw_old(up_threshold_old, up_threshold);
-define_one_rw_old(down_threshold_old, down_threshold);
-define_one_rw_old(ignore_nice_load_old, ignore_nice_load);
-define_one_rw_old(freq_step_old, freq_step);
+cpufreq_freq_attr_rw_old(sampling_rate);
+cpufreq_freq_attr_rw_old(sampling_down_factor);
+cpufreq_freq_attr_rw_old(up_threshold);
+cpufreq_freq_attr_rw_old(down_threshold);
+cpufreq_freq_attr_rw_old(ignore_nice_load);
+cpufreq_freq_attr_rw_old(freq_step);
static struct attribute *dbs_attributes_old[] = {
&sampling_rate_max_old.attr,
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 8e9dbdc..e131421 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -246,12 +246,8 @@
return sprintf(buf, "%u\n", min_sampling_rate);
}
-#define define_one_ro(_name) \
-static struct global_attr _name = \
-__ATTR(_name, 0444, show_##_name, NULL)
-
-define_one_ro(sampling_rate_max);
-define_one_ro(sampling_rate_min);
+define_one_global_ro(sampling_rate_max);
+define_one_global_ro(sampling_rate_min);
/* cpufreq_ondemand Governor Tunables */
#define show_one(file_name, object) \
@@ -287,12 +283,8 @@
show_one_old(sampling_rate_min);
show_one_old(sampling_rate_max);
-#define define_one_ro_old(object, _name) \
-static struct freq_attr object = \
-__ATTR(_name, 0444, show_##_name##_old, NULL)
-
-define_one_ro_old(sampling_rate_min_old, sampling_rate_min);
-define_one_ro_old(sampling_rate_max_old, sampling_rate_max);
+cpufreq_freq_attr_ro_old(sampling_rate_min);
+cpufreq_freq_attr_ro_old(sampling_rate_max);
/*** delete after deprecation time ***/
@@ -406,15 +398,11 @@
return count;
}
-#define define_one_rw(_name) \
-static struct global_attr _name = \
-__ATTR(_name, 0644, show_##_name, store_##_name)
-
-define_one_rw(sampling_rate);
-define_one_rw(io_is_busy);
-define_one_rw(up_threshold);
-define_one_rw(ignore_nice_load);
-define_one_rw(powersave_bias);
+define_one_global_rw(sampling_rate);
+define_one_global_rw(io_is_busy);
+define_one_global_rw(up_threshold);
+define_one_global_rw(ignore_nice_load);
+define_one_global_rw(powersave_bias);
static struct attribute *dbs_attributes[] = {
&sampling_rate_max.attr,
@@ -447,14 +435,10 @@
write_one_old(ignore_nice_load);
write_one_old(powersave_bias);
-#define define_one_rw_old(object, _name) \
-static struct freq_attr object = \
-__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old)
-
-define_one_rw_old(sampling_rate_old, sampling_rate);
-define_one_rw_old(up_threshold_old, up_threshold);
-define_one_rw_old(ignore_nice_load_old, ignore_nice_load);
-define_one_rw_old(powersave_bias_old, powersave_bias);
+cpufreq_freq_attr_rw_old(sampling_rate);
+cpufreq_freq_attr_rw_old(up_threshold);
+cpufreq_freq_attr_rw_old(ignore_nice_load);
+cpufreq_freq_attr_rw_old(powersave_bias);
static struct attribute *dbs_attributes_old[] = {
&sampling_rate_max_old.attr,
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 1aea715..f8e57c6 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -100,7 +100,6 @@
int needs_update;
unsigned int expected_us;
- unsigned int measured_us;
u64 predicted_us;
unsigned int exit_us;
unsigned int bucket;
@@ -187,14 +186,14 @@
int i;
int multiplier;
- data->last_state_idx = 0;
- data->exit_us = 0;
-
if (data->needs_update) {
menu_update(dev);
data->needs_update = 0;
}
+ data->last_state_idx = 0;
+ data->exit_us = 0;
+
/* Special case when user has set very strict latency requirement */
if (unlikely(latency_req == 0))
return 0;
@@ -294,7 +293,7 @@
new_factor = data->correction_factor[data->bucket]
* (DECAY - 1) / DECAY;
- if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING)
+ if (data->expected_us > 0 && measured_us < MAX_INTERESTING)
new_factor += RESOLUTION * measured_us / data->expected_us;
else
/*
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 7cc31b3..6f25a20 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -290,6 +290,7 @@
struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
struct sh_desc *desc;
struct sh_dmae_slave *param = chan->private;
+ int ret;
pm_runtime_get_sync(sh_chan->dev);
@@ -301,11 +302,15 @@
struct sh_dmae_slave_config *cfg;
cfg = sh_dmae_find_slave(sh_chan, param->slave_id);
- if (!cfg)
- return -EINVAL;
+ if (!cfg) {
+ ret = -EINVAL;
+ goto efindslave;
+ }
- if (test_and_set_bit(param->slave_id, sh_dmae_slave_used))
- return -EBUSY;
+ if (test_and_set_bit(param->slave_id, sh_dmae_slave_used)) {
+ ret = -EBUSY;
+ goto etestused;
+ }
param->config = cfg;
@@ -334,10 +339,20 @@
}
spin_unlock_bh(&sh_chan->desc_lock);
- if (!sh_chan->descs_allocated)
- pm_runtime_put(sh_chan->dev);
+ if (!sh_chan->descs_allocated) {
+ ret = -ENOMEM;
+ goto edescalloc;
+ }
return sh_chan->descs_allocated;
+
+edescalloc:
+ if (param)
+ clear_bit(param->slave_id, sh_dmae_slave_used);
+etestused:
+efindslave:
+ pm_runtime_put(sh_chan->dev);
+ return ret;
}
/*
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c
index 753219c..41a9388 100644
--- a/drivers/gpio/it8761e_gpio.c
+++ b/drivers/gpio/it8761e_gpio.c
@@ -80,8 +80,8 @@
u16 reg;
u8 bit;
- bit = gpio_num % 7;
- reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba;
+ bit = gpio_num % 8;
+ reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
return !!(inb(reg) & (1 << bit));
}
@@ -91,8 +91,8 @@
u8 curr_dirs;
u8 io_reg, bit;
- bit = gpio_num % 7;
- io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO;
+ bit = gpio_num % 8;
+ io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
spin_lock(&sio_lock);
@@ -116,8 +116,8 @@
u8 curr_vals, bit;
u16 reg;
- bit = gpio_num % 7;
- reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba;
+ bit = gpio_num % 8;
+ reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba;
spin_lock(&sio_lock);
@@ -135,8 +135,8 @@
{
u8 curr_dirs, io_reg, bit;
- bit = gpio_num % 7;
- io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO;
+ bit = gpio_num % 8;
+ io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO;
it8761e_gpio_set(gc, gpio_num, val);
@@ -200,7 +200,7 @@
return -EBUSY;
it8761e_gpio_chip.base = -1;
- it8761e_gpio_chip.ngpio = 14;
+ it8761e_gpio_chip.ngpio = 16;
err = gpiochip_add(&it8761e_gpio_chip);
if (err < 0)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2b8b969..df6a9cd 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -456,11 +456,15 @@
for (page = 0; page < page_count; page++) {
void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
+ unsigned long flags;
+
if (d == NULL)
goto unwind;
- s = kmap_atomic(src_priv->pages[page], KM_USER0);
+ local_irq_save(flags);
+ s = kmap_atomic(src_priv->pages[page], KM_IRQ0);
memcpy(d, s, PAGE_SIZE);
- kunmap_atomic(s, KM_USER0);
+ kunmap_atomic(s, KM_IRQ0);
+ local_irq_restore(flags);
dst->pages[page] = d;
}
dst->page_count = page_count;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 4b05563..b3749d4 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -216,6 +216,7 @@
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .read = drm_read,
#ifdef CONFIG_COMPAT
.compat_ioctl = radeon_compat_ioctl,
#endif
@@ -304,6 +305,7 @@
.mmap = radeon_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+ .read = drm_read,
#ifdef CONFIG_COMPAT
.compat_ioctl = radeon_kms_compat_ioctl,
#endif
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
index 40ab6d9..cc5316d 100644
--- a/drivers/gpu/drm/radeon/radeon_state.c
+++ b/drivers/gpu/drm/radeon/radeon_state.c
@@ -424,7 +424,7 @@
if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
(*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
- offset = *cmd << 10;
+ offset = *cmd3 << 10;
if (radeon_check_and_fixup_offset
(dev_priv, file_priv, &offset)) {
DRM_ERROR("Invalid second packet offset\n");
@@ -2895,9 +2895,12 @@
return rv;
rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,
cmdbuf->bufsz);
- if (rv)
+ if (rv) {
+ drm_buffer_free(cmdbuf->buffer);
return rv;
- }
+ }
+ } else
+ goto done;
orig_nbox = cmdbuf->nbox;
@@ -2905,8 +2908,7 @@
int temp;
temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
- if (cmdbuf->bufsz != 0)
- drm_buffer_free(cmdbuf->buffer);
+ drm_buffer_free(cmdbuf->buffer);
return temp;
}
@@ -3012,16 +3014,15 @@
}
}
- if (cmdbuf->bufsz != 0)
- drm_buffer_free(cmdbuf->buffer);
+ drm_buffer_free(cmdbuf->buffer);
+ done:
DRM_DEBUG("DONE\n");
COMMIT_RING();
return 0;
err:
- if (cmdbuf->bufsz != 0)
- drm_buffer_free(cmdbuf->buffer);
+ drm_buffer_free(cmdbuf->buffer);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index dd47b2a..0e3754a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1716,40 +1716,12 @@
}
EXPORT_SYMBOL(ttm_bo_wait);
-void ttm_bo_unblock_reservation(struct ttm_buffer_object *bo)
-{
- atomic_set(&bo->reserved, 0);
- wake_up_all(&bo->event_queue);
-}
-
-int ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible,
- bool no_wait)
-{
- int ret;
-
- while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
- if (no_wait)
- return -EBUSY;
- else if (interruptible) {
- ret = wait_event_interruptible
- (bo->event_queue, atomic_read(&bo->reserved) == 0);
- if (unlikely(ret != 0))
- return ret;
- } else {
- wait_event(bo->event_queue,
- atomic_read(&bo->reserved) == 0);
- }
- }
- return 0;
-}
-
int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait)
{
int ret = 0;
/*
- * Using ttm_bo_reserve instead of ttm_bo_block_reservation
- * makes sure the lru lists are updated.
+ * Using ttm_bo_reserve makes sure the lru lists are updated.
*/
ret = ttm_bo_reserve(bo, true, no_wait, false, 0);
diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c
index 3d172ef..de41e55 100644
--- a/drivers/gpu/drm/ttm/ttm_lock.c
+++ b/drivers/gpu/drm/ttm/ttm_lock.c
@@ -204,7 +204,6 @@
lock->flags &= ~TTM_VT_LOCK;
wake_up_all(&lock->queue);
spin_unlock(&lock->lock);
- printk(KERN_INFO TTM_PFX "vt unlock.\n");
return ret;
}
@@ -265,10 +264,8 @@
ttm_lock_type, &ttm_vt_lock_remove, NULL);
if (ret)
(void)__ttm_vt_unlock(lock);
- else {
+ else
lock->vt_holder = tfile;
- printk(KERN_INFO TTM_PFX "vt lock.\n");
- }
return ret;
}
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c
index 7e597d7..24663a8 100644
--- a/drivers/hid/hid-cherry.c
+++ b/drivers/hid/hid-cherry.c
@@ -59,6 +59,7 @@
static const struct hid_device_id ch_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
{ }
};
MODULE_DEVICE_TABLE(hid, ch_devices);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 2e2aa75..143e788 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1043,13 +1043,8 @@
if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
hid->hiddev_report_event(hid, report);
- if (hid->claimed & HID_CLAIMED_HIDRAW) {
- /* numbered reports need to be passed with the report num */
- if (report_enum->numbered)
- hidraw_report_event(hid, data - 1, size + 1);
- else
- hidraw_report_event(hid, data, size);
- }
+ if (hid->claimed & HID_CLAIMED_HIDRAW)
+ hidraw_report_event(hid, data, size);
for (a = 0; a < report->maxfield; a++)
hid_input_field(hid, report->field[a], cdata, interrupt);
@@ -1296,6 +1291,7 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 797e064..09d2764 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -131,6 +131,7 @@
#define USB_VENDOR_ID_CHERRY 0x046a
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
+#define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR 0x0027
#define USB_VENDOR_ID_CHIC 0x05fe
#define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 9b24fc5..4777bbf 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -1,8 +1,8 @@
/*
* HID driver for N-Trig touchscreens
*
- * Copyright (c) 2008 Rafi Rubin
- * Copyright (c) 2009 Stephane Chatty
+ * Copyright (c) 2008-2010 Rafi Rubin
+ * Copyright (c) 2009-2010 Stephane Chatty
*
*/
@@ -15,6 +15,8 @@
#include <linux/device.h>
#include <linux/hid.h>
+#include <linux/usb.h>
+#include "usbhid/usbhid.h"
#include <linux/module.h>
#include <linux/slab.h>
@@ -22,17 +24,16 @@
#define NTRIG_DUPLICATE_USAGES 0x001
-#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
- EV_KEY, (c))
-
struct ntrig_data {
/* Incoming raw values for a single contact */
__u16 x, y, w, h;
__u16 id;
- __u8 confidence;
+
+ bool tipswitch;
+ bool confidence;
+ bool first_contact_touch;
bool reading_mt;
- __u8 first_contact_confidence;
__u8 mt_footer[4];
__u8 mt_foot_count;
@@ -139,9 +140,10 @@
case 0xff000001:
/* Tag indicating the start of a multitouch group */
nd->reading_mt = 1;
- nd->first_contact_confidence = 0;
+ nd->first_contact_touch = 0;
break;
case HID_DG_TIPSWITCH:
+ nd->tipswitch = value;
/* Prevent emission of touch until validated */
return 1;
case HID_DG_CONFIDENCE:
@@ -169,8 +171,14 @@
* to emit a normal (X, Y) position
*/
if (!nd->reading_mt) {
+ /*
+ * TipSwitch indicates the presence of a
+ * finger in single touch mode.
+ */
+ input_report_key(input, BTN_TOUCH,
+ nd->tipswitch);
input_report_key(input, BTN_TOOL_DOUBLETAP,
- (nd->confidence != 0));
+ nd->tipswitch);
input_event(input, EV_ABS, ABS_X, nd->x);
input_event(input, EV_ABS, ABS_Y, nd->y);
}
@@ -209,7 +217,13 @@
/* emit a normal (X, Y) for the first point only */
if (nd->id == 0) {
- nd->first_contact_confidence = nd->confidence;
+ /*
+ * TipSwitch is superfluous in multitouch
+ * mode. The footer events tell us
+ * if there is a finger on the screen or
+ * not.
+ */
+ nd->first_contact_touch = nd->confidence;
input_event(input, EV_ABS, ABS_X, nd->x);
input_event(input, EV_ABS, ABS_Y, nd->y);
}
@@ -239,30 +253,11 @@
nd->reading_mt = 0;
- if (nd->first_contact_confidence) {
- switch (value) {
- case 0: /* for single touch devices */
- case 1:
- input_report_key(input,
- BTN_TOOL_DOUBLETAP, 1);
- break;
- case 2:
- input_report_key(input,
- BTN_TOOL_TRIPLETAP, 1);
- break;
- case 3:
- default:
- input_report_key(input,
- BTN_TOOL_QUADTAP, 1);
- }
+ if (nd->first_contact_touch) {
+ input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
input_report_key(input, BTN_TOUCH, 1);
} else {
- input_report_key(input,
- BTN_TOOL_DOUBLETAP, 0);
- input_report_key(input,
- BTN_TOOL_TRIPLETAP, 0);
- input_report_key(input,
- BTN_TOOL_QUADTAP, 0);
+ input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
input_report_key(input, BTN_TOUCH, 0);
}
break;
@@ -286,6 +281,7 @@
struct ntrig_data *nd;
struct hid_input *hidinput;
struct input_dev *input;
+ struct hid_report *report;
if (id->driver_data)
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
@@ -327,13 +323,7 @@
__clear_bit(BTN_TOOL_PEN, input->keybit);
__clear_bit(BTN_TOOL_FINGER, input->keybit);
__clear_bit(BTN_0, input->keybit);
- /*
- * A little something special to enable
- * two and three finger taps.
- */
__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
- __set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
- __set_bit(BTN_TOOL_QUADTAP, input->keybit);
/*
* The physical touchscreen (single touch)
* input has a value for physical, whereas
@@ -349,6 +339,12 @@
}
}
+ /* This is needed for devices with more recent firmware versions */
+ report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a];
+ if (report)
+ usbhid_submit_report(hdev, report, USB_DIR_OUT);
+
+
return 0;
err_free:
kfree(nd);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 7502a4b..402d557 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -76,7 +76,7 @@
static int sony_set_operational_bt(struct hid_device *hdev)
{
- unsigned char buf[] = { 0x53, 0xf4, 0x42, 0x03, 0x00, 0x00 };
+ unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 };
return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
}
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index f7700cf..f947d83 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -277,7 +277,6 @@
ret = hid_register_driver(&wacom_driver);
if (ret)
printk(KERN_ERR "can't register wacom driver\n");
- printk(KERN_ERR "wacom driver registered\n");
return ret;
}
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 56d06cd..7b85b69 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -999,13 +999,6 @@
}
}
- init_waitqueue_head(&usbhid->wait);
- INIT_WORK(&usbhid->reset_work, hid_reset);
- INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
- setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
-
- spin_lock_init(&usbhid->lock);
-
usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
if (!usbhid->urbctrl) {
ret = -ENOMEM;
@@ -1179,6 +1172,12 @@
usbhid->intf = intf;
usbhid->ifnum = interface->desc.bInterfaceNumber;
+ init_waitqueue_head(&usbhid->wait);
+ INIT_WORK(&usbhid->reset_work, hid_reset);
+ INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
+ setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+ spin_lock_init(&usbhid->lock);
+
ret = hid_add_device(hid);
if (ret) {
if (ret != -ENODEV)
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 0f28d91..f085c18 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -195,6 +195,9 @@
/* Indicates whether this computer has light sensors and keyboard backlight. */
static unsigned int applesmc_light;
+/* The number of fans handled by the driver */
+static unsigned int fans_handled;
+
/* Indicates which temperature sensors set to use. */
static unsigned int applesmc_temperature_set;
@@ -1492,39 +1495,24 @@
/* create fan files */
count = applesmc_get_fan_count();
- if (count < 0) {
+ if (count < 0)
printk(KERN_ERR "applesmc: Cannot get the number of fans.\n");
- } else {
+ else
printk(KERN_INFO "applesmc: %d fans found.\n", count);
- switch (count) {
- default:
- printk(KERN_WARNING "applesmc: More than 4 fans found,"
- " but at most 4 fans are supported"
- " by the driver.\n");
- case 4:
- ret = sysfs_create_group(&pdev->dev.kobj,
- &fan_attribute_groups[3]);
- if (ret)
- goto out_key_enumeration;
- case 3:
- ret = sysfs_create_group(&pdev->dev.kobj,
- &fan_attribute_groups[2]);
- if (ret)
- goto out_key_enumeration;
- case 2:
- ret = sysfs_create_group(&pdev->dev.kobj,
- &fan_attribute_groups[1]);
- if (ret)
- goto out_key_enumeration;
- case 1:
- ret = sysfs_create_group(&pdev->dev.kobj,
- &fan_attribute_groups[0]);
- if (ret)
- goto out_fan_1;
- case 0:
- ;
- }
+ if (count > 4) {
+ count = 4;
+ printk(KERN_WARNING "applesmc: More than 4 fans found,"
+ " but at most 4 fans are supported"
+ " by the driver.\n");
+ }
+
+ while (fans_handled < count) {
+ ret = sysfs_create_group(&pdev->dev.kobj,
+ &fan_attribute_groups[fans_handled]);
+ if (ret)
+ goto out_fans;
+ fans_handled++;
}
for (i = 0;
@@ -1593,10 +1581,10 @@
applesmc_release_accelerometer();
out_temperature:
sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
- sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
-out_fan_1:
- sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
-out_key_enumeration:
+out_fans:
+ while (fans_handled)
+ sysfs_remove_group(&pdev->dev.kobj,
+ &fan_attribute_groups[--fans_handled]);
sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
out_name:
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
@@ -1622,8 +1610,9 @@
if (applesmc_accelerometer)
applesmc_release_accelerometer();
sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group);
- sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]);
- sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]);
+ while (fans_handled)
+ sysfs_remove_group(&pdev->dev.kobj,
+ &fan_attribute_groups[--fans_handled]);
sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group);
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr);
platform_device_unregister(pdev);
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 7f94810..0f388ad 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -268,8 +268,11 @@
if (strict_strtol(buf, 10, &reqval))
return -EINVAL;
+ /* If a minimum RPM of zero is requested, then we set the register to
+ 0xffff. This value allows the fan to be stopped completely without
+ generating an alarm. */
reqval =
- (SENSORS_LIMIT((reqval) <= 0 ? 0 : 5400000 / (reqval), 0, 65534));
+ (reqval <= 0 ? 0xffff : SENSORS_LIMIT(5400000 / reqval, 0, 0xfffe));
mutex_lock(&data->update_lock);
data->reg[param->msb[0]] = (reqval >> 8) & 0xff;
@@ -285,8 +288,9 @@
* Voltages are scaled in the device so that the nominal voltage
* is 3/4ths of the 0-255 range (i.e. 192).
* If all voltages are 'normal' then all voltage registers will
- * read 0xC0. This doesn't help us if we don't have a point of refernce.
- * The data sheet however provides us with the full scale value for each
+ * read 0xC0.
+ *
+ * The data sheet provides us with the 3/4 scale value for each voltage
* which is stored in in_scaling. The sda->index parameter value provides
* the index into in_scaling.
*
@@ -295,7 +299,7 @@
*/
static int asc7621_in_scaling[] = {
- 3320, 3000, 4380, 6640, 16000
+ 2500, 2250, 3300, 5000, 12000
};
static ssize_t show_in10(struct device *dev, struct device_attribute *attr,
@@ -306,19 +310,12 @@
u8 nr = sda->index;
mutex_lock(&data->update_lock);
- regval = (data->reg[param->msb[0]] * asc7621_in_scaling[nr]) / 256;
-
- /* The LSB value is a 2-bit scaling of the MSB's LSbit value.
- * I.E. If the maximim voltage for this input is 6640 millivolts then
- * a MSB register value of 0 = 0mv and 255 = 6640mv.
- * A 1 step change therefore represents 25.9mv (6640 / 256).
- * The extra 2-bits therefore represent increments of 6.48mv.
- */
- regval += ((asc7621_in_scaling[nr] / 256) / 4) *
- (data->reg[param->lsb[0]] >> 6);
-
+ regval = (data->reg[param->msb[0]] << 8) | (data->reg[param->lsb[0]]);
mutex_unlock(&data->update_lock);
+ /* The LSB value is a 2-bit scaling of the MSB's LSbit value. */
+ regval = (regval >> 6) * asc7621_in_scaling[nr] / (0xc0 << 2);
+
return sprintf(buf, "%u\n", regval);
}
@@ -331,7 +328,7 @@
return sprintf(buf, "%u\n",
((data->reg[param->msb[0]] *
- asc7621_in_scaling[nr]) / 256));
+ asc7621_in_scaling[nr]) / 0xc0));
}
static ssize_t store_in8(struct device *dev, struct device_attribute *attr,
@@ -344,9 +341,11 @@
if (strict_strtol(buf, 10, &reqval))
return -EINVAL;
- reqval = SENSORS_LIMIT(reqval, 0, asc7621_in_scaling[nr]);
+ reqval = SENSORS_LIMIT(reqval, 0, 0xffff);
- reqval = (reqval * 255 + 128) / asc7621_in_scaling[nr];
+ reqval = reqval * 0xc0 / asc7621_in_scaling[nr];
+
+ reqval = SENSORS_LIMIT(reqval, 0, 0xff);
mutex_lock(&data->update_lock);
data->reg[param->msb[0]] = reqval;
@@ -846,11 +845,11 @@
PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8),
PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8),
- PREAD(in0_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 0, bitmask),
- PREAD(in1_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 1, bitmask),
- PREAD(in2_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 2, bitmask),
- PREAD(in3_alarm, 3, PRI_LOW, 0x41, 0, 0x01, 3, bitmask),
- PREAD(in4_alarm, 4, PRI_LOW, 0x42, 0, 0x01, 0, bitmask),
+ PREAD(in0_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 0, bitmask),
+ PREAD(in1_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 1, bitmask),
+ PREAD(in2_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 2, bitmask),
+ PREAD(in3_alarm, 3, PRI_HIGH, 0x41, 0, 0x01, 3, bitmask),
+ PREAD(in4_alarm, 4, PRI_HIGH, 0x42, 0, 0x01, 0, bitmask),
PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16),
PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16),
@@ -862,10 +861,10 @@
PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16),
PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16),
- PREAD(fan1_alarm, 0, PRI_LOW, 0x42, 0, 0x01, 0, bitmask),
- PREAD(fan2_alarm, 1, PRI_LOW, 0x42, 0, 0x01, 1, bitmask),
- PREAD(fan3_alarm, 2, PRI_LOW, 0x42, 0, 0x01, 2, bitmask),
- PREAD(fan4_alarm, 3, PRI_LOW, 0x42, 0, 0x01, 3, bitmask),
+ PREAD(fan1_alarm, 0, PRI_HIGH, 0x42, 0, 0x01, 2, bitmask),
+ PREAD(fan2_alarm, 1, PRI_HIGH, 0x42, 0, 0x01, 3, bitmask),
+ PREAD(fan3_alarm, 2, PRI_HIGH, 0x42, 0, 0x01, 4, bitmask),
+ PREAD(fan4_alarm, 3, PRI_HIGH, 0x42, 0, 0x01, 5, bitmask),
PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10),
PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10),
@@ -886,10 +885,10 @@
PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8),
PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8),
- PREAD(temp1_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 4, bitmask),
- PREAD(temp2_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 5, bitmask),
- PREAD(temp3_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 6, bitmask),
- PREAD(temp4_alarm, 3, PRI_LOW, 0x43, 0, 0x01, 0, bitmask),
+ PREAD(temp1_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 4, bitmask),
+ PREAD(temp2_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 5, bitmask),
+ PREAD(temp3_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 6, bitmask),
+ PREAD(temp4_alarm, 3, PRI_HIGH, 0x43, 0, 0x01, 0, bitmask),
PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask),
PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask),
@@ -898,7 +897,7 @@
PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask),
PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask),
- PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x64, 0, 0x01, 3, bitmask),
+ PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x63, 0, 0x01, 3, bitmask),
PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask),
PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st),
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index c8ab505..7580f55 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -328,8 +328,8 @@
lis3lv02d_joystick_disable();
lis3lv02d_poweroff(&lis3_dev);
- flush_work(&hpled_led.work);
led_classdev_unregister(&hpled_led.led_classdev);
+ flush_work(&hpled_led.work);
return lis3lv02d_remove_fs(&lis3_dev);
}
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 7e18bcf..46239e4 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -59,11 +59,11 @@
unsigned long flags;
unsigned int count;
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x00, 0x43);
count = inb_p(0x40);
count |= inb_p(0x40) << 8;
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
return count;
}
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 1c0b529..4afe0a3 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -146,11 +146,11 @@
unsigned long flags;
unsigned int count;
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x00, 0x43);
count = inb_p(0x40);
count |= inb_p(0x40) << 8;
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
return count;
}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index b1edd77..405febd 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -54,6 +54,9 @@
static signed short abs_joystick[] =
{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
+static signed short abs_joystick_rudder[] =
+{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, -1 };
+
static signed short abs_avb_pegasus[] =
{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y,
ABS_HAT1X, ABS_HAT1Y, -1 };
@@ -76,8 +79,9 @@
{ 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
{ 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce },
{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
+ { 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce },
{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
- { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //?
+ { 0x06f8, 0xa302, "Guillemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //?
{ 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce },
{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
};
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index b41303d..6c96631 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -212,6 +212,7 @@
{ USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */
{ USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */
{ USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
+ { USB_DEVICE(0x06f8, 0x0003) }, /* Guillemot Jet Leader Force Feedback */
{ USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */
{ USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */
{ } /* Terminating entry */
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index ea4e1fd..f080dd3 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -30,7 +30,7 @@
#include <asm/i8253.h>
#else
#include <asm/8253pit.h>
-static DEFINE_SPINLOCK(i8253_lock);
+static DEFINE_RAW_SPINLOCK(i8253_lock);
#endif
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -50,7 +50,7 @@
if (value > 20 && value < 32767)
count = PIT_TICK_RATE / value;
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
if (count) {
/* set command for counter 2, 2 byte write */
@@ -65,7 +65,7 @@
outb(inb_p(0x61) & 0xFC, 0x61);
}
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
return 0;
}
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 0520c2e..112b4ee 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -185,7 +185,7 @@
int fingers;
static int old_fingers;
- if (etd->fw_version_maj == 0x01) {
+ if (etd->fw_version < 0x020000) {
/*
* byte 0: D U p1 p2 1 p3 R L
* byte 1: f 0 th tw x9 x8 y9 y8
@@ -227,7 +227,7 @@
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
- if ((etd->fw_version_maj == 0x01) &&
+ if (etd->fw_version < 0x020000 &&
(etd->capabilities & ETP_CAP_HAS_ROCKER)) {
/* rocker up */
input_report_key(dev, BTN_FORWARD, packet[0] & 0x40);
@@ -321,7 +321,7 @@
unsigned char p1, p2, p3;
/* Parity bits are placed differently */
- if (etd->fw_version_maj == 0x01) {
+ if (etd->fw_version < 0x020000) {
/* byte 0: D U p1 p2 1 p3 R L */
p1 = (packet[0] & 0x20) >> 5;
p2 = (packet[0] & 0x10) >> 4;
@@ -457,7 +457,7 @@
switch (etd->hw_version) {
case 1:
/* Rocker button */
- if ((etd->fw_version_maj == 0x01) &&
+ if (etd->fw_version < 0x020000 &&
(etd->capabilities & ETP_CAP_HAS_ROCKER)) {
__set_bit(BTN_FORWARD, dev->keybit);
__set_bit(BTN_BACK, dev->keybit);
@@ -686,15 +686,14 @@
pr_err("elantech.c: failed to query firmware version.\n");
goto init_fail;
}
- etd->fw_version_maj = param[0];
- etd->fw_version_min = param[2];
+
+ etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2];
/*
* Assume every version greater than this is new EeePC style
* hardware with 6 byte packets
*/
- if ((etd->fw_version_maj == 0x02 && etd->fw_version_min >= 0x30) ||
- etd->fw_version_maj > 0x02) {
+ if (etd->fw_version >= 0x020030) {
etd->hw_version = 2;
/* For now show extra debug information */
etd->debug = 1;
@@ -704,8 +703,9 @@
etd->hw_version = 1;
etd->paritycheck = 1;
}
- pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n",
- etd->hw_version, etd->fw_version_maj, etd->fw_version_min);
+
+ pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n",
+ etd->hw_version, param[0], param[1], param[2]);
if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) {
pr_err("elantech.c: failed to query capabilities.\n");
@@ -720,8 +720,8 @@
* a touch action starts causing the mouse cursor or scrolled page
* to jump. Enable a workaround.
*/
- if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) {
- pr_info("elantech.c: firmware version 2.34 detected, "
+ if (etd->fw_version == 0x020022) {
+ pr_info("elantech.c: firmware version 2.0.34 detected, "
"enabling jumpy cursor workaround\n");
etd->jumpy_cursor = 1;
}
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index feac5f7..ac57bde 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -100,11 +100,10 @@
unsigned char reg_26;
unsigned char debug;
unsigned char capabilities;
- unsigned char fw_version_maj;
- unsigned char fw_version_min;
- unsigned char hw_version;
unsigned char paritycheck;
unsigned char jumpy_cursor;
+ unsigned char hw_version;
+ unsigned int fw_version;
unsigned char parity[256];
};
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index cbc8072..a3c9731 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -1394,6 +1394,7 @@
struct psmouse *psmouse = serio_get_drvdata(serio);
struct psmouse *parent = NULL;
struct serio_driver *drv = serio->drv;
+ unsigned char type;
int rc = -1;
if (!drv || !psmouse) {
@@ -1413,10 +1414,15 @@
if (psmouse->reconnect) {
if (psmouse->reconnect(psmouse))
goto out;
- } else if (psmouse_probe(psmouse) < 0 ||
- psmouse->type != psmouse_extensions(psmouse,
- psmouse_max_proto, false)) {
- goto out;
+ } else {
+ psmouse_reset(psmouse);
+
+ if (psmouse_probe(psmouse) < 0)
+ goto out;
+
+ type = psmouse_extensions(psmouse, psmouse_max_proto, false);
+ if (psmouse->type != type)
+ goto out;
}
/* ok, the device type (and capabilities) match the old one,
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index e019d53d..0d2d7e5 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -156,9 +156,14 @@
u16 reset;
u16 ref_on;
u16 command;
- u16 sample;
struct spi_message msg;
struct spi_transfer xfer[6];
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ u16 sample ____cacheline_aligned;
};
struct ad7877 {
@@ -182,8 +187,6 @@
u8 averaging;
u8 pen_down_acc_interval;
- u16 conversion_data[AD7877_NR_SENSE];
-
struct spi_transfer xfer[AD7877_NR_SENSE + 2];
struct spi_message msg;
@@ -195,6 +198,12 @@
spinlock_t lock;
struct timer_list timer; /* P: lock */
unsigned pending:1; /* P: lock */
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned;
};
static int gpio3;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 9712b2e..cefd63d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2109,12 +2109,18 @@
if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */
/* .. if the array isn't clean, an 'even' event must also go
* to spares. */
- if ((mddev->events&1)==0)
+ if ((mddev->events&1)==0) {
nospares = 0;
+ sync_req = 2; /* force a second update to get the
+ * even/odd in sync */
+ }
} else {
/* otherwise an 'odd' event must go to spares */
- if ((mddev->events&1))
+ if ((mddev->events&1)) {
nospares = 0;
+ sync_req = 2; /* force a second update to get the
+ * even/odd in sync */
+ }
}
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 58ea0ec..15348c3 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1527,7 +1527,7 @@
clear_bit(R5_UPTODATE, &sh->dev[i].flags);
atomic_inc(&rdev->read_errors);
- if (conf->mddev->degraded)
+ if (conf->mddev->degraded >= conf->max_degraded)
printk_rl(KERN_WARNING
"raid5:%s: read error not correctable "
"(sector %llu on %s).\n",
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index fd8e1f4..7364b96 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -423,15 +423,14 @@
}
}
-int saa7146_vv_devinit(struct saa7146_dev *dev)
-{
- return v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
-}
-EXPORT_SYMBOL_GPL(saa7146_vv_devinit);
-
int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
{
struct saa7146_vv *vv;
+ int err;
+
+ err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
+ if (err)
+ return err;
vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
if (vv == NULL) {
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 5ed7526..b8b2c55 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -558,9 +558,11 @@
/* ok, accept it */
vv->ov_fb = *fb;
vv->ov_fmt = fmt;
- if (0 == vv->ov_fb.fmt.bytesperline)
- vv->ov_fb.fmt.bytesperline =
- vv->ov_fb.fmt.width * fmt->depth / 8;
+
+ if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
+ vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
+ DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline));
+ }
mutex_unlock(&dev->lock);
return 0;
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
index a3c07fe..9697280 100644
--- a/drivers/media/dvb/frontends/stv090x.c
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -4470,6 +4470,10 @@
if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
goto err;
+ /* workaround for stuck DiSEqC output */
+ if (config->diseqc_envelope_mode)
+ stv090x_send_diseqc_burst(fe, SEC_MINI_A);
+
return 0;
err:
dprintk(FE_ERROR, 1, "I/O error");
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 9fdf26c..1500210 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -643,9 +643,6 @@
&budget->i2c_adap,
&tt1600_isl6423_config);
- } else {
- dvb_frontend_detach(budget->dvb_frontend);
- budget->dvb_frontend = NULL;
}
}
break;
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index f8fc865..9644cf7 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -361,7 +361,7 @@
config VIDEO_SAA7191
tristate "Philips SAA7191 video decoder"
- depends on VIDEO_V4L1 && I2C
+ depends on VIDEO_V4L2 && I2C
---help---
Support for the Philips SAA7191 video decoder.
@@ -756,7 +756,7 @@
config VIDEO_MXB
tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
- depends on PCI && VIDEO_V4L1 && I2C
+ depends on PCI && VIDEO_V4L2 && I2C
select VIDEO_SAA7146_VV
select VIDEO_TUNER
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index b88b617..c51c386 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -160,8 +160,6 @@
obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
-obj-$(CONFIG_ARCH_DAVINCI) += davinci/
-
obj-$(CONFIG_VIDEO_AU0828) += au0828/
obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
index 7cf042f..398dbe7 100644
--- a/drivers/media/video/davinci/vpfe_capture.c
+++ b/drivers/media/video/davinci/vpfe_capture.c
@@ -223,7 +223,6 @@
BUG_ON(!dev->hw_ops.get_frame_format);
BUG_ON(!dev->hw_ops.get_pixel_format);
BUG_ON(!dev->hw_ops.set_pixel_format);
- BUG_ON(!dev->hw_ops.set_params);
BUG_ON(!dev->hw_ops.set_image_window);
BUG_ON(!dev->hw_ops.get_image_window);
BUG_ON(!dev->hw_ops.get_line_length);
@@ -1689,11 +1688,12 @@
struct vpfe_device *vpfe_dev = video_drvdata(file);
int ret = 0;
- v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");
+ v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");
if (vpfe_dev->started) {
/* only allowed if streaming is not started */
- v4l2_err(&vpfe_dev->v4l2_dev, "device already started\n");
+ v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+ "device already started\n");
return -EBUSY;
}
@@ -1705,16 +1705,23 @@
case VPFE_CMD_S_CCDC_RAW_PARAMS:
v4l2_warn(&vpfe_dev->v4l2_dev,
"VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n");
- ret = ccdc_dev->hw_ops.set_params(param);
- if (ret) {
- v4l2_err(&vpfe_dev->v4l2_dev,
- "Error in setting parameters in CCDC\n");
- goto unlock_out;
- }
- if (vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt) < 0) {
- v4l2_err(&vpfe_dev->v4l2_dev,
- "Invalid image format at CCDC\n");
- goto unlock_out;
+ if (ccdc_dev->hw_ops.set_params) {
+ ret = ccdc_dev->hw_ops.set_params(param);
+ if (ret) {
+ v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+ "Error setting parameters in CCDC\n");
+ goto unlock_out;
+ }
+ if (vpfe_get_ccdc_image_format(vpfe_dev,
+ &vpfe_dev->fmt) < 0) {
+ v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+ "Invalid image format at CCDC\n");
+ goto unlock_out;
+ }
+ } else {
+ ret = -EINVAL;
+ v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
+ "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n");
}
break;
default:
@@ -1830,7 +1837,7 @@
if (NULL == ccdc_cfg) {
v4l2_err(pdev->dev.driver,
"Memory allocation failed for ccdc_cfg\n");
- goto probe_free_dev_mem;
+ goto probe_free_lock;
}
strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32);
@@ -1982,8 +1989,9 @@
probe_out_release_irq:
free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
probe_free_ccdc_cfg_mem:
- mutex_unlock(&ccdc_lock);
kfree(ccdc_cfg);
+probe_free_lock:
+ mutex_unlock(&ccdc_lock);
probe_free_dev_mem:
kfree(vpfe_dev);
return ret;
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index 38a6e15..3dee3e5 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -1427,7 +1427,7 @@
struct gspca_dev *gspca_dev = (struct gspca_dev *)data;
struct sd *sd = (struct sd *) gspca_dev;
- DECLARE_WAIT_QUEUE_HEAD(wait);
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait);
set_freezable();
for (;;) {
if (kthread_should_stop())
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
index 15b2eef..edf0fe1 100644
--- a/drivers/media/video/gspca/spca508.c
+++ b/drivers/media/video/gspca/spca508.c
@@ -1513,7 +1513,6 @@
static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
{USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
- {USB_DEVICE(0x0461, 0x0815), .driver_info = MicroInnovationIC200},
{USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
{USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
{USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index dc7f2b0..b9c80e21 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -1053,6 +1053,7 @@
{USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
{USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
{USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
+ {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},
{USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
{USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
{USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
index af73da3..14f179a 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -524,8 +524,6 @@
{USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
/* QuickCam Messenger (new) */
{USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
- /* QuickCam Messenger (new) */
- {USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 },
{}
};
MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
index e620a3a..ad2c232 100644
--- a/drivers/media/video/hexium_gemini.c
+++ b/drivers/media/video/hexium_gemini.c
@@ -356,9 +356,6 @@
DEB_EE((".\n"));
- ret = saa7146_vv_devinit(dev);
- if (ret)
- return ret;
hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) {
printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index fe596a1..938a1f8 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -216,10 +216,6 @@
return -EFAULT;
}
- err = saa7146_vv_devinit(dev);
- if (err)
- return err;
-
hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) {
printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 3c8ebfc..34a6601 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -49,8 +49,6 @@
/*
* CSI registers
*/
-#define DMA_CCR(x) (0x8c + ((x) << 6)) /* Control Registers */
-#define DMA_DIMR 0x08 /* Interrupt mask Register */
#define CSICR1 0x00 /* CSI Control Register 1 */
#define CSISR 0x08 /* CSI Status Register */
#define CSIRXR 0x10 /* CSI RxFIFO Register */
@@ -784,7 +782,7 @@
pcdev);
imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO,
- IMX_DMA_MEMSIZE_32, DMA_REQ_CSI_R, 0);
+ IMX_DMA_MEMSIZE_32, MX1_DMA_REQ_CSI_R, 0);
/* burst length : 16 words = 64 bytes */
imx_dma_config_burstlen(pcdev->dma_chan, 0);
@@ -798,8 +796,8 @@
set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end -
&mx1_camera_sof_fiq_start);
- regs.ARM_r8 = DMA_BASE + DMA_DIMR;
- regs.ARM_r9 = DMA_BASE + DMA_CCR(pcdev->dma_chan);
+ regs.ARM_r8 = (long)MX1_DMA_DIMR;
+ regs.ARM_r9 = (long)MX1_DMA_CCR(pcdev->dma_chan);
regs.ARM_r10 = (long)pcdev->base + CSICR1;
regs.ARM_fp = (long)pcdev->base + CSISR;
regs.ARM_sp = 1 << pcdev->dma_chan;
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index 9f01f14..ef0c817 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -169,11 +169,7 @@
static int mxb_probe(struct saa7146_dev *dev)
{
struct mxb *mxb = NULL;
- int err;
- err = saa7146_vv_devinit(dev);
- if (err)
- return err;
mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
if (mxb == NULL) {
DEB_D(("not enough kernel memory.\n"));
@@ -699,14 +695,17 @@
/* this function only gets called when the probing was successful */
static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
{
- struct mxb *mxb = (struct mxb *)dev->ext_priv;
+ struct mxb *mxb;
DEB_EE(("dev:%p\n", dev));
- /* checking for i2c-devices can be omitted here, because we
- already did this in "mxb_vl42_probe" */
-
saa7146_vv_init(dev, &vv_data);
+ if (mxb_probe(dev)) {
+ saa7146_vv_release(dev);
+ return -1;
+ }
+ mxb = (struct mxb *)dev->ext_priv;
+
vv_data.ops.vidioc_queryctrl = vidioc_queryctrl;
vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl;
vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl;
@@ -726,6 +725,7 @@
vv_data.ops.vidioc_default = vidioc_default;
if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
ERR(("cannot register capture v4l2 device. skipping.\n"));
+ saa7146_vv_release(dev);
return -1;
}
@@ -846,7 +846,6 @@
.pci_tbl = &pci_tbl[0],
.module = THIS_MODULE,
- .probe = mxb_probe,
.attach = mxb_attach,
.detach = mxb_detach,
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index b189fe6..ce76d95 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1405,7 +1405,7 @@
}
size = 0;
- for (i = first; i <= last; i++) {
+ for (i = first; i <= last && i < VIDEO_MAX_FRAME; i++) {
struct videobuf_dmabuf *dma = videobuf_to_dma(vbq->bufs[i]);
for (j = 0; j < dma->sglen; j++) {
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 5ecc30d..04bf5c1 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -609,12 +609,9 @@
*/
static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev)
{
- unsigned long cicr0, cifr;
+ unsigned long cicr0;
dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__);
- /* Reset the FIFOs */
- cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F;
- __raw_writel(cifr, pcdev->base + CIFR);
/* Enable End-Of-Frame Interrupt */
cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB;
cicr0 &= ~CICR0_EOFM;
@@ -935,7 +932,7 @@
static irqreturn_t pxa_camera_irq(int irq, void *data)
{
struct pxa_camera_dev *pcdev = data;
- unsigned long status, cicr0;
+ unsigned long status, cifr, cicr0;
struct pxa_buffer *buf;
struct videobuf_buffer *vb;
@@ -949,6 +946,10 @@
__raw_writel(status, pcdev->base + CISR);
if (status & CISR_EOF) {
+ /* Reset the FIFOs */
+ cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F;
+ __raw_writel(cifr, pcdev->base + CIFR);
+
pcdev->active = list_first_entry(&pcdev->capture,
struct pxa_buffer, vb.queue);
vb = &pcdev->active->vb;
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 6e16b39..1ad980f 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -1633,7 +1633,7 @@
height = pix->height;
pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt);
- if (pix->bytesperline < 0)
+ if ((int)pix->bytesperline < 0)
return pix->bytesperline;
pix->sizeimage = height * pix->bytesperline;
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index a3d5728..f2ab025 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -349,6 +349,9 @@
goto disable;
}
+ /* If an interrupt arrived late clean up after it */
+ try_wait_for_completion(&wm831x->auxadc_done);
+
/* Ignore the result to allow us to soldier on without IRQ hookup */
wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5));
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index e400a3b..b580748 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -363,6 +363,10 @@
reg |= 1 << channel | WM8350_AUXADC_POLL;
wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);
+ /* If a late IRQ left the completion signalled then consume
+ * the completion. */
+ try_wait_for_completion(&wm8350->auxadc_done);
+
/* We ignore the result of the completion and just check for a
* conversion result, allowing us to soldier on if the IRQ
* infrastructure is not set up for the chip. */
diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmware_balloon.c
index e7161c4..db9cd02 100644
--- a/drivers/misc/vmware_balloon.c
+++ b/drivers/misc/vmware_balloon.c
@@ -41,7 +41,7 @@
#include <linux/workqueue.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
-#include <asm/vmware.h>
+#include <asm/hypervisor.h>
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
@@ -767,7 +767,7 @@
* Check if we are running on VMware's hypervisor and bail out
* if we are not.
*/
- if (!vmware_platform())
+ if (x86_hyper != &x86_hyper_vmware)
return -ENODEV;
vmballoon_wq = create_freezeable_workqueue("vmmemctl");
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index a6dd7da..336d9f5 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -314,8 +314,8 @@
dmabuf = (unsigned *)tmpv;
}
+ flush_kernel_dcache_page(sg_page(sg));
kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
- dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount);
data->bytes_xfered += amount;
if (size == 0)
break;
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 88be37d..fb279f4 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -266,7 +266,7 @@
"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
cmd->opcode, cmd->arg, cmd->flags,
cmd->resp[0], cmd->resp[1], cmd->resp[2],
- cmd->resp[2], cmd->error);
+ cmd->resp[3], cmd->error);
if (data)
seq_printf(s, "DATA %u / %u * %u flg %x err %d\n",
data->bytes_xfered, data->blocks,
@@ -276,7 +276,7 @@
"CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n",
stop->opcode, stop->arg, stop->flags,
stop->resp[0], stop->resp[1], stop->resp[2],
- stop->resp[2], stop->error);
+ stop->resp[3], stop->error);
}
spin_unlock_bh(&slot->host->lock);
@@ -569,9 +569,10 @@
{
struct mmc_data *data = host->data;
- dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
- ((data->flags & MMC_DATA_WRITE)
- ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
+ if (data)
+ dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
+ ((data->flags & MMC_DATA_WRITE)
+ ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
}
static void atmci_stop_dma(struct atmel_mci *host)
@@ -1099,8 +1100,8 @@
"command error: status=0x%08x\n", status);
if (cmd->data) {
- host->data = NULL;
atmci_stop_dma(host);
+ host->data = NULL;
mci_writel(host, IDR, MCI_NOTBUSY
| MCI_TXRDY | MCI_RXRDY
| ATMCI_DATA_ERROR_FLAGS);
@@ -1293,6 +1294,7 @@
} else {
data->bytes_xfered = data->blocks * data->blksz;
data->error = 0;
+ mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS);
}
if (!data->stop) {
@@ -1751,13 +1753,13 @@
ret = -ENODEV;
if (pdata->slot[0].bus_width) {
ret = atmci_init_slot(host, &pdata->slot[0],
- MCI_SDCSEL_SLOT_A, 0);
+ 0, MCI_SDCSEL_SLOT_A);
if (!ret)
nr_slots++;
}
if (pdata->slot[1].bus_width) {
ret = atmci_init_slot(host, &pdata->slot[1],
- MCI_SDCSEL_SLOT_B, 1);
+ 1, MCI_SDCSEL_SLOT_B);
if (!ret)
nr_slots++;
}
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index ed5e974..a8f0512 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -674,6 +674,7 @@
{ ZORRO_PROD_AMERISTAR_A2065 },
{ 0 }
};
+MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl);
static struct zorro_driver a2065_driver = {
.name = "a2065",
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index fa1a235..4b30a46 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -145,6 +145,7 @@
{ ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
{ 0 }
};
+MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl);
static struct zorro_driver ariadne_driver = {
.name = "ariadne",
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 4e97ca1..5d3763f 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1649,6 +1649,7 @@
sizeof(struct rxbd8) * priv->total_rx_ring_size,
priv->tx_queue[0]->tx_bd_base,
priv->tx_queue[0]->tx_bd_dma_base);
+ skb_queue_purge(&priv->rx_recycle);
}
void gfar_start(struct net_device *dev)
@@ -2088,7 +2089,6 @@
disable_napi(priv);
- skb_queue_purge(&priv->rx_recycle);
cancel_work_sync(&priv->reset_task);
stop_gfar(dev);
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 24724b4..07d8e5b 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -71,6 +71,7 @@
{ ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
{ 0 }
};
+MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl);
static struct zorro_driver hydra_driver = {
.name = "hydra",
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 0cd80e4..e67691d 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -32,6 +32,7 @@
static struct phy_driver ks8001_driver = {
.phy_id = PHY_ID_KS8001,
+ .name = "Micrel KS8001",
.phy_id_mask = 0x00fffff0,
.features = PHY_BASIC_FEATURES,
.flags = PHY_POLL,
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index f9f0730..5ec542d 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -187,7 +187,6 @@
return NETDEV_TX_OK;
rx_drop:
- kfree_skb(skb);
rcv_stats->rx_dropped++;
return NETDEV_TX_OK;
}
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index 99a6da4..e1c2fca 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -727,12 +727,16 @@
{
struct device *parent = aru->udev->dev.parent;
+ complete(&aru->firmware_loading_complete);
+
/* unbind anything failed */
if (parent)
down(&parent->sem);
device_release_driver(&aru->udev->dev);
if (parent)
up(&parent->sem);
+
+ usb_put_dev(aru->udev);
}
static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context)
@@ -761,6 +765,8 @@
if (err)
goto err_unrx;
+ complete(&aru->firmware_loading_complete);
+ usb_put_dev(aru->udev);
return;
err_unrx:
@@ -858,6 +864,7 @@
init_usb_anchor(&aru->tx_pending);
init_usb_anchor(&aru->tx_submitted);
init_completion(&aru->cmd_wait);
+ init_completion(&aru->firmware_loading_complete);
spin_lock_init(&aru->tx_urb_lock);
aru->tx_pending_urbs = 0;
@@ -877,6 +884,7 @@
if (err)
goto err_freehw;
+ usb_get_dev(aru->udev);
return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw",
&aru->udev->dev, GFP_KERNEL, aru,
ar9170_usb_firmware_step2);
@@ -896,6 +904,9 @@
return;
aru->common.state = AR9170_IDLE;
+
+ wait_for_completion(&aru->firmware_loading_complete);
+
ar9170_unregister(&aru->common);
ar9170_usb_cancel_urbs(aru);
diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h
index a2ce3b1..919b060 100644
--- a/drivers/net/wireless/ath/ar9170/usb.h
+++ b/drivers/net/wireless/ath/ar9170/usb.h
@@ -71,6 +71,7 @@
unsigned int tx_pending_urbs;
struct completion cmd_wait;
+ struct completion firmware_loading_complete;
int readlen;
u8 *readbuf;
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6383d9f..f4e59ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2621,7 +2621,9 @@
#define PROBE_OPTION_MAX_3945 4
#define PROBE_OPTION_MAX 20
#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF)
-#define IWL_GOOD_CRC_TH cpu_to_le16(1)
+#define IWL_GOOD_CRC_TH_DISABLED 0
+#define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1)
+#define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff)
#define IWL_MAX_SCAN_SIZE 1024
#define IWL_MAX_CMD_SIZE 4096
#define IWL_MAX_PROBE_REQUEST 200
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 12e455a..741e65e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -813,16 +813,29 @@
rate = IWL_RATE_1M_PLCP;
rate_flags = RATE_MCS_CCK_MSK;
}
- scan->good_CRC_th = 0;
+ scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED;
} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
band = IEEE80211_BAND_5GHZ;
rate = IWL_RATE_6M_PLCP;
/*
- * If active scaning is requested but a certain channel
- * is marked passive, we can do active scanning if we
- * detect transmissions.
+ * If active scanning is requested but a certain channel is
+ * marked passive, we can do active scanning if we detect
+ * transmissions.
+ *
+ * There is an issue with some firmware versions that triggers
+ * a sysassert on a "good CRC threshold" of zero (== disabled),
+ * on a radar channel even though this means that we should NOT
+ * send probes.
+ *
+ * The "good CRC threshold" is the number of frames that we
+ * need to receive during our dwell time on a channel before
+ * sending out probes -- setting this to a huge value will
+ * mean we never reach it, but at the same time work around
+ * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+ * here instead of IWL_GOOD_CRC_TH_DISABLED.
*/
- scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+ IWL_GOOD_CRC_TH_NEVER;
/* Force use of chains B and C (0x6) for scan Rx for 4965
* Avoid A (0x1) because of its off-channel reception on A-band.
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index b55e4f3..b74a56c 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2967,7 +2967,8 @@
* is marked passive, we can do active scanning if we
* detect transmissions.
*/
- scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
+ scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+ IWL_GOOD_CRC_TH_DISABLED;
band = IEEE80211_BAND_5GHZ;
} else {
IWL_WARN(priv, "Invalid scan band count\n");
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index 81c753a..9548cbb 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -102,6 +102,7 @@
{ ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
{ 0 }
};
+MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
static struct zorro_driver zorro8390_driver = {
.name = "zorro8390",
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 7581dbe..219f79e 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -30,23 +30,7 @@
#define OP_BUFFER_FLAGS 0
-/*
- * Read and write access is using spin locking. Thus, writing to the
- * buffer by NMI handler (x86) could occur also during critical
- * sections when reading the buffer. To avoid this, there are 2
- * buffers for independent read and write access. Read access is in
- * process context only, write access only in the NMI handler. If the
- * read buffer runs empty, both buffers are swapped atomically. There
- * is potentially a small window during swapping where the buffers are
- * disabled and samples could be lost.
- *
- * Using 2 buffers is a little bit overhead, but the solution is clear
- * and does not require changes in the ring buffer implementation. It
- * can be changed to a single buffer solution when the ring buffer
- * access is implemented as non-locking atomic code.
- */
-static struct ring_buffer *op_ring_buffer_read;
-static struct ring_buffer *op_ring_buffer_write;
+static struct ring_buffer *op_ring_buffer;
DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer);
static void wq_sync_buffer(struct work_struct *work);
@@ -68,12 +52,9 @@
void free_cpu_buffers(void)
{
- if (op_ring_buffer_read)
- ring_buffer_free(op_ring_buffer_read);
- op_ring_buffer_read = NULL;
- if (op_ring_buffer_write)
- ring_buffer_free(op_ring_buffer_write);
- op_ring_buffer_write = NULL;
+ if (op_ring_buffer)
+ ring_buffer_free(op_ring_buffer);
+ op_ring_buffer = NULL;
}
#define RB_EVENT_HDR_SIZE 4
@@ -86,11 +67,8 @@
unsigned long byte_size = buffer_size * (sizeof(struct op_sample) +
RB_EVENT_HDR_SIZE);
- op_ring_buffer_read = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
- if (!op_ring_buffer_read)
- goto fail;
- op_ring_buffer_write = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
- if (!op_ring_buffer_write)
+ op_ring_buffer = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS);
+ if (!op_ring_buffer)
goto fail;
for_each_possible_cpu(i) {
@@ -162,16 +140,11 @@
*op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size)
{
entry->event = ring_buffer_lock_reserve
- (op_ring_buffer_write, sizeof(struct op_sample) +
+ (op_ring_buffer, sizeof(struct op_sample) +
size * sizeof(entry->sample->data[0]));
- if (entry->event)
- entry->sample = ring_buffer_event_data(entry->event);
- else
- entry->sample = NULL;
-
- if (!entry->sample)
+ if (!entry->event)
return NULL;
-
+ entry->sample = ring_buffer_event_data(entry->event);
entry->size = size;
entry->data = entry->sample->data;
@@ -180,25 +153,16 @@
int op_cpu_buffer_write_commit(struct op_entry *entry)
{
- return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event);
+ return ring_buffer_unlock_commit(op_ring_buffer, entry->event);
}
struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu)
{
struct ring_buffer_event *e;
- e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL, NULL);
- if (e)
- goto event;
- if (ring_buffer_swap_cpu(op_ring_buffer_read,
- op_ring_buffer_write,
- cpu))
+ e = ring_buffer_consume(op_ring_buffer, cpu, NULL, NULL);
+ if (!e)
return NULL;
- e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL, NULL);
- if (e)
- goto event;
- return NULL;
-event:
entry->event = e;
entry->sample = ring_buffer_event_data(e);
entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample))
@@ -209,8 +173,7 @@
unsigned long op_cpu_buffer_entries(int cpu)
{
- return ring_buffer_entries_cpu(op_ring_buffer_read, cpu)
- + ring_buffer_entries_cpu(op_ring_buffer_write, cpu);
+ return ring_buffer_entries_cpu(op_ring_buffer, cpu);
}
static int
@@ -356,8 +319,16 @@
void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
{
- int is_kernel = !user_mode(regs);
- unsigned long pc = profile_pc(regs);
+ int is_kernel;
+ unsigned long pc;
+
+ if (likely(regs)) {
+ is_kernel = !user_mode(regs);
+ pc = profile_pc(regs);
+ } else {
+ is_kernel = 0; /* This value will not be used */
+ pc = ESCAPE_CODE; /* as this causes an early return. */
+ }
__oprofile_add_ext_sample(pc, regs, event, is_kernel);
}
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
index dc8a042..b336cd9 100644
--- a/drivers/oprofile/oprof.c
+++ b/drivers/oprofile/oprof.c
@@ -253,22 +253,26 @@
int err;
err = oprofile_arch_init(&oprofile_ops);
-
if (err < 0 || timer) {
printk(KERN_INFO "oprofile: using timer interrupt.\n");
- oprofile_timer_init(&oprofile_ops);
+ err = oprofile_timer_init(&oprofile_ops);
+ if (err)
+ goto out_arch;
}
-
err = oprofilefs_register();
if (err)
- oprofile_arch_exit();
+ goto out_arch;
+ return 0;
+out_arch:
+ oprofile_arch_exit();
return err;
}
static void __exit oprofile_exit(void)
{
+ oprofile_timer_exit();
oprofilefs_unregister();
oprofile_arch_exit();
}
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h
index cb92f5c..47e12cb 100644
--- a/drivers/oprofile/oprof.h
+++ b/drivers/oprofile/oprof.h
@@ -34,7 +34,8 @@
struct dentry;
void oprofile_create_files(struct super_block *sb, struct dentry *root);
-void oprofile_timer_init(struct oprofile_operations *ops);
+int oprofile_timer_init(struct oprofile_operations *ops);
+void oprofile_timer_exit(void);
int oprofile_set_backtrace(unsigned long depth);
int oprofile_set_timeout(unsigned long time);
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c
index 333f915..dc0ae4d 100644
--- a/drivers/oprofile/timer_int.c
+++ b/drivers/oprofile/timer_int.c
@@ -13,34 +13,94 @@
#include <linux/oprofile.h>
#include <linux/profile.h>
#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/hrtimer.h>
+#include <asm/irq_regs.h>
#include <asm/ptrace.h>
#include "oprof.h"
-static int timer_notify(struct pt_regs *regs)
+static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer);
+
+static enum hrtimer_restart oprofile_hrtimer_notify(struct hrtimer *hrtimer)
{
- oprofile_add_sample(regs, 0);
+ oprofile_add_sample(get_irq_regs(), 0);
+ hrtimer_forward_now(hrtimer, ns_to_ktime(TICK_NSEC));
+ return HRTIMER_RESTART;
+}
+
+static void __oprofile_hrtimer_start(void *unused)
+{
+ struct hrtimer *hrtimer = &__get_cpu_var(oprofile_hrtimer);
+
+ hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ hrtimer->function = oprofile_hrtimer_notify;
+
+ hrtimer_start(hrtimer, ns_to_ktime(TICK_NSEC),
+ HRTIMER_MODE_REL_PINNED);
+}
+
+static int oprofile_hrtimer_start(void)
+{
+ on_each_cpu(__oprofile_hrtimer_start, NULL, 1);
return 0;
}
-static int timer_start(void)
+static void __oprofile_hrtimer_stop(int cpu)
{
- return register_timer_hook(timer_notify);
+ struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu);
+
+ hrtimer_cancel(hrtimer);
}
-
-static void timer_stop(void)
+static void oprofile_hrtimer_stop(void)
{
- unregister_timer_hook(timer_notify);
+ int cpu;
+
+ for_each_online_cpu(cpu)
+ __oprofile_hrtimer_stop(cpu);
}
-
-void __init oprofile_timer_init(struct oprofile_operations *ops)
+static int __cpuinit oprofile_cpu_notify(struct notifier_block *self,
+ unsigned long action, void *hcpu)
{
+ long cpu = (long) hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ smp_call_function_single(cpu, __oprofile_hrtimer_start,
+ NULL, 1);
+ break;
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ __oprofile_hrtimer_stop(cpu);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata oprofile_cpu_notifier = {
+ .notifier_call = oprofile_cpu_notify,
+};
+
+int __init oprofile_timer_init(struct oprofile_operations *ops)
+{
+ int rc;
+
+ rc = register_hotcpu_notifier(&oprofile_cpu_notifier);
+ if (rc)
+ return rc;
ops->create_files = NULL;
ops->setup = NULL;
ops->shutdown = NULL;
- ops->start = timer_start;
- ops->stop = timer_stop;
+ ops->start = oprofile_hrtimer_start;
+ ops->stop = oprofile_hrtimer_stop;
ops->cpu_type = "timer";
+ return 0;
+}
+
+void __exit oprofile_timer_exit(void)
+{
+ unregister_hotcpu_notifier(&oprofile_cpu_notifier);
}
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 4173125..371dc56 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -3626,14 +3626,15 @@
domain_remove_one_dev_info(dmar_domain, pdev);
}
-static int intel_iommu_map_range(struct iommu_domain *domain,
- unsigned long iova, phys_addr_t hpa,
- size_t size, int iommu_prot)
+static int intel_iommu_map(struct iommu_domain *domain,
+ unsigned long iova, phys_addr_t hpa,
+ int gfp_order, int iommu_prot)
{
struct dmar_domain *dmar_domain = domain->priv;
u64 max_addr;
int addr_width;
int prot = 0;
+ size_t size;
int ret;
if (iommu_prot & IOMMU_READ)
@@ -3643,6 +3644,7 @@
if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
prot |= DMA_PTE_SNP;
+ size = PAGE_SIZE << gfp_order;
max_addr = iova + size;
if (dmar_domain->max_addr < max_addr) {
int min_agaw;
@@ -3669,19 +3671,19 @@
return ret;
}
-static void intel_iommu_unmap_range(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+static int intel_iommu_unmap(struct iommu_domain *domain,
+ unsigned long iova, int gfp_order)
{
struct dmar_domain *dmar_domain = domain->priv;
-
- if (!size)
- return;
+ size_t size = PAGE_SIZE << gfp_order;
dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
(iova + size - 1) >> VTD_PAGE_SHIFT);
if (dmar_domain->max_addr == iova + size)
dmar_domain->max_addr = iova;
+
+ return gfp_order;
}
static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
@@ -3714,8 +3716,8 @@
.domain_destroy = intel_iommu_domain_destroy,
.attach_dev = intel_iommu_attach_device,
.detach_dev = intel_iommu_detach_device,
- .map = intel_iommu_map_range,
- .unmap = intel_iommu_unmap_range,
+ .map = intel_iommu_map,
+ .unmap = intel_iommu_unmap,
.iova_to_phys = intel_iommu_iova_to_phys,
.domain_has_cap = intel_iommu_domain_has_cap,
};
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 4fe36d2..19b1113 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -838,65 +838,11 @@
}
}
-static int __init pci_bus_get_depth(struct pci_bus *bus)
-{
- int depth = 0;
- struct pci_dev *dev;
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- int ret;
- struct pci_bus *b = dev->subordinate;
- if (!b)
- continue;
-
- ret = pci_bus_get_depth(b);
- if (ret + 1 > depth)
- depth = ret + 1;
- }
-
- return depth;
-}
-static int __init pci_get_max_depth(void)
-{
- int depth = 0;
- struct pci_bus *bus;
-
- list_for_each_entry(bus, &pci_root_buses, node) {
- int ret;
-
- ret = pci_bus_get_depth(bus);
- if (ret > depth)
- depth = ret;
- }
-
- return depth;
-}
-
-/*
- * first try will not touch pci bridge res
- * second and later try will clear small leaf bridge res
- * will stop till to the max deepth if can not find good one
- */
void __init
pci_assign_unassigned_resources(void)
{
struct pci_bus *bus;
- int tried_times = 0;
- enum release_type rel_type = leaf_only;
- struct resource_list_x head, *list;
- unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
- IORESOURCE_PREFETCH;
- unsigned long failed_type;
- int max_depth = pci_get_max_depth();
- int pci_try_num;
- head.next = NULL;
-
- pci_try_num = max_depth + 1;
- printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
- max_depth, pci_try_num);
-
-again:
/* Depth first, calculate sizes and alignments of all
subordinate buses. */
list_for_each_entry(bus, &pci_root_buses, node) {
@@ -904,65 +850,9 @@
}
/* Depth last, allocate resources and update the hardware. */
list_for_each_entry(bus, &pci_root_buses, node) {
- __pci_bus_assign_resources(bus, &head);
- }
- tried_times++;
-
- /* any device complain? */
- if (!head.next)
- goto enable_and_dump;
- failed_type = 0;
- for (list = head.next; list;) {
- failed_type |= list->flags;
- list = list->next;
- }
- /*
- * io port are tight, don't try extra
- * or if reach the limit, don't want to try more
- */
- failed_type &= type_mask;
- if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) {
- free_failed_list(&head);
- goto enable_and_dump;
- }
-
- printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
- tried_times + 1);
-
- /* third times and later will not check if it is leaf */
- if ((tried_times + 1) > 2)
- rel_type = whole_subtree;
-
- /*
- * Try to release leaf bridge's resources that doesn't fit resource of
- * child device under that bridge
- */
- for (list = head.next; list;) {
- bus = list->dev->bus;
- pci_bus_release_bridge_resources(bus, list->flags & type_mask,
- rel_type);
- list = list->next;
- }
- /* restore size and flags */
- for (list = head.next; list;) {
- struct resource *res = list->res;
-
- res->start = list->start;
- res->end = list->end;
- res->flags = list->flags;
- if (list->dev->subordinate)
- res->flags = 0;
-
- list = list->next;
- }
- free_failed_list(&head);
-
- goto again;
-
-enable_and_dump:
- /* Depth last, update the hardware. */
- list_for_each_entry(bus, &pci_root_buses, node)
+ pci_bus_assign_resources(bus);
pci_enable_bridges(bus);
+ }
/* dump the resource on buses */
list_for_each_entry(bus, &pci_root_buses, node) {
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 75ed866..c338375 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -671,20 +671,22 @@
socket_remove(skt);
if (sysfs_events & PCMCIA_UEVENT_INSERT)
socket_insert(skt);
- if ((sysfs_events & PCMCIA_UEVENT_RESUME) &&
- !(skt->state & SOCKET_CARDBUS)) {
- ret = socket_resume(skt);
- if (!ret && skt->callback)
- skt->callback->resume(skt);
- }
if ((sysfs_events & PCMCIA_UEVENT_SUSPEND) &&
!(skt->state & SOCKET_CARDBUS)) {
if (skt->callback)
ret = skt->callback->suspend(skt);
else
ret = 0;
- if (!ret)
+ if (!ret) {
socket_suspend(skt);
+ msleep(100);
+ }
+ }
+ if ((sysfs_events & PCMCIA_UEVENT_RESUME) &&
+ !(skt->state & SOCKET_CARDBUS)) {
+ ret = socket_resume(skt);
+ if (!ret && skt->callback)
+ skt->callback->resume(skt);
}
if ((sysfs_events & PCMCIA_UEVENT_REQUERY) &&
!(skt->state & SOCKET_CARDBUS)) {
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 508f94a..041eee4 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1283,6 +1283,7 @@
destroy_cis_cache(skt);
kfree(skt->fake_cis);
skt->fake_cis = NULL;
+ s->functions = 0;
mutex_unlock(&s->ops_mutex);
/* now, add the new card */
ds_event(skt, CS_EVENT_CARD_INSERTION,
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 104e73d..7631faa 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -711,7 +711,7 @@
warning_printed = 1;
}
- if (s->pcmcia_state.present)
+ if (atomic_read(&s->present))
queue_event(user, CS_EVENT_CARD_INSERTION);
out:
unlock_kernel();
@@ -770,9 +770,6 @@
return -EIO;
s = user->socket;
- if (s->pcmcia_state.dead)
- return -EIO;
-
ret = wait_event_interruptible(s->queue, !queue_empty(user));
if (ret == 0)
ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4;
@@ -838,8 +835,6 @@
return -EIO;
s = user->socket;
- if (s->pcmcia_state.dead)
- return -EIO;
size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
if (size > sizeof(ds_ioctl_arg_t))
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 35bb44a..100e4d9 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -274,26 +274,6 @@
pnp_add_bus_resource(dev, start, end);
}
-static u64 addr_space_length(struct pnp_dev *dev, u64 min, u64 max, u64 len)
-{
- u64 max_len;
-
- max_len = max - min + 1;
- if (len <= max_len)
- return len;
-
- /*
- * Per 6.4.3.5, _LEN cannot exceed _MAX - _MIN + 1, but some BIOSes
- * don't do this correctly, e.g.,
- * https://bugzilla.kernel.org/show_bug.cgi?id=15480
- */
- dev_info(&dev->dev,
- "resource length %#llx doesn't fit in %#llx-%#llx, trimming\n",
- (unsigned long long) len, (unsigned long long) min,
- (unsigned long long) max);
- return max_len;
-}
-
static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
struct acpi_resource *res)
{
@@ -309,7 +289,8 @@
return;
}
- len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
+ /* Windows apparently computes length rather than using _LEN */
+ len = p->maximum - p->minimum + 1;
window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
if (p->resource_type == ACPI_MEMORY_RANGE)
@@ -330,7 +311,8 @@
int window;
u64 len;
- len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
+ /* Windows apparently computes length rather than using _LEN */
+ len = p->maximum - p->minimum + 1;
window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
if (p->resource_type == ACPI_MEMORY_RANGE)
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 2e54e6a..e3446ab 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -211,6 +211,8 @@
if (tres->flags & IORESOURCE_IO) {
if (cannot_compare(tres->flags))
continue;
+ if (tres->flags & IORESOURCE_WINDOW)
+ continue;
tport = &tres->start;
tend = &tres->end;
if (ranged_conflict(port, end, tport, tend))
@@ -271,6 +273,8 @@
if (tres->flags & IORESOURCE_MEM) {
if (cannot_compare(tres->flags))
continue;
+ if (tres->flags & IORESOURCE_WINDOW)
+ continue;
taddr = &tres->start;
tend = &tres->end;
if (ranged_conflict(addr, end, taddr, tend))
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index acf222f..fa2339c 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -37,6 +37,9 @@
*/
#define DASD_CHANQ_MAX_SIZE 4
+#define DASD_SLEEPON_START_TAG (void *) 1
+#define DASD_SLEEPON_END_TAG (void *) 2
+
/*
* SECTION: exported variables of dasd.c
*/
@@ -1472,7 +1475,10 @@
*/
static void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data)
{
- wake_up((wait_queue_head_t *) data);
+ spin_lock_irq(get_ccwdev_lock(cqr->startdev->cdev));
+ cqr->callback_data = DASD_SLEEPON_END_TAG;
+ spin_unlock_irq(get_ccwdev_lock(cqr->startdev->cdev));
+ wake_up(&generic_waitq);
}
static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)
@@ -1482,10 +1488,7 @@
device = cqr->startdev;
spin_lock_irq(get_ccwdev_lock(device->cdev));
- rc = ((cqr->status == DASD_CQR_DONE ||
- cqr->status == DASD_CQR_NEED_ERP ||
- cqr->status == DASD_CQR_TERMINATED) &&
- list_empty(&cqr->devlist));
+ rc = (cqr->callback_data == DASD_SLEEPON_END_TAG);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
return rc;
}
@@ -1573,7 +1576,7 @@
wait_event(generic_waitq, !(device->stopped));
cqr->callback = dasd_wakeup_cb;
- cqr->callback_data = (void *) &generic_waitq;
+ cqr->callback_data = DASD_SLEEPON_START_TAG;
dasd_add_request_tail(cqr);
if (interruptible) {
rc = wait_event_interruptible(
@@ -1652,7 +1655,7 @@
}
cqr->callback = dasd_wakeup_cb;
- cqr->callback_data = (void *) &generic_waitq;
+ cqr->callback_data = DASD_SLEEPON_START_TAG;
cqr->status = DASD_CQR_QUEUED;
list_add(&cqr->devlist, &device->ccw_queue);
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 9201afe6..7f87979 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -4724,6 +4724,10 @@
BUG_ON((unsigned long)asc_dvc->overrun_buf & 7);
asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf,
ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(board->dev, asc_dvc->overrun_dma)) {
+ warn_code = -ENOMEM;
+ goto err_dma_map;
+ }
phy_addr = cpu_to_le32(asc_dvc->overrun_dma);
AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
(uchar *)&phy_addr, 1);
@@ -4739,14 +4743,23 @@
AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
- return warn_code;
+ warn_code = UW_ERR;
+ goto err_mcode_start;
}
if (AscStartChip(iop_base) != 1) {
asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
- return warn_code;
+ warn_code = UW_ERR;
+ goto err_mcode_start;
}
return warn_code;
+
+err_mcode_start:
+ dma_unmap_single(board->dev, asc_dvc->overrun_dma,
+ ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
+err_dma_map:
+ asc_dvc->overrun_dma = 0;
+ return warn_code;
}
static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
@@ -4802,6 +4815,8 @@
}
release_firmware(fw);
warn_code |= AscInitMicroCodeVar(asc_dvc);
+ if (!asc_dvc->overrun_dma)
+ return warn_code;
asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
AscEnableInterrupt(iop_base);
return warn_code;
@@ -7978,9 +7993,10 @@
status = AscInitAsc1000Driver(asc_dvc);
/* Refer to ASC_IERR_* definitions for meaning of 'err_code'. */
- if (asc_dvc->err_code) {
+ if (asc_dvc->err_code || !asc_dvc->overrun_dma) {
scmd_printk(KERN_INFO, scp, "SCSI bus reset error: "
- "0x%x\n", asc_dvc->err_code);
+ "0x%x, status: 0x%x\n", asc_dvc->err_code,
+ status);
ret = FAILED;
} else if (status) {
scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: "
@@ -12311,7 +12327,7 @@
asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL);
if (!asc_dvc_varp->overrun_buf) {
ret = -ENOMEM;
- goto err_free_wide_mem;
+ goto err_free_irq;
}
warn_code = AscInitAsc1000Driver(asc_dvc_varp);
@@ -12320,30 +12336,36 @@
"warn 0x%x, error 0x%x\n",
asc_dvc_varp->init_state, warn_code,
asc_dvc_varp->err_code);
- if (asc_dvc_varp->err_code) {
+ if (!asc_dvc_varp->overrun_dma) {
ret = -ENODEV;
- kfree(asc_dvc_varp->overrun_buf);
+ goto err_free_mem;
}
}
} else {
- if (advansys_wide_init_chip(shost))
+ if (advansys_wide_init_chip(shost)) {
ret = -ENODEV;
+ goto err_free_mem;
+ }
}
- if (ret)
- goto err_free_wide_mem;
-
ASC_DBG_PRT_SCSI_HOST(2, shost);
ret = scsi_add_host(shost, boardp->dev);
if (ret)
- goto err_free_wide_mem;
+ goto err_free_mem;
scsi_scan_host(shost);
return 0;
- err_free_wide_mem:
- advansys_wide_free_mem(boardp);
+ err_free_mem:
+ if (ASC_NARROW_BOARD(boardp)) {
+ if (asc_dvc_varp->overrun_dma)
+ dma_unmap_single(boardp->dev, asc_dvc_varp->overrun_dma,
+ ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
+ kfree(asc_dvc_varp->overrun_buf);
+ } else
+ advansys_wide_free_mem(boardp);
+ err_free_irq:
free_irq(boardp->irq, shost);
err_free_dma:
#ifdef CONFIG_ISA
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 6d5ae44..633e090 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -471,12 +471,12 @@
WARN_ON(hdrlength >= 256);
hdr->hlength = hdrlength & 0xFF;
+ hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
if (session->tt->init_task && session->tt->init_task(task))
return -EIO;
task->state = ISCSI_TASK_RUNNING;
- hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn);
session->cmdsn++;
conn->scsicmd_pdus_cnt++;
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index b00efd1..88f7446 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -395,11 +395,15 @@
void sas_ata_task_abort(struct sas_task *task)
{
struct ata_queued_cmd *qc = task->uldd_task;
+ struct request_queue *q = qc->scsicmd->device->request_queue;
struct completion *waiting;
+ unsigned long flags;
/* Bounce SCSI-initiated commands to the SCSI EH */
if (qc->scsicmd) {
+ spin_lock_irqsave(q->queue_lock, flags);
blk_abort_request(qc->scsicmd->request);
+ spin_unlock_irqrestore(q->queue_lock, flags);
scsi_schedule_eh(qc->scsicmd->device->host);
return;
}
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 2660e1b..8228350 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -1030,6 +1030,8 @@
void sas_task_abort(struct sas_task *task)
{
struct scsi_cmnd *sc = task->uldd_task;
+ struct request_queue *q = sc->device->request_queue;
+ unsigned long flags;
/* Escape for libsas internal commands */
if (!sc) {
@@ -1044,7 +1046,9 @@
return;
}
+ spin_lock_irqsave(q->queue_lock, flags);
blk_abort_request(sc->request);
+ spin_unlock_irqrestore(q->queue_lock, flags);
scsi_schedule_eh(sc->device->host);
}
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 3e10c30..3a5bfd1 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -957,7 +957,8 @@
static sector_t get_sdebug_capacity(void)
{
if (scsi_debug_virtual_gb > 0)
- return 2048 * 1024 * (sector_t)scsi_debug_virtual_gb;
+ return (sector_t)scsi_debug_virtual_gb *
+ (1073741824 / scsi_debug_sector_size);
else
return sdebug_store_sectors;
}
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index d45c69c..7ad53fa 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -302,7 +302,20 @@
if (scmd->device->allow_restart &&
(sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
return FAILED;
- return SUCCESS;
+
+ if (blk_barrier_rq(scmd->request))
+ /*
+ * barrier requests should always retry on UA
+ * otherwise block will get a spurious error
+ */
+ return NEEDS_RETRY;
+ else
+ /*
+ * for normal (non barrier) commands, pass the
+ * UA upwards for a determination in the
+ * completion functions
+ */
+ return SUCCESS;
/* these three are not supported */
case COPY_ABORTED:
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8b827f3..de6c603 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1040,6 +1040,7 @@
{
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->timeout = SD_TIMEOUT;
+ rq->retries = SD_MAX_RETRIES;
rq->cmd[0] = SYNCHRONIZE_CACHE;
rq->cmd_len = 10;
}
diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c
index 105449c..e17764d 100644
--- a/drivers/scsi/zorro7xx.c
+++ b/drivers/scsi/zorro7xx.c
@@ -69,6 +69,7 @@
},
{ 0 }
};
+MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl);
static int __devinit zorro7xx_init_one(struct zorro_dev *z,
const struct zorro_device_id *ent)
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 4315b23..eacb588 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -120,7 +120,8 @@
#define MX2_UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */
#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
#define UCR3_BPEN (1<<0) /* Preset registers enable */
-#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */
+#define UCR4_CTSTL_SHF 10 /* CTS trigger level shift */
+#define UCR4_CTSTL_MASK 0x3F /* CTS trigger is 6 bits wide */
#define UCR4_INVR (1<<9) /* Inverted infrared reception */
#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */
#define UCR4_WKEN (1<<7) /* Wake interrupt enable */
@@ -591,6 +592,9 @@
return 0;
}
+/* half the RX buffer size */
+#define CTSTL 16
+
static int imx_startup(struct uart_port *port)
{
struct imx_port *sport = (struct imx_port *)port;
@@ -607,6 +611,10 @@
if (USE_IRDA(sport))
temp |= UCR4_IRSC;
+ /* set the trigger level for CTS */
+ temp &= ~(UCR4_CTSTL_MASK<< UCR4_CTSTL_SHF);
+ temp |= CTSTL<< UCR4_CTSTL_SHF;
+
writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
if (USE_IRDA(sport)) {
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index a176ab4..02469c3 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -1467,7 +1467,7 @@
/*
* Map the PSC FIFO Controller and init if on MPC512x.
*/
- if (psc_ops->fifoc_init) {
+ if (psc_ops && psc_ops->fifoc_init) {
ret = psc_ops->fifoc_init();
if (ret)
return ret;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 4a6366a..111a01a 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -380,6 +380,7 @@
mutex_lock(&inode->i_mutex);
dentry_unhash(dentry);
if (usbfs_empty(dentry)) {
+ dont_mount(dentry);
drop_nlink(dentry->d_inode);
drop_nlink(dentry->d_inode);
dput(dentry);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index e69d238..49fa953 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1035,7 +1035,12 @@
/* This actually signals the guest, using eventfd. */
void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
{
- __u16 flags = 0;
+ __u16 flags;
+ /* Flush out used index updates. This is paired
+ * with the barrier that the Guest executes when enabling
+ * interrupts. */
+ smp_mb();
+
if (get_user(flags, &vq->avail->flags)) {
vq_err(vq, "Failed to get flags");
return;
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index dca48df..e5d6b56 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -50,8 +50,9 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
-
+#include <linux/platform_device.h>
#include <linux/uaccess.h>
+
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
@@ -1135,7 +1136,7 @@
* Interface to the low level console driver
*/
-static void amifb_deinit(void);
+static void amifb_deinit(struct platform_device *pdev);
/*
* Internal routines
@@ -2246,7 +2247,7 @@
* Initialisation
*/
-static int __init amifb_init(void)
+static int __init amifb_probe(struct platform_device *pdev)
{
int tag, i, err = 0;
u_long chipptr;
@@ -2261,16 +2262,6 @@
}
amifb_setup(option);
#endif
- if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
- return -ENODEV;
-
- /*
- * We request all registers starting from bplpt[0]
- */
- if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120,
- "amifb [Denise/Lisa]"))
- return -EBUSY;
-
custom.dmacon = DMAF_ALL | DMAF_MASTER;
switch (amiga_chipset) {
@@ -2377,6 +2368,7 @@
fb_info.fbops = &amifb_ops;
fb_info.par = ¤tpar;
fb_info.flags = FBINFO_DEFAULT;
+ fb_info.device = &pdev->dev;
if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
@@ -2451,18 +2443,18 @@
return 0;
amifb_error:
- amifb_deinit();
+ amifb_deinit(pdev);
return err;
}
-static void amifb_deinit(void)
+static void amifb_deinit(struct platform_device *pdev)
{
if (fb_info.cmap.len)
fb_dealloc_cmap(&fb_info.cmap);
+ fb_dealloc_cmap(&fb_info.cmap);
chipfree();
if (videomemory)
iounmap((void*)videomemory);
- release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
custom.dmacon = DMAF_ALL | DMAF_MASTER;
}
@@ -3794,14 +3786,35 @@
}
}
-static void __exit amifb_exit(void)
+static int __exit amifb_remove(struct platform_device *pdev)
{
unregister_framebuffer(&fb_info);
- amifb_deinit();
+ amifb_deinit(pdev);
amifb_video_off();
+ return 0;
+}
+
+static struct platform_driver amifb_driver = {
+ .remove = __exit_p(amifb_remove),
+ .driver = {
+ .name = "amiga-video",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init amifb_init(void)
+{
+ return platform_driver_probe(&amifb_driver, amifb_probe);
}
module_init(amifb_init);
+
+static void __exit amifb_exit(void)
+{
+ platform_driver_unregister(&amifb_driver);
+}
+
module_exit(amifb_exit);
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:amiga-video");
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 44e49c2..c2ec3dcd 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -488,9 +488,9 @@
fbinfo->fbops = &bfin_t350mcqb_fb_ops;
fbinfo->flags = FBINFO_FLAG_DEFAULT;
- info->fb_buffer =
- dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
- GFP_KERNEL);
+ info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len +
+ ACTIVE_VIDEO_MEM_OFFSET,
+ &info->dma_handle, GFP_KERNEL);
if (NULL == info->fb_buffer) {
printk(KERN_ERR DRIVER_NAME
@@ -568,8 +568,8 @@
out6:
fb_dealloc_cmap(&fbinfo->cmap);
out4:
- dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
- info->dma_handle);
+ dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET,
+ info->fb_buffer, info->dma_handle);
out3:
framebuffer_release(fbinfo);
out2:
@@ -592,8 +592,9 @@
free_irq(info->irq, info);
if (info->fb_buffer != NULL)
- dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
- info->dma_handle);
+ dma_free_coherent(NULL, fbinfo->fix.smem_len +
+ ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer,
+ info->dma_handle);
fb_dealloc_cmap(&fbinfo->cmap);
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 8d8dfda..6df7c54 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -299,6 +299,7 @@
},
{ 0 }
};
+MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
static const struct {
zorro_id id2;
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 6c91c61..1b0feb8 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -219,6 +219,7 @@
{ ZORRO_PROD_HELFRICH_RAINBOW_II },
{ 0 }
};
+MODULE_DEVICE_TABLE(zorro, fm2fb_devices);
static struct zorro_driver fm2fb_driver = {
.name = "fm2fb",
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index e14bd07..e8c7699 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -695,6 +695,7 @@
* 1) Enable Runtime PM
* 2) Force Runtime PM Resume since hardware is accessed from probe()
*/
+ priv->dev = &pdev->dev;
pm_runtime_enable(priv->dev);
pm_runtime_resume(priv->dev);
return 0;
@@ -957,25 +958,24 @@
if (!pdev->dev.platform_data) {
dev_err(&pdev->dev, "no platform data defined\n");
- error = -EINVAL;
- goto err0;
+ return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i = platform_get_irq(pdev, 0);
if (!res || i < 0) {
dev_err(&pdev->dev, "cannot get platform resources\n");
- error = -ENOENT;
- goto err0;
+ return -ENOENT;
}
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "cannot allocate device data\n");
- error = -ENOMEM;
- goto err0;
+ return -ENOMEM;
}
+ platform_set_drvdata(pdev, priv);
+
error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,
dev_name(&pdev->dev), priv);
if (error) {
@@ -984,8 +984,6 @@
}
priv->irq = i;
- priv->dev = &pdev->dev;
- platform_set_drvdata(pdev, priv);
pdata = pdev->dev.platform_data;
j = 0;
@@ -1099,9 +1097,9 @@
info = ch->info;
if (info->fbdefio) {
- priv->ch->sglist = vmalloc(sizeof(struct scatterlist) *
+ ch->sglist = vmalloc(sizeof(struct scatterlist) *
info->fix.smem_len >> PAGE_SHIFT);
- if (!priv->ch->sglist) {
+ if (!ch->sglist) {
dev_err(&pdev->dev, "cannot allocate sglist\n");
goto err1;
}
@@ -1126,9 +1124,9 @@
}
return 0;
- err1:
+err1:
sh_mobile_lcdc_remove(pdev);
- err0:
+
return error;
}
@@ -1139,7 +1137,7 @@
int i;
for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
- if (priv->ch[i].info->dev)
+ if (priv->ch[i].info && priv->ch[i].info->dev)
unregister_framebuffer(priv->ch[i].info);
sh_mobile_lcdc_stop(priv);
@@ -1162,7 +1160,8 @@
if (priv->dot_clk)
clk_put(priv->dot_clk);
- pm_runtime_disable(priv->dev);
+ if (priv->dev)
+ pm_runtime_disable(priv->dev);
if (priv->base)
iounmap(priv->base);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 0bf5020..b87ba23 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -175,7 +175,7 @@
config MPCORE_WATCHDOG
tristate "MPcore watchdog"
- depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS
+ depends on HAVE_ARM_TWD
help
Watchdog timer embedded into the MPcore system.
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index 016c6a7..b8ec7ac 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -31,8 +31,9 @@
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
+#include <linux/io.h>
-#include <asm/hardware/arm_twd.h>
+#include <asm/smp_twd.h>
struct mpcore_wdt {
unsigned long timer_alive;
@@ -44,7 +45,7 @@
};
static struct platform_device *mpcore_wdt_dev;
-extern unsigned int mpcore_timer_rate;
+static DEFINE_SPINLOCK(wdt_lock);
#define TIMER_MARGIN 60
static int mpcore_margin = TIMER_MARGIN;
@@ -94,13 +95,15 @@
*/
static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt)
{
- unsigned int count;
+ unsigned long count;
+ spin_lock(&wdt_lock);
/* Assume prescale is set to 256 */
- count = (mpcore_timer_rate / 256) * mpcore_margin;
+ count = __raw_readl(wdt->base + TWD_WDOG_COUNTER);
+ count = (0xFFFFFFFFU - count) * (HZ / 5);
+ count = (count / 256) * mpcore_margin;
/* Reload the counter */
- spin_lock(&wdt_lock);
writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
wdt->perturb = wdt->perturb ? 0 : 1;
spin_unlock(&wdt_lock);
@@ -119,7 +122,6 @@
{
dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
- spin_lock(&wdt_lock);
/* This loads the count register but does NOT start the count yet */
mpcore_wdt_keepalive(wdt);
@@ -130,7 +132,6 @@
/* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
}
- spin_unlock(&wdt_lock);
}
static int mpcore_wdt_set_heartbeat(int t)
@@ -360,7 +361,7 @@
mpcore_wdt_miscdev.parent = &dev->dev;
ret = misc_register(&mpcore_wdt_miscdev);
if (ret) {
- dev_printk(KERN_ERR, _dev,
+ dev_printk(KERN_ERR, wdt->dev,
"cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
goto err_misc;
@@ -369,13 +370,13 @@
ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED,
"mpcore_wdt", wdt);
if (ret) {
- dev_printk(KERN_ERR, _dev,
+ dev_printk(KERN_ERR, wdt->dev,
"cannot register IRQ%d for watchdog\n", wdt->irq);
goto err_irq;
}
mpcore_wdt_stop(wdt);
- platform_set_drvdata(&dev->dev, wdt);
+ platform_set_drvdata(dev, wdt);
mpcore_wdt_dev = dev;
return 0;
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index d47c47f..3c7046d 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -97,7 +97,7 @@
static int zorro_seq_show(struct seq_file *m, void *v)
{
- u_int slot = *(loff_t *)v;
+ unsigned int slot = *(loff_t *)v;
struct zorro_dev *z = &zorro_autocon[slot];
seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id,
@@ -129,7 +129,7 @@
static struct proc_dir_entry *proc_bus_zorro_dir;
-static int __init zorro_proc_attach_device(u_int slot)
+static int __init zorro_proc_attach_device(unsigned int slot)
{
struct proc_dir_entry *entry;
char name[4];
@@ -146,7 +146,7 @@
static int __init zorro_proc_init(void)
{
- u_int slot;
+ unsigned int slot;
if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) {
proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL);
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c
index 53180a3..7ee2b6e 100644
--- a/drivers/zorro/zorro-driver.c
+++ b/drivers/zorro/zorro-driver.c
@@ -137,10 +137,34 @@
return 0;
}
+static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+#ifdef CONFIG_HOTPLUG
+ struct zorro_dev *z;
+
+ if (!dev)
+ return -ENODEV;
+
+ z = to_zorro_dev(dev);
+ if (!z)
+ return -ENODEV;
+
+ if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) ||
+ add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) ||
+ add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) ||
+ add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id))
+ return -ENOMEM;
+
+ return 0;
+#else /* !CONFIG_HOTPLUG */
+ return -ENODEV;
+#endif /* !CONFIG_HOTPLUG */
+}
struct bus_type zorro_bus_type = {
.name = "zorro",
.match = zorro_bus_match,
+ .uevent = zorro_uevent,
.probe = zorro_device_probe,
.remove = zorro_device_remove,
};
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index 1d2a772e..eb924e0 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -77,6 +77,16 @@
.read = zorro_read_config,
};
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct zorro_dev *z = to_zorro_dev(dev);
+
+ return sprintf(buf, ZORRO_DEVICE_MODALIAS_FMT "\n", z->id);
+}
+
+static DEVICE_ATTR(modalias, S_IRUGO, modalias_show, NULL);
+
int zorro_create_sysfs_dev_files(struct zorro_dev *z)
{
struct device *dev = &z->dev;
@@ -89,6 +99,7 @@
(error = device_create_file(dev, &dev_attr_slotaddr)) ||
(error = device_create_file(dev, &dev_attr_slotsize)) ||
(error = device_create_file(dev, &dev_attr_resource)) ||
+ (error = device_create_file(dev, &dev_attr_modalias)) ||
(error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr)))
return error;
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index d45fb34..6455f3a 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -15,6 +15,8 @@
#include <linux/zorro.h>
#include <linux/bitops.h>
#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <asm/setup.h>
#include <asm/amigahw.h>
@@ -26,24 +28,17 @@
* Zorro Expansion Devices
*/
-u_int zorro_num_autocon = 0;
+unsigned int zorro_num_autocon;
struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];
/*
- * Single Zorro bus
+ * Zorro bus
*/
-struct zorro_bus zorro_bus = {\
- .resources = {
- /* Zorro II regions (on Zorro II/III) */
- { .name = "Zorro II exp", .start = 0x00e80000, .end = 0x00efffff },
- { .name = "Zorro II mem", .start = 0x00200000, .end = 0x009fffff },
- /* Zorro III regions (on Zorro III only) */
- { .name = "Zorro III exp", .start = 0xff000000, .end = 0xffffffff },
- { .name = "Zorro III cfg", .start = 0x40000000, .end = 0x7fffffff }
- },
- .name = "Zorro bus"
+struct zorro_bus {
+ struct list_head devices; /* list of devices on this bus */
+ struct device dev;
};
@@ -53,18 +48,19 @@
struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from)
{
- struct zorro_dev *z;
+ struct zorro_dev *z;
- if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
+ if (!zorro_num_autocon)
+ return NULL;
+
+ for (z = from ? from+1 : &zorro_autocon[0];
+ z < zorro_autocon+zorro_num_autocon;
+ z++)
+ if (id == ZORRO_WILDCARD || id == z->id)
+ return z;
return NULL;
-
- for (z = from ? from+1 : &zorro_autocon[0];
- z < zorro_autocon+zorro_num_autocon;
- z++)
- if (id == ZORRO_WILDCARD || id == z->id)
- return z;
- return NULL;
}
+EXPORT_SYMBOL(zorro_find_device);
/*
@@ -83,121 +79,138 @@
*/
DECLARE_BITMAP(zorro_unused_z2ram, 128);
+EXPORT_SYMBOL(zorro_unused_z2ram);
static void __init mark_region(unsigned long start, unsigned long end,
int flag)
{
- if (flag)
- start += Z2RAM_CHUNKMASK;
- else
- end += Z2RAM_CHUNKMASK;
- start &= ~Z2RAM_CHUNKMASK;
- end &= ~Z2RAM_CHUNKMASK;
-
- if (end <= Z2RAM_START || start >= Z2RAM_END)
- return;
- start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START;
- end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START;
- while (start < end) {
- u32 chunk = start>>Z2RAM_CHUNKSHIFT;
if (flag)
- set_bit(chunk, zorro_unused_z2ram);
+ start += Z2RAM_CHUNKMASK;
else
- clear_bit(chunk, zorro_unused_z2ram);
- start += Z2RAM_CHUNKSIZE;
- }
-}
+ end += Z2RAM_CHUNKMASK;
+ start &= ~Z2RAM_CHUNKMASK;
+ end &= ~Z2RAM_CHUNKMASK;
-
-static struct resource __init *zorro_find_parent_resource(struct zorro_dev *z)
-{
- int i;
-
- for (i = 0; i < zorro_bus.num_resources; i++)
- if (zorro_resource_start(z) >= zorro_bus.resources[i].start &&
- zorro_resource_end(z) <= zorro_bus.resources[i].end)
- return &zorro_bus.resources[i];
- return &iomem_resource;
-}
-
-
- /*
- * Initialization
- */
-
-static int __init zorro_init(void)
-{
- struct zorro_dev *z;
- unsigned int i;
- int error;
-
- if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
- return 0;
-
- pr_info("Zorro: Probing AutoConfig expansion devices: %d device%s\n",
- zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
-
- /* Initialize the Zorro bus */
- INIT_LIST_HEAD(&zorro_bus.devices);
- dev_set_name(&zorro_bus.dev, "zorro");
- error = device_register(&zorro_bus.dev);
- if (error) {
- pr_err("Zorro: Error registering zorro_bus\n");
- return error;
- }
-
- /* Request the resources */
- zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2;
- for (i = 0; i < zorro_bus.num_resources; i++)
- request_resource(&iomem_resource, &zorro_bus.resources[i]);
-
- /* Register all devices */
- for (i = 0; i < zorro_num_autocon; i++) {
- z = &zorro_autocon[i];
- z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8);
- if (z->id == ZORRO_PROD_GVP_EPC_BASE) {
- /* GVP quirk */
- unsigned long magic = zorro_resource_start(z)+0x8000;
- z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK;
+ if (end <= Z2RAM_START || start >= Z2RAM_END)
+ return;
+ start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START;
+ end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START;
+ while (start < end) {
+ u32 chunk = start>>Z2RAM_CHUNKSHIFT;
+ if (flag)
+ set_bit(chunk, zorro_unused_z2ram);
+ else
+ clear_bit(chunk, zorro_unused_z2ram);
+ start += Z2RAM_CHUNKSIZE;
}
- sprintf(z->name, "Zorro device %08x", z->id);
- zorro_name_device(z);
- z->resource.name = z->name;
- if (request_resource(zorro_find_parent_resource(z), &z->resource))
- pr_err("Zorro: Address space collision on device %s %pR\n",
- z->name, &z->resource);
- dev_set_name(&z->dev, "%02x", i);
- z->dev.parent = &zorro_bus.dev;
- z->dev.bus = &zorro_bus_type;
- error = device_register(&z->dev);
+}
+
+
+static struct resource __init *zorro_find_parent_resource(
+ struct platform_device *bridge, struct zorro_dev *z)
+{
+ int i;
+
+ for (i = 0; i < bridge->num_resources; i++) {
+ struct resource *r = &bridge->resource[i];
+ if (zorro_resource_start(z) >= r->start &&
+ zorro_resource_end(z) <= r->end)
+ return r;
+ }
+ return &iomem_resource;
+}
+
+
+
+static int __init amiga_zorro_probe(struct platform_device *pdev)
+{
+ struct zorro_bus *bus;
+ struct zorro_dev *z;
+ struct resource *r;
+ unsigned int i;
+ int error;
+
+ /* Initialize the Zorro bus */
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&bus->devices);
+ bus->dev.parent = &pdev->dev;
+ dev_set_name(&bus->dev, "zorro");
+ error = device_register(&bus->dev);
if (error) {
- pr_err("Zorro: Error registering device %s\n", z->name);
- continue;
+ pr_err("Zorro: Error registering zorro_bus\n");
+ kfree(bus);
+ return error;
}
- error = zorro_create_sysfs_dev_files(z);
- if (error)
- dev_err(&z->dev, "Error creating sysfs files\n");
- }
+ platform_set_drvdata(pdev, bus);
- /* Mark all available Zorro II memory */
- zorro_for_each_dev(z) {
- if (z->rom.er_Type & ERTF_MEMLIST)
- mark_region(zorro_resource_start(z), zorro_resource_end(z)+1, 1);
- }
+ /* Register all devices */
+ pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n",
+ zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
- /* Unmark all used Zorro II memory */
- for (i = 0; i < m68k_num_memory; i++)
- if (m68k_memory[i].addr < 16*1024*1024)
- mark_region(m68k_memory[i].addr,
- m68k_memory[i].addr+m68k_memory[i].size, 0);
+ for (i = 0; i < zorro_num_autocon; i++) {
+ z = &zorro_autocon[i];
+ z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8);
+ if (z->id == ZORRO_PROD_GVP_EPC_BASE) {
+ /* GVP quirk */
+ unsigned long magic = zorro_resource_start(z)+0x8000;
+ z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK;
+ }
+ sprintf(z->name, "Zorro device %08x", z->id);
+ zorro_name_device(z);
+ z->resource.name = z->name;
+ r = zorro_find_parent_resource(pdev, z);
+ error = request_resource(r, &z->resource);
+ if (error)
+ dev_err(&bus->dev,
+ "Address space collision on device %s %pR\n",
+ z->name, &z->resource);
+ dev_set_name(&z->dev, "%02x", i);
+ z->dev.parent = &bus->dev;
+ z->dev.bus = &zorro_bus_type;
+ error = device_register(&z->dev);
+ if (error) {
+ dev_err(&bus->dev, "Error registering device %s\n",
+ z->name);
+ continue;
+ }
+ error = zorro_create_sysfs_dev_files(z);
+ if (error)
+ dev_err(&z->dev, "Error creating sysfs files\n");
+ }
- return 0;
+ /* Mark all available Zorro II memory */
+ zorro_for_each_dev(z) {
+ if (z->rom.er_Type & ERTF_MEMLIST)
+ mark_region(zorro_resource_start(z),
+ zorro_resource_end(z)+1, 1);
+ }
+
+ /* Unmark all used Zorro II memory */
+ for (i = 0; i < m68k_num_memory; i++)
+ if (m68k_memory[i].addr < 16*1024*1024)
+ mark_region(m68k_memory[i].addr,
+ m68k_memory[i].addr+m68k_memory[i].size,
+ 0);
+
+ return 0;
}
-subsys_initcall(zorro_init);
+static struct platform_driver amiga_zorro_driver = {
+ .driver = {
+ .name = "amiga-zorro",
+ .owner = THIS_MODULE,
+ },
+};
-EXPORT_SYMBOL(zorro_find_device);
-EXPORT_SYMBOL(zorro_unused_z2ram);
+static int __init amiga_zorro_init(void)
+{
+ return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe);
+}
+
+module_init(amiga_zorro_init);
MODULE_LICENSE("GPL");
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 109a6c6..e8e5e63 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -177,8 +177,7 @@
}
/* Trigger mount for path component or follow link */
} else if (ino->flags & AUTOFS_INF_PENDING ||
- autofs4_need_mount(flags) ||
- current->link_count) {
+ autofs4_need_mount(flags)) {
DPRINTK("waiting for mount name=%.*s",
dentry->d_name.len, dentry->d_name.name);
@@ -262,7 +261,7 @@
spin_unlock(&dcache_lock);
spin_unlock(&sbi->fs_lock);
- status = try_to_fill_dentry(dentry, 0);
+ status = try_to_fill_dentry(dentry, nd->flags);
if (status)
goto out_error;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index e84ef60..97a9783 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1481,12 +1481,17 @@
ret = -EBADF;
goto out_drop_write;
}
+
src = src_file->f_dentry->d_inode;
ret = -EINVAL;
if (src == inode)
goto out_fput;
+ /* the src must be open for reading */
+ if (!(src_file->f_mode & FMODE_READ))
+ goto out_fput;
+
ret = -EISDIR;
if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
goto out_fput;
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index f7c255f..a8cd821 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -34,6 +34,7 @@
loff_t i_size; /* object size */
unsigned long flags;
#define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */
+#define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */
atomic_t usage; /* object usage count */
uint8_t type; /* object type */
uint8_t new; /* T if object new */
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index d5db84a1e..f4a7840 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -93,6 +93,59 @@
}
/*
+ * mark the owner of a dentry, if there is one, to indicate that that dentry
+ * has been preemptively deleted
+ * - the caller must hold the i_mutex on the dentry's parent as required to
+ * call vfs_unlink(), vfs_rmdir() or vfs_rename()
+ */
+static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
+ struct dentry *dentry)
+{
+ struct cachefiles_object *object;
+ struct rb_node *p;
+
+ _enter(",'%*.*s'",
+ dentry->d_name.len, dentry->d_name.len, dentry->d_name.name);
+
+ write_lock(&cache->active_lock);
+
+ p = cache->active_nodes.rb_node;
+ while (p) {
+ object = rb_entry(p, struct cachefiles_object, active_node);
+ if (object->dentry > dentry)
+ p = p->rb_left;
+ else if (object->dentry < dentry)
+ p = p->rb_right;
+ else
+ goto found_dentry;
+ }
+
+ write_unlock(&cache->active_lock);
+ _leave(" [no owner]");
+ return;
+
+ /* found the dentry for */
+found_dentry:
+ kdebug("preemptive burial: OBJ%x [%s] %p",
+ object->fscache.debug_id,
+ fscache_object_states[object->fscache.state],
+ dentry);
+
+ if (object->fscache.state < FSCACHE_OBJECT_DYING) {
+ printk(KERN_ERR "\n");
+ printk(KERN_ERR "CacheFiles: Error:"
+ " Can't preemptively bury live object\n");
+ cachefiles_printk_object(object, NULL);
+ } else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
+ printk(KERN_ERR "CacheFiles: Error:"
+ " Object already preemptively buried\n");
+ }
+
+ write_unlock(&cache->active_lock);
+ _leave(" [owner marked]");
+}
+
+/*
* record the fact that an object is now active
*/
static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
@@ -219,7 +272,8 @@
*/
static int cachefiles_bury_object(struct cachefiles_cache *cache,
struct dentry *dir,
- struct dentry *rep)
+ struct dentry *rep,
+ bool preemptive)
{
struct dentry *grave, *trap;
char nbuffer[8 + 8 + 1];
@@ -229,11 +283,16 @@
dir->d_name.len, dir->d_name.len, dir->d_name.name,
rep->d_name.len, rep->d_name.len, rep->d_name.name);
+ _debug("remove %p from %p", rep, dir);
+
/* non-directories can just be unlinked */
if (!S_ISDIR(rep->d_inode->i_mode)) {
_debug("unlink stale object");
ret = vfs_unlink(dir->d_inode, rep);
+ if (preemptive)
+ cachefiles_mark_object_buried(cache, rep);
+
mutex_unlock(&dir->d_inode->i_mutex);
if (ret == -EIO)
@@ -325,6 +384,9 @@
if (ret != 0 && ret != -ENOMEM)
cachefiles_io_error(cache, "Rename failed with error %d", ret);
+ if (preemptive)
+ cachefiles_mark_object_buried(cache, rep);
+
unlock_rename(cache->graveyard, dir);
dput(grave);
_leave(" = 0");
@@ -340,7 +402,7 @@
struct dentry *dir;
int ret;
- _enter(",{%p}", object->dentry);
+ _enter(",OBJ%x{%p}", object->fscache.debug_id, object->dentry);
ASSERT(object->dentry);
ASSERT(object->dentry->d_inode);
@@ -350,15 +412,25 @@
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
- /* we need to check that our parent is _still_ our parent - it may have
- * been renamed */
- if (dir == object->dentry->d_parent) {
- ret = cachefiles_bury_object(cache, dir, object->dentry);
- } else {
- /* it got moved, presumably by cachefilesd culling it, so it's
- * no longer in the key path and we can ignore it */
+ if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
+ /* object allocation for the same key preemptively deleted this
+ * object's file so that it could create its own file */
+ _debug("object preemptively buried");
mutex_unlock(&dir->d_inode->i_mutex);
ret = 0;
+ } else {
+ /* we need to check that our parent is _still_ our parent - it
+ * may have been renamed */
+ if (dir == object->dentry->d_parent) {
+ ret = cachefiles_bury_object(cache, dir,
+ object->dentry, false);
+ } else {
+ /* it got moved, presumably by cachefilesd culling it,
+ * so it's no longer in the key path and we can ignore
+ * it */
+ mutex_unlock(&dir->d_inode->i_mutex);
+ ret = 0;
+ }
}
dput(dir);
@@ -381,7 +453,9 @@
const char *name;
int ret, nlen;
- _enter("{%p},,%s,", parent->dentry, key);
+ _enter("OBJ%x{%p},OBJ%x,%s,",
+ parent->fscache.debug_id, parent->dentry,
+ object->fscache.debug_id, key);
cache = container_of(parent->fscache.cache,
struct cachefiles_cache, cache);
@@ -509,7 +583,7 @@
* mutex) */
object->dentry = NULL;
- ret = cachefiles_bury_object(cache, dir, next);
+ ret = cachefiles_bury_object(cache, dir, next, true);
dput(next);
next = NULL;
@@ -828,7 +902,7 @@
/* actually remove the victim (drops the dir mutex) */
_debug("bury");
- ret = cachefiles_bury_object(cache, dir, victim);
+ ret = cachefiles_bury_object(cache, dir, victim, false);
if (ret < 0)
goto error;
diff --git a/fs/cachefiles/security.c b/fs/cachefiles/security.c
index b5808cd..039b501 100644
--- a/fs/cachefiles/security.c
+++ b/fs/cachefiles/security.c
@@ -77,6 +77,8 @@
/*
* check the security details of the on-disk cache
* - must be called with security override in force
+ * - must return with a security override in force - even in the case of an
+ * error
*/
int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
struct dentry *root,
@@ -99,6 +101,8 @@
* which create files */
ret = set_create_files_as(new, root->d_inode);
if (ret < 0) {
+ abort_creds(new);
+ cachefiles_begin_secure(cache, _saved_cred);
_leave(" = %d [cfa]", ret);
return ret;
}
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 4b42c2b..a9005d8 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -504,7 +504,6 @@
int i;
struct ceph_snap_context *snapc = req->r_snapc;
struct address_space *mapping = inode->i_mapping;
- struct writeback_control *wbc = req->r_wbc;
__s32 rc = -EIO;
u64 bytes = 0;
struct ceph_client *client = ceph_inode_to_client(inode);
@@ -546,10 +545,6 @@
clear_bdi_congested(&client->backing_dev_info,
BLK_RW_ASYNC);
- if (i >= wrote) {
- dout("inode %p skipping page %p\n", inode, page);
- wbc->pages_skipped++;
- }
ceph_put_snap_context((void *)page->private);
page->private = 0;
ClearPagePrivate(page);
@@ -799,7 +794,6 @@
alloc_page_vec(client, req);
req->r_callback = writepages_finish;
req->r_inode = inode;
- req->r_wbc = wbc;
}
/* note position of first page in pvec */
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 0c16818..d940053 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -858,6 +858,8 @@
}
/*
+ * Remove a cap. Take steps to deal with a racing iterate_session_caps.
+ *
* caller should hold i_lock.
* caller will not hold session s_mutex if called from destroy_inode.
*/
@@ -866,15 +868,10 @@
struct ceph_mds_session *session = cap->session;
struct ceph_inode_info *ci = cap->ci;
struct ceph_mds_client *mdsc = &ceph_client(ci->vfs_inode.i_sb)->mdsc;
+ int removed = 0;
dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);
- /* remove from inode list */
- rb_erase(&cap->ci_node, &ci->i_caps);
- cap->ci = NULL;
- if (ci->i_auth_cap == cap)
- ci->i_auth_cap = NULL;
-
/* remove from session list */
spin_lock(&session->s_cap_lock);
if (session->s_cap_iterator == cap) {
@@ -885,10 +882,18 @@
list_del_init(&cap->session_caps);
session->s_nr_caps--;
cap->session = NULL;
+ removed = 1;
}
+ /* protect backpointer with s_cap_lock: see iterate_session_caps */
+ cap->ci = NULL;
spin_unlock(&session->s_cap_lock);
- if (cap->session == NULL)
+ /* remove from inode list */
+ rb_erase(&cap->ci_node, &ci->i_caps);
+ if (ci->i_auth_cap == cap)
+ ci->i_auth_cap = NULL;
+
+ if (removed)
ceph_put_cap(cap);
if (!__ceph_is_any_caps(ci) && ci->i_snap_realm) {
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 261f3e6..85b4d2f 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -733,6 +733,10 @@
__ceph_get_fmode(ci, cap_fmode);
spin_unlock(&inode->i_lock);
}
+ } else if (cap_fmode >= 0) {
+ pr_warning("mds issued no caps on %llx.%llx\n",
+ ceph_vinop(inode));
+ __ceph_get_fmode(ci, cap_fmode);
}
/* update delegation info? */
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 60a9a4a..24561a5 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -736,9 +736,10 @@
}
/*
- * Helper to safely iterate over all caps associated with a session.
+ * Helper to safely iterate over all caps associated with a session, with
+ * special care taken to handle a racing __ceph_remove_cap().
*
- * caller must hold session s_mutex
+ * Caller must hold session s_mutex.
*/
static int iterate_session_caps(struct ceph_mds_session *session,
int (*cb)(struct inode *, struct ceph_cap *,
@@ -2136,7 +2137,7 @@
struct ceph_mds_session *session = NULL;
struct ceph_msg *reply;
struct rb_node *p;
- int err;
+ int err = -ENOMEM;
struct ceph_pagelist *pagelist;
pr_info("reconnect to recovering mds%d\n", mds);
@@ -2185,7 +2186,7 @@
goto fail;
err = iterate_session_caps(session, encode_caps_cb, pagelist);
if (err < 0)
- goto out;
+ goto fail;
/*
* snaprealms. we provide mds with the ino, seq (version), and
@@ -2213,28 +2214,31 @@
reply->nr_pages = calc_pages_for(0, pagelist->length);
ceph_con_send(&session->s_con, reply);
- if (session) {
- session->s_state = CEPH_MDS_SESSION_OPEN;
- __wake_requests(mdsc, &session->s_waiting);
- }
+ session->s_state = CEPH_MDS_SESSION_OPEN;
+ mutex_unlock(&session->s_mutex);
-out:
+ mutex_lock(&mdsc->mutex);
+ __wake_requests(mdsc, &session->s_waiting);
+ mutex_unlock(&mdsc->mutex);
+
+ ceph_put_mds_session(session);
+
up_read(&mdsc->snap_rwsem);
- if (session) {
- mutex_unlock(&session->s_mutex);
- ceph_put_mds_session(session);
- }
mutex_lock(&mdsc->mutex);
return;
fail:
ceph_msg_put(reply);
+ up_read(&mdsc->snap_rwsem);
+ mutex_unlock(&session->s_mutex);
+ ceph_put_mds_session(session);
fail_nomsg:
ceph_pagelist_release(pagelist);
kfree(pagelist);
fail_nopagelist:
- pr_err("ENOMEM preparing reconnect for mds%d\n", mds);
- goto out;
+ pr_err("error %d preparing reconnect for mds%d\n", err, mds);
+ mutex_lock(&mdsc->mutex);
+ return;
}
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c
index 509f57d..cd4fadb 100644
--- a/fs/ceph/messenger.c
+++ b/fs/ceph/messenger.c
@@ -492,7 +492,14 @@
list_move_tail(&m->list_head, &con->out_sent);
}
- m->hdr.seq = cpu_to_le64(++con->out_seq);
+ /*
+ * only assign outgoing seq # if we haven't sent this message
+ * yet. if it is requeued, resend with it's original seq.
+ */
+ if (m->needs_out_seq) {
+ m->hdr.seq = cpu_to_le64(++con->out_seq);
+ m->needs_out_seq = false;
+ }
dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n",
m, con->out_seq, le16_to_cpu(m->hdr.type),
@@ -1986,6 +1993,8 @@
BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len));
+ msg->needs_out_seq = true;
+
/* queue */
mutex_lock(&con->mutex);
BUG_ON(!list_empty(&msg->list_head));
@@ -2085,15 +2094,19 @@
kref_init(&m->kref);
INIT_LIST_HEAD(&m->list_head);
+ m->hdr.tid = 0;
m->hdr.type = cpu_to_le16(type);
+ m->hdr.priority = cpu_to_le16(CEPH_MSG_PRIO_DEFAULT);
+ m->hdr.version = 0;
m->hdr.front_len = cpu_to_le32(front_len);
m->hdr.middle_len = 0;
m->hdr.data_len = cpu_to_le32(page_len);
m->hdr.data_off = cpu_to_le16(page_off);
- m->hdr.priority = cpu_to_le16(CEPH_MSG_PRIO_DEFAULT);
+ m->hdr.reserved = 0;
m->footer.front_crc = 0;
m->footer.middle_crc = 0;
m->footer.data_crc = 0;
+ m->footer.flags = 0;
m->front_max = front_len;
m->front_is_vmalloc = false;
m->more_to_follow = false;
diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h
index a343dae..a5caf91 100644
--- a/fs/ceph/messenger.h
+++ b/fs/ceph/messenger.h
@@ -86,6 +86,7 @@
struct kref kref;
bool front_is_vmalloc;
bool more_to_follow;
+ bool needs_out_seq;
int front_max;
struct ceph_msgpool *pool;
diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c
index c7b4ded..3514f71 100644
--- a/fs/ceph/osd_client.c
+++ b/fs/ceph/osd_client.c
@@ -565,7 +565,8 @@
{
struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
struct ceph_pg pgid;
- int o = -1;
+ int acting[CEPH_PG_MAX_SIZE];
+ int o = -1, num = 0;
int err;
dout("map_osds %p tid %lld\n", req, req->r_tid);
@@ -576,10 +577,16 @@
pgid = reqhead->layout.ol_pgid;
req->r_pgid = pgid;
- o = ceph_calc_pg_primary(osdc->osdmap, pgid);
+ err = ceph_calc_pg_acting(osdc->osdmap, pgid, acting);
+ if (err > 0) {
+ o = acting[0];
+ num = err;
+ }
if ((req->r_osd && req->r_osd->o_osd == o &&
- req->r_sent >= req->r_osd->o_incarnation) ||
+ req->r_sent >= req->r_osd->o_incarnation &&
+ req->r_num_pg_osds == num &&
+ memcmp(req->r_pg_osds, acting, sizeof(acting[0])*num) == 0) ||
(req->r_osd == NULL && o == -1))
return 0; /* no change */
@@ -587,6 +594,10 @@
req->r_tid, le32_to_cpu(pgid.pool), le16_to_cpu(pgid.ps), o,
req->r_osd ? req->r_osd->o_osd : -1);
+ /* record full pg acting set */
+ memcpy(req->r_pg_osds, acting, sizeof(acting[0]) * num);
+ req->r_num_pg_osds = num;
+
if (req->r_osd) {
__cancel_request(req);
list_del_init(&req->r_osd_item);
@@ -612,7 +623,7 @@
__remove_osd_from_lru(req->r_osd);
list_add(&req->r_osd_item, &req->r_osd->o_requests);
}
- err = 1; /* osd changed */
+ err = 1; /* osd or pg changed */
out:
return err;
@@ -779,16 +790,18 @@
struct ceph_osd_request *req;
u64 tid;
int numops, object_len, flags;
+ s32 result;
tid = le64_to_cpu(msg->hdr.tid);
if (msg->front.iov_len < sizeof(*rhead))
goto bad;
numops = le32_to_cpu(rhead->num_ops);
object_len = le32_to_cpu(rhead->object_len);
+ result = le32_to_cpu(rhead->result);
if (msg->front.iov_len != sizeof(*rhead) + object_len +
numops * sizeof(struct ceph_osd_op))
goto bad;
- dout("handle_reply %p tid %llu\n", msg, tid);
+ dout("handle_reply %p tid %llu result %d\n", msg, tid, (int)result);
/* lookup */
mutex_lock(&osdc->request_mutex);
@@ -834,7 +847,8 @@
dout("handle_reply tid %llu flags %d\n", tid, flags);
/* either this is a read, or we got the safe response */
- if ((flags & CEPH_OSD_FLAG_ONDISK) ||
+ if (result < 0 ||
+ (flags & CEPH_OSD_FLAG_ONDISK) ||
((flags & CEPH_OSD_FLAG_WRITE) == 0))
__unregister_request(osdc, req);
diff --git a/fs/ceph/osd_client.h b/fs/ceph/osd_client.h
index b075991..ce77698 100644
--- a/fs/ceph/osd_client.h
+++ b/fs/ceph/osd_client.h
@@ -48,6 +48,8 @@
struct list_head r_osd_item;
struct ceph_osd *r_osd;
struct ceph_pg r_pgid;
+ int r_pg_osds[CEPH_PG_MAX_SIZE];
+ int r_num_pg_osds;
struct ceph_connection *r_con_filling_msg;
@@ -66,7 +68,6 @@
struct list_head r_unsafe_item;
struct inode *r_inode; /* for use by callbacks */
- struct writeback_control *r_wbc; /* ditto */
char r_oid[40]; /* object name */
int r_oid_len;
diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c
index 2e2c15e..cfdd8f4 100644
--- a/fs/ceph/osdmap.c
+++ b/fs/ceph/osdmap.c
@@ -1041,12 +1041,33 @@
}
/*
+ * Return acting set for given pgid.
+ */
+int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
+ int *acting)
+{
+ int rawosds[CEPH_PG_MAX_SIZE], *osds;
+ int i, o, num = CEPH_PG_MAX_SIZE;
+
+ osds = calc_pg_raw(osdmap, pgid, rawosds, &num);
+ if (!osds)
+ return -1;
+
+ /* primary is first up osd */
+ o = 0;
+ for (i = 0; i < num; i++)
+ if (ceph_osd_is_up(osdmap, osds[i]))
+ acting[o++] = osds[i];
+ return o;
+}
+
+/*
* Return primary osd for given pgid, or -1 if none.
*/
int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid)
{
- int rawosds[10], *osds;
- int i, num = ARRAY_SIZE(rawosds);
+ int rawosds[CEPH_PG_MAX_SIZE], *osds;
+ int i, num = CEPH_PG_MAX_SIZE;
osds = calc_pg_raw(osdmap, pgid, rawosds, &num);
if (!osds)
@@ -1054,9 +1075,7 @@
/* primary is first up osd */
for (i = 0; i < num; i++)
- if (ceph_osd_is_up(osdmap, osds[i])) {
+ if (ceph_osd_is_up(osdmap, osds[i]))
return osds[i];
- break;
- }
return -1;
}
diff --git a/fs/ceph/osdmap.h b/fs/ceph/osdmap.h
index 8bc9f1e..970b547 100644
--- a/fs/ceph/osdmap.h
+++ b/fs/ceph/osdmap.h
@@ -120,6 +120,8 @@
const char *oid,
struct ceph_file_layout *fl,
struct ceph_osdmap *osdmap);
+extern int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid,
+ int *acting);
extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap,
struct ceph_pg pgid);
diff --git a/fs/ceph/rados.h b/fs/ceph/rados.h
index a1fc1d0..fd56451 100644
--- a/fs/ceph/rados.h
+++ b/fs/ceph/rados.h
@@ -58,6 +58,7 @@
#define CEPH_PG_LAYOUT_LINEAR 2
#define CEPH_PG_LAYOUT_HYBRID 3
+#define CEPH_PG_MAX_SIZE 16 /* max # osds in a single pg */
/*
* placement group.
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index f888cf4..110857b 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -47,10 +47,20 @@
*/
static void ceph_put_super(struct super_block *s)
{
- struct ceph_client *cl = ceph_client(s);
+ struct ceph_client *client = ceph_sb_to_client(s);
dout("put_super\n");
- ceph_mdsc_close_sessions(&cl->mdsc);
+ ceph_mdsc_close_sessions(&client->mdsc);
+
+ /*
+ * ensure we release the bdi before put_anon_super releases
+ * the device name.
+ */
+ if (s->s_bdi == &client->backing_dev_info) {
+ bdi_unregister(&client->backing_dev_info);
+ s->s_bdi = NULL;
+ }
+
return;
}
@@ -636,6 +646,8 @@
destroy_workqueue(client->pg_inv_wq);
destroy_workqueue(client->trunc_wq);
+ bdi_destroy(&client->backing_dev_info);
+
if (client->msgr)
ceph_messenger_destroy(client->msgr);
mempool_destroy(client->wb_pagevec_pool);
@@ -876,14 +888,14 @@
{
int err;
- sb->s_bdi = &client->backing_dev_info;
-
/* set ra_pages based on rsize mount option? */
if (client->mount_args->rsize >= PAGE_CACHE_SIZE)
client->backing_dev_info.ra_pages =
(client->mount_args->rsize + PAGE_CACHE_SIZE - 1)
>> PAGE_SHIFT;
err = bdi_register_dev(&client->backing_dev_info, sb->s_dev);
+ if (!err)
+ sb->s_bdi = &client->backing_dev_info;
return err;
}
@@ -957,9 +969,6 @@
dout("kill_sb %p\n", s);
ceph_mdsc_pre_umount(&client->mdsc);
kill_anon_super(s); /* will call put_super after sb is r/o */
- if (s->s_bdi == &client->backing_dev_info)
- bdi_unregister(&client->backing_dev_info);
- bdi_destroy(&client->backing_dev_info);
ceph_destroy_client(client);
}
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index a20bea5..cfd1ce3 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -492,17 +492,13 @@
int
decode_negTokenInit(unsigned char *security_blob, int length,
- enum securityEnum *secType)
+ struct TCP_Server_Info *server)
{
struct asn1_ctx ctx;
unsigned char *end;
unsigned char *sequence_end;
unsigned long *oid = NULL;
unsigned int cls, con, tag, oidlen, rc;
- bool use_ntlmssp = false;
- bool use_kerberos = false;
- bool use_kerberosu2u = false;
- bool use_mskerberos = false;
/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
@@ -510,11 +506,11 @@
/* GSSAPI header */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
- cFYI(1, ("Error decoding negTokenInit header"));
+ cFYI(1, "Error decoding negTokenInit header");
return 0;
} else if ((cls != ASN1_APL) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
- cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
+ cFYI(1, "cls = %d con = %d tag = %d", cls, con, tag);
return 0;
}
@@ -535,56 +531,52 @@
/* SPNEGO OID not present or garbled -- bail out */
if (!rc) {
- cFYI(1, ("Error decoding negTokenInit header"));
+ cFYI(1, "Error decoding negTokenInit header");
return 0;
}
/* SPNEGO */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
- cFYI(1, ("Error decoding negTokenInit"));
+ cFYI(1, "Error decoding negTokenInit");
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
- cFYI(1,
- ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
- cls, con, tag, end, *end));
+ cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0",
+ cls, con, tag, end, *end);
return 0;
}
/* negTokenInit */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
- cFYI(1, ("Error decoding negTokenInit"));
+ cFYI(1, "Error decoding negTokenInit");
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
- cFYI(1,
- ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
- cls, con, tag, end, *end));
+ cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1",
+ cls, con, tag, end, *end);
return 0;
}
/* sequence */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
- cFYI(1, ("Error decoding 2nd part of negTokenInit"));
+ cFYI(1, "Error decoding 2nd part of negTokenInit");
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
- cFYI(1,
- ("cls = %d con = %d tag = %d end = %p (%d) exit 0",
- cls, con, tag, end, *end));
+ cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0",
+ cls, con, tag, end, *end);
return 0;
}
/* sequence of */
if (asn1_header_decode
(&ctx, &sequence_end, &cls, &con, &tag) == 0) {
- cFYI(1, ("Error decoding 2nd part of negTokenInit"));
+ cFYI(1, "Error decoding 2nd part of negTokenInit");
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
- cFYI(1,
- ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
- cls, con, tag, end, *end));
+ cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1",
+ cls, con, tag, end, *end);
return 0;
}
@@ -592,37 +584,33 @@
while (!asn1_eoc_decode(&ctx, sequence_end)) {
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (!rc) {
- cFYI(1,
- ("Error decoding negTokenInit hdr exit2"));
+ cFYI(1, "Error decoding negTokenInit hdr exit2");
return 0;
}
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) {
- cFYI(1, ("OID len = %d oid = 0x%lx 0x%lx "
- "0x%lx 0x%lx", oidlen, *oid,
- *(oid + 1), *(oid + 2), *(oid + 3)));
+ cFYI(1, "OID len = %d oid = 0x%lx 0x%lx "
+ "0x%lx 0x%lx", oidlen, *oid,
+ *(oid + 1), *(oid + 2), *(oid + 3));
if (compare_oid(oid, oidlen, MSKRB5_OID,
- MSKRB5_OID_LEN) &&
- !use_mskerberos)
- use_mskerberos = true;
+ MSKRB5_OID_LEN))
+ server->sec_mskerberos = true;
else if (compare_oid(oid, oidlen, KRB5U2U_OID,
- KRB5U2U_OID_LEN) &&
- !use_kerberosu2u)
- use_kerberosu2u = true;
+ KRB5U2U_OID_LEN))
+ server->sec_kerberosu2u = true;
else if (compare_oid(oid, oidlen, KRB5_OID,
- KRB5_OID_LEN) &&
- !use_kerberos)
- use_kerberos = true;
+ KRB5_OID_LEN))
+ server->sec_kerberos = true;
else if (compare_oid(oid, oidlen, NTLMSSP_OID,
NTLMSSP_OID_LEN))
- use_ntlmssp = true;
+ server->sec_ntlmssp = true;
kfree(oid);
}
} else {
- cFYI(1, ("Should be an oid what is going on?"));
+ cFYI(1, "Should be an oid what is going on?");
}
}
@@ -632,54 +620,47 @@
no mechListMic (e.g. NTLMSSP instead of KRB5) */
if (ctx.error == ASN1_ERR_DEC_EMPTY)
goto decode_negtoken_exit;
- cFYI(1, ("Error decoding last part negTokenInit exit3"));
+ cFYI(1, "Error decoding last part negTokenInit exit3");
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
/* tag = 3 indicating mechListMIC */
- cFYI(1, ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
- cls, con, tag, end, *end));
+ cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end);
return 0;
}
/* sequence */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
- cFYI(1, ("Error decoding last part negTokenInit exit5"));
+ cFYI(1, "Error decoding last part negTokenInit exit5");
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
- cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
- cls, con, tag, end, *end));
+ cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end);
}
/* sequence of */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
- cFYI(1, ("Error decoding last part negTokenInit exit 7"));
+ cFYI(1, "Error decoding last part negTokenInit exit 7");
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
- cFYI(1, ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
- cls, con, tag, end, *end));
+ cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end);
return 0;
}
/* general string */
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
- cFYI(1, ("Error decoding last part negTokenInit exit9"));
+ cFYI(1, "Error decoding last part negTokenInit exit9");
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|| (tag != ASN1_GENSTR)) {
- cFYI(1, ("Exit10 cls = %d con = %d tag = %d end = %p (%d)",
- cls, con, tag, end, *end));
+ cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
+ cls, con, tag, end, *end);
return 0;
}
- cFYI(1, ("Need to call asn1_octets_decode() function for %s",
- ctx.pointer)); /* is this UTF-8 or ASCII? */
+ cFYI(1, "Need to call asn1_octets_decode() function for %s",
+ ctx.pointer); /* is this UTF-8 or ASCII? */
decode_negtoken_exit:
- if (use_kerberos)
- *secType = Kerberos;
- else if (use_mskerberos)
- *secType = MSKerberos;
- else if (use_ntlmssp)
- *secType = RawNTLMSSP;
-
return 1;
}
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 42cec2a..4fce6e6 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -60,10 +60,10 @@
#ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr *smb)
{
- cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
+ cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
smb->Command, smb->Status.CifsError,
- smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
- cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
+ smb->Flags, smb->Flags2, smb->Mid, smb->Pid);
+ cERROR(1, "smb buf %p len %d", smb, smbCalcSize_LE(smb));
}
@@ -75,25 +75,25 @@
if (server == NULL)
return;
- cERROR(1, ("Dump pending requests:"));
+ cERROR(1, "Dump pending requests:");
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
- cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
+ cERROR(1, "State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
- mid_entry->mid));
+ mid_entry->mid);
#ifdef CONFIG_CIFS_STATS2
- cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
+ cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld",
mid_entry->largeBuf,
mid_entry->resp_buf,
mid_entry->when_received,
- jiffies));
+ jiffies);
#endif /* STATS2 */
- cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
- mid_entry->multiEnd));
+ cERROR(1, "IsMult: %d IsEnd: %d", mid_entry->multiRsp,
+ mid_entry->multiEnd);
if (mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf);
cifs_dump_mem("existing buf: ",
@@ -716,7 +716,7 @@
static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
{
- seq_printf(m, "0x%x\n", extended_security);
+ seq_printf(m, "0x%x\n", global_secflags);
return 0;
}
@@ -744,13 +744,13 @@
/* single char or single char followed by null */
c = flags_string[0];
if (c == '0' || c == 'n' || c == 'N') {
- extended_security = CIFSSEC_DEF; /* default */
+ global_secflags = CIFSSEC_DEF; /* default */
return count;
} else if (c == '1' || c == 'y' || c == 'Y') {
- extended_security = CIFSSEC_MAX;
+ global_secflags = CIFSSEC_MAX;
return count;
} else if (!isdigit(c)) {
- cERROR(1, ("invalid flag %c", c));
+ cERROR(1, "invalid flag %c", c);
return -EINVAL;
}
}
@@ -758,26 +758,26 @@
flags = simple_strtoul(flags_string, NULL, 0);
- cFYI(1, ("sec flags 0x%x", flags));
+ cFYI(1, "sec flags 0x%x", flags);
if (flags <= 0) {
- cERROR(1, ("invalid security flags %s", flags_string));
+ cERROR(1, "invalid security flags %s", flags_string);
return -EINVAL;
}
if (flags & ~CIFSSEC_MASK) {
- cERROR(1, ("attempt to set unsupported security flags 0x%x",
- flags & ~CIFSSEC_MASK));
+ cERROR(1, "attempt to set unsupported security flags 0x%x",
+ flags & ~CIFSSEC_MASK);
return -EINVAL;
}
/* flags look ok - update the global security flags for cifs module */
- extended_security = flags;
- if (extended_security & CIFSSEC_MUST_SIGN) {
+ global_secflags = flags;
+ if (global_secflags & CIFSSEC_MUST_SIGN) {
/* requiring signing implies signing is allowed */
- extended_security |= CIFSSEC_MAY_SIGN;
- cFYI(1, ("packet signing now required"));
- } else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) {
- cFYI(1, ("packet signing disabled"));
+ global_secflags |= CIFSSEC_MAY_SIGN;
+ cFYI(1, "packet signing now required");
+ } else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) {
+ cFYI(1, "packet signing disabled");
}
/* BB should we turn on MAY flags for other MUST options? */
return count;
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index 5eb3b83..aa31689 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -43,34 +43,54 @@
*/
#ifdef CIFS_DEBUG
-
/* information message: e.g., configuration, major event */
extern int cifsFYI;
-#define cifsfyi(format,arg...) if (cifsFYI & CIFS_INFO) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
+#define cifsfyi(fmt, arg...) \
+do { \
+ if (cifsFYI & CIFS_INFO) \
+ printk(KERN_DEBUG "%s: " fmt "\n", __FILE__, ##arg); \
+} while (0)
-#define cFYI(button,prspec) if (button) cifsfyi prspec
+#define cFYI(set, fmt, arg...) \
+do { \
+ if (set) \
+ cifsfyi(fmt, ##arg); \
+} while (0)
-#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
+#define cifswarn(fmt, arg...) \
+ printk(KERN_WARNING fmt "\n", ##arg)
/* debug event message: */
extern int cifsERROR;
-#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
+#define cEVENT(fmt, arg...) \
+do { \
+ if (cifsERROR) \
+ printk(KERN_EVENT "%s: " fmt "\n", __FILE__, ##arg); \
+} while (0)
/* error event message: e.g., i/o error */
-#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
+#define cifserror(fmt, arg...) \
+do { \
+ if (cifsERROR) \
+ printk(KERN_ERR "CIFS VFS: " fmt "\n", ##arg); \
+} while (0)
-#define cERROR(button, prspec) if (button) cifserror prspec
+#define cERROR(set, fmt, arg...) \
+do { \
+ if (set) \
+ cifserror(fmt, ##arg); \
+} while (0)
/*
* debug OFF
* ---------
*/
#else /* _CIFS_DEBUG */
-#define cERROR(button, prspec)
-#define cEVENT(format, arg...)
-#define cFYI(button, prspec)
-#define cifserror(format, arg...)
+#define cERROR(set, fmt, arg...)
+#define cEVENT(fmt, arg...)
+#define cFYI(set, fmt, arg...)
+#define cifserror(fmt, arg...)
#endif /* _CIFS_DEBUG */
#endif /* _H_CIFS_DEBUG */
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 78e4d2a..ac19a6f 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -85,8 +85,8 @@
/* find server name end */
pSep = memchr(UNC+2, '\\', len-2);
if (!pSep) {
- cERROR(1, ("%s: no server name end in node name: %s",
- __func__, node_name));
+ cERROR(1, "%s: no server name end in node name: %s",
+ __func__, node_name);
kfree(UNC);
return ERR_PTR(-EINVAL);
}
@@ -142,8 +142,8 @@
rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
if (rc != 0) {
- cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d",
- __func__, *devname, rc));
+ cERROR(1, "%s: Failed to resolve server part of %s to IP: %d",
+ __func__, *devname, rc);
goto compose_mount_options_err;
}
/* md_len = strlen(...) + 12 for 'sep+prefixpath='
@@ -217,8 +217,8 @@
strcat(mountdata, fullpath + ref->path_consumed);
}
- /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
- /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
+ /*cFYI(1, "%s: parent mountdata: %s", __func__,sb_mountdata);*/
+ /*cFYI(1, "%s: submount mountdata: %s", __func__, mountdata );*/
compose_mount_options_out:
kfree(srvIP);
@@ -294,11 +294,11 @@
static void dump_referral(const struct dfs_info3_param *ref)
{
- cFYI(1, ("DFS: ref path: %s", ref->path_name));
- cFYI(1, ("DFS: node path: %s", ref->node_name));
- cFYI(1, ("DFS: fl: %hd, srv_type: %hd", ref->flags, ref->server_type));
- cFYI(1, ("DFS: ref_flags: %hd, path_consumed: %hd", ref->ref_flag,
- ref->path_consumed));
+ cFYI(1, "DFS: ref path: %s", ref->path_name);
+ cFYI(1, "DFS: node path: %s", ref->node_name);
+ cFYI(1, "DFS: fl: %hd, srv_type: %hd", ref->flags, ref->server_type);
+ cFYI(1, "DFS: ref_flags: %hd, path_consumed: %hd", ref->ref_flag,
+ ref->path_consumed);
}
@@ -314,7 +314,7 @@
int rc = 0;
struct vfsmount *mnt = ERR_PTR(-ENOENT);
- cFYI(1, ("in %s", __func__));
+ cFYI(1, "in %s", __func__);
BUG_ON(IS_ROOT(dentry));
xid = GetXid();
@@ -352,15 +352,15 @@
/* connect to a node */
len = strlen(referrals[i].node_name);
if (len < 2) {
- cERROR(1, ("%s: Net Address path too short: %s",
- __func__, referrals[i].node_name));
+ cERROR(1, "%s: Net Address path too short: %s",
+ __func__, referrals[i].node_name);
rc = -EINVAL;
goto out_err;
}
mnt = cifs_dfs_do_refmount(nd->path.mnt,
nd->path.dentry, referrals + i);
- cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__,
- referrals[i].node_name, mnt));
+ cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__,
+ referrals[i].node_name, mnt);
/* complete mount procedure if we accured submount */
if (!IS_ERR(mnt))
@@ -378,7 +378,7 @@
FreeXid(xid);
free_dfs_info_array(referrals, num_referrals);
kfree(full_path);
- cFYI(1, ("leaving %s" , __func__));
+ cFYI(1, "leaving %s" , __func__);
return ERR_PTR(rc);
out_err:
path_put(&nd->path);
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 310d12f..379bd7d 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -133,9 +133,9 @@
dp = description + strlen(description);
/* for now, only sec=krb5 and sec=mskrb5 are valid */
- if (server->secType == Kerberos)
+ if (server->sec_kerberos)
sprintf(dp, ";sec=krb5");
- else if (server->secType == MSKerberos)
+ else if (server->sec_mskerberos)
sprintf(dp, ";sec=mskrb5");
else
goto out;
@@ -149,7 +149,7 @@
dp = description + strlen(description);
sprintf(dp, ";pid=0x%x", current->pid);
- cFYI(1, ("key description = %s", description));
+ cFYI(1, "key description = %s", description);
spnego_key = request_key(&cifs_spnego_key_type, description, "");
#ifdef CONFIG_CIFS_DEBUG2
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index d07676b..430f510 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -200,9 +200,8 @@
/* works for 2.4.0 kernel or later */
charlen = codepage->char2uni(from, len, &wchar_to[i]);
if (charlen < 1) {
- cERROR(1,
- ("strtoUCS: char2uni of %d returned %d",
- (int)*from, charlen));
+ cERROR(1, "strtoUCS: char2uni of %d returned %d",
+ (int)*from, charlen);
/* A question mark */
to[i] = cpu_to_le16(0x003f);
charlen = 1;
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 9b716d0..85d7cf7 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -87,11 +87,11 @@
continue; /* all sub_auth values do not match */
}
- cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
+ cFYI(1, "matching sid: %s\n", wksidarr[i].sidname);
return 0; /* sids compare/match */
}
- cFYI(1, ("No matching sid"));
+ cFYI(1, "No matching sid");
return -1;
}
@@ -208,14 +208,14 @@
*pbits_to_set &= ~S_IXUGO;
return;
} else if (type != ACCESS_ALLOWED) {
- cERROR(1, ("unknown access control type %d", type));
+ cERROR(1, "unknown access control type %d", type);
return;
}
/* else ACCESS_ALLOWED type */
if (flags & GENERIC_ALL) {
*pmode |= (S_IRWXUGO & (*pbits_to_set));
- cFYI(DBG2, ("all perms"));
+ cFYI(DBG2, "all perms");
return;
}
if ((flags & GENERIC_WRITE) ||
@@ -228,7 +228,7 @@
((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
*pmode |= (S_IXUGO & (*pbits_to_set));
- cFYI(DBG2, ("access flags 0x%x mode now 0x%x", flags, *pmode));
+ cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
return;
}
@@ -257,7 +257,7 @@
if (mode & S_IXUGO)
*pace_flags |= SET_FILE_EXEC_RIGHTS;
- cFYI(DBG2, ("mode: 0x%x, access flags now 0x%x", mode, *pace_flags));
+ cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
return;
}
@@ -297,24 +297,24 @@
/* validate that we do not go past end of acl */
if (le16_to_cpu(pace->size) < 16) {
- cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size)));
+ cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
return;
}
if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
- cERROR(1, ("ACL too small to parse ACE"));
+ cERROR(1, "ACL too small to parse ACE");
return;
}
num_subauth = pace->sid.num_subauth;
if (num_subauth) {
int i;
- cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d",
+ cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
pace->sid.revision, pace->sid.num_subauth, pace->type,
- pace->flags, le16_to_cpu(pace->size)));
+ pace->flags, le16_to_cpu(pace->size));
for (i = 0; i < num_subauth; ++i) {
- cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
- le32_to_cpu(pace->sid.sub_auth[i])));
+ cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
+ le32_to_cpu(pace->sid.sub_auth[i]));
}
/* BB add length check to make sure that we do not have huge
@@ -347,13 +347,13 @@
/* validate that we do not go past end of acl */
if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
- cERROR(1, ("ACL too small to parse DACL"));
+ cERROR(1, "ACL too small to parse DACL");
return;
}
- cFYI(DBG2, ("DACL revision %d size %d num aces %d",
+ cFYI(DBG2, "DACL revision %d size %d num aces %d",
le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
- le32_to_cpu(pdacl->num_aces)));
+ le32_to_cpu(pdacl->num_aces));
/* reset rwx permissions for user/group/other.
Also, if num_aces is 0 i.e. DACL has no ACEs,
@@ -437,25 +437,25 @@
/* validate that we do not go past end of ACL - sid must be at least 8
bytes long (assuming no sub-auths - e.g. the null SID */
if (end_of_acl < (char *)psid + 8) {
- cERROR(1, ("ACL too small to parse SID %p", psid));
+ cERROR(1, "ACL too small to parse SID %p", psid);
return -EINVAL;
}
if (psid->num_subauth) {
#ifdef CONFIG_CIFS_DEBUG2
int i;
- cFYI(1, ("SID revision %d num_auth %d",
- psid->revision, psid->num_subauth));
+ cFYI(1, "SID revision %d num_auth %d",
+ psid->revision, psid->num_subauth);
for (i = 0; i < psid->num_subauth; i++) {
- cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
- le32_to_cpu(psid->sub_auth[i])));
+ cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
+ le32_to_cpu(psid->sub_auth[i]));
}
/* BB add length check to make sure that we do not have huge
num auths and therefore go off the end */
- cFYI(1, ("RID 0x%x",
- le32_to_cpu(psid->sub_auth[psid->num_subauth-1])));
+ cFYI(1, "RID 0x%x",
+ le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
#endif
}
@@ -482,11 +482,11 @@
le32_to_cpu(pntsd->gsidoffset));
dacloffset = le32_to_cpu(pntsd->dacloffset);
dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
- cFYI(DBG2, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
+ cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
"sacloffset 0x%x dacloffset 0x%x",
pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
le32_to_cpu(pntsd->gsidoffset),
- le32_to_cpu(pntsd->sacloffset), dacloffset));
+ le32_to_cpu(pntsd->sacloffset), dacloffset);
/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
rc = parse_sid(owner_sid_ptr, end_of_acl);
if (rc)
@@ -500,7 +500,7 @@
parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
group_sid_ptr, fattr);
else
- cFYI(1, ("no ACL")); /* BB grant all or default perms? */
+ cFYI(1, "no ACL"); /* BB grant all or default perms? */
/* cifscred->uid = owner_sid_ptr->rid;
cifscred->gid = group_sid_ptr->rid;
@@ -563,7 +563,7 @@
FreeXid(xid);
- cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
+ cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
return pntsd;
}
@@ -581,12 +581,12 @@
&fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
- cERROR(1, ("Unable to open file to get ACL"));
+ cERROR(1, "Unable to open file to get ACL");
goto out;
}
rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
- cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
+ cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
CIFSSMBClose(xid, cifs_sb->tcon, fid);
out:
@@ -621,7 +621,7 @@
rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
FreeXid(xid);
- cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
+ cFYI(DBG2, "SetCIFSACL rc = %d", rc);
return rc;
}
@@ -638,12 +638,12 @@
&fid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
- cERROR(1, ("Unable to open file to set ACL"));
+ cERROR(1, "Unable to open file to set ACL");
goto out;
}
rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen);
- cFYI(DBG2, ("SetCIFSACL rc = %d", rc));
+ cFYI(DBG2, "SetCIFSACL rc = %d", rc);
CIFSSMBClose(xid, cifs_sb->tcon, fid);
out:
@@ -659,7 +659,7 @@
struct cifsFileInfo *open_file;
int rc;
- cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
+ cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
open_file = find_readable_file(CIFS_I(inode));
if (!open_file)
@@ -679,7 +679,7 @@
u32 acllen = 0;
int rc = 0;
- cFYI(DBG2, ("converting ACL to mode for %s", path));
+ cFYI(DBG2, "converting ACL to mode for %s", path);
if (pfid)
pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
@@ -690,7 +690,7 @@
if (pntsd)
rc = parse_sec_desc(pntsd, acllen, fattr);
if (rc)
- cFYI(1, ("parse sec desc failed rc = %d", rc));
+ cFYI(1, "parse sec desc failed rc = %d", rc);
kfree(pntsd);
return;
@@ -704,7 +704,7 @@
struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
- cFYI(DBG2, ("set ACL from mode for %s", path));
+ cFYI(DBG2, "set ACL from mode for %s", path);
/* Get the security descriptor */
pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
@@ -721,19 +721,19 @@
DEFSECDESCLEN : secdesclen;
pnntsd = kmalloc(secdesclen, GFP_KERNEL);
if (!pnntsd) {
- cERROR(1, ("Unable to allocate security descriptor"));
+ cERROR(1, "Unable to allocate security descriptor");
kfree(pntsd);
return -ENOMEM;
}
rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
- cFYI(DBG2, ("build_sec_desc rc: %d", rc));
+ cFYI(DBG2, "build_sec_desc rc: %d", rc);
if (!rc) {
/* Set the security descriptor */
rc = set_cifs_acl(pnntsd, secdesclen, inode, path);
- cFYI(DBG2, ("set_cifs_acl rc: %d", rc));
+ cFYI(DBG2, "set_cifs_acl rc: %d", rc);
}
kfree(pnntsd);
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index fbe9864..847628d 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -103,7 +103,7 @@
if (iov[i].iov_len == 0)
continue;
if (iov[i].iov_base == NULL) {
- cERROR(1, ("null iovec entry"));
+ cERROR(1, "null iovec entry");
return -EIO;
}
/* The first entry includes a length field (which does not get
@@ -181,8 +181,8 @@
/* Do not need to verify session setups with signature "BSRSPYL " */
if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0)
- cFYI(1, ("dummy signature received for smb command 0x%x",
- cifs_pdu->Command));
+ cFYI(1, "dummy signature received for smb command 0x%x",
+ cifs_pdu->Command);
/* save off the origiginal signature so we can modify the smb and check
its signature against what the server sent */
@@ -291,7 +291,7 @@
if (password)
strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);
- if (!encrypt && extended_security & CIFSSEC_MAY_PLNTXT) {
+ if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) {
memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE);
memcpy(lnm_session_key, password_with_pad,
CIFS_ENCPWD_SIZE);
@@ -398,7 +398,7 @@
/* calculate buf->ntlmv2_hash */
rc = calc_ntlmv2_hash(ses, nls_cp);
if (rc)
- cERROR(1, ("could not get v2 hash rc %d", rc));
+ cERROR(1, "could not get v2 hash rc %d", rc);
CalcNTLMv2_response(ses, resp_buf);
/* now calculate the MAC key for NTLMv2 */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index ad235d6..78c02eb 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -49,10 +49,6 @@
#include "cifs_spnego.h"
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
-#ifdef CONFIG_CIFS_QUOTA
-static const struct quotactl_ops cifs_quotactl_ops;
-#endif /* QUOTA */
-
int cifsFYI = 0;
int cifsERROR = 1;
int traceSMB = 0;
@@ -61,7 +57,7 @@
unsigned int linuxExtEnabled = 1;
unsigned int lookupCacheEnabled = 1;
unsigned int multiuser_mount = 0;
-unsigned int extended_security = CIFSSEC_DEF;
+unsigned int global_secflags = CIFSSEC_DEF;
/* unsigned int ntlmv2_support = 0; */
unsigned int sign_CIFS_PDUs = 1;
static const struct super_operations cifs_super_ops;
@@ -86,8 +82,6 @@
extern mempool_t *cifs_req_poolp;
extern mempool_t *cifs_mid_poolp;
-extern struct kmem_cache *cifs_oplock_cachep;
-
static int
cifs_read_super(struct super_block *sb, void *data,
const char *devname, int silent)
@@ -135,8 +129,7 @@
if (rc) {
if (!silent)
- cERROR(1,
- ("cifs_mount failed w/return code = %d", rc));
+ cERROR(1, "cifs_mount failed w/return code = %d", rc);
goto out_mount_failed;
}
@@ -146,9 +139,6 @@
/* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
sb->s_blocksize =
cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
-#ifdef CONFIG_CIFS_QUOTA
- sb->s_qcop = &cifs_quotactl_ops;
-#endif
sb->s_blocksize = CIFS_MAX_MSGSIZE;
sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
inode = cifs_root_iget(sb, ROOT_I);
@@ -168,7 +158,7 @@
#ifdef CONFIG_CIFS_EXPERIMENTAL
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- cFYI(1, ("export ops supported"));
+ cFYI(1, "export ops supported");
sb->s_export_op = &cifs_export_ops;
}
#endif /* EXPERIMENTAL */
@@ -176,7 +166,7 @@
return 0;
out_no_root:
- cERROR(1, ("cifs_read_super: get root inode failed"));
+ cERROR(1, "cifs_read_super: get root inode failed");
if (inode)
iput(inode);
@@ -203,10 +193,10 @@
int rc = 0;
struct cifs_sb_info *cifs_sb;
- cFYI(1, ("In cifs_put_super"));
+ cFYI(1, "In cifs_put_super");
cifs_sb = CIFS_SB(sb);
if (cifs_sb == NULL) {
- cFYI(1, ("Empty cifs superblock info passed to unmount"));
+ cFYI(1, "Empty cifs superblock info passed to unmount");
return;
}
@@ -214,7 +204,7 @@
rc = cifs_umount(sb, cifs_sb);
if (rc)
- cERROR(1, ("cifs_umount failed with return code %d", rc));
+ cERROR(1, "cifs_umount failed with return code %d", rc);
#ifdef CONFIG_CIFS_DFS_UPCALL
if (cifs_sb->mountdata) {
kfree(cifs_sb->mountdata);
@@ -300,7 +290,6 @@
static struct kmem_cache *cifs_inode_cachep;
static struct kmem_cache *cifs_req_cachep;
static struct kmem_cache *cifs_mid_cachep;
-struct kmem_cache *cifs_oplock_cachep;
static struct kmem_cache *cifs_sm_req_cachep;
mempool_t *cifs_sm_req_poolp;
mempool_t *cifs_req_poolp;
@@ -432,106 +421,6 @@
return 0;
}
-#ifdef CONFIG_CIFS_QUOTA
-int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
- struct fs_disk_quota *pdquota)
-{
- int xid;
- int rc = 0;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
-
- if (cifs_sb)
- pTcon = cifs_sb->tcon;
- else
- return -EIO;
-
-
- xid = GetXid();
- if (pTcon) {
- cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
- } else
- rc = -EIO;
-
- FreeXid(xid);
- return rc;
-}
-
-int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid,
- struct fs_disk_quota *pdquota)
-{
- int xid;
- int rc = 0;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
-
- if (cifs_sb)
- pTcon = cifs_sb->tcon;
- else
- return -EIO;
-
- xid = GetXid();
- if (pTcon) {
- cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
- } else
- rc = -EIO;
-
- FreeXid(xid);
- return rc;
-}
-
-int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation)
-{
- int xid;
- int rc = 0;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
-
- if (cifs_sb)
- pTcon = cifs_sb->tcon;
- else
- return -EIO;
-
- xid = GetXid();
- if (pTcon) {
- cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation));
- } else
- rc = -EIO;
-
- FreeXid(xid);
- return rc;
-}
-
-int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats)
-{
- int xid;
- int rc = 0;
- struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- struct cifsTconInfo *pTcon;
-
- if (cifs_sb)
- pTcon = cifs_sb->tcon;
- else
- return -EIO;
-
- xid = GetXid();
- if (pTcon) {
- cFYI(1, ("pqstats %p", qstats));
- } else
- rc = -EIO;
-
- FreeXid(xid);
- return rc;
-}
-
-static const struct quotactl_ops cifs_quotactl_ops = {
- .set_xquota = cifs_xquota_set,
- .get_xquota = cifs_xquota_get,
- .set_xstate = cifs_xstate_set,
- .get_xstate = cifs_xstate_get,
-};
-#endif
-
static void cifs_umount_begin(struct super_block *sb)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -558,7 +447,7 @@
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
/* cancel_notify_requests(tcon); */
if (tcon->ses && tcon->ses->server) {
- cFYI(1, ("wake up tasks now - umount begin not complete"));
+ cFYI(1, "wake up tasks now - umount begin not complete");
wake_up_all(&tcon->ses->server->request_q);
wake_up_all(&tcon->ses->server->response_q);
msleep(1); /* yield */
@@ -609,7 +498,7 @@
int rc;
struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
- cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
+ cFYI(1, "Devname: %s flags: %d ", dev_name, flags);
if (IS_ERR(sb))
return PTR_ERR(sb);
@@ -656,7 +545,6 @@
return generic_file_llseek_unlocked(file, offset, origin);
}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
{
/* note that this is called by vfs setlease with the BKL held
@@ -685,7 +573,6 @@
else
return -EAGAIN;
}
-#endif
struct file_system_type cifs_fs_type = {
.owner = THIS_MODULE,
@@ -762,10 +649,7 @@
#ifdef CONFIG_CIFS_POSIX
.unlocked_ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
-
-#ifdef CONFIG_CIFS_EXPERIMENTAL
.setlease = cifs_setlease,
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
const struct file_operations cifs_file_direct_ops = {
@@ -784,9 +668,7 @@
.unlocked_ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
.llseek = cifs_llseek,
-#ifdef CONFIG_CIFS_EXPERIMENTAL
.setlease = cifs_setlease,
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
const struct file_operations cifs_file_nobrl_ops = {
.read = do_sync_read,
@@ -803,10 +685,7 @@
#ifdef CONFIG_CIFS_POSIX
.unlocked_ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
-
-#ifdef CONFIG_CIFS_EXPERIMENTAL
.setlease = cifs_setlease,
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
const struct file_operations cifs_file_direct_nobrl_ops = {
@@ -824,9 +703,7 @@
.unlocked_ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
.llseek = cifs_llseek,
-#ifdef CONFIG_CIFS_EXPERIMENTAL
.setlease = cifs_setlease,
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
const struct file_operations cifs_dir_ops = {
@@ -878,7 +755,7 @@
} else {
CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
}
-/* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */
+/* cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */
cifs_req_cachep = kmem_cache_create("cifs_request",
CIFSMaxBufSize +
MAX_CIFS_HDR_SIZE, 0,
@@ -890,7 +767,7 @@
cifs_min_rcv = 1;
else if (cifs_min_rcv > 64) {
cifs_min_rcv = 64;
- cERROR(1, ("cifs_min_rcv set to maximum (64)"));
+ cERROR(1, "cifs_min_rcv set to maximum (64)");
}
cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
@@ -921,7 +798,7 @@
cifs_min_small = 2;
else if (cifs_min_small > 256) {
cifs_min_small = 256;
- cFYI(1, ("cifs_min_small set to maximum (256)"));
+ cFYI(1, "cifs_min_small set to maximum (256)");
}
cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
@@ -962,15 +839,6 @@
return -ENOMEM;
}
- cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
- sizeof(struct oplock_q_entry), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (cifs_oplock_cachep == NULL) {
- mempool_destroy(cifs_mid_poolp);
- kmem_cache_destroy(cifs_mid_cachep);
- return -ENOMEM;
- }
-
return 0;
}
@@ -979,7 +847,6 @@
{
mempool_destroy(cifs_mid_poolp);
kmem_cache_destroy(cifs_mid_cachep);
- kmem_cache_destroy(cifs_oplock_cachep);
}
static int __init
@@ -1019,10 +886,10 @@
if (cifs_max_pending < 2) {
cifs_max_pending = 2;
- cFYI(1, ("cifs_max_pending set to min of 2"));
+ cFYI(1, "cifs_max_pending set to min of 2");
} else if (cifs_max_pending > 256) {
cifs_max_pending = 256;
- cFYI(1, ("cifs_max_pending set to max of 256"));
+ cFYI(1, "cifs_max_pending set to max of 256");
}
rc = cifs_init_inodecache();
@@ -1080,7 +947,7 @@
static void __exit
exit_cifs(void)
{
- cFYI(DBG2, ("exit_cifs"));
+ cFYI(DBG2, "exit_cifs");
cifs_proc_clean();
#ifdef CONFIG_CIFS_DFS_UPCALL
cifs_dfs_release_automount_timer();
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 7aa57ec..0242ff9 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -114,5 +114,5 @@
extern const struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
-#define CIFS_VERSION "1.62"
+#define CIFS_VERSION "1.64"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ecf0ffb..a88479c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -87,7 +87,6 @@
RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
/* NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */
Kerberos, /* Kerberos via SPNEGO */
- MSKerberos, /* MS Kerberos via SPNEGO */
};
enum protocolEnum {
@@ -185,6 +184,12 @@
struct mac_key mac_signing_key;
char ntlmv2_hash[16];
unsigned long lstrp; /* when we got last response from this server */
+ u16 dialect; /* dialect index that server chose */
+ /* extended security flavors that server supports */
+ bool sec_kerberos; /* supports plain Kerberos */
+ bool sec_mskerberos; /* supports legacy MS Kerberos */
+ bool sec_kerberosu2u; /* supports U2U Kerberos */
+ bool sec_ntlmssp; /* supports NTLMSSP */
};
/*
@@ -502,6 +507,7 @@
#define CIFS_FATTR_DFS_REFERRAL 0x1
#define CIFS_FATTR_DELETE_PENDING 0x2
#define CIFS_FATTR_NEED_REVAL 0x4
+#define CIFS_FATTR_INO_COLLISION 0x8
struct cifs_fattr {
u32 cf_flags;
@@ -717,7 +723,7 @@
GLOBAL_EXTERN unsigned int oplockEnabled;
GLOBAL_EXTERN unsigned int experimEnabled;
GLOBAL_EXTERN unsigned int lookupCacheEnabled;
-GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent
+GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent
with more secure ntlmssp2 challenge/resp */
GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */
GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 39e47f4..fb1657e 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -39,8 +39,20 @@
unsigned int /* length */);
extern unsigned int _GetXid(void);
extern void _FreeXid(unsigned int);
-#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
-#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
+#define GetXid() \
+({ \
+ int __xid = (int)_GetXid(); \
+ cFYI(1, "CIFS VFS: in %s as Xid: %d with uid: %d", \
+ __func__, __xid, current_fsuid()); \
+ __xid; \
+})
+
+#define FreeXid(curr_xid) \
+do { \
+ _FreeXid(curr_xid); \
+ cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \
+ __func__, curr_xid, (int)rc); \
+} while (0)
extern char *build_path_from_dentry(struct dentry *);
extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
@@ -73,7 +85,7 @@
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
- enum securityEnum *secType);
+ struct TCP_Server_Info *server);
extern int cifs_convert_address(char *src, void *dst);
extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
extern void header_assemble(struct smb_hdr *, char /* command */ ,
@@ -83,7 +95,6 @@
struct cifsSesInfo *ses,
void **request_buf);
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
- const int stage,
const struct nls_table *nls_cp);
extern __u16 GetNextMid(struct TCP_Server_Info *server);
extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
@@ -95,8 +106,11 @@
__u16 fileHandle, struct file *file,
struct vfsmount *mnt, unsigned int oflags);
extern int cifs_posix_open(char *full_path, struct inode **pinode,
- struct vfsmount *mnt, int mode, int oflags,
- __u32 *poplock, __u16 *pnetfid, int xid);
+ struct vfsmount *mnt,
+ struct super_block *sb,
+ int mode, int oflags,
+ __u32 *poplock, __u16 *pnetfid, int xid);
+void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr);
extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
FILE_UNIX_BASIC_INFO *info,
struct cifs_sb_info *cifs_sb);
@@ -125,7 +139,9 @@
void cifs_proc_init(void);
void cifs_proc_clean(void);
-extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
+extern int cifs_negotiate_protocol(unsigned int xid,
+ struct cifsSesInfo *ses);
+extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses,
struct nls_table *nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 5d3f29f..c65c341 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifssmb.c
*
- * Copyright (C) International Business Machines Corp., 2002,2009
+ * Copyright (C) International Business Machines Corp., 2002,2010
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for constructing the SMB PDUs themselves
@@ -130,8 +130,8 @@
if (smb_command != SMB_COM_WRITE_ANDX &&
smb_command != SMB_COM_OPEN_ANDX &&
smb_command != SMB_COM_TREE_DISCONNECT) {
- cFYI(1, ("can not send cmd %d while umounting",
- smb_command));
+ cFYI(1, "can not send cmd %d while umounting",
+ smb_command);
return -ENODEV;
}
}
@@ -157,7 +157,7 @@
* back on-line
*/
if (!tcon->retry || ses->status == CifsExiting) {
- cFYI(1, ("gave up waiting on reconnect in smb_init"));
+ cFYI(1, "gave up waiting on reconnect in smb_init");
return -EHOSTDOWN;
}
}
@@ -172,7 +172,8 @@
* reconnect the same SMB session
*/
mutex_lock(&ses->session_mutex);
- if (ses->need_reconnect)
+ rc = cifs_negotiate_protocol(0, ses);
+ if (rc == 0 && ses->need_reconnect)
rc = cifs_setup_session(0, ses, nls_codepage);
/* do we need to reconnect tcon? */
@@ -184,7 +185,7 @@
mark_open_files_invalid(tcon);
rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
mutex_unlock(&ses->session_mutex);
- cFYI(1, ("reconnect tcon rc = %d", rc));
+ cFYI(1, "reconnect tcon rc = %d", rc);
if (rc)
goto out;
@@ -355,7 +356,6 @@
struct TCP_Server_Info *server;
u16 count;
unsigned int secFlags;
- u16 dialect;
if (ses->server)
server = ses->server;
@@ -372,9 +372,9 @@
if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */
else /* if override flags set only sign/seal OR them with global auth */
- secFlags = extended_security | ses->overrideSecFlg;
+ secFlags = global_secflags | ses->overrideSecFlg;
- cFYI(1, ("secFlags 0x%x", secFlags));
+ cFYI(1, "secFlags 0x%x", secFlags);
pSMB->hdr.Mid = GetNextMid(server);
pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
@@ -382,14 +382,14 @@
if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
- cFYI(1, ("Kerberos only mechanism, enable extended security"));
+ cFYI(1, "Kerberos only mechanism, enable extended security");
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
}
#ifdef CONFIG_CIFS_EXPERIMENTAL
else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
- cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
+ cFYI(1, "NTLMSSP only mechanism, enable extended security");
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
}
#endif
@@ -408,10 +408,10 @@
if (rc != 0)
goto neg_err_exit;
- dialect = le16_to_cpu(pSMBr->DialectIndex);
- cFYI(1, ("Dialect: %d", dialect));
+ server->dialect = le16_to_cpu(pSMBr->DialectIndex);
+ cFYI(1, "Dialect: %d", server->dialect);
/* Check wct = 1 error case */
- if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) {
+ if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) {
/* core returns wct = 1, but we do not ask for core - otherwise
small wct just comes when dialect index is -1 indicating we
could not negotiate a common dialect */
@@ -419,8 +419,8 @@
goto neg_err_exit;
#ifdef CONFIG_CIFS_WEAK_PW_HASH
} else if ((pSMBr->hdr.WordCount == 13)
- && ((dialect == LANMAN_PROT)
- || (dialect == LANMAN2_PROT))) {
+ && ((server->dialect == LANMAN_PROT)
+ || (server->dialect == LANMAN2_PROT))) {
__s16 tmp;
struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr;
@@ -428,8 +428,8 @@
(secFlags & CIFSSEC_MAY_PLNTXT))
server->secType = LANMAN;
else {
- cERROR(1, ("mount failed weak security disabled"
- " in /proc/fs/cifs/SecurityFlags"));
+ cERROR(1, "mount failed weak security disabled"
+ " in /proc/fs/cifs/SecurityFlags");
rc = -EOPNOTSUPP;
goto neg_err_exit;
}
@@ -462,9 +462,9 @@
utc = CURRENT_TIME;
ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
rsp->SrvTime.Time, 0);
- cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d",
+ cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d",
(int)ts.tv_sec, (int)utc.tv_sec,
- (int)(utc.tv_sec - ts.tv_sec)));
+ (int)(utc.tv_sec - ts.tv_sec));
val = (int)(utc.tv_sec - ts.tv_sec);
seconds = abs(val);
result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
@@ -478,7 +478,7 @@
server->timeAdj = (int)tmp;
server->timeAdj *= 60; /* also in seconds */
}
- cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj));
+ cFYI(1, "server->timeAdj: %d seconds", server->timeAdj);
/* BB get server time for time conversions and add
@@ -493,14 +493,14 @@
goto neg_err_exit;
}
- cFYI(1, ("LANMAN negotiated"));
+ cFYI(1, "LANMAN negotiated");
/* we will not end up setting signing flags - as no signing
was in LANMAN and server did not return the flags on */
goto signing_check;
#else /* weak security disabled */
} else if (pSMBr->hdr.WordCount == 13) {
- cERROR(1, ("mount failed, cifs module not built "
- "with CIFS_WEAK_PW_HASH support"));
+ cERROR(1, "mount failed, cifs module not built "
+ "with CIFS_WEAK_PW_HASH support");
rc = -EOPNOTSUPP;
#endif /* WEAK_PW_HASH */
goto neg_err_exit;
@@ -512,14 +512,14 @@
/* else wct == 17 NTLM */
server->secMode = pSMBr->SecurityMode;
if ((server->secMode & SECMODE_USER) == 0)
- cFYI(1, ("share mode security"));
+ cFYI(1, "share mode security");
if ((server->secMode & SECMODE_PW_ENCRYPT) == 0)
#ifdef CONFIG_CIFS_WEAK_PW_HASH
if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
#endif /* CIFS_WEAK_PW_HASH */
- cERROR(1, ("Server requests plain text password"
- " but client support disabled"));
+ cERROR(1, "Server requests plain text password"
+ " but client support disabled");
if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
server->secType = NTLMv2;
@@ -539,7 +539,7 @@
#endif */
else {
rc = -EOPNOTSUPP;
- cERROR(1, ("Invalid security type"));
+ cERROR(1, "Invalid security type");
goto neg_err_exit;
}
/* else ... any others ...? */
@@ -551,7 +551,7 @@
server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
- cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
+ cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
server->capabilities = le32_to_cpu(pSMBr->Capabilities);
server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
@@ -582,7 +582,7 @@
if (memcmp(server->server_GUID,
pSMBr->u.extended_response.
GUID, 16) != 0) {
- cFYI(1, ("server UID changed"));
+ cFYI(1, "server UID changed");
memcpy(server->server_GUID,
pSMBr->u.extended_response.GUID,
16);
@@ -597,13 +597,19 @@
server->secType = RawNTLMSSP;
} else {
rc = decode_negTokenInit(pSMBr->u.extended_response.
- SecurityBlob,
- count - 16,
- &server->secType);
+ SecurityBlob, count - 16,
+ server);
if (rc == 1)
rc = 0;
else
rc = -EINVAL;
+
+ if (server->sec_kerberos || server->sec_mskerberos)
+ server->secType = Kerberos;
+ else if (server->sec_ntlmssp)
+ server->secType = RawNTLMSSP;
+ else
+ rc = -EOPNOTSUPP;
}
} else
server->capabilities &= ~CAP_EXTENDED_SECURITY;
@@ -614,22 +620,21 @@
if ((secFlags & CIFSSEC_MAY_SIGN) == 0) {
/* MUST_SIGN already includes the MAY_SIGN FLAG
so if this is zero it means that signing is disabled */
- cFYI(1, ("Signing disabled"));
+ cFYI(1, "Signing disabled");
if (server->secMode & SECMODE_SIGN_REQUIRED) {
- cERROR(1, ("Server requires "
+ cERROR(1, "Server requires "
"packet signing to be enabled in "
- "/proc/fs/cifs/SecurityFlags."));
+ "/proc/fs/cifs/SecurityFlags.");
rc = -EOPNOTSUPP;
}
server->secMode &=
~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
} else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
/* signing required */
- cFYI(1, ("Must sign - secFlags 0x%x", secFlags));
+ cFYI(1, "Must sign - secFlags 0x%x", secFlags);
if ((server->secMode &
(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
- cERROR(1,
- ("signing required but server lacks support"));
+ cERROR(1, "signing required but server lacks support");
rc = -EOPNOTSUPP;
} else
server->secMode |= SECMODE_SIGN_REQUIRED;
@@ -643,7 +648,7 @@
neg_err_exit:
cifs_buf_release(pSMB);
- cFYI(1, ("negprot rc %d", rc));
+ cFYI(1, "negprot rc %d", rc);
return rc;
}
@@ -653,7 +658,7 @@
struct smb_hdr *smb_buffer;
int rc = 0;
- cFYI(1, ("In tree disconnect"));
+ cFYI(1, "In tree disconnect");
/* BB: do we need to check this? These should never be NULL. */
if ((tcon->ses == NULL) || (tcon->ses->server == NULL))
@@ -675,7 +680,7 @@
rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
if (rc)
- cFYI(1, ("Tree disconnect failed %d", rc));
+ cFYI(1, "Tree disconnect failed %d", rc);
/* No need to return error on this operation if tid invalidated and
closed on server already e.g. due to tcp session crashing */
@@ -691,7 +696,7 @@
LOGOFF_ANDX_REQ *pSMB;
int rc = 0;
- cFYI(1, ("In SMBLogoff for session disconnect"));
+ cFYI(1, "In SMBLogoff for session disconnect");
/*
* BB: do we need to check validity of ses and server? They should
@@ -744,7 +749,7 @@
int bytes_returned = 0;
__u16 params, param_offset, offset, byte_count;
- cFYI(1, ("In POSIX delete"));
+ cFYI(1, "In POSIX delete");
PsxDelete:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -796,7 +801,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc)
- cFYI(1, ("Posix delete returned %d", rc));
+ cFYI(1, "Posix delete returned %d", rc);
cifs_buf_release(pSMB);
cifs_stats_inc(&tcon->num_deletes);
@@ -843,7 +848,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_deletes);
if (rc)
- cFYI(1, ("Error in RMFile = %d", rc));
+ cFYI(1, "Error in RMFile = %d", rc);
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
@@ -862,7 +867,7 @@
int bytes_returned;
int name_len;
- cFYI(1, ("In CIFSSMBRmDir"));
+ cFYI(1, "In CIFSSMBRmDir");
RmDirRetry:
rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -887,7 +892,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_rmdirs);
if (rc)
- cFYI(1, ("Error in RMDir = %d", rc));
+ cFYI(1, "Error in RMDir = %d", rc);
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
@@ -905,7 +910,7 @@
int bytes_returned;
int name_len;
- cFYI(1, ("In CIFSSMBMkDir"));
+ cFYI(1, "In CIFSSMBMkDir");
MkDirRetry:
rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -930,7 +935,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_mkdirs);
if (rc)
- cFYI(1, ("Error in Mkdir = %d", rc));
+ cFYI(1, "Error in Mkdir = %d", rc);
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
@@ -953,7 +958,7 @@
OPEN_PSX_REQ *pdata;
OPEN_PSX_RSP *psx_rsp;
- cFYI(1, ("In POSIX Create"));
+ cFYI(1, "In POSIX Create");
PsxCreat:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -1007,11 +1012,11 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Posix create returned %d", rc));
+ cFYI(1, "Posix create returned %d", rc);
goto psx_create_err;
}
- cFYI(1, ("copying inode info"));
+ cFYI(1, "copying inode info");
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) {
@@ -1033,11 +1038,11 @@
/* check to make sure response data is there */
if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
pRetData->Type = cpu_to_le32(-1); /* unknown */
- cFYI(DBG2, ("unknown type"));
+ cFYI(DBG2, "unknown type");
} else {
if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
+ sizeof(FILE_UNIX_BASIC_INFO)) {
- cERROR(1, ("Open response data too small"));
+ cERROR(1, "Open response data too small");
pRetData->Type = cpu_to_le32(-1);
goto psx_create_err;
}
@@ -1084,7 +1089,7 @@
ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
break;
default:
- cFYI(1, ("unknown disposition %d", disposition));
+ cFYI(1, "unknown disposition %d", disposition);
ofun = SMBOPEN_OAPPEND; /* regular open */
}
return ofun;
@@ -1175,7 +1180,7 @@
(struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
cifs_stats_inc(&tcon->num_opens);
if (rc) {
- cFYI(1, ("Error in Open = %d", rc));
+ cFYI(1, "Error in Open = %d", rc);
} else {
/* BB verify if wct == 15 */
@@ -1288,7 +1293,7 @@
(struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
cifs_stats_inc(&tcon->num_opens);
if (rc) {
- cFYI(1, ("Error in Open = %d", rc));
+ cFYI(1, "Error in Open = %d", rc);
} else {
*pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
*netfid = pSMBr->Fid; /* cifs fid stays in le */
@@ -1326,7 +1331,7 @@
int resp_buf_type = 0;
struct kvec iov[1];
- cFYI(1, ("Reading %d bytes on fid %d", count, netfid));
+ cFYI(1, "Reading %d bytes on fid %d", count, netfid);
if (tcon->ses->capabilities & CAP_LARGE_FILES)
wct = 12;
else {
@@ -1371,7 +1376,7 @@
cifs_stats_inc(&tcon->num_reads);
pSMBr = (READ_RSP *)iov[0].iov_base;
if (rc) {
- cERROR(1, ("Send error in read = %d", rc));
+ cERROR(1, "Send error in read = %d", rc);
} else {
int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
data_length = data_length << 16;
@@ -1381,15 +1386,15 @@
/*check that DataLength would not go beyond end of SMB */
if ((data_length > CIFSMaxBufSize)
|| (data_length > count)) {
- cFYI(1, ("bad length %d for count %d",
- data_length, count));
+ cFYI(1, "bad length %d for count %d",
+ data_length, count);
rc = -EIO;
*nbytes = 0;
} else {
pReadData = (char *) (&pSMBr->hdr.Protocol) +
le16_to_cpu(pSMBr->DataOffset);
/* if (rc = copy_to_user(buf, pReadData, data_length)) {
- cERROR(1,("Faulting on read rc = %d",rc));
+ cERROR(1, "Faulting on read rc = %d",rc);
rc = -EFAULT;
}*/ /* can not use copy_to_user when using page cache*/
if (*buf)
@@ -1433,7 +1438,7 @@
*nbytes = 0;
- /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
+ /* cFYI(1, "write at %lld %d bytes", offset, count);*/
if (tcon->ses == NULL)
return -ECONNABORTED;
@@ -1514,7 +1519,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, long_op);
cifs_stats_inc(&tcon->num_writes);
if (rc) {
- cFYI(1, ("Send error in write = %d", rc));
+ cFYI(1, "Send error in write = %d", rc);
} else {
*nbytes = le16_to_cpu(pSMBr->CountHigh);
*nbytes = (*nbytes) << 16;
@@ -1551,7 +1556,7 @@
*nbytes = 0;
- cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));
+ cFYI(1, "write2 at %lld %d bytes", (long long)offset, count);
if (tcon->ses->capabilities & CAP_LARGE_FILES) {
wct = 14;
@@ -1606,7 +1611,7 @@
long_op);
cifs_stats_inc(&tcon->num_writes);
if (rc) {
- cFYI(1, ("Send error Write2 = %d", rc));
+ cFYI(1, "Send error Write2 = %d", rc);
} else if (resp_buf_type == 0) {
/* presumably this can not happen, but best to be safe */
rc = -EIO;
@@ -1651,7 +1656,7 @@
int timeout = 0;
__u16 count;
- cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock));
+ cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock);
rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
if (rc)
@@ -1699,7 +1704,7 @@
}
cifs_stats_inc(&tcon->num_locks);
if (rc)
- cFYI(1, ("Send error in Lock = %d", rc));
+ cFYI(1, "Send error in Lock = %d", rc);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -1722,7 +1727,7 @@
__u16 params, param_offset, offset, byte_count, count;
struct kvec iov[1];
- cFYI(1, ("Posix Lock"));
+ cFYI(1, "Posix Lock");
if (pLockData == NULL)
return -EINVAL;
@@ -1792,7 +1797,7 @@
}
if (rc) {
- cFYI(1, ("Send error in Posix Lock = %d", rc));
+ cFYI(1, "Send error in Posix Lock = %d", rc);
} else if (get_flag) {
/* lock structure can be returned on get */
__u16 data_offset;
@@ -1849,7 +1854,7 @@
{
int rc = 0;
CLOSE_REQ *pSMB = NULL;
- cFYI(1, ("In CIFSSMBClose"));
+ cFYI(1, "In CIFSSMBClose");
/* do not retry on dead session on close */
rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
@@ -1866,7 +1871,7 @@
if (rc) {
if (rc != -EINTR) {
/* EINTR is expected when user ctl-c to kill app */
- cERROR(1, ("Send error in Close = %d", rc));
+ cERROR(1, "Send error in Close = %d", rc);
}
}
@@ -1882,7 +1887,7 @@
{
int rc = 0;
FLUSH_REQ *pSMB = NULL;
- cFYI(1, ("In CIFSSMBFlush"));
+ cFYI(1, "In CIFSSMBFlush");
rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB);
if (rc)
@@ -1893,7 +1898,7 @@
rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
cifs_stats_inc(&tcon->num_flushes);
if (rc)
- cERROR(1, ("Send error in Flush = %d", rc));
+ cERROR(1, "Send error in Flush = %d", rc);
return rc;
}
@@ -1910,7 +1915,7 @@
int name_len, name_len2;
__u16 count;
- cFYI(1, ("In CIFSSMBRename"));
+ cFYI(1, "In CIFSSMBRename");
renameRetry:
rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -1956,7 +1961,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_renames);
if (rc)
- cFYI(1, ("Send error in rename = %d", rc));
+ cFYI(1, "Send error in rename = %d", rc);
cifs_buf_release(pSMB);
@@ -1980,7 +1985,7 @@
int len_of_str;
__u16 params, param_offset, offset, count, byte_count;
- cFYI(1, ("Rename to File by handle"));
+ cFYI(1, "Rename to File by handle");
rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
@@ -2035,7 +2040,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&pTcon->num_t2renames);
if (rc)
- cFYI(1, ("Send error in Rename (by file handle) = %d", rc));
+ cFYI(1, "Send error in Rename (by file handle) = %d", rc);
cifs_buf_release(pSMB);
@@ -2057,7 +2062,7 @@
int name_len, name_len2;
__u16 count;
- cFYI(1, ("In CIFSSMBCopy"));
+ cFYI(1, "In CIFSSMBCopy");
copyRetry:
rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -2102,8 +2107,8 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in copy = %d with %d files copied",
- rc, le16_to_cpu(pSMBr->CopyCount)));
+ cFYI(1, "Send error in copy = %d with %d files copied",
+ rc, le16_to_cpu(pSMBr->CopyCount));
}
cifs_buf_release(pSMB);
@@ -2127,7 +2132,7 @@
int bytes_returned = 0;
__u16 params, param_offset, offset, byte_count;
- cFYI(1, ("In Symlink Unix style"));
+ cFYI(1, "In Symlink Unix style");
createSymLinkRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -2192,7 +2197,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_symlinks);
if (rc)
- cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc));
+ cFYI(1, "Send error in SetPathInfo create symlink = %d", rc);
cifs_buf_release(pSMB);
@@ -2216,7 +2221,7 @@
int bytes_returned = 0;
__u16 params, param_offset, offset, byte_count;
- cFYI(1, ("In Create Hard link Unix style"));
+ cFYI(1, "In Create Hard link Unix style");
createHardLinkRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -2278,7 +2283,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_hardlinks);
if (rc)
- cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
+ cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc);
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
@@ -2299,7 +2304,7 @@
int name_len, name_len2;
__u16 count;
- cFYI(1, ("In CIFSCreateHardLink"));
+ cFYI(1, "In CIFSCreateHardLink");
winCreateHardLinkRetry:
rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
@@ -2350,7 +2355,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_hardlinks);
if (rc)
- cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
+ cFYI(1, "Send error in hard link (NT rename) = %d", rc);
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
@@ -2373,7 +2378,7 @@
__u16 params, byte_count;
char *data_start;
- cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
+ cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName);
querySymLinkRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -2420,7 +2425,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
+ cFYI(1, "Send error in QuerySymLinkInfo = %d", rc);
} else {
/* decode response */
@@ -2521,21 +2526,21 @@
/* should we also check that parm and data areas do not overlap? */
if (*ppparm > end_of_smb) {
- cFYI(1, ("parms start after end of smb"));
+ cFYI(1, "parms start after end of smb");
return -EINVAL;
} else if (parm_count + *ppparm > end_of_smb) {
- cFYI(1, ("parm end after end of smb"));
+ cFYI(1, "parm end after end of smb");
return -EINVAL;
} else if (*ppdata > end_of_smb) {
- cFYI(1, ("data starts after end of smb"));
+ cFYI(1, "data starts after end of smb");
return -EINVAL;
} else if (data_count + *ppdata > end_of_smb) {
- cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
+ cFYI(1, "data %p + count %d (%p) past smb end %p start %p",
*ppdata, data_count, (data_count + *ppdata),
- end_of_smb, pSMBr));
+ end_of_smb, pSMBr);
return -EINVAL;
} else if (parm_count + data_count > pSMBr->ByteCount) {
- cFYI(1, ("parm count and data count larger than SMB"));
+ cFYI(1, "parm count and data count larger than SMB");
return -EINVAL;
}
*pdatalen = data_count;
@@ -2554,7 +2559,7 @@
struct smb_com_transaction_ioctl_req *pSMB;
struct smb_com_transaction_ioctl_rsp *pSMBr;
- cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
+ cFYI(1, "In Windows reparse style QueryLink for path %s", searchName);
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
@@ -2583,7 +2588,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
+ cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc);
} else { /* decode response */
__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
__u32 data_count = le32_to_cpu(pSMBr->DataCount);
@@ -2607,7 +2612,7 @@
if ((reparse_buf->LinkNamesBuf +
reparse_buf->TargetNameOffset +
reparse_buf->TargetNameLen) > end_of_smb) {
- cFYI(1, ("reparse buf beyond SMB"));
+ cFYI(1, "reparse buf beyond SMB");
rc = -EIO;
goto qreparse_out;
}
@@ -2628,12 +2633,12 @@
}
} else {
rc = -EIO;
- cFYI(1, ("Invalid return data count on "
- "get reparse info ioctl"));
+ cFYI(1, "Invalid return data count on "
+ "get reparse info ioctl");
}
symlinkinfo[buflen] = 0; /* just in case so the caller
does not go off the end of the buffer */
- cFYI(1, ("readlink result - %s", symlinkinfo));
+ cFYI(1, "readlink result - %s", symlinkinfo);
}
qreparse_out:
@@ -2656,7 +2661,7 @@
ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
- /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
+ /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */
return;
}
@@ -2682,8 +2687,8 @@
size += sizeof(struct cifs_posix_ace) * count;
/* check if we would go beyond end of SMB */
if (size_of_data_area < size) {
- cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d",
- size_of_data_area, size));
+ cFYI(1, "bad CIFS POSIX ACL size %d vs. %d",
+ size_of_data_area, size);
return -EINVAL;
}
} else if (acl_type & ACL_TYPE_DEFAULT) {
@@ -2730,7 +2735,7 @@
cifs_ace->cifs_uid = cpu_to_le64(-1);
} else
cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
- /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
+ /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/
return rc;
}
@@ -2748,12 +2753,12 @@
return 0;
count = posix_acl_xattr_count((size_t)buflen);
- cFYI(1, ("setting acl with %d entries from buf of length %d and "
+ cFYI(1, "setting acl with %d entries from buf of length %d and "
"version of %d",
- count, buflen, le32_to_cpu(local_acl->a_version)));
+ count, buflen, le32_to_cpu(local_acl->a_version));
if (le32_to_cpu(local_acl->a_version) != 2) {
- cFYI(1, ("unknown POSIX ACL version %d",
- le32_to_cpu(local_acl->a_version)));
+ cFYI(1, "unknown POSIX ACL version %d",
+ le32_to_cpu(local_acl->a_version));
return 0;
}
cifs_acl->version = cpu_to_le16(1);
@@ -2762,7 +2767,7 @@
else if (acl_type == ACL_TYPE_DEFAULT)
cifs_acl->default_entry_count = cpu_to_le16(count);
else {
- cFYI(1, ("unknown ACL type %d", acl_type));
+ cFYI(1, "unknown ACL type %d", acl_type);
return 0;
}
for (i = 0; i < count; i++) {
@@ -2795,7 +2800,7 @@
int name_len;
__u16 params, byte_count;
- cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
+ cFYI(1, "In GetPosixACL (Unix) for path %s", searchName);
queryAclRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -2847,7 +2852,7 @@
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_acl_get);
if (rc) {
- cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
+ cFYI(1, "Send error in Query POSIX ACL = %d", rc);
} else {
/* decode response */
@@ -2884,7 +2889,7 @@
int bytes_returned = 0;
__u16 params, byte_count, data_count, param_offset, offset;
- cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
+ cFYI(1, "In SetPosixACL (Unix) for path %s", fileName);
setAclRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -2939,7 +2944,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc)
- cFYI(1, ("Set POSIX ACL returned %d", rc));
+ cFYI(1, "Set POSIX ACL returned %d", rc);
setACLerrorExit:
cifs_buf_release(pSMB);
@@ -2959,7 +2964,7 @@
int bytes_returned;
__u16 params, byte_count;
- cFYI(1, ("In GetExtAttr"));
+ cFYI(1, "In GetExtAttr");
if (tcon == NULL)
return -ENODEV;
@@ -2998,7 +3003,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("error %d in GetExtAttr", rc));
+ cFYI(1, "error %d in GetExtAttr", rc);
} else {
/* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -3013,7 +3018,7 @@
struct file_chattr_info *pfinfo;
/* BB Do we need a cast or hash here ? */
if (count != 16) {
- cFYI(1, ("Illegal size ret in GetExtAttr"));
+ cFYI(1, "Illegal size ret in GetExtAttr");
rc = -EIO;
goto GetExtAttrOut;
}
@@ -3043,7 +3048,7 @@
QUERY_SEC_DESC_REQ *pSMB;
struct kvec iov[1];
- cFYI(1, ("GetCifsACL"));
+ cFYI(1, "GetCifsACL");
*pbuflen = 0;
*acl_inf = NULL;
@@ -3068,7 +3073,7 @@
CIFS_STD_OP);
cifs_stats_inc(&tcon->num_acl_get);
if (rc) {
- cFYI(1, ("Send error in QuerySecDesc = %d", rc));
+ cFYI(1, "Send error in QuerySecDesc = %d", rc);
} else { /* decode response */
__le32 *parm;
__u32 parm_len;
@@ -3083,7 +3088,7 @@
goto qsec_out;
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
- cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));
+ cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf);
if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
rc = -EIO; /* bad smb */
@@ -3095,8 +3100,8 @@
acl_len = le32_to_cpu(*parm);
if (acl_len != *pbuflen) {
- cERROR(1, ("acl length %d does not match %d",
- acl_len, *pbuflen));
+ cERROR(1, "acl length %d does not match %d",
+ acl_len, *pbuflen);
if (*pbuflen > acl_len)
*pbuflen = acl_len;
}
@@ -3105,7 +3110,7 @@
header followed by the smallest SID */
if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
(*pbuflen >= 64 * 1024)) {
- cERROR(1, ("bad acl length %d", *pbuflen));
+ cERROR(1, "bad acl length %d", *pbuflen);
rc = -EINVAL;
*pbuflen = 0;
} else {
@@ -3179,9 +3184,9 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
- cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc));
+ cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc);
if (rc)
- cFYI(1, ("Set CIFS ACL returned %d", rc));
+ cFYI(1, "Set CIFS ACL returned %d", rc);
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
@@ -3205,7 +3210,7 @@
int bytes_returned;
int name_len;
- cFYI(1, ("In SMBQPath path %s", searchName));
+ cFYI(1, "In SMBQPath path %s", searchName);
QInfRetry:
rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -3231,7 +3236,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QueryInfo = %d", rc));
+ cFYI(1, "Send error in QueryInfo = %d", rc);
} else if (pFinfo) {
struct timespec ts;
__u32 time = le32_to_cpu(pSMBr->last_write_time);
@@ -3305,7 +3310,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QPathInfo = %d", rc));
+ cFYI(1, "Send error in QPathInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -3343,7 +3348,7 @@
int name_len;
__u16 params, byte_count;
-/* cFYI(1, ("In QPathInfo path %s", searchName)); */
+/* cFYI(1, "In QPathInfo path %s", searchName); */
QPathInfoRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -3393,7 +3398,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QPathInfo = %d", rc));
+ cFYI(1, "Send error in QPathInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -3473,14 +3478,14 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QPathInfo = %d", rc));
+ cFYI(1, "Send error in QPathInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
- cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
+ cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
"Unix Extensions can be disabled on mount "
- "by specifying the nosfu mount option."));
+ "by specifying the nosfu mount option.");
rc = -EIO; /* bad smb */
} else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
@@ -3512,7 +3517,7 @@
int name_len;
__u16 params, byte_count;
- cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
+ cFYI(1, "In QPathInfo (Unix) the path %s", searchName);
UnixQPathInfoRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -3559,14 +3564,14 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QPathInfo = %d", rc));
+ cFYI(1, "Send error in QPathInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
- cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
+ cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n"
"Unix Extensions can be disabled on mount "
- "by specifying the nosfu mount option."));
+ "by specifying the nosfu mount option.");
rc = -EIO; /* bad smb */
} else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
@@ -3600,7 +3605,7 @@
int name_len;
__u16 params, byte_count;
- cFYI(1, ("In FindFirst for %s", searchName));
+ cFYI(1, "In FindFirst for %s", searchName);
findFirstRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -3677,7 +3682,7 @@
if (rc) {/* BB add logic to retry regular search if Unix search
rejected unexpectedly by server */
/* BB Add code to handle unsupported level rc */
- cFYI(1, ("Error in FindFirst = %d", rc));
+ cFYI(1, "Error in FindFirst = %d", rc);
cifs_buf_release(pSMB);
@@ -3716,7 +3721,7 @@
lnoff = le16_to_cpu(parms->LastNameOffset);
if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
lnoff) {
- cERROR(1, ("ignoring corrupt resume name"));
+ cERROR(1, "ignoring corrupt resume name");
psrch_inf->last_entry = NULL;
return rc;
}
@@ -3744,7 +3749,7 @@
int bytes_returned, name_len;
__u16 params, byte_count;
- cFYI(1, ("In FindNext"));
+ cFYI(1, "In FindNext");
if (psrch_inf->endOfSearch)
return -ENOENT;
@@ -3808,7 +3813,7 @@
cifs_buf_release(pSMB);
rc = 0; /* search probably was closed at end of search*/
} else
- cFYI(1, ("FindNext returned = %d", rc));
+ cFYI(1, "FindNext returned = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -3844,15 +3849,15 @@
lnoff = le16_to_cpu(parms->LastNameOffset);
if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE <
lnoff) {
- cERROR(1, ("ignoring corrupt resume name"));
+ cERROR(1, "ignoring corrupt resume name");
psrch_inf->last_entry = NULL;
return rc;
} else
psrch_inf->last_entry =
psrch_inf->srch_entries_start + lnoff;
-/* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",
- psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */
+/* cFYI(1, "fnxt2 entries in buf %d index_of_last %d",
+ psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */
/* BB fixme add unlock here */
}
@@ -3877,7 +3882,7 @@
int rc = 0;
FINDCLOSE_REQ *pSMB = NULL;
- cFYI(1, ("In CIFSSMBFindClose"));
+ cFYI(1, "In CIFSSMBFindClose");
rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
/* no sense returning error if session restarted
@@ -3891,7 +3896,7 @@
pSMB->ByteCount = 0;
rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
if (rc)
- cERROR(1, ("Send error in FindClose = %d", rc));
+ cERROR(1, "Send error in FindClose = %d", rc);
cifs_stats_inc(&tcon->num_fclose);
@@ -3914,7 +3919,7 @@
int name_len, bytes_returned;
__u16 params, byte_count;
- cFYI(1, ("In GetSrvInodeNum for %s", searchName));
+ cFYI(1, "In GetSrvInodeNum for %s", searchName);
if (tcon == NULL)
return -ENODEV;
@@ -3964,7 +3969,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("error %d in QueryInternalInfo", rc));
+ cFYI(1, "error %d in QueryInternalInfo", rc);
} else {
/* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -3979,7 +3984,7 @@
struct file_internal_info *pfinfo;
/* BB Do we need a cast or hash here ? */
if (count < 8) {
- cFYI(1, ("Illegal size ret in QryIntrnlInf"));
+ cFYI(1, "Illegal size ret in QryIntrnlInf");
rc = -EIO;
goto GetInodeNumOut;
}
@@ -4020,16 +4025,16 @@
*num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
if (*num_of_nodes < 1) {
- cERROR(1, ("num_referrals: must be at least > 0,"
- "but we get num_referrals = %d\n", *num_of_nodes));
+ cERROR(1, "num_referrals: must be at least > 0,"
+ "but we get num_referrals = %d\n", *num_of_nodes);
rc = -EINVAL;
goto parse_DFS_referrals_exit;
}
ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
if (ref->VersionNumber != cpu_to_le16(3)) {
- cERROR(1, ("Referrals of V%d version are not supported,"
- "should be V3", le16_to_cpu(ref->VersionNumber)));
+ cERROR(1, "Referrals of V%d version are not supported,"
+ "should be V3", le16_to_cpu(ref->VersionNumber));
rc = -EINVAL;
goto parse_DFS_referrals_exit;
}
@@ -4038,14 +4043,14 @@
data_end = (char *)(&(pSMBr->PathConsumed)) +
le16_to_cpu(pSMBr->t2.DataCount);
- cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
+ cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n",
*num_of_nodes,
- le32_to_cpu(pSMBr->DFSFlags)));
+ le32_to_cpu(pSMBr->DFSFlags));
*target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
*num_of_nodes, GFP_KERNEL);
if (*target_nodes == NULL) {
- cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
+ cERROR(1, "Failed to allocate buffer for target_nodes\n");
rc = -ENOMEM;
goto parse_DFS_referrals_exit;
}
@@ -4121,7 +4126,7 @@
*num_of_nodes = 0;
*target_nodes = NULL;
- cFYI(1, ("In GetDFSRefer the path %s", searchName));
+ cFYI(1, "In GetDFSRefer the path %s", searchName);
if (ses == NULL)
return -ENODEV;
getDFSRetry:
@@ -4188,7 +4193,7 @@
rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in GetDFSRefer = %d", rc));
+ cFYI(1, "Send error in GetDFSRefer = %d", rc);
goto GetDFSRefExit;
}
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4199,9 +4204,9 @@
goto GetDFSRefExit;
}
- cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
+ cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d",
pSMBr->ByteCount,
- le16_to_cpu(pSMBr->t2.DataOffset)));
+ le16_to_cpu(pSMBr->t2.DataOffset));
/* parse returned result into more usable form */
rc = parse_DFS_referrals(pSMBr, num_of_nodes,
@@ -4229,7 +4234,7 @@
int bytes_returned = 0;
__u16 params, byte_count;
- cFYI(1, ("OldQFSInfo"));
+ cFYI(1, "OldQFSInfo");
oldQFSInfoRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -4262,7 +4267,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QFSInfo = %d", rc));
+ cFYI(1, "Send error in QFSInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4270,8 +4275,8 @@
rc = -EIO; /* bad smb */
else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- cFYI(1, ("qfsinf resp BCC: %d Offset %d",
- pSMBr->ByteCount, data_offset));
+ cFYI(1, "qfsinf resp BCC: %d Offset %d",
+ pSMBr->ByteCount, data_offset);
response_data = (FILE_SYSTEM_ALLOC_INFO *)
(((char *) &pSMBr->hdr.Protocol) + data_offset);
@@ -4283,11 +4288,10 @@
le32_to_cpu(response_data->TotalAllocationUnits);
FSData->f_bfree = FSData->f_bavail =
le32_to_cpu(response_data->FreeAllocationUnits);
- cFYI(1,
- ("Blocks: %lld Free: %lld Block size %ld",
- (unsigned long long)FSData->f_blocks,
- (unsigned long long)FSData->f_bfree,
- FSData->f_bsize));
+ cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
+ (unsigned long long)FSData->f_blocks,
+ (unsigned long long)FSData->f_bfree,
+ FSData->f_bsize);
}
}
cifs_buf_release(pSMB);
@@ -4309,7 +4313,7 @@
int bytes_returned = 0;
__u16 params, byte_count;
- cFYI(1, ("In QFSInfo"));
+ cFYI(1, "In QFSInfo");
QFSInfoRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -4342,7 +4346,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QFSInfo = %d", rc));
+ cFYI(1, "Send error in QFSInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4363,11 +4367,10 @@
le64_to_cpu(response_data->TotalAllocationUnits);
FSData->f_bfree = FSData->f_bavail =
le64_to_cpu(response_data->FreeAllocationUnits);
- cFYI(1,
- ("Blocks: %lld Free: %lld Block size %ld",
- (unsigned long long)FSData->f_blocks,
- (unsigned long long)FSData->f_bfree,
- FSData->f_bsize));
+ cFYI(1, "Blocks: %lld Free: %lld Block size %ld",
+ (unsigned long long)FSData->f_blocks,
+ (unsigned long long)FSData->f_bfree,
+ FSData->f_bsize);
}
}
cifs_buf_release(pSMB);
@@ -4389,7 +4392,7 @@
int bytes_returned = 0;
__u16 params, byte_count;
- cFYI(1, ("In QFSAttributeInfo"));
+ cFYI(1, "In QFSAttributeInfo");
QFSAttributeRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -4423,7 +4426,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
+ cERROR(1, "Send error in QFSAttributeInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4459,7 +4462,7 @@
int bytes_returned = 0;
__u16 params, byte_count;
- cFYI(1, ("In QFSDeviceInfo"));
+ cFYI(1, "In QFSDeviceInfo");
QFSDeviceRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -4494,7 +4497,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
+ cFYI(1, "Send error in QFSDeviceInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4529,7 +4532,7 @@
int bytes_returned = 0;
__u16 params, byte_count;
- cFYI(1, ("In QFSUnixInfo"));
+ cFYI(1, "In QFSUnixInfo");
QFSUnixRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -4563,7 +4566,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
+ cERROR(1, "Send error in QFSUnixInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4598,7 +4601,7 @@
int bytes_returned = 0;
__u16 params, param_offset, offset, byte_count;
- cFYI(1, ("In SETFSUnixInfo"));
+ cFYI(1, "In SETFSUnixInfo");
SETFSUnixRetry:
/* BB switch to small buf init to save memory */
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -4646,7 +4649,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
+ cERROR(1, "Send error in SETFSUnixInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc)
@@ -4674,7 +4677,7 @@
int bytes_returned = 0;
__u16 params, byte_count;
- cFYI(1, ("In QFSPosixInfo"));
+ cFYI(1, "In QFSPosixInfo");
QFSPosixRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -4708,7 +4711,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
+ cFYI(1, "Send error in QFSUnixInfo = %d", rc);
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -4768,7 +4771,7 @@
int bytes_returned = 0;
__u16 params, byte_count, data_count, param_offset, offset;
- cFYI(1, ("In SetEOF"));
+ cFYI(1, "In SetEOF");
SetEOFRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -4834,7 +4837,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc)
- cFYI(1, ("SetPathInfo (file size) returned %d", rc));
+ cFYI(1, "SetPathInfo (file size) returned %d", rc);
cifs_buf_release(pSMB);
@@ -4854,8 +4857,8 @@
int rc = 0;
__u16 params, param_offset, offset, byte_count, count;
- cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
- (long long)size));
+ cFYI(1, "SetFileSize (via SetFileInfo) %lld",
+ (long long)size);
rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
if (rc)
@@ -4914,9 +4917,7 @@
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
if (rc) {
- cFYI(1,
- ("Send error in SetFileInfo (SetFileSize) = %d",
- rc));
+ cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc);
}
/* Note: On -EAGAIN error only caller can retry on handle based calls
@@ -4940,7 +4941,7 @@
int rc = 0;
__u16 params, param_offset, offset, byte_count, count;
- cFYI(1, ("Set Times (via SetFileInfo)"));
+ cFYI(1, "Set Times (via SetFileInfo)");
rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
if (rc)
@@ -4985,7 +4986,7 @@
memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
if (rc)
- cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
+ cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -5002,7 +5003,7 @@
int rc = 0;
__u16 params, param_offset, offset, byte_count, count;
- cFYI(1, ("Set File Disposition (via SetFileInfo)"));
+ cFYI(1, "Set File Disposition (via SetFileInfo)");
rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
if (rc)
@@ -5044,7 +5045,7 @@
*data_offset = delete_file ? 1 : 0;
rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
if (rc)
- cFYI(1, ("Send error in SetFileDisposition = %d", rc));
+ cFYI(1, "Send error in SetFileDisposition = %d", rc);
return rc;
}
@@ -5062,7 +5063,7 @@
char *data_offset;
__u16 params, param_offset, offset, byte_count, count;
- cFYI(1, ("In SetTimes"));
+ cFYI(1, "In SetTimes");
SetTimesRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
@@ -5118,7 +5119,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc)
- cFYI(1, ("SetPathInfo (times) returned %d", rc));
+ cFYI(1, "SetPathInfo (times) returned %d", rc);
cifs_buf_release(pSMB);
@@ -5143,7 +5144,7 @@
int bytes_returned;
int name_len;
- cFYI(1, ("In SetAttrLegacy"));
+ cFYI(1, "In SetAttrLegacy");
SetAttrLgcyRetry:
rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
@@ -5169,7 +5170,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc)
- cFYI(1, ("Error in LegacySetAttr = %d", rc));
+ cFYI(1, "Error in LegacySetAttr = %d", rc);
cifs_buf_release(pSMB);
@@ -5231,7 +5232,7 @@
int rc = 0;
u16 params, param_offset, offset, byte_count, count;
- cFYI(1, ("Set Unix Info (via SetFileInfo)"));
+ cFYI(1, "Set Unix Info (via SetFileInfo)");
rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
if (rc)
@@ -5276,7 +5277,7 @@
rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
if (rc)
- cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
+ cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -5297,7 +5298,7 @@
FILE_UNIX_BASIC_INFO *data_offset;
__u16 params, param_offset, offset, count, byte_count;
- cFYI(1, ("In SetUID/GID/Mode"));
+ cFYI(1, "In SetUID/GID/Mode");
setPermsRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -5353,7 +5354,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc)
- cFYI(1, ("SetPathInfo (perms) returned %d", rc));
+ cFYI(1, "SetPathInfo (perms) returned %d", rc);
cifs_buf_release(pSMB);
if (rc == -EAGAIN)
@@ -5372,7 +5373,7 @@
struct dir_notify_req *dnotify_req;
int bytes_returned;
- cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid));
+ cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid);
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
@@ -5406,7 +5407,7 @@
(struct smb_hdr *)pSMBr, &bytes_returned,
CIFS_ASYNC_OP);
if (rc) {
- cFYI(1, ("Error in Notify = %d", rc));
+ cFYI(1, "Error in Notify = %d", rc);
} else {
/* Add file to outstanding requests */
/* BB change to kmem cache alloc */
@@ -5462,7 +5463,7 @@
char *end_of_smb;
__u16 params, byte_count, data_offset;
- cFYI(1, ("In Query All EAs path %s", searchName));
+ cFYI(1, "In Query All EAs path %s", searchName);
QAllEAsRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -5509,7 +5510,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("Send error in QueryAllEAs = %d", rc));
+ cFYI(1, "Send error in QueryAllEAs = %d", rc);
goto QAllEAsOut;
}
@@ -5537,16 +5538,16 @@
(((char *) &pSMBr->hdr.Protocol) + data_offset);
list_len = le32_to_cpu(ea_response_data->list_len);
- cFYI(1, ("ea length %d", list_len));
+ cFYI(1, "ea length %d", list_len);
if (list_len <= 8) {
- cFYI(1, ("empty EA list returned from server"));
+ cFYI(1, "empty EA list returned from server");
goto QAllEAsOut;
}
/* make sure list_len doesn't go past end of SMB */
end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr);
if ((char *)ea_response_data + list_len > end_of_smb) {
- cFYI(1, ("EA list appears to go beyond SMB"));
+ cFYI(1, "EA list appears to go beyond SMB");
rc = -EIO;
goto QAllEAsOut;
}
@@ -5563,7 +5564,7 @@
temp_ptr += 4;
/* make sure we can read name_len and value_len */
if (list_len < 0) {
- cFYI(1, ("EA entry goes beyond length of list"));
+ cFYI(1, "EA entry goes beyond length of list");
rc = -EIO;
goto QAllEAsOut;
}
@@ -5572,7 +5573,7 @@
value_len = le16_to_cpu(temp_fea->value_len);
list_len -= name_len + 1 + value_len;
if (list_len < 0) {
- cFYI(1, ("EA entry goes beyond length of list"));
+ cFYI(1, "EA entry goes beyond length of list");
rc = -EIO;
goto QAllEAsOut;
}
@@ -5639,7 +5640,7 @@
int bytes_returned = 0;
__u16 params, param_offset, byte_count, offset, count;
- cFYI(1, ("In SetEA"));
+ cFYI(1, "In SetEA");
SetEARetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -5721,7 +5722,7 @@
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc)
- cFYI(1, ("SetPathInfo (EA) returned %d", rc));
+ cFYI(1, "SetPathInfo (EA) returned %d", rc);
cifs_buf_release(pSMB);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d9566bf..2208f06 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -102,6 +102,7 @@
bool sockopt_tcp_nodelay:1;
unsigned short int port;
char *prepath;
+ struct nls_table *local_nls;
};
static int ipv4_connect(struct TCP_Server_Info *server);
@@ -135,7 +136,7 @@
spin_unlock(&GlobalMid_Lock);
server->maxBuf = 0;
- cFYI(1, ("Reconnecting tcp session"));
+ cFYI(1, "Reconnecting tcp session");
/* before reconnecting the tcp session, mark the smb session (uid)
and the tid bad so they are not used until reconnected */
@@ -153,12 +154,12 @@
/* do not want to be sending data on a socket we are freeing */
mutex_lock(&server->srv_mutex);
if (server->ssocket) {
- cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
- server->ssocket->flags));
+ cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state,
+ server->ssocket->flags);
kernel_sock_shutdown(server->ssocket, SHUT_WR);
- cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
+ cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx",
server->ssocket->state,
- server->ssocket->flags));
+ server->ssocket->flags);
sock_release(server->ssocket);
server->ssocket = NULL;
}
@@ -187,7 +188,7 @@
else
rc = ipv4_connect(server);
if (rc) {
- cFYI(1, ("reconnect error %d", rc));
+ cFYI(1, "reconnect error %d", rc);
msleep(3000);
} else {
atomic_inc(&tcpSesReconnectCount);
@@ -223,7 +224,7 @@
/* check for plausible wct, bcc and t2 data and parm sizes */
/* check for parm and data offset going beyond end of smb */
if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
- cFYI(1, ("invalid transact2 word count"));
+ cFYI(1, "invalid transact2 word count");
return -EINVAL;
}
@@ -237,15 +238,15 @@
if (remaining == 0)
return 0;
else if (remaining < 0) {
- cFYI(1, ("total data %d smaller than data in frame %d",
- total_data_size, data_in_this_rsp));
+ cFYI(1, "total data %d smaller than data in frame %d",
+ total_data_size, data_in_this_rsp);
return -EINVAL;
} else {
- cFYI(1, ("missing %d bytes from transact2, check next response",
- remaining));
+ cFYI(1, "missing %d bytes from transact2, check next response",
+ remaining);
if (total_data_size > maxBufSize) {
- cERROR(1, ("TotalDataSize %d is over maximum buffer %d",
- total_data_size, maxBufSize));
+ cERROR(1, "TotalDataSize %d is over maximum buffer %d",
+ total_data_size, maxBufSize);
return -EINVAL;
}
return remaining;
@@ -267,7 +268,7 @@
total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
- cFYI(1, ("total data size of primary and secondary t2 differ"));
+ cFYI(1, "total data size of primary and secondary t2 differ");
}
total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
@@ -282,7 +283,7 @@
total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
if (remaining < total_in_buf2) {
- cFYI(1, ("transact2 2nd response contains too much data"));
+ cFYI(1, "transact2 2nd response contains too much data");
}
/* find end of first SMB data area */
@@ -311,7 +312,7 @@
pTargetSMB->smb_buf_length = byte_count;
if (remaining == total_in_buf2) {
- cFYI(1, ("found the last secondary response"));
+ cFYI(1, "found the last secondary response");
return 0; /* we are done */
} else /* more responses to go */
return 1;
@@ -339,7 +340,7 @@
int reconnect;
current->flags |= PF_MEMALLOC;
- cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
+ cFYI(1, "Demultiplex PID: %d", task_pid_nr(current));
length = atomic_inc_return(&tcpSesAllocCount);
if (length > 1)
@@ -353,7 +354,7 @@
if (bigbuf == NULL) {
bigbuf = cifs_buf_get();
if (!bigbuf) {
- cERROR(1, ("No memory for large SMB response"));
+ cERROR(1, "No memory for large SMB response");
msleep(3000);
/* retry will check if exiting */
continue;
@@ -366,7 +367,7 @@
if (smallbuf == NULL) {
smallbuf = cifs_small_buf_get();
if (!smallbuf) {
- cERROR(1, ("No memory for SMB response"));
+ cERROR(1, "No memory for SMB response");
msleep(1000);
/* retry will check if exiting */
continue;
@@ -391,9 +392,9 @@
if (server->tcpStatus == CifsExiting) {
break;
} else if (server->tcpStatus == CifsNeedReconnect) {
- cFYI(1, ("Reconnect after server stopped responding"));
+ cFYI(1, "Reconnect after server stopped responding");
cifs_reconnect(server);
- cFYI(1, ("call to reconnect done"));
+ cFYI(1, "call to reconnect done");
csocket = server->ssocket;
continue;
} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
@@ -411,7 +412,7 @@
continue;
} else if (length <= 0) {
if (server->tcpStatus == CifsNew) {
- cFYI(1, ("tcp session abend after SMBnegprot"));
+ cFYI(1, "tcp session abend after SMBnegprot");
/* some servers kill the TCP session rather than
returning an SMB negprot error, in which
case reconnecting here is not going to help,
@@ -419,18 +420,18 @@
break;
}
if (!try_to_freeze() && (length == -EINTR)) {
- cFYI(1, ("cifsd thread killed"));
+ cFYI(1, "cifsd thread killed");
break;
}
- cFYI(1, ("Reconnect after unexpected peek error %d",
- length));
+ cFYI(1, "Reconnect after unexpected peek error %d",
+ length);
cifs_reconnect(server);
csocket = server->ssocket;
wake_up(&server->response_q);
continue;
} else if (length < pdu_length) {
- cFYI(1, ("requested %d bytes but only got %d bytes",
- pdu_length, length));
+ cFYI(1, "requested %d bytes but only got %d bytes",
+ pdu_length, length);
pdu_length -= length;
msleep(1);
goto incomplete_rcv;
@@ -450,18 +451,18 @@
pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length);
smb_buffer->smb_buf_length = pdu_length;
- cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
+ cFYI(1, "rfc1002 length 0x%x", pdu_length+4);
if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
continue;
} else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
- cFYI(1, ("Good RFC 1002 session rsp"));
+ cFYI(1, "Good RFC 1002 session rsp");
continue;
} else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
/* we get this from Windows 98 instead of
an error on SMB negprot response */
- cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)",
- pdu_length));
+ cFYI(1, "Negative RFC1002 Session Response Error 0x%x)",
+ pdu_length);
if (server->tcpStatus == CifsNew) {
/* if nack on negprot (rather than
ret of smb negprot error) reconnecting
@@ -484,7 +485,7 @@
continue;
}
} else if (temp != (char) 0) {
- cERROR(1, ("Unknown RFC 1002 frame"));
+ cERROR(1, "Unknown RFC 1002 frame");
cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
length);
cifs_reconnect(server);
@@ -495,8 +496,8 @@
/* else we have an SMB response */
if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
(pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
- cERROR(1, ("Invalid size SMB length %d pdu_length %d",
- length, pdu_length+4));
+ cERROR(1, "Invalid size SMB length %d pdu_length %d",
+ length, pdu_length+4);
cifs_reconnect(server);
csocket = server->ssocket;
wake_up(&server->response_q);
@@ -539,8 +540,8 @@
length = 0;
continue;
} else if (length <= 0) {
- cERROR(1, ("Received no data, expecting %d",
- pdu_length - total_read));
+ cERROR(1, "Received no data, expecting %d",
+ pdu_length - total_read);
cifs_reconnect(server);
csocket = server->ssocket;
reconnect = 1;
@@ -588,7 +589,7 @@
}
} else {
if (!isLargeBuf) {
- cERROR(1,("1st trans2 resp needs bigbuf"));
+ cERROR(1, "1st trans2 resp needs bigbuf");
/* BB maybe we can fix this up, switch
to already allocated large buffer? */
} else {
@@ -630,8 +631,8 @@
wake_up_process(task_to_wake);
} else if (!is_valid_oplock_break(smb_buffer, server) &&
!isMultiRsp) {
- cERROR(1, ("No task to wake, unknown frame received! "
- "NumMids %d", midCount.counter));
+ cERROR(1, "No task to wake, unknown frame received! "
+ "NumMids %d", midCount.counter);
cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
sizeof(struct smb_hdr));
#ifdef CONFIG_CIFS_DEBUG2
@@ -708,8 +709,8 @@
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
- cFYI(1, ("Clearing Mid 0x%x - waking up ",
- mid_entry->mid));
+ cFYI(1, "Clearing Mid 0x%x - waking up ",
+ mid_entry->mid);
task_to_wake = mid_entry->tsk;
if (task_to_wake)
wake_up_process(task_to_wake);
@@ -728,7 +729,7 @@
to wait at least 45 seconds before giving up
on a request getting a response and going ahead
and killing cifsd */
- cFYI(1, ("Wait for exit from demultiplex thread"));
+ cFYI(1, "Wait for exit from demultiplex thread");
msleep(46000);
/* if threads still have not exited they are probably never
coming home not much else we can do but free the memory */
@@ -849,7 +850,7 @@
separator[0] = options[4];
options += 5;
} else {
- cFYI(1, ("Null separator not allowed"));
+ cFYI(1, "Null separator not allowed");
}
}
@@ -974,7 +975,7 @@
}
} else if (strnicmp(data, "sec", 3) == 0) {
if (!value || !*value) {
- cERROR(1, ("no security value specified"));
+ cERROR(1, "no security value specified");
continue;
} else if (strnicmp(value, "krb5i", 5) == 0) {
vol->secFlg |= CIFSSEC_MAY_KRB5 |
@@ -982,7 +983,7 @@
} else if (strnicmp(value, "krb5p", 5) == 0) {
/* vol->secFlg |= CIFSSEC_MUST_SEAL |
CIFSSEC_MAY_KRB5; */
- cERROR(1, ("Krb5 cifs privacy not supported"));
+ cERROR(1, "Krb5 cifs privacy not supported");
return 1;
} else if (strnicmp(value, "krb5", 4) == 0) {
vol->secFlg |= CIFSSEC_MAY_KRB5;
@@ -1014,7 +1015,7 @@
} else if (strnicmp(value, "none", 4) == 0) {
vol->nullauth = 1;
} else {
- cERROR(1, ("bad security option: %s", value));
+ cERROR(1, "bad security option: %s", value);
return 1;
}
} else if ((strnicmp(data, "unc", 3) == 0)
@@ -1053,7 +1054,7 @@
a domain name and need special handling? */
if (strnlen(value, 256) < 256) {
vol->domainname = value;
- cFYI(1, ("Domain name set"));
+ cFYI(1, "Domain name set");
} else {
printk(KERN_WARNING "CIFS: domain name too "
"long\n");
@@ -1076,7 +1077,7 @@
strcpy(vol->prepath+1, value);
} else
strcpy(vol->prepath, value);
- cFYI(1, ("prefix path %s", vol->prepath));
+ cFYI(1, "prefix path %s", vol->prepath);
} else {
printk(KERN_WARNING "CIFS: prefix too long\n");
return 1;
@@ -1092,7 +1093,7 @@
vol->iocharset = value;
/* if iocharset not set then load_nls_default
is used by caller */
- cFYI(1, ("iocharset set to %s", value));
+ cFYI(1, "iocharset set to %s", value);
} else {
printk(KERN_WARNING "CIFS: iocharset name "
"too long.\n");
@@ -1144,14 +1145,14 @@
}
} else if (strnicmp(data, "sockopt", 5) == 0) {
if (!value || !*value) {
- cERROR(1, ("no socket option specified"));
+ cERROR(1, "no socket option specified");
continue;
} else if (strnicmp(value, "TCP_NODELAY", 11) == 0) {
vol->sockopt_tcp_nodelay = 1;
}
} else if (strnicmp(data, "netbiosname", 4) == 0) {
if (!value || !*value || (*value == ' ')) {
- cFYI(1, ("invalid (empty) netbiosname"));
+ cFYI(1, "invalid (empty) netbiosname");
} else {
memset(vol->source_rfc1001_name, 0x20, 15);
for (i = 0; i < 15; i++) {
@@ -1175,7 +1176,7 @@
} else if (strnicmp(data, "servern", 7) == 0) {
/* servernetbiosname specified override *SMBSERVER */
if (!value || !*value || (*value == ' ')) {
- cFYI(1, ("empty server netbiosname specified"));
+ cFYI(1, "empty server netbiosname specified");
} else {
/* last byte, type, is 0x20 for servr type */
memset(vol->target_rfc1001_name, 0x20, 16);
@@ -1434,7 +1435,7 @@
++server->srv_count;
write_unlock(&cifs_tcp_ses_lock);
- cFYI(1, ("Existing tcp session with server found"));
+ cFYI(1, "Existing tcp session with server found");
return server;
}
write_unlock(&cifs_tcp_ses_lock);
@@ -1475,7 +1476,7 @@
memset(&addr, 0, sizeof(struct sockaddr_storage));
- cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip));
+ cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
if (volume_info->UNCip && volume_info->UNC) {
rc = cifs_convert_address(volume_info->UNCip, &addr);
@@ -1487,13 +1488,12 @@
} else if (volume_info->UNCip) {
/* BB using ip addr as tcp_ses name to connect to the
DFS root below */
- cERROR(1, ("Connecting to DFS root not implemented yet"));
+ cERROR(1, "Connecting to DFS root not implemented yet");
rc = -EINVAL;
goto out_err;
} else /* which tcp_sess DFS root would we conect to */ {
- cERROR(1,
- ("CIFS mount error: No UNC path (e.g. -o "
- "unc=//192.168.1.100/public) specified"));
+ cERROR(1, "CIFS mount error: No UNC path (e.g. -o "
+ "unc=//192.168.1.100/public) specified");
rc = -EINVAL;
goto out_err;
}
@@ -1540,7 +1540,7 @@
++tcp_ses->srv_count;
if (addr.ss_family == AF_INET6) {
- cFYI(1, ("attempting ipv6 connect"));
+ cFYI(1, "attempting ipv6 connect");
/* BB should we allow ipv6 on port 139? */
/* other OS never observed in Wild doing 139 with v6 */
sin_server6->sin6_port = htons(volume_info->port);
@@ -1554,7 +1554,7 @@
rc = ipv4_connect(tcp_ses);
}
if (rc < 0) {
- cERROR(1, ("Error connecting to socket. Aborting operation"));
+ cERROR(1, "Error connecting to socket. Aborting operation");
goto out_err;
}
@@ -1567,7 +1567,7 @@
tcp_ses, "cifsd");
if (IS_ERR(tcp_ses->tsk)) {
rc = PTR_ERR(tcp_ses->tsk);
- cERROR(1, ("error %d create cifsd thread", rc));
+ cERROR(1, "error %d create cifsd thread", rc);
module_put(THIS_MODULE);
goto out_err;
}
@@ -1616,6 +1616,7 @@
int xid;
struct TCP_Server_Info *server = ses->server;
+ cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
write_lock(&cifs_tcp_ses_lock);
if (--ses->ses_count > 0) {
write_unlock(&cifs_tcp_ses_lock);
@@ -1634,6 +1635,102 @@
cifs_put_tcp_session(server);
}
+static struct cifsSesInfo *
+cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
+{
+ int rc = -ENOMEM, xid;
+ struct cifsSesInfo *ses;
+
+ xid = GetXid();
+
+ ses = cifs_find_smb_ses(server, volume_info->username);
+ if (ses) {
+ cFYI(1, "Existing smb sess found (status=%d)", ses->status);
+
+ /* existing SMB ses has a server reference already */
+ cifs_put_tcp_session(server);
+
+ mutex_lock(&ses->session_mutex);
+ rc = cifs_negotiate_protocol(xid, ses);
+ if (rc) {
+ mutex_unlock(&ses->session_mutex);
+ /* problem -- put our ses reference */
+ cifs_put_smb_ses(ses);
+ FreeXid(xid);
+ return ERR_PTR(rc);
+ }
+ if (ses->need_reconnect) {
+ cFYI(1, "Session needs reconnect");
+ rc = cifs_setup_session(xid, ses,
+ volume_info->local_nls);
+ if (rc) {
+ mutex_unlock(&ses->session_mutex);
+ /* problem -- put our reference */
+ cifs_put_smb_ses(ses);
+ FreeXid(xid);
+ return ERR_PTR(rc);
+ }
+ }
+ mutex_unlock(&ses->session_mutex);
+ FreeXid(xid);
+ return ses;
+ }
+
+ cFYI(1, "Existing smb sess not found");
+ ses = sesInfoAlloc();
+ if (ses == NULL)
+ goto get_ses_fail;
+
+ /* new SMB session uses our server ref */
+ ses->server = server;
+ if (server->addr.sockAddr6.sin6_family == AF_INET6)
+ sprintf(ses->serverName, "%pI6",
+ &server->addr.sockAddr6.sin6_addr);
+ else
+ sprintf(ses->serverName, "%pI4",
+ &server->addr.sockAddr.sin_addr.s_addr);
+
+ if (volume_info->username)
+ strncpy(ses->userName, volume_info->username,
+ MAX_USERNAME_SIZE);
+
+ /* volume_info->password freed at unmount */
+ if (volume_info->password) {
+ ses->password = kstrdup(volume_info->password, GFP_KERNEL);
+ if (!ses->password)
+ goto get_ses_fail;
+ }
+ if (volume_info->domainname) {
+ int len = strlen(volume_info->domainname);
+ ses->domainName = kmalloc(len + 1, GFP_KERNEL);
+ if (ses->domainName)
+ strcpy(ses->domainName, volume_info->domainname);
+ }
+ ses->linux_uid = volume_info->linux_uid;
+ ses->overrideSecFlg = volume_info->secFlg;
+
+ mutex_lock(&ses->session_mutex);
+ rc = cifs_negotiate_protocol(xid, ses);
+ if (!rc)
+ rc = cifs_setup_session(xid, ses, volume_info->local_nls);
+ mutex_unlock(&ses->session_mutex);
+ if (rc)
+ goto get_ses_fail;
+
+ /* success, put it on the list */
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&ses->smb_ses_list, &server->smb_ses_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ FreeXid(xid);
+ return ses;
+
+get_ses_fail:
+ sesInfoFree(ses);
+ FreeXid(xid);
+ return ERR_PTR(rc);
+}
+
static struct cifsTconInfo *
cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
{
@@ -1662,6 +1759,7 @@
int xid;
struct cifsSesInfo *ses = tcon->ses;
+ cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
write_lock(&cifs_tcp_ses_lock);
if (--tcon->tc_count > 0) {
write_unlock(&cifs_tcp_ses_lock);
@@ -1679,6 +1777,80 @@
cifs_put_smb_ses(ses);
}
+static struct cifsTconInfo *
+cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
+{
+ int rc, xid;
+ struct cifsTconInfo *tcon;
+
+ tcon = cifs_find_tcon(ses, volume_info->UNC);
+ if (tcon) {
+ cFYI(1, "Found match on UNC path");
+ /* existing tcon already has a reference */
+ cifs_put_smb_ses(ses);
+ if (tcon->seal != volume_info->seal)
+ cERROR(1, "transport encryption setting "
+ "conflicts with existing tid");
+ return tcon;
+ }
+
+ tcon = tconInfoAlloc();
+ if (tcon == NULL) {
+ rc = -ENOMEM;
+ goto out_fail;
+ }
+
+ tcon->ses = ses;
+ if (volume_info->password) {
+ tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
+ if (!tcon->password) {
+ rc = -ENOMEM;
+ goto out_fail;
+ }
+ }
+
+ if (strchr(volume_info->UNC + 3, '\\') == NULL
+ && strchr(volume_info->UNC + 3, '/') == NULL) {
+ cERROR(1, "Missing share name");
+ rc = -ENODEV;
+ goto out_fail;
+ }
+
+ /* BB Do we need to wrap session_mutex around
+ * this TCon call and Unix SetFS as
+ * we do on SessSetup and reconnect? */
+ xid = GetXid();
+ rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls);
+ FreeXid(xid);
+ cFYI(1, "CIFS Tcon rc = %d", rc);
+ if (rc)
+ goto out_fail;
+
+ if (volume_info->nodfs) {
+ tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
+ cFYI(1, "DFS disabled (%d)", tcon->Flags);
+ }
+ tcon->seal = volume_info->seal;
+ /* we can have only one retry value for a connection
+ to a share so for resources mounted more than once
+ to the same server share the last value passed in
+ for the retry flag is used */
+ tcon->retry = volume_info->retry;
+ tcon->nocase = volume_info->nocase;
+ tcon->local_lease = volume_info->local_lease;
+
+ write_lock(&cifs_tcp_ses_lock);
+ list_add(&tcon->tcon_list, &ses->tcon_list);
+ write_unlock(&cifs_tcp_ses_lock);
+
+ return tcon;
+
+out_fail:
+ tconInfoFree(tcon);
+ return ERR_PTR(rc);
+}
+
+
int
get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
@@ -1703,8 +1875,7 @@
strcpy(temp_unc + 2, pSesInfo->serverName);
strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
- cFYI(1,
- ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));
+ cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid);
kfree(temp_unc);
}
if (rc == 0)
@@ -1777,12 +1948,12 @@
rc = sock_create_kern(PF_INET, SOCK_STREAM,
IPPROTO_TCP, &socket);
if (rc < 0) {
- cERROR(1, ("Error %d creating socket", rc));
+ cERROR(1, "Error %d creating socket", rc);
return rc;
}
/* BB other socket options to set KEEPALIVE, NODELAY? */
- cFYI(1, ("Socket created"));
+ cFYI(1, "Socket created");
server->ssocket = socket;
socket->sk->sk_allocation = GFP_NOFS;
cifs_reclassify_socket4(socket);
@@ -1827,7 +1998,7 @@
if (!connected) {
if (orig_port)
server->addr.sockAddr.sin_port = orig_port;
- cFYI(1, ("Error %d connecting to server via ipv4", rc));
+ cFYI(1, "Error %d connecting to server via ipv4", rc);
sock_release(socket);
server->ssocket = NULL;
return rc;
@@ -1855,12 +2026,12 @@
rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
(char *)&val, sizeof(val));
if (rc)
- cFYI(1, ("set TCP_NODELAY socket option error %d", rc));
+ cFYI(1, "set TCP_NODELAY socket option error %d", rc);
}
- cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
+ cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
socket->sk->sk_sndbuf,
- socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo));
+ socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
/* send RFC1001 sessinit */
if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) {
@@ -1938,13 +2109,13 @@
rc = sock_create_kern(PF_INET6, SOCK_STREAM,
IPPROTO_TCP, &socket);
if (rc < 0) {
- cERROR(1, ("Error %d creating ipv6 socket", rc));
+ cERROR(1, "Error %d creating ipv6 socket", rc);
socket = NULL;
return rc;
}
/* BB other socket options to set KEEPALIVE, NODELAY? */
- cFYI(1, ("ipv6 Socket created"));
+ cFYI(1, "ipv6 Socket created");
server->ssocket = socket;
socket->sk->sk_allocation = GFP_NOFS;
cifs_reclassify_socket6(socket);
@@ -1988,7 +2159,7 @@
if (!connected) {
if (orig_port)
server->addr.sockAddr6.sin6_port = orig_port;
- cFYI(1, ("Error %d connecting to server via ipv6", rc));
+ cFYI(1, "Error %d connecting to server via ipv6", rc);
sock_release(socket);
server->ssocket = NULL;
return rc;
@@ -2007,7 +2178,7 @@
rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
(char *)&val, sizeof(val));
if (rc)
- cFYI(1, ("set TCP_NODELAY socket option error %d", rc));
+ cFYI(1, "set TCP_NODELAY socket option error %d", rc);
}
server->ssocket = socket;
@@ -2032,13 +2203,13 @@
if (vol_info && vol_info->no_linux_ext) {
tcon->fsUnixInfo.Capability = 0;
tcon->unix_ext = 0; /* Unix Extensions disabled */
- cFYI(1, ("Linux protocol extensions disabled"));
+ cFYI(1, "Linux protocol extensions disabled");
return;
} else if (vol_info)
tcon->unix_ext = 1; /* Unix Extensions supported */
if (tcon->unix_ext == 0) {
- cFYI(1, ("Unix extensions disabled so not set on reconnect"));
+ cFYI(1, "Unix extensions disabled so not set on reconnect");
return;
}
@@ -2054,12 +2225,11 @@
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
- cERROR(1, ("POSIXPATH support change"));
+ cERROR(1, "POSIXPATH support change");
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
} else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
- cERROR(1, ("possible reconnect error"));
- cERROR(1,
- ("server disabled POSIX path support"));
+ cERROR(1, "possible reconnect error");
+ cERROR(1, "server disabled POSIX path support");
}
}
@@ -2067,7 +2237,7 @@
if (vol_info && vol_info->no_psx_acl)
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
- cFYI(1, ("negotiated posix acl support"));
+ cFYI(1, "negotiated posix acl support");
if (sb)
sb->s_flags |= MS_POSIXACL;
}
@@ -2075,7 +2245,7 @@
if (vol_info && vol_info->posix_paths == 0)
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
- cFYI(1, ("negotiate posix pathnames"));
+ cFYI(1, "negotiate posix pathnames");
if (sb)
CIFS_SB(sb)->mnt_cifs_flags |=
CIFS_MOUNT_POSIX_PATHS;
@@ -2090,39 +2260,38 @@
if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
CIFS_SB(sb)->rsize = 127 * 1024;
- cFYI(DBG2,
- ("larger reads not supported by srv"));
+ cFYI(DBG2, "larger reads not supported by srv");
}
}
- cFYI(1, ("Negotiate caps 0x%x", (int)cap));
+ cFYI(1, "Negotiate caps 0x%x", (int)cap);
#ifdef CONFIG_CIFS_DEBUG2
if (cap & CIFS_UNIX_FCNTL_CAP)
- cFYI(1, ("FCNTL cap"));
+ cFYI(1, "FCNTL cap");
if (cap & CIFS_UNIX_EXTATTR_CAP)
- cFYI(1, ("EXTATTR cap"));
+ cFYI(1, "EXTATTR cap");
if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
- cFYI(1, ("POSIX path cap"));
+ cFYI(1, "POSIX path cap");
if (cap & CIFS_UNIX_XATTR_CAP)
- cFYI(1, ("XATTR cap"));
+ cFYI(1, "XATTR cap");
if (cap & CIFS_UNIX_POSIX_ACL_CAP)
- cFYI(1, ("POSIX ACL cap"));
+ cFYI(1, "POSIX ACL cap");
if (cap & CIFS_UNIX_LARGE_READ_CAP)
- cFYI(1, ("very large read cap"));
+ cFYI(1, "very large read cap");
if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
- cFYI(1, ("very large write cap"));
+ cFYI(1, "very large write cap");
#endif /* CIFS_DEBUG2 */
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
if (vol_info == NULL) {
- cFYI(1, ("resetting capabilities failed"));
+ cFYI(1, "resetting capabilities failed");
} else
- cERROR(1, ("Negotiating Unix capabilities "
+ cERROR(1, "Negotiating Unix capabilities "
"with the server failed. Consider "
"mounting with the Unix Extensions\n"
"disabled, if problems are found, "
"by specifying the nounix mount "
- "option."));
+ "option.");
}
}
@@ -2152,8 +2321,8 @@
struct cifs_sb_info *cifs_sb)
{
if (pvolume_info->rsize > CIFSMaxBufSize) {
- cERROR(1, ("rsize %d too large, using MaxBufSize",
- pvolume_info->rsize));
+ cERROR(1, "rsize %d too large, using MaxBufSize",
+ pvolume_info->rsize);
cifs_sb->rsize = CIFSMaxBufSize;
} else if ((pvolume_info->rsize) &&
(pvolume_info->rsize <= CIFSMaxBufSize))
@@ -2162,8 +2331,8 @@
cifs_sb->rsize = CIFSMaxBufSize;
if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
- cERROR(1, ("wsize %d too large, using 4096 instead",
- pvolume_info->wsize));
+ cERROR(1, "wsize %d too large, using 4096 instead",
+ pvolume_info->wsize);
cifs_sb->wsize = 4096;
} else if (pvolume_info->wsize)
cifs_sb->wsize = pvolume_info->wsize;
@@ -2181,7 +2350,7 @@
if (cifs_sb->rsize < 2048) {
cifs_sb->rsize = 2048;
/* Windows ME may prefer this */
- cFYI(1, ("readsize set to minimum: 2048"));
+ cFYI(1, "readsize set to minimum: 2048");
}
/* calculate prepath */
cifs_sb->prepath = pvolume_info->prepath;
@@ -2199,8 +2368,8 @@
cifs_sb->mnt_gid = pvolume_info->linux_gid;
cifs_sb->mnt_file_mode = pvolume_info->file_mode;
cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
- cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
- cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
+ cFYI(1, "file mode: 0x%x dir mode: 0x%x",
+ cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
if (pvolume_info->noperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
@@ -2229,13 +2398,13 @@
if (pvolume_info->dynperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
if (pvolume_info->direct_io) {
- cFYI(1, ("mounting share using direct i/o"));
+ cFYI(1, "mounting share using direct i/o");
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
}
if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
- cERROR(1, ("mount option dynperm ignored if cifsacl "
- "mount option supported"));
+ cERROR(1, "mount option dynperm ignored if cifsacl "
+ "mount option supported");
}
static int
@@ -2262,7 +2431,7 @@
{
struct smb_vol *volume_info;
- if (!pvolume_info && !*pvolume_info)
+ if (!pvolume_info || !*pvolume_info)
return;
volume_info = *pvolume_info;
@@ -2344,11 +2513,11 @@
}
if (volume_info->nullauth) {
- cFYI(1, ("null user"));
+ cFYI(1, "null user");
volume_info->username = "";
} else if (volume_info->username) {
/* BB fixme parse for domain name here */
- cFYI(1, ("Username: %s", volume_info->username));
+ cFYI(1, "Username: %s", volume_info->username);
} else {
cifserror("No username specified");
/* In userspace mount helper we can get user name from alternate
@@ -2357,20 +2526,20 @@
goto out;
}
-
/* this is needed for ASCII cp to Unicode converts */
if (volume_info->iocharset == NULL) {
- cifs_sb->local_nls = load_nls_default();
- /* load_nls_default can not return null */
+ /* load_nls_default cannot return null */
+ volume_info->local_nls = load_nls_default();
} else {
- cifs_sb->local_nls = load_nls(volume_info->iocharset);
- if (cifs_sb->local_nls == NULL) {
- cERROR(1, ("CIFS mount error: iocharset %s not found",
- volume_info->iocharset));
+ volume_info->local_nls = load_nls(volume_info->iocharset);
+ if (volume_info->local_nls == NULL) {
+ cERROR(1, "CIFS mount error: iocharset %s not found",
+ volume_info->iocharset);
rc = -ELIBACC;
goto out;
}
}
+ cifs_sb->local_nls = volume_info->local_nls;
/* get a reference to a tcp session */
srvTcp = cifs_get_tcp_session(volume_info);
@@ -2379,148 +2548,30 @@
goto out;
}
- pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username);
- if (pSesInfo) {
- cFYI(1, ("Existing smb sess found (status=%d)",
- pSesInfo->status));
- /*
- * The existing SMB session already has a reference to srvTcp,
- * so we can put back the extra one we got before
- */
- cifs_put_tcp_session(srvTcp);
-
- mutex_lock(&pSesInfo->session_mutex);
- if (pSesInfo->need_reconnect) {
- cFYI(1, ("Session needs reconnect"));
- rc = cifs_setup_session(xid, pSesInfo,
- cifs_sb->local_nls);
- }
- mutex_unlock(&pSesInfo->session_mutex);
- } else if (!rc) {
- cFYI(1, ("Existing smb sess not found"));
- pSesInfo = sesInfoAlloc();
- if (pSesInfo == NULL) {
- rc = -ENOMEM;
- goto mount_fail_check;
- }
-
- /* new SMB session uses our srvTcp ref */
- pSesInfo->server = srvTcp;
- if (srvTcp->addr.sockAddr6.sin6_family == AF_INET6)
- sprintf(pSesInfo->serverName, "%pI6",
- &srvTcp->addr.sockAddr6.sin6_addr);
- else
- sprintf(pSesInfo->serverName, "%pI4",
- &srvTcp->addr.sockAddr.sin_addr.s_addr);
-
- write_lock(&cifs_tcp_ses_lock);
- list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
- write_unlock(&cifs_tcp_ses_lock);
-
- /* volume_info->password freed at unmount */
- if (volume_info->password) {
- pSesInfo->password = kstrdup(volume_info->password,
- GFP_KERNEL);
- if (!pSesInfo->password) {
- rc = -ENOMEM;
- goto mount_fail_check;
- }
- }
- if (volume_info->username)
- strncpy(pSesInfo->userName, volume_info->username,
- MAX_USERNAME_SIZE);
- if (volume_info->domainname) {
- int len = strlen(volume_info->domainname);
- pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
- if (pSesInfo->domainName)
- strcpy(pSesInfo->domainName,
- volume_info->domainname);
- }
- pSesInfo->linux_uid = volume_info->linux_uid;
- pSesInfo->overrideSecFlg = volume_info->secFlg;
- mutex_lock(&pSesInfo->session_mutex);
-
- /* BB FIXME need to pass vol->secFlgs BB */
- rc = cifs_setup_session(xid, pSesInfo,
- cifs_sb->local_nls);
- mutex_unlock(&pSesInfo->session_mutex);
+ /* get a reference to a SMB session */
+ pSesInfo = cifs_get_smb_ses(srvTcp, volume_info);
+ if (IS_ERR(pSesInfo)) {
+ rc = PTR_ERR(pSesInfo);
+ pSesInfo = NULL;
+ goto mount_fail_check;
}
- /* search for existing tcon to this server share */
- if (!rc) {
- setup_cifs_sb(volume_info, cifs_sb);
-
- tcon = cifs_find_tcon(pSesInfo, volume_info->UNC);
- if (tcon) {
- cFYI(1, ("Found match on UNC path"));
- /* existing tcon already has a reference */
- cifs_put_smb_ses(pSesInfo);
- if (tcon->seal != volume_info->seal)
- cERROR(1, ("transport encryption setting "
- "conflicts with existing tid"));
- } else {
- tcon = tconInfoAlloc();
- if (tcon == NULL) {
- rc = -ENOMEM;
- goto mount_fail_check;
- }
-
- tcon->ses = pSesInfo;
- if (volume_info->password) {
- tcon->password = kstrdup(volume_info->password,
- GFP_KERNEL);
- if (!tcon->password) {
- rc = -ENOMEM;
- goto mount_fail_check;
- }
- }
-
- if ((strchr(volume_info->UNC + 3, '\\') == NULL)
- && (strchr(volume_info->UNC + 3, '/') == NULL)) {
- cERROR(1, ("Missing share name"));
- rc = -ENODEV;
- goto mount_fail_check;
- } else {
- /* BB Do we need to wrap sesSem around
- * this TCon call and Unix SetFS as
- * we do on SessSetup and reconnect? */
- rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
- tcon, cifs_sb->local_nls);
- cFYI(1, ("CIFS Tcon rc = %d", rc));
- if (volume_info->nodfs) {
- tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
- cFYI(1, ("DFS disabled (%d)",
- tcon->Flags));
- }
- }
- if (rc)
- goto remote_path_check;
- tcon->seal = volume_info->seal;
- write_lock(&cifs_tcp_ses_lock);
- list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
- write_unlock(&cifs_tcp_ses_lock);
- }
-
- /* we can have only one retry value for a connection
- to a share so for resources mounted more than once
- to the same server share the last value passed in
- for the retry flag is used */
- tcon->retry = volume_info->retry;
- tcon->nocase = volume_info->nocase;
- tcon->local_lease = volume_info->local_lease;
- }
- if (pSesInfo) {
- if (pSesInfo->capabilities & CAP_LARGE_FILES)
- sb->s_maxbytes = MAX_LFS_FILESIZE;
- else
- sb->s_maxbytes = MAX_NON_LFS;
- }
+ setup_cifs_sb(volume_info, cifs_sb);
+ if (pSesInfo->capabilities & CAP_LARGE_FILES)
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ else
+ sb->s_maxbytes = MAX_NON_LFS;
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
sb->s_time_gran = 100;
- if (rc)
+ /* search for existing tcon to this server share */
+ tcon = cifs_get_tcon(pSesInfo, volume_info);
+ if (IS_ERR(tcon)) {
+ rc = PTR_ERR(tcon);
+ tcon = NULL;
goto remote_path_check;
+ }
cifs_sb->tcon = tcon;
@@ -2544,7 +2595,7 @@
if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
cifs_sb->rsize = 1024 * 127;
- cFYI(DBG2, ("no very large read support, rsize now 127K"));
+ cFYI(DBG2, "no very large read support, rsize now 127K");
}
if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
cifs_sb->wsize = min(cifs_sb->wsize,
@@ -2593,7 +2644,7 @@
goto mount_fail_check;
}
- cFYI(1, ("Getting referral for: %s", full_path));
+ cFYI(1, "Getting referral for: %s", full_path);
rc = get_dfs_path(xid, pSesInfo , full_path + 1,
cifs_sb->local_nls, &num_referrals, &referrals,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -2707,7 +2758,7 @@
by Samba (not sure whether other servers allow
NTLMv2 password here) */
#ifdef CONFIG_CIFS_WEAK_PW_HASH
- if ((extended_security & CIFSSEC_MAY_LANMAN) &&
+ if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
(ses->server->secType == LANMAN))
calc_lanman_hash(tcon->password, ses->server->cryptKey,
ses->server->secMode &
@@ -2778,13 +2829,13 @@
if (length == 3) {
if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
(bcc_ptr[2] == 'C')) {
- cFYI(1, ("IPC connection"));
+ cFYI(1, "IPC connection");
tcon->ipc = 1;
}
} else if (length == 2) {
if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
/* the most common case */
- cFYI(1, ("disk share connection"));
+ cFYI(1, "disk share connection");
}
}
bcc_ptr += length + 1;
@@ -2797,7 +2848,7 @@
bytes_left, is_unicode,
nls_codepage);
- cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem));
+ cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem);
if ((smb_buffer_response->WordCount == 3) ||
(smb_buffer_response->WordCount == 7))
@@ -2805,7 +2856,7 @@
tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
else
tcon->Flags = 0;
- cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
+ cFYI(1, "Tcon flags: 0x%x ", tcon->Flags);
} else if ((rc == 0) && tcon == NULL) {
/* all we need to save for IPC$ connection */
ses->ipc_tid = smb_buffer_response->Tid;
@@ -2833,57 +2884,61 @@
return rc;
}
-int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
- struct nls_table *nls_info)
+int cifs_negotiate_protocol(unsigned int xid, struct cifsSesInfo *ses)
{
int rc = 0;
- int first_time = 0;
- struct TCP_Server_Info *server = pSesInfo->server;
+ struct TCP_Server_Info *server = ses->server;
- /* what if server changes its buffer size after dropping the session? */
- if (server->maxBuf == 0) /* no need to send on reconnect */ {
- rc = CIFSSMBNegotiate(xid, pSesInfo);
- if (rc == -EAGAIN) {
- /* retry only once on 1st time connection */
- rc = CIFSSMBNegotiate(xid, pSesInfo);
- if (rc == -EAGAIN)
- rc = -EHOSTDOWN;
- }
- if (rc == 0) {
- spin_lock(&GlobalMid_Lock);
- if (server->tcpStatus != CifsExiting)
- server->tcpStatus = CifsGood;
- else
- rc = -EHOSTDOWN;
- spin_unlock(&GlobalMid_Lock);
+ /* only send once per connect */
+ if (server->maxBuf != 0)
+ return 0;
- }
- first_time = 1;
+ rc = CIFSSMBNegotiate(xid, ses);
+ if (rc == -EAGAIN) {
+ /* retry only once on 1st time connection */
+ rc = CIFSSMBNegotiate(xid, ses);
+ if (rc == -EAGAIN)
+ rc = -EHOSTDOWN;
+ }
+ if (rc == 0) {
+ spin_lock(&GlobalMid_Lock);
+ if (server->tcpStatus != CifsExiting)
+ server->tcpStatus = CifsGood;
+ else
+ rc = -EHOSTDOWN;
+ spin_unlock(&GlobalMid_Lock);
+
}
- if (rc)
- goto ss_err_exit;
+ return rc;
+}
- pSesInfo->flags = 0;
- pSesInfo->capabilities = server->capabilities;
+
+int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses,
+ struct nls_table *nls_info)
+{
+ int rc = 0;
+ struct TCP_Server_Info *server = ses->server;
+
+ ses->flags = 0;
+ ses->capabilities = server->capabilities;
if (linuxExtEnabled == 0)
- pSesInfo->capabilities &= (~CAP_UNIX);
+ ses->capabilities &= (~CAP_UNIX);
- cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
- server->secMode, server->capabilities, server->timeAdj));
+ cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
+ server->secMode, server->capabilities, server->timeAdj);
- rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
+ rc = CIFS_SessSetup(xid, ses, nls_info);
if (rc) {
- cERROR(1, ("Send error in SessSetup = %d", rc));
+ cERROR(1, "Send error in SessSetup = %d", rc);
} else {
- cFYI(1, ("CIFS Session Established successfully"));
+ cFYI(1, "CIFS Session Established successfully");
spin_lock(&GlobalMid_Lock);
- pSesInfo->status = CifsGood;
- pSesInfo->need_reconnect = false;
+ ses->status = CifsGood;
+ ses->need_reconnect = false;
spin_unlock(&GlobalMid_Lock);
}
-ss_err_exit:
return rc;
}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e9f7ecc..391816b 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -73,7 +73,7 @@
namelen += (1 + temp->d_name.len);
temp = temp->d_parent;
if (temp == NULL) {
- cERROR(1, ("corrupt dentry"));
+ cERROR(1, "corrupt dentry");
return NULL;
}
}
@@ -90,19 +90,18 @@
full_path[namelen] = dirsep;
strncpy(full_path + namelen + 1, temp->d_name.name,
temp->d_name.len);
- cFYI(0, ("name: %s", full_path + namelen));
+ cFYI(0, "name: %s", full_path + namelen);
}
temp = temp->d_parent;
if (temp == NULL) {
- cERROR(1, ("corrupt dentry"));
+ cERROR(1, "corrupt dentry");
kfree(full_path);
return NULL;
}
}
if (namelen != pplen + dfsplen) {
- cERROR(1,
- ("did not end path lookup where expected namelen is %d",
- namelen));
+ cERROR(1, "did not end path lookup where expected namelen is %d",
+ namelen);
/* presumably this is only possible if racing with a rename
of one of the parent directories (we can not lock the dentries
above us to prevent this, but retrying should be harmless) */
@@ -130,6 +129,12 @@
return full_path;
}
+/*
+ * When called with struct file pointer set to NULL, there is no way we could
+ * update file->private_data, but getting it stuck on openFileList provides a
+ * way to access it from cifs_fill_filedata and thereby set file->private_data
+ * from cifs_open.
+ */
struct cifsFileInfo *
cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
struct file *file, struct vfsmount *mnt, unsigned int oflags)
@@ -173,7 +178,7 @@
if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = true;
pCifsInode->clientCanCacheRead = true;
- cFYI(1, ("Exclusive Oplock inode %p", newinode));
+ cFYI(1, "Exclusive Oplock inode %p", newinode);
} else if ((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = true;
}
@@ -183,16 +188,17 @@
}
int cifs_posix_open(char *full_path, struct inode **pinode,
- struct vfsmount *mnt, int mode, int oflags,
- __u32 *poplock, __u16 *pnetfid, int xid)
+ struct vfsmount *mnt, struct super_block *sb,
+ int mode, int oflags,
+ __u32 *poplock, __u16 *pnetfid, int xid)
{
int rc;
FILE_UNIX_BASIC_INFO *presp_data;
__u32 posix_flags = 0;
- struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_fattr fattr;
- cFYI(1, ("posix open %s", full_path));
+ cFYI(1, "posix open %s", full_path);
presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
if (presp_data == NULL)
@@ -242,7 +248,8 @@
/* get new inode and set it up */
if (*pinode == NULL) {
- *pinode = cifs_iget(mnt->mnt_sb, &fattr);
+ cifs_fill_uniqueid(sb, &fattr);
+ *pinode = cifs_iget(sb, &fattr);
if (!*pinode) {
rc = -ENOMEM;
goto posix_open_ret;
@@ -251,7 +258,18 @@
cifs_fattr_to_inode(*pinode, &fattr);
}
- cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
+ /*
+ * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
+ * file->private_data.
+ */
+ if (mnt) {
+ struct cifsFileInfo *pfile_info;
+
+ pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
+ oflags);
+ if (pfile_info == NULL)
+ rc = -ENOMEM;
+ }
posix_open_ret:
kfree(presp_data);
@@ -315,13 +333,14 @@
if (nd && (nd->flags & LOOKUP_OPEN))
oflags = nd->intent.open.flags;
else
- oflags = FMODE_READ;
+ oflags = FMODE_READ | SMB_O_CREAT;
if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
- rc = cifs_posix_open(full_path, &newinode, nd->path.mnt,
- mode, oflags, &oplock, &fileHandle, xid);
+ rc = cifs_posix_open(full_path, &newinode,
+ nd ? nd->path.mnt : NULL,
+ inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
/* EIO could indicate that (posix open) operation is not
supported, despite what server claimed in capability
negotation. EREMOTE indicates DFS junction, which is not
@@ -358,7 +377,7 @@
else if ((oflags & O_CREAT) == O_CREAT)
disposition = FILE_OPEN_IF;
else
- cFYI(1, ("Create flag not set in create function"));
+ cFYI(1, "Create flag not set in create function");
}
/* BB add processing to set equivalent of mode - e.g. via CreateX with
@@ -394,7 +413,7 @@
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
}
if (rc) {
- cFYI(1, ("cifs_create returned 0x%x", rc));
+ cFYI(1, "cifs_create returned 0x%x", rc);
goto cifs_create_out;
}
@@ -457,15 +476,22 @@
if (rc == 0)
setup_cifs_dentry(tcon, direntry, newinode);
else
- cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc));
+ cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
/* nfsd case - nfs srv does not set nd */
if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
/* mknod case - do not leave file open */
CIFSSMBClose(xid, tcon, fileHandle);
} else if (!(posix_create) && (newinode)) {
- cifs_new_fileinfo(newinode, fileHandle, NULL,
- nd->path.mnt, oflags);
+ struct cifsFileInfo *pfile_info;
+ /*
+ * cifs_fill_filedata() takes care of setting cifsFileInfo
+ * pointer to file->private_data.
+ */
+ pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL,
+ nd->path.mnt, oflags);
+ if (pfile_info == NULL)
+ rc = -ENOMEM;
}
cifs_create_out:
kfree(buf);
@@ -531,7 +557,7 @@
u16 fileHandle;
FILE_ALL_INFO *buf;
- cFYI(1, ("sfu compat create special file"));
+ cFYI(1, "sfu compat create special file");
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (buf == NULL) {
@@ -616,8 +642,8 @@
xid = GetXid();
- cFYI(1, ("parent inode = 0x%p name is: %s and dentry = 0x%p",
- parent_dir_inode, direntry->d_name.name, direntry));
+ cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
+ parent_dir_inode, direntry->d_name.name, direntry);
/* check whether path exists */
@@ -632,7 +658,7 @@
int i;
for (i = 0; i < direntry->d_name.len; i++)
if (direntry->d_name.name[i] == '\\') {
- cFYI(1, ("Invalid file name"));
+ cFYI(1, "Invalid file name");
FreeXid(xid);
return ERR_PTR(-EINVAL);
}
@@ -657,11 +683,11 @@
}
if (direntry->d_inode != NULL) {
- cFYI(1, ("non-NULL inode in lookup"));
+ cFYI(1, "non-NULL inode in lookup");
} else {
- cFYI(1, ("NULL inode in lookup"));
+ cFYI(1, "NULL inode in lookup");
}
- cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
+ cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
/* Posix open is only called (at lookup time) for file create now.
* For opens (rather than creates), because we do not know if it
@@ -678,6 +704,7 @@
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
(nd->intent.open.flags & O_CREAT)) {
rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
+ parent_dir_inode->i_sb,
nd->intent.open.create_mode,
nd->intent.open.flags, &oplock,
&fileHandle, xid);
@@ -723,7 +750,7 @@
/* if it was once a directory (but how can we tell?) we could do
shrink_dcache_parent(direntry); */
} else if (rc != -EACCES) {
- cERROR(1, ("Unexpected lookup error %d", rc));
+ cERROR(1, "Unexpected lookup error %d", rc);
/* We special case check for Access Denied - since that
is a common return code */
}
@@ -742,8 +769,8 @@
if (cifs_revalidate_dentry(direntry))
return 0;
} else {
- cFYI(1, ("neg dentry 0x%p name = %s",
- direntry, direntry->d_name.name));
+ cFYI(1, "neg dentry 0x%p name = %s",
+ direntry, direntry->d_name.name);
if (time_after(jiffies, direntry->d_time + HZ) ||
!lookupCacheEnabled) {
d_drop(direntry);
@@ -758,7 +785,7 @@
{
int rc = 0;
- cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
+ cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
return rc;
} */
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c
index 6f8a0e3..4db2c5e 100644
--- a/fs/cifs/dns_resolve.c
+++ b/fs/cifs/dns_resolve.c
@@ -106,14 +106,14 @@
/* search for server name delimiter */
len = strlen(unc);
if (len < 3) {
- cFYI(1, ("%s: unc is too short: %s", __func__, unc));
+ cFYI(1, "%s: unc is too short: %s", __func__, unc);
return -EINVAL;
}
len -= 2;
name = memchr(unc+2, '\\', len);
if (!name) {
- cFYI(1, ("%s: probably server name is whole unc: %s",
- __func__, unc));
+ cFYI(1, "%s: probably server name is whole unc: %s",
+ __func__, unc);
} else {
len = (name - unc) - 2/* leading // */;
}
@@ -127,8 +127,8 @@
name[len] = 0;
if (is_ip(name)) {
- cFYI(1, ("%s: it is IP, skipping dns upcall: %s",
- __func__, name));
+ cFYI(1, "%s: it is IP, skipping dns upcall: %s",
+ __func__, name);
data = name;
goto skip_upcall;
}
@@ -138,7 +138,7 @@
len = rkey->type_data.x[0];
data = rkey->payload.data;
} else {
- cERROR(1, ("%s: unable to resolve: %s", __func__, name));
+ cERROR(1, "%s: unable to resolve: %s", __func__, name);
goto out;
}
@@ -148,10 +148,10 @@
if (*ip_addr) {
memcpy(*ip_addr, data, len + 1);
if (!IS_ERR(rkey))
- cFYI(1, ("%s: resolved: %s to %s", __func__,
+ cFYI(1, "%s: resolved: %s to %s", __func__,
name,
*ip_addr
- ));
+ );
rc = 0;
} else {
rc = -ENOMEM;
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 6177f7c..993f820 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -49,7 +49,7 @@
static struct dentry *cifs_get_parent(struct dentry *dentry)
{
/* BB need to add code here eventually to enable export via NFSD */
- cFYI(1, ("get parent for %p", dentry));
+ cFYI(1, "get parent for %p", dentry);
return ERR_PTR(-EACCES);
}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 9b11a8f..a83541e 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3,7 +3,7 @@
*
* vfs operations that deal with files
*
- * Copyright (C) International Business Machines Corp., 2002,2007
+ * Copyright (C) International Business Machines Corp., 2002,2010
* Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org)
*
@@ -108,8 +108,7 @@
/* all arguments to this function must be checked for validity in caller */
static inline int
cifs_posix_open_inode_helper(struct inode *inode, struct file *file,
- struct cifsInodeInfo *pCifsInode,
- struct cifsFileInfo *pCifsFile, __u32 oplock,
+ struct cifsInodeInfo *pCifsInode, __u32 oplock,
u16 netfid)
{
@@ -136,15 +135,15 @@
if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
(file->f_path.dentry->d_inode->i_size ==
(loff_t)le64_to_cpu(buf->EndOfFile))) {
- cFYI(1, ("inode unchanged on server"));
+ cFYI(1, "inode unchanged on server");
} else {
if (file->f_path.dentry->d_inode->i_mapping) {
rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
if (rc != 0)
CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
}
- cFYI(1, ("invalidating remote inode since open detected it "
- "changed"));
+ cFYI(1, "invalidating remote inode since open detected it "
+ "changed");
invalidate_remote_inode(file->f_path.dentry->d_inode);
} */
@@ -152,8 +151,8 @@
if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = true;
pCifsInode->clientCanCacheRead = true;
- cFYI(1, ("Exclusive Oplock granted on inode %p",
- file->f_path.dentry->d_inode));
+ cFYI(1, "Exclusive Oplock granted on inode %p",
+ file->f_path.dentry->d_inode);
} else if ((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = true;
@@ -190,8 +189,8 @@
if (file->private_data != NULL) {
return pCifsFile;
} else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
- cERROR(1, ("could not find file instance for "
- "new file %p", file));
+ cERROR(1, "could not find file instance for "
+ "new file %p", file);
return NULL;
}
@@ -217,7 +216,7 @@
if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
(file->f_path.dentry->d_inode->i_size ==
(loff_t)le64_to_cpu(buf->EndOfFile))) {
- cFYI(1, ("inode unchanged on server"));
+ cFYI(1, "inode unchanged on server");
} else {
if (file->f_path.dentry->d_inode->i_mapping) {
/* BB no need to lock inode until after invalidate
@@ -226,8 +225,8 @@
if (rc != 0)
CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
}
- cFYI(1, ("invalidating remote inode since open detected it "
- "changed"));
+ cFYI(1, "invalidating remote inode since open detected it "
+ "changed");
invalidate_remote_inode(file->f_path.dentry->d_inode);
}
@@ -242,8 +241,8 @@
if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = true;
pCifsInode->clientCanCacheRead = true;
- cFYI(1, ("Exclusive Oplock granted on inode %p",
- file->f_path.dentry->d_inode));
+ cFYI(1, "Exclusive Oplock granted on inode %p",
+ file->f_path.dentry->d_inode);
} else if ((*oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = true;
@@ -285,8 +284,8 @@
return rc;
}
- cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
- inode, file->f_flags, full_path));
+ cFYI(1, "inode = 0x%p file flags are 0x%x for %s",
+ inode, file->f_flags, full_path);
if (oplockEnabled)
oplock = REQ_OPLOCK;
@@ -298,27 +297,29 @@
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
int oflags = (int) cifs_posix_convert_flags(file->f_flags);
+ oflags |= SMB_O_CREAT;
/* can not refresh inode info since size could be stale */
rc = cifs_posix_open(full_path, &inode, file->f_path.mnt,
- cifs_sb->mnt_file_mode /* ignored */,
- oflags, &oplock, &netfid, xid);
+ inode->i_sb,
+ cifs_sb->mnt_file_mode /* ignored */,
+ oflags, &oplock, &netfid, xid);
if (rc == 0) {
- cFYI(1, ("posix open succeeded"));
+ cFYI(1, "posix open succeeded");
/* no need for special case handling of setting mode
on read only files needed here */
pCifsFile = cifs_fill_filedata(file);
cifs_posix_open_inode_helper(inode, file, pCifsInode,
- pCifsFile, oplock, netfid);
+ oplock, netfid);
goto out;
} else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
if (tcon->ses->serverNOS)
- cERROR(1, ("server %s of type %s returned"
+ cERROR(1, "server %s of type %s returned"
" unexpected error on SMB posix open"
", disabling posix open support."
" Check if server update available.",
tcon->ses->serverName,
- tcon->ses->serverNOS));
+ tcon->ses->serverNOS);
tcon->broken_posix_open = true;
} else if ((rc != -EIO) && (rc != -EREMOTE) &&
(rc != -EOPNOTSUPP)) /* path not found or net err */
@@ -386,7 +387,7 @@
& CIFS_MOUNT_MAP_SPECIAL_CHR);
}
if (rc) {
- cFYI(1, ("cifs_open returned 0x%x", rc));
+ cFYI(1, "cifs_open returned 0x%x", rc);
goto out;
}
@@ -469,7 +470,7 @@
}
if (file->f_path.dentry == NULL) {
- cERROR(1, ("no valid name if dentry freed"));
+ cERROR(1, "no valid name if dentry freed");
dump_stack();
rc = -EBADF;
goto reopen_error_exit;
@@ -477,7 +478,7 @@
inode = file->f_path.dentry->d_inode;
if (inode == NULL) {
- cERROR(1, ("inode not valid"));
+ cERROR(1, "inode not valid");
dump_stack();
rc = -EBADF;
goto reopen_error_exit;
@@ -499,8 +500,8 @@
return rc;
}
- cFYI(1, ("inode = 0x%p file flags 0x%x for %s",
- inode, file->f_flags, full_path));
+ cFYI(1, "inode = 0x%p file flags 0x%x for %s",
+ inode, file->f_flags, full_path);
if (oplockEnabled)
oplock = REQ_OPLOCK;
@@ -513,10 +514,11 @@
int oflags = (int) cifs_posix_convert_flags(file->f_flags);
/* can not refresh inode info since size could be stale */
rc = cifs_posix_open(full_path, NULL, file->f_path.mnt,
- cifs_sb->mnt_file_mode /* ignored */,
- oflags, &oplock, &netfid, xid);
+ inode->i_sb,
+ cifs_sb->mnt_file_mode /* ignored */,
+ oflags, &oplock, &netfid, xid);
if (rc == 0) {
- cFYI(1, ("posix reopen succeeded"));
+ cFYI(1, "posix reopen succeeded");
goto reopen_success;
}
/* fallthrough to retry open the old way on errors, especially
@@ -537,8 +539,8 @@
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
mutex_unlock(&pCifsFile->fh_mutex);
- cFYI(1, ("cifs_open returned 0x%x", rc));
- cFYI(1, ("oplock: %d", oplock));
+ cFYI(1, "cifs_open returned 0x%x", rc);
+ cFYI(1, "oplock: %d", oplock);
} else {
reopen_success:
pCifsFile->netfid = netfid;
@@ -570,8 +572,8 @@
if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = true;
pCifsInode->clientCanCacheRead = true;
- cFYI(1, ("Exclusive Oplock granted on inode %p",
- file->f_path.dentry->d_inode));
+ cFYI(1, "Exclusive Oplock granted on inode %p",
+ file->f_path.dentry->d_inode);
} else if ((oplock & 0xF) == OPLOCK_READ) {
pCifsInode->clientCanCacheRead = true;
pCifsInode->clientCanCacheAll = false;
@@ -619,8 +621,7 @@
the struct would be in each open file,
but this should give enough time to
clear the socket */
- cFYI(DBG2,
- ("close delay, write pending"));
+ cFYI(DBG2, "close delay, write pending");
msleep(timeout);
timeout *= 4;
}
@@ -653,7 +654,7 @@
read_lock(&GlobalSMBSeslock);
if (list_empty(&(CIFS_I(inode)->openFileList))) {
- cFYI(1, ("closing last open instance for inode %p", inode));
+ cFYI(1, "closing last open instance for inode %p", inode);
/* if the file is not open we do not know if we can cache info
on this inode, much less write behind and read ahead */
CIFS_I(inode)->clientCanCacheRead = false;
@@ -674,7 +675,7 @@
(struct cifsFileInfo *)file->private_data;
char *ptmp;
- cFYI(1, ("Closedir inode = 0x%p", inode));
+ cFYI(1, "Closedir inode = 0x%p", inode);
xid = GetXid();
@@ -685,22 +686,22 @@
pTcon = cifs_sb->tcon;
- cFYI(1, ("Freeing private data in close dir"));
+ cFYI(1, "Freeing private data in close dir");
write_lock(&GlobalSMBSeslock);
if (!pCFileStruct->srch_inf.endOfSearch &&
!pCFileStruct->invalidHandle) {
pCFileStruct->invalidHandle = true;
write_unlock(&GlobalSMBSeslock);
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
- cFYI(1, ("Closing uncompleted readdir with rc %d",
- rc));
+ cFYI(1, "Closing uncompleted readdir with rc %d",
+ rc);
/* not much we can do if it fails anyway, ignore rc */
rc = 0;
} else
write_unlock(&GlobalSMBSeslock);
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
if (ptmp) {
- cFYI(1, ("closedir free smb buf in srch struct"));
+ cFYI(1, "closedir free smb buf in srch struct");
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
if (pCFileStruct->srch_inf.smallBuf)
cifs_small_buf_release(ptmp);
@@ -748,49 +749,49 @@
rc = -EACCES;
xid = GetXid();
- cFYI(1, ("Lock parm: 0x%x flockflags: "
+ cFYI(1, "Lock parm: 0x%x flockflags: "
"0x%x flocktype: 0x%x start: %lld end: %lld",
cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
- pfLock->fl_end));
+ pfLock->fl_end);
if (pfLock->fl_flags & FL_POSIX)
- cFYI(1, ("Posix"));
+ cFYI(1, "Posix");
if (pfLock->fl_flags & FL_FLOCK)
- cFYI(1, ("Flock"));
+ cFYI(1, "Flock");
if (pfLock->fl_flags & FL_SLEEP) {
- cFYI(1, ("Blocking lock"));
+ cFYI(1, "Blocking lock");
wait_flag = true;
}
if (pfLock->fl_flags & FL_ACCESS)
- cFYI(1, ("Process suspended by mandatory locking - "
- "not implemented yet"));
+ cFYI(1, "Process suspended by mandatory locking - "
+ "not implemented yet");
if (pfLock->fl_flags & FL_LEASE)
- cFYI(1, ("Lease on file - not implemented yet"));
+ cFYI(1, "Lease on file - not implemented yet");
if (pfLock->fl_flags &
(~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
- cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
+ cFYI(1, "Unknown lock flags 0x%x", pfLock->fl_flags);
if (pfLock->fl_type == F_WRLCK) {
- cFYI(1, ("F_WRLCK "));
+ cFYI(1, "F_WRLCK ");
numLock = 1;
} else if (pfLock->fl_type == F_UNLCK) {
- cFYI(1, ("F_UNLCK"));
+ cFYI(1, "F_UNLCK");
numUnlock = 1;
/* Check if unlock includes more than
one lock range */
} else if (pfLock->fl_type == F_RDLCK) {
- cFYI(1, ("F_RDLCK"));
+ cFYI(1, "F_RDLCK");
lockType |= LOCKING_ANDX_SHARED_LOCK;
numLock = 1;
} else if (pfLock->fl_type == F_EXLCK) {
- cFYI(1, ("F_EXLCK"));
+ cFYI(1, "F_EXLCK");
numLock = 1;
} else if (pfLock->fl_type == F_SHLCK) {
- cFYI(1, ("F_SHLCK"));
+ cFYI(1, "F_SHLCK");
lockType |= LOCKING_ANDX_SHARED_LOCK;
numLock = 1;
} else
- cFYI(1, ("Unknown type of lock"));
+ cFYI(1, "Unknown type of lock");
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
tcon = cifs_sb->tcon;
@@ -833,8 +834,8 @@
0 /* wait flag */ );
pfLock->fl_type = F_UNLCK;
if (rc != 0)
- cERROR(1, ("Error unlocking previously locked "
- "range %d during test of lock", rc));
+ cERROR(1, "Error unlocking previously locked "
+ "range %d during test of lock", rc);
rc = 0;
} else {
@@ -856,9 +857,9 @@
0 /* wait flag */);
pfLock->fl_type = F_RDLCK;
if (rc != 0)
- cERROR(1, ("Error unlocking "
+ cERROR(1, "Error unlocking "
"previously locked range %d "
- "during test of lock", rc));
+ "during test of lock", rc);
rc = 0;
} else {
pfLock->fl_type = F_WRLCK;
@@ -923,9 +924,10 @@
1, 0, li->type, false);
if (stored_rc)
rc = stored_rc;
-
- list_del(&li->llist);
- kfree(li);
+ else {
+ list_del(&li->llist);
+ kfree(li);
+ }
}
}
mutex_unlock(&fid->lock_mutex);
@@ -988,9 +990,8 @@
pTcon = cifs_sb->tcon;
- /* cFYI(1,
- (" write %d bytes to offset %lld of %s", write_size,
- *poffset, file->f_path.dentry->d_name.name)); */
+ /* cFYI(1, " write %d bytes to offset %lld of %s", write_size,
+ *poffset, file->f_path.dentry->d_name.name); */
if (file->private_data == NULL)
return -EBADF;
@@ -1091,8 +1092,8 @@
pTcon = cifs_sb->tcon;
- cFYI(1, ("write %zd bytes to offset %lld of %s", write_size,
- *poffset, file->f_path.dentry->d_name.name));
+ cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
+ *poffset, file->f_path.dentry->d_name.name);
if (file->private_data == NULL)
return -EBADF;
@@ -1233,7 +1234,7 @@
it being zero) during stress testcases so we need to check for it */
if (cifs_inode == NULL) {
- cERROR(1, ("Null inode passed to cifs_writeable_file"));
+ cERROR(1, "Null inode passed to cifs_writeable_file");
dump_stack();
return NULL;
}
@@ -1277,7 +1278,7 @@
again. Note that it would be bad
to hold up writepages here (rather than
in caller) with continuous retries */
- cFYI(1, ("wp failed on reopen file"));
+ cFYI(1, "wp failed on reopen file");
read_lock(&GlobalSMBSeslock);
/* can not use this handle, no write
pending on this one after all */
@@ -1353,7 +1354,7 @@
else if (bytes_written < 0)
rc = bytes_written;
} else {
- cFYI(1, ("No writeable filehandles for inode"));
+ cFYI(1, "No writeable filehandles for inode");
rc = -EIO;
}
@@ -1525,7 +1526,7 @@
*/
open_file = find_writable_file(CIFS_I(mapping->host));
if (!open_file) {
- cERROR(1, ("No writable handles for inode"));
+ cERROR(1, "No writable handles for inode");
rc = -EBADF;
} else {
long_op = cifs_write_timeout(cifsi, offset);
@@ -1538,8 +1539,8 @@
cifs_update_eof(cifsi, offset, bytes_written);
if (rc || bytes_written < bytes_to_write) {
- cERROR(1, ("Write2 ret %d, wrote %d",
- rc, bytes_written));
+ cERROR(1, "Write2 ret %d, wrote %d",
+ rc, bytes_written);
/* BB what if continued retry is
requested via mount flags? */
if (rc == -ENOSPC)
@@ -1600,7 +1601,7 @@
/* BB add check for wbc flags */
page_cache_get(page);
if (!PageUptodate(page))
- cFYI(1, ("ppw - page not up to date"));
+ cFYI(1, "ppw - page not up to date");
/*
* Set the "writeback" flag, and clear "dirty" in the radix tree.
@@ -1629,8 +1630,8 @@
int rc;
struct inode *inode = mapping->host;
- cFYI(1, ("write_end for page %p from pos %lld with %d bytes",
- page, pos, copied));
+ cFYI(1, "write_end for page %p from pos %lld with %d bytes",
+ page, pos, copied);
if (PageChecked(page)) {
if (copied == len)
@@ -1686,8 +1687,8 @@
xid = GetXid();
- cFYI(1, ("Sync file - name: %s datasync: 0x%x",
- dentry->d_name.name, datasync));
+ cFYI(1, "Sync file - name: %s datasync: 0x%x",
+ dentry->d_name.name, datasync);
rc = filemap_write_and_wait(inode->i_mapping);
if (rc == 0) {
@@ -1711,7 +1712,7 @@
unsigned int rpages = 0;
int rc = 0;
- cFYI(1, ("sync page %p",page));
+ cFYI(1, "sync page %p", page);
mapping = page->mapping;
if (!mapping)
return 0;
@@ -1722,7 +1723,7 @@
/* fill in rpages then
result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
-/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index));
+/* cFYI(1, "rpages is %d for sync page of Index %ld", rpages, index);
#if 0
if (rc < 0)
@@ -1756,7 +1757,7 @@
CIFS_I(inode)->write_behind_rc = 0;
}
- cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc));
+ cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc);
return rc;
}
@@ -1788,7 +1789,7 @@
open_file = (struct cifsFileInfo *)file->private_data;
if ((file->f_flags & O_ACCMODE) == O_WRONLY)
- cFYI(1, ("attempting read on write only file instance"));
+ cFYI(1, "attempting read on write only file instance");
for (total_read = 0, current_offset = read_data;
read_size > total_read;
@@ -1869,7 +1870,7 @@
open_file = (struct cifsFileInfo *)file->private_data;
if ((file->f_flags & O_ACCMODE) == O_WRONLY)
- cFYI(1, ("attempting read on write only file instance"));
+ cFYI(1, "attempting read on write only file instance");
for (total_read = 0, current_offset = read_data;
read_size > total_read;
@@ -1920,7 +1921,7 @@
xid = GetXid();
rc = cifs_revalidate_file(file);
if (rc) {
- cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
+ cFYI(1, "Validation prior to mmap failed, error=%d", rc);
FreeXid(xid);
return rc;
}
@@ -1931,8 +1932,7 @@
static void cifs_copy_cache_pages(struct address_space *mapping,
- struct list_head *pages, int bytes_read, char *data,
- struct pagevec *plru_pvec)
+ struct list_head *pages, int bytes_read, char *data)
{
struct page *page;
char *target;
@@ -1944,10 +1944,10 @@
page = list_entry(pages->prev, struct page, lru);
list_del(&page->lru);
- if (add_to_page_cache(page, mapping, page->index,
+ if (add_to_page_cache_lru(page, mapping, page->index,
GFP_KERNEL)) {
page_cache_release(page);
- cFYI(1, ("Add page cache failed"));
+ cFYI(1, "Add page cache failed");
data += PAGE_CACHE_SIZE;
bytes_read -= PAGE_CACHE_SIZE;
continue;
@@ -1970,8 +1970,6 @@
flush_dcache_page(page);
SetPageUptodate(page);
unlock_page(page);
- if (!pagevec_add(plru_pvec, page))
- __pagevec_lru_add_file(plru_pvec);
data += PAGE_CACHE_SIZE;
}
return;
@@ -1990,7 +1988,6 @@
unsigned int read_size, i;
char *smb_read_data = NULL;
struct smb_com_read_rsp *pSMBr;
- struct pagevec lru_pvec;
struct cifsFileInfo *open_file;
int buf_type = CIFS_NO_BUFFER;
@@ -2004,8 +2001,7 @@
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
- pagevec_init(&lru_pvec, 0);
- cFYI(DBG2, ("rpages: num pages %d", num_pages));
+ cFYI(DBG2, "rpages: num pages %d", num_pages);
for (i = 0; i < num_pages; ) {
unsigned contig_pages;
struct page *tmp_page;
@@ -2038,8 +2034,8 @@
/* Read size needs to be in multiples of one page */
read_size = min_t(const unsigned int, read_size,
cifs_sb->rsize & PAGE_CACHE_MASK);
- cFYI(DBG2, ("rpages: read size 0x%x contiguous pages %d",
- read_size, contig_pages));
+ cFYI(DBG2, "rpages: read size 0x%x contiguous pages %d",
+ read_size, contig_pages);
rc = -EAGAIN;
while (rc == -EAGAIN) {
if ((open_file->invalidHandle) &&
@@ -2066,14 +2062,14 @@
}
}
if ((rc < 0) || (smb_read_data == NULL)) {
- cFYI(1, ("Read error in readpages: %d", rc));
+ cFYI(1, "Read error in readpages: %d", rc);
break;
} else if (bytes_read > 0) {
task_io_account_read(bytes_read);
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
cifs_copy_cache_pages(mapping, page_list, bytes_read,
smb_read_data + 4 /* RFC1001 hdr */ +
- le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
+ le16_to_cpu(pSMBr->DataOffset));
i += bytes_read >> PAGE_CACHE_SHIFT;
cifs_stats_bytes_read(pTcon, bytes_read);
@@ -2089,9 +2085,9 @@
/* break; */
}
} else {
- cFYI(1, ("No bytes read (%d) at offset %lld . "
- "Cleaning remaining pages from readahead list",
- bytes_read, offset));
+ cFYI(1, "No bytes read (%d) at offset %lld . "
+ "Cleaning remaining pages from readahead list",
+ bytes_read, offset);
/* BB turn off caching and do new lookup on
file size at server? */
break;
@@ -2106,8 +2102,6 @@
bytes_read = 0;
}
- pagevec_lru_add_file(&lru_pvec);
-
/* need to free smb_read_data buf before exit */
if (smb_read_data) {
if (buf_type == CIFS_SMALL_BUFFER)
@@ -2136,7 +2130,7 @@
if (rc < 0)
goto io_error;
else
- cFYI(1, ("Bytes read %d", rc));
+ cFYI(1, "Bytes read %d", rc);
file->f_path.dentry->d_inode->i_atime =
current_fs_time(file->f_path.dentry->d_inode->i_sb);
@@ -2168,8 +2162,8 @@
return rc;
}
- cFYI(1, ("readpage %p at offset %d 0x%x\n",
- page, (int)offset, (int)offset));
+ cFYI(1, "readpage %p at offset %d 0x%x\n",
+ page, (int)offset, (int)offset);
rc = cifs_readpage_worker(file, page, &offset);
@@ -2239,7 +2233,7 @@
struct page *page;
int rc = 0;
- cFYI(1, ("write_begin from %lld len %d", (long long)pos, len));
+ cFYI(1, "write_begin from %lld len %d", (long long)pos, len);
page = grab_cache_page_write_begin(mapping, index, flags);
if (!page) {
@@ -2311,12 +2305,10 @@
int rc, waitrc = 0;
if (inode && S_ISREG(inode->i_mode)) {
-#ifdef CONFIG_CIFS_EXPERIMENTAL
- if (cinode->clientCanCacheAll == 0)
+ if (cinode->clientCanCacheRead)
break_lease(inode, O_RDONLY);
- else if (cinode->clientCanCacheRead == 0)
+ else
break_lease(inode, O_WRONLY);
-#endif
rc = filemap_fdatawrite(inode->i_mapping);
if (cinode->clientCanCacheRead == 0) {
waitrc = filemap_fdatawait(inode->i_mapping);
@@ -2326,7 +2318,7 @@
rc = waitrc;
if (rc)
cinode->write_behind_rc = rc;
- cFYI(1, ("Oplock flush inode %p rc %d", inode, rc));
+ cFYI(1, "Oplock flush inode %p rc %d", inode, rc);
}
/*
@@ -2338,7 +2330,7 @@
if (!cfile->closePend && !cfile->oplock_break_cancelled) {
rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0,
LOCKING_ANDX_OPLOCK_RELEASE, false);
- cFYI(1, ("Oplock release rc = %d", rc));
+ cFYI(1, "Oplock release rc = %d", rc);
}
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 35ec117..62b324f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/inode.c
*
- * Copyright (C) International Business Machines Corp., 2002,2008
+ * Copyright (C) International Business Machines Corp., 2002,2010
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -86,30 +86,30 @@
{
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
- cFYI(1, ("%s: revalidating inode %llu", __func__, cifs_i->uniqueid));
+ cFYI(1, "%s: revalidating inode %llu", __func__, cifs_i->uniqueid);
if (inode->i_state & I_NEW) {
- cFYI(1, ("%s: inode %llu is new", __func__, cifs_i->uniqueid));
+ cFYI(1, "%s: inode %llu is new", __func__, cifs_i->uniqueid);
return;
}
/* don't bother with revalidation if we have an oplock */
if (cifs_i->clientCanCacheRead) {
- cFYI(1, ("%s: inode %llu is oplocked", __func__,
- cifs_i->uniqueid));
+ cFYI(1, "%s: inode %llu is oplocked", __func__,
+ cifs_i->uniqueid);
return;
}
/* revalidate if mtime or size have changed */
if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
cifs_i->server_eof == fattr->cf_eof) {
- cFYI(1, ("%s: inode %llu is unchanged", __func__,
- cifs_i->uniqueid));
+ cFYI(1, "%s: inode %llu is unchanged", __func__,
+ cifs_i->uniqueid);
return;
}
- cFYI(1, ("%s: invalidating inode %llu mapping", __func__,
- cifs_i->uniqueid));
+ cFYI(1, "%s: invalidating inode %llu mapping", __func__,
+ cifs_i->uniqueid);
cifs_i->invalid_mapping = true;
}
@@ -137,15 +137,14 @@
inode->i_mode = fattr->cf_mode;
cifs_i->cifsAttrs = fattr->cf_cifsattrs;
- cifs_i->uniqueid = fattr->cf_uniqueid;
if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
cifs_i->time = 0;
else
cifs_i->time = jiffies;
- cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
- oldtime, cifs_i->time));
+ cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode,
+ oldtime, cifs_i->time);
cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
@@ -170,6 +169,17 @@
cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL);
}
+void
+cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+ return;
+
+ fattr->cf_uniqueid = iunique(sb, ROOT_I);
+}
+
/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
void
cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
@@ -227,7 +237,7 @@
/* safest to call it a file if we do not know */
fattr->cf_mode |= S_IFREG;
fattr->cf_dtype = DT_REG;
- cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
+ cFYI(1, "unknown type %d", le32_to_cpu(info->Type));
break;
}
@@ -256,7 +266,7 @@
{
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- cFYI(1, ("creating fake fattr for DFS referral"));
+ cFYI(1, "creating fake fattr for DFS referral");
memset(fattr, 0, sizeof(*fattr));
fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
@@ -305,7 +315,7 @@
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
tcon = cifs_sb->tcon;
- cFYI(1, ("Getting info on %s", full_path));
+ cFYI(1, "Getting info on %s", full_path);
/* could have done a find first instead but this returns more info */
rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
@@ -323,6 +333,7 @@
if (*pinode == NULL) {
/* get new inode */
+ cifs_fill_uniqueid(sb, &fattr);
*pinode = cifs_iget(sb, &fattr);
if (!*pinode)
rc = -ENOMEM;
@@ -373,7 +384,7 @@
&bytes_read, &pbuf, &buf_type);
if ((rc == 0) && (bytes_read >= 8)) {
if (memcmp("IntxBLK", pbuf, 8) == 0) {
- cFYI(1, ("Block device"));
+ cFYI(1, "Block device");
fattr->cf_mode |= S_IFBLK;
fattr->cf_dtype = DT_BLK;
if (bytes_read == 24) {
@@ -385,7 +396,7 @@
fattr->cf_rdev = MKDEV(mjr, mnr);
}
} else if (memcmp("IntxCHR", pbuf, 8) == 0) {
- cFYI(1, ("Char device"));
+ cFYI(1, "Char device");
fattr->cf_mode |= S_IFCHR;
fattr->cf_dtype = DT_CHR;
if (bytes_read == 24) {
@@ -397,7 +408,7 @@
fattr->cf_rdev = MKDEV(mjr, mnr);
}
} else if (memcmp("IntxLNK", pbuf, 7) == 0) {
- cFYI(1, ("Symlink"));
+ cFYI(1, "Symlink");
fattr->cf_mode |= S_IFLNK;
fattr->cf_dtype = DT_LNK;
} else {
@@ -439,10 +450,10 @@
else if (rc > 3) {
mode = le32_to_cpu(*((__le32 *)ea_value));
fattr->cf_mode &= ~SFBITS_MASK;
- cFYI(1, ("special bits 0%o org mode 0%o", mode,
- fattr->cf_mode));
+ cFYI(1, "special bits 0%o org mode 0%o", mode,
+ fattr->cf_mode);
fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
- cFYI(1, ("special mode bits 0%o", mode));
+ cFYI(1, "special mode bits 0%o", mode);
}
return 0;
@@ -548,11 +559,11 @@
struct cifs_fattr fattr;
pTcon = cifs_sb->tcon;
- cFYI(1, ("Getting info on %s", full_path));
+ cFYI(1, "Getting info on %s", full_path);
if ((pfindData == NULL) && (*pinode != NULL)) {
if (CIFS_I(*pinode)->clientCanCacheRead) {
- cFYI(1, ("No need to revalidate cached inode sizes"));
+ cFYI(1, "No need to revalidate cached inode sizes");
return rc;
}
}
@@ -618,7 +629,7 @@
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc1 || !fattr.cf_uniqueid) {
- cFYI(1, ("GetSrvInodeNum rc %d", rc1));
+ cFYI(1, "GetSrvInodeNum rc %d", rc1);
fattr.cf_uniqueid = iunique(sb, ROOT_I);
cifs_autodisable_serverino(cifs_sb);
}
@@ -634,13 +645,13 @@
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
if (tmprc)
- cFYI(1, ("cifs_sfu_type failed: %d", tmprc));
+ cFYI(1, "cifs_sfu_type failed: %d", tmprc);
}
#ifdef CONFIG_CIFS_EXPERIMENTAL
/* fill in 0777 bits from ACL */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
- cFYI(1, ("Getting mode bits from ACL"));
+ cFYI(1, "Getting mode bits from ACL");
cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
}
#endif
@@ -715,6 +726,16 @@
if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
return 0;
+ /*
+ * uh oh -- it's a directory. We can't use it since hardlinked dirs are
+ * verboten. Disable serverino and return it as if it were found, the
+ * caller can discard it, generate a uniqueid and retry the find
+ */
+ if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) {
+ fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
+ cifs_autodisable_serverino(CIFS_SB(inode->i_sb));
+ }
+
return 1;
}
@@ -734,15 +755,22 @@
unsigned long hash;
struct inode *inode;
- cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
+retry_iget5_locked:
+ cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid);
/* hash down to 32-bits on 32-bit arch */
hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
-
- /* we have fattrs in hand, update the inode */
if (inode) {
+ /* was there a problematic inode number collision? */
+ if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
+ iput(inode);
+ fattr->cf_uniqueid = iunique(sb, ROOT_I);
+ fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
+ goto retry_iget5_locked;
+ }
+
cifs_fattr_to_inode(inode, fattr);
if (sb->s_flags & MS_NOATIME)
inode->i_flags |= S_NOATIME | S_NOCMTIME;
@@ -780,7 +808,7 @@
return ERR_PTR(-ENOMEM);
if (rc && cifs_sb->tcon->ipc) {
- cFYI(1, ("ipc connection - fake read inode"));
+ cFYI(1, "ipc connection - fake read inode");
inode->i_mode |= S_IFDIR;
inode->i_nlink = 2;
inode->i_op = &cifs_ipc_inode_ops;
@@ -842,7 +870,7 @@
* server times.
*/
if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
- cFYI(1, ("CIFS - CTIME changed"));
+ cFYI(1, "CIFS - CTIME changed");
info_buf.ChangeTime =
cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
} else
@@ -877,8 +905,8 @@
goto out;
}
- cFYI(1, ("calling SetFileInfo since SetPathInfo for "
- "times not supported by this server"));
+ cFYI(1, "calling SetFileInfo since SetPathInfo for "
+ "times not supported by this server");
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
CREATE_NOT_DIR, &netfid, &oplock,
@@ -1036,7 +1064,7 @@
struct iattr *attrs = NULL;
__u32 dosattr = 0, origattr = 0;
- cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry));
+ cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
xid = GetXid();
@@ -1055,7 +1083,7 @@
rc = CIFSPOSIXDelFile(xid, tcon, full_path,
SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
- cFYI(1, ("posix del rc %d", rc));
+ cFYI(1, "posix del rc %d", rc);
if ((rc == 0) || (rc == -ENOENT))
goto psx_del_no_retry;
}
@@ -1129,7 +1157,7 @@
struct inode *newinode = NULL;
struct cifs_fattr fattr;
- cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
+ cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode);
xid = GetXid();
@@ -1164,7 +1192,7 @@
kfree(pInfo);
goto mkdir_retry_old;
} else if (rc) {
- cFYI(1, ("posix mkdir returned 0x%x", rc));
+ cFYI(1, "posix mkdir returned 0x%x", rc);
d_drop(direntry);
} else {
if (pInfo->Type == cpu_to_le32(-1)) {
@@ -1181,6 +1209,7 @@
direntry->d_op = &cifs_dentry_ops;
cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
+ cifs_fill_uniqueid(inode->i_sb, &fattr);
newinode = cifs_iget(inode->i_sb, &fattr);
if (!newinode) {
kfree(pInfo);
@@ -1190,12 +1219,12 @@
d_instantiate(direntry, newinode);
#ifdef CONFIG_CIFS_DEBUG2
- cFYI(1, ("instantiated dentry %p %s to inode %p",
- direntry, direntry->d_name.name, newinode));
+ cFYI(1, "instantiated dentry %p %s to inode %p",
+ direntry, direntry->d_name.name, newinode);
if (newinode->i_nlink != 2)
- cFYI(1, ("unexpected number of links %d",
- newinode->i_nlink));
+ cFYI(1, "unexpected number of links %d",
+ newinode->i_nlink);
#endif
}
kfree(pInfo);
@@ -1206,7 +1235,7 @@
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc) {
- cFYI(1, ("cifs_mkdir returned 0x%x", rc));
+ cFYI(1, "cifs_mkdir returned 0x%x", rc);
d_drop(direntry);
} else {
mkdir_get_info:
@@ -1309,7 +1338,7 @@
char *full_path = NULL;
struct cifsInodeInfo *cifsInode;
- cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
+ cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
xid = GetXid();
@@ -1511,6 +1540,11 @@
if (time_after_eq(jiffies, cifs_i->time + HZ))
return true;
+ /* hardlinked files w/ noserverino get "special" treatment */
+ if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
+ S_ISREG(inode->i_mode) && inode->i_nlink != 1)
+ return true;
+
return false;
}
@@ -1577,9 +1611,9 @@
goto check_inval;
}
- cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
+ cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
"jiffies %ld", full_path, inode, inode->i_count.counter,
- dentry, dentry->d_time, jiffies));
+ dentry, dentry->d_time, jiffies);
if (CIFS_SB(sb)->tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
@@ -1673,12 +1707,12 @@
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
npid, false);
cifsFileInfo_put(open_file);
- cFYI(1, ("SetFSize for attrs rc = %d", rc));
+ cFYI(1, "SetFSize for attrs rc = %d", rc);
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL, 1);
- cFYI(1, ("Wrt seteof rc %d", rc));
+ cFYI(1, "Wrt seteof rc %d", rc);
}
} else
rc = -EINVAL;
@@ -1692,7 +1726,7 @@
false, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
+ cFYI(1, "SetEOF by path (setattrs) rc = %d", rc);
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid;
int oplock = 0;
@@ -1709,7 +1743,7 @@
attrs->ia_size,
&bytes_written, NULL,
NULL, 1);
- cFYI(1, ("wrt seteof rc %d", rc));
+ cFYI(1, "wrt seteof rc %d", rc);
CIFSSMBClose(xid, pTcon, netfid);
}
}
@@ -1737,8 +1771,8 @@
struct cifs_unix_set_info_args *args = NULL;
struct cifsFileInfo *open_file;
- cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
- direntry->d_name.name, attrs->ia_valid));
+ cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x",
+ direntry->d_name.name, attrs->ia_valid);
xid = GetXid();
@@ -1868,8 +1902,8 @@
xid = GetXid();
- cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
- direntry->d_name.name, attrs->ia_valid));
+ cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
+ direntry->d_name.name, attrs->ia_valid);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
/* check if we have permission to change attrs */
@@ -1926,7 +1960,7 @@
attrs->ia_valid &= ~ATTR_MODE;
if (attrs->ia_valid & ATTR_MODE) {
- cFYI(1, ("Mode changed to 0%o", attrs->ia_mode));
+ cFYI(1, "Mode changed to 0%o", attrs->ia_mode);
mode = attrs->ia_mode;
}
@@ -2012,7 +2046,7 @@
#if 0
void cifs_delete_inode(struct inode *inode)
{
- cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
+ cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode);
/* may have to add back in if and when safe distributed caching of
directories added e.g. via FindNotify */
}
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index f946506..505926f 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -47,7 +47,7 @@
xid = GetXid();
- cFYI(1, ("ioctl file %p cmd %u arg %lu", filep, command, arg));
+ cFYI(1, "ioctl file %p cmd %u arg %lu", filep, command, arg);
cifs_sb = CIFS_SB(inode->i_sb);
@@ -64,12 +64,12 @@
switch (command) {
case CIFS_IOC_CHECKUMOUNT:
- cFYI(1, ("User unmount attempted"));
+ cFYI(1, "User unmount attempted");
if (cifs_sb->mnt_uid == current_uid())
rc = 0;
else {
rc = -EACCES;
- cFYI(1, ("uids do not match"));
+ cFYI(1, "uids do not match");
}
break;
#ifdef CONFIG_CIFS_POSIX
@@ -97,11 +97,11 @@
/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
extAttrBits, &ExtAttrMask);*/
}
- cFYI(1, ("set flags not implemented yet"));
+ cFYI(1, "set flags not implemented yet");
break;
#endif /* CONFIG_CIFS_POSIX */
default:
- cFYI(1, ("unsupported ioctl"));
+ cFYI(1, "unsupported ioctl");
break;
}
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index c1a9d42..473ca80 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -139,7 +139,7 @@
if (!full_path)
goto out;
- cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
+ cFYI(1, "Full path: %s inode = 0x%p", full_path, inode);
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
cifs_sb->local_nls);
@@ -178,8 +178,8 @@
return rc;
}
- cFYI(1, ("Full path: %s", full_path));
- cFYI(1, ("symname is %s", symname));
+ cFYI(1, "Full path: %s", full_path);
+ cFYI(1, "symname is %s", symname);
/* BB what if DFS and this volume is on different share? BB */
if (pTcon->unix_ext)
@@ -198,8 +198,8 @@
inode->i_sb, xid, NULL);
if (rc != 0) {
- cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
- rc));
+ cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d",
+ rc);
} else {
if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index d147499..1394aa3 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -51,7 +51,7 @@
if (GlobalTotalActiveXid > GlobalMaxActiveXid)
GlobalMaxActiveXid = GlobalTotalActiveXid;
if (GlobalTotalActiveXid > 65000)
- cFYI(1, ("warning: more than 65000 requests active"));
+ cFYI(1, "warning: more than 65000 requests active");
xid = GlobalCurrentXid++;
spin_unlock(&GlobalMid_Lock);
return xid;
@@ -88,7 +88,7 @@
sesInfoFree(struct cifsSesInfo *buf_to_free)
{
if (buf_to_free == NULL) {
- cFYI(1, ("Null buffer passed to sesInfoFree"));
+ cFYI(1, "Null buffer passed to sesInfoFree");
return;
}
@@ -126,7 +126,7 @@
tconInfoFree(struct cifsTconInfo *buf_to_free)
{
if (buf_to_free == NULL) {
- cFYI(1, ("Null buffer passed to tconInfoFree"));
+ cFYI(1, "Null buffer passed to tconInfoFree");
return;
}
atomic_dec(&tconInfoAllocCount);
@@ -166,7 +166,7 @@
cifs_buf_release(void *buf_to_free)
{
if (buf_to_free == NULL) {
- /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
+ /* cFYI(1, "Null buffer passed to cifs_buf_release");*/
return;
}
mempool_free(buf_to_free, cifs_req_poolp);
@@ -202,7 +202,7 @@
{
if (buf_to_free == NULL) {
- cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
+ cFYI(1, "Null buffer passed to cifs_small_buf_release");
return;
}
mempool_free(buf_to_free, cifs_sm_req_poolp);
@@ -345,19 +345,19 @@
/* with userid/password pairs found on the smb session */
/* for other target tcp/ip addresses BB */
if (current_fsuid() != treeCon->ses->linux_uid) {
- cFYI(1, ("Multiuser mode and UID "
- "did not match tcon uid"));
+ cFYI(1, "Multiuser mode and UID "
+ "did not match tcon uid");
read_lock(&cifs_tcp_ses_lock);
list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
if (ses->linux_uid == current_fsuid()) {
if (ses->server == treeCon->ses->server) {
- cFYI(1, ("found matching uid substitute right smb_uid"));
+ cFYI(1, "found matching uid substitute right smb_uid");
buffer->Uid = ses->Suid;
break;
} else {
/* BB eventually call cifs_setup_session here */
- cFYI(1, ("local UID found but no smb sess with this server exists"));
+ cFYI(1, "local UID found but no smb sess with this server exists");
}
}
}
@@ -394,17 +394,16 @@
if (smb->Command == SMB_COM_LOCKING_ANDX)
return 0;
else
- cERROR(1, ("Received Request not response"));
+ cERROR(1, "Received Request not response");
}
} else { /* bad signature or mid */
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
- cERROR(1,
- ("Bad protocol string signature header %x",
- *(unsigned int *) smb->Protocol));
+ cERROR(1, "Bad protocol string signature header %x",
+ *(unsigned int *) smb->Protocol);
if (mid != smb->Mid)
- cERROR(1, ("Mids do not match"));
+ cERROR(1, "Mids do not match");
}
- cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
+ cERROR(1, "bad smb detected. The Mid=%d", smb->Mid);
return 1;
}
@@ -413,7 +412,7 @@
{
__u32 len = smb->smb_buf_length;
__u32 clc_len; /* calculated length */
- cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
+ cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len);
if (length < 2 + sizeof(struct smb_hdr)) {
if ((length >= sizeof(struct smb_hdr) - 1)
@@ -437,15 +436,15 @@
tmp[sizeof(struct smb_hdr)+1] = 0;
return 0;
}
- cERROR(1, ("rcvd invalid byte count (bcc)"));
+ cERROR(1, "rcvd invalid byte count (bcc)");
} else {
- cERROR(1, ("Length less than smb header size"));
+ cERROR(1, "Length less than smb header size");
}
return 1;
}
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
- cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
- smb->Mid));
+ cERROR(1, "smb length greater than MaxBufSize, mid=%d",
+ smb->Mid);
return 1;
}
@@ -454,8 +453,8 @@
clc_len = smbCalcSize_LE(smb);
if (4 + len != length) {
- cERROR(1, ("Length read does not match RFC1001 length %d",
- len));
+ cERROR(1, "Length read does not match RFC1001 length %d",
+ len);
return 1;
}
@@ -466,8 +465,8 @@
if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
return 0; /* bcc wrapped */
}
- cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
- clc_len, 4 + len, smb->Mid));
+ cFYI(1, "Calculated size %d vs length %d mismatch for mid %d",
+ clc_len, 4 + len, smb->Mid);
/* Windows XP can return a few bytes too much, presumably
an illegal pad, at the end of byte range lock responses
so we allow for that three byte pad, as long as actual
@@ -482,8 +481,8 @@
if ((4+len > clc_len) && (len <= clc_len + 512))
return 0;
else {
- cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
- len, smb->Mid));
+ cERROR(1, "RFC1001 size %d bigger than SMB for Mid=%d",
+ len, smb->Mid);
return 1;
}
}
@@ -501,7 +500,7 @@
struct cifsFileInfo *netfile;
int rc;
- cFYI(1, ("Checking for oplock break or dnotify response"));
+ cFYI(1, "Checking for oplock break or dnotify response");
if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
(pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
struct smb_com_transaction_change_notify_rsp *pSMBr =
@@ -513,15 +512,15 @@
pnotify = (struct file_notify_information *)
((char *)&pSMBr->hdr.Protocol + data_offset);
- cFYI(1, ("dnotify on %s Action: 0x%x",
- pnotify->FileName, pnotify->Action));
+ cFYI(1, "dnotify on %s Action: 0x%x",
+ pnotify->FileName, pnotify->Action);
/* cifs_dump_mem("Rcvd notify Data: ",buf,
sizeof(struct smb_hdr)+60); */
return true;
}
if (pSMBr->hdr.Status.CifsError) {
- cFYI(1, ("notify err 0x%d",
- pSMBr->hdr.Status.CifsError));
+ cFYI(1, "notify err 0x%d",
+ pSMBr->hdr.Status.CifsError);
return true;
}
return false;
@@ -535,7 +534,7 @@
large dirty files cached on the client */
if ((NT_STATUS_INVALID_HANDLE) ==
le32_to_cpu(pSMB->hdr.Status.CifsError)) {
- cFYI(1, ("invalid handle on oplock break"));
+ cFYI(1, "invalid handle on oplock break");
return true;
} else if (ERRbadfid ==
le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
@@ -547,8 +546,8 @@
if (pSMB->hdr.WordCount != 8)
return false;
- cFYI(1, ("oplock type 0x%d level 0x%d",
- pSMB->LockType, pSMB->OplockLevel));
+ cFYI(1, "oplock type 0x%d level 0x%d",
+ pSMB->LockType, pSMB->OplockLevel);
if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
return false;
@@ -579,15 +578,15 @@
return true;
}
- cFYI(1, ("file id match, oplock break"));
+ cFYI(1, "file id match, oplock break");
pCifsInode = CIFS_I(netfile->pInode);
pCifsInode->clientCanCacheAll = false;
if (pSMB->OplockLevel == 0)
pCifsInode->clientCanCacheRead = false;
rc = slow_work_enqueue(&netfile->oplock_break);
if (rc) {
- cERROR(1, ("failed to enqueue oplock "
- "break: %d\n", rc));
+ cERROR(1, "failed to enqueue oplock "
+ "break: %d\n", rc);
} else {
netfile->oplock_break_cancelled = false;
}
@@ -597,12 +596,12 @@
}
read_unlock(&GlobalSMBSeslock);
read_unlock(&cifs_tcp_ses_lock);
- cFYI(1, ("No matching file for oplock break"));
+ cFYI(1, "No matching file for oplock break");
return true;
}
}
read_unlock(&cifs_tcp_ses_lock);
- cFYI(1, ("Can not process oplock break for non-existent connection"));
+ cFYI(1, "Can not process oplock break for non-existent connection");
return true;
}
@@ -721,11 +720,11 @@
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
- cERROR(1, ("Autodisabling the use of server inode numbers on "
+ cERROR(1, "Autodisabling the use of server inode numbers on "
"%s. This server doesn't seem to support them "
"properly. Hardlinks will not be recognized on this "
"mount. Consider mounting with the \"noserverino\" "
"option to silence this message.",
- cifs_sb->tcon->treeName));
+ cifs_sb->tcon->treeName);
}
}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index bd6d689..d35d528 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -149,7 +149,7 @@
else if (address_family == AF_INET6)
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
- cFYI(DBG2, ("address conversion returned %d for %s", ret, cp));
+ cFYI(DBG2, "address conversion returned %d for %s", ret, cp);
if (ret > 0)
ret = 1;
return ret;
@@ -870,8 +870,8 @@
}
/* else ERRHRD class errors or junk - return EIO */
- cFYI(1, ("Mapping smb error code %d to POSIX err %d",
- smberrcode, rc));
+ cFYI(1, "Mapping smb error code %d to POSIX err %d",
+ smberrcode, rc);
/* generic corrective action e.g. reconnect SMB session on
* ERRbaduid could be added */
@@ -940,20 +940,20 @@
SMB_TIME *st = (SMB_TIME *)&time;
SMB_DATE *sd = (SMB_DATE *)&date;
- cFYI(1, ("date %d time %d", date, time));
+ cFYI(1, "date %d time %d", date, time);
sec = 2 * st->TwoSeconds;
min = st->Minutes;
if ((sec > 59) || (min > 59))
- cERROR(1, ("illegal time min %d sec %d", min, sec));
+ cERROR(1, "illegal time min %d sec %d", min, sec);
sec += (min * 60);
sec += 60 * 60 * st->Hours;
if (st->Hours > 24)
- cERROR(1, ("illegal hours %d", st->Hours));
+ cERROR(1, "illegal hours %d", st->Hours);
days = sd->Day;
month = sd->Month;
if ((days > 31) || (month > 12)) {
- cERROR(1, ("illegal date, month %d day: %d", month, days));
+ cERROR(1, "illegal date, month %d day: %d", month, days);
if (month > 12)
month = 12;
}
@@ -979,7 +979,7 @@
ts.tv_sec = sec + offset;
- /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */
+ /* cFYI(1, "sec after cnvrt dos to unix time %d",sec); */
ts.tv_nsec = 0;
return ts;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 18e0bc1..daf1753 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -47,15 +47,15 @@
if (file) {
cf = file->private_data;
if (cf == NULL) {
- cFYI(1, ("empty cifs private file data"));
+ cFYI(1, "empty cifs private file data");
return;
}
if (cf->invalidHandle)
- cFYI(1, ("invalid handle"));
+ cFYI(1, "invalid handle");
if (cf->srch_inf.endOfSearch)
- cFYI(1, ("end of search"));
+ cFYI(1, "end of search");
if (cf->srch_inf.emptyDir)
- cFYI(1, ("empty dir"));
+ cFYI(1, "empty dir");
}
}
#else
@@ -76,7 +76,7 @@
struct inode *inode;
struct super_block *sb = parent->d_inode->i_sb;
- cFYI(1, ("For %s", name->name));
+ cFYI(1, "For %s", name->name);
if (parent->d_op && parent->d_op->d_hash)
parent->d_op->d_hash(parent, name);
@@ -214,7 +214,7 @@
fid,
cifs_sb->local_nls);
if (CIFSSMBClose(xid, ptcon, fid)) {
- cFYI(1, ("Error closing temporary reparsepoint open)"));
+ cFYI(1, "Error closing temporary reparsepoint open");
}
}
}
@@ -252,7 +252,7 @@
if (full_path == NULL)
return -ENOMEM;
- cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos));
+ cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);
ffirst_retry:
/* test for Unix extensions */
@@ -297,7 +297,7 @@
if (ustr[len] == 0)
return len << 1;
}
- cFYI(1, ("Unicode string longer than PATH_MAX found"));
+ cFYI(1, "Unicode string longer than PATH_MAX found");
return len << 1;
}
@@ -314,19 +314,18 @@
pfData->FileNameLength;
} else
new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
- cFYI(1, ("new entry %p old entry %p", new_entry, old_entry));
+ cFYI(1, "new entry %p old entry %p", new_entry, old_entry);
/* validate that new_entry is not past end of SMB */
if (new_entry >= end_of_smb) {
- cERROR(1,
- ("search entry %p began after end of SMB %p old entry %p",
- new_entry, end_of_smb, old_entry));
+ cERROR(1, "search entry %p began after end of SMB %p old entry %p",
+ new_entry, end_of_smb, old_entry);
return NULL;
} else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
(new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
|| ((level != SMB_FIND_FILE_INFO_STANDARD) &&
(new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
- cERROR(1, ("search entry %p extends after end of SMB %p",
- new_entry, end_of_smb));
+ cERROR(1, "search entry %p extends after end of SMB %p",
+ new_entry, end_of_smb);
return NULL;
} else
return new_entry;
@@ -380,8 +379,8 @@
filename = &pFindData->FileName[0];
len = pFindData->FileNameLength;
} else {
- cFYI(1, ("Unknown findfirst level %d",
- cfile->srch_inf.info_level));
+ cFYI(1, "Unknown findfirst level %d",
+ cfile->srch_inf.info_level);
}
if (filename) {
@@ -481,7 +480,7 @@
len = (unsigned int)pFindData->FileNameLength;
cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
} else {
- cFYI(1, ("Unknown findfirst level %d", level));
+ cFYI(1, "Unknown findfirst level %d", level);
return -EINVAL;
}
cifsFile->srch_inf.resume_name_len = len;
@@ -525,7 +524,7 @@
is_dir_changed(file)) ||
(index_to_find < first_entry_in_buffer)) {
/* close and restart search */
- cFYI(1, ("search backing up - close and restart search"));
+ cFYI(1, "search backing up - close and restart search");
write_lock(&GlobalSMBSeslock);
if (!cifsFile->srch_inf.endOfSearch &&
!cifsFile->invalidHandle) {
@@ -535,7 +534,7 @@
} else
write_unlock(&GlobalSMBSeslock);
if (cifsFile->srch_inf.ntwrk_buf_start) {
- cFYI(1, ("freeing SMB ff cache buf on search rewind"));
+ cFYI(1, "freeing SMB ff cache buf on search rewind");
if (cifsFile->srch_inf.smallBuf)
cifs_small_buf_release(cifsFile->srch_inf.
ntwrk_buf_start);
@@ -546,8 +545,8 @@
}
rc = initiate_cifs_search(xid, file);
if (rc) {
- cFYI(1, ("error %d reinitiating a search on rewind",
- rc));
+ cFYI(1, "error %d reinitiating a search on rewind",
+ rc);
return rc;
}
cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
@@ -555,7 +554,7 @@
while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
(rc == 0) && !cifsFile->srch_inf.endOfSearch) {
- cFYI(1, ("calling findnext2"));
+ cFYI(1, "calling findnext2");
rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
&cifsFile->srch_inf);
cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
@@ -575,7 +574,7 @@
first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
- cifsFile->srch_inf.entries_in_buffer;
pos_in_buf = index_to_find - first_entry_in_buffer;
- cFYI(1, ("found entry - pos_in_buf %d", pos_in_buf));
+ cFYI(1, "found entry - pos_in_buf %d", pos_in_buf);
for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) {
/* go entry by entry figuring out which is first */
@@ -584,19 +583,19 @@
}
if ((current_entry == NULL) && (i < pos_in_buf)) {
/* BB fixme - check if we should flag this error */
- cERROR(1, ("reached end of buf searching for pos in buf"
+ cERROR(1, "reached end of buf searching for pos in buf"
" %d index to find %lld rc %d",
- pos_in_buf, index_to_find, rc));
+ pos_in_buf, index_to_find, rc);
}
rc = 0;
*ppCurrentEntry = current_entry;
} else {
- cFYI(1, ("index not in buffer - could not findnext into it"));
+ cFYI(1, "index not in buffer - could not findnext into it");
return 0;
}
if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
- cFYI(1, ("can not return entries pos_in_buf beyond last"));
+ cFYI(1, "can not return entries pos_in_buf beyond last");
*num_to_ret = 0;
} else
*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
@@ -656,12 +655,12 @@
/* one byte length, no name conversion */
len = (unsigned int)pFindData->FileNameLength;
} else {
- cFYI(1, ("Unknown findfirst level %d", level));
+ cFYI(1, "Unknown findfirst level %d", level);
return -EINVAL;
}
if (len > max_len) {
- cERROR(1, ("bad search response length %d past smb end", len));
+ cERROR(1, "bad search response length %d past smb end", len);
return -EINVAL;
}
@@ -754,7 +753,7 @@
* case already. Why should we be clobbering other errors from it?
*/
if (rc) {
- cFYI(1, ("filldir rc = %d", rc));
+ cFYI(1, "filldir rc = %d", rc);
rc = -EOVERFLOW;
}
dput(tmp_dentry);
@@ -786,7 +785,7 @@
case 0:
if (filldir(direntry, ".", 1, file->f_pos,
file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
- cERROR(1, ("Filldir for current dir failed"));
+ cERROR(1, "Filldir for current dir failed");
rc = -ENOMEM;
break;
}
@@ -794,7 +793,7 @@
case 1:
if (filldir(direntry, "..", 2, file->f_pos,
file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
- cERROR(1, ("Filldir for parent dir failed"));
+ cERROR(1, "Filldir for parent dir failed");
rc = -ENOMEM;
break;
}
@@ -807,7 +806,7 @@
if (file->private_data == NULL) {
rc = initiate_cifs_search(xid, file);
- cFYI(1, ("initiate cifs search rc %d", rc));
+ cFYI(1, "initiate cifs search rc %d", rc);
if (rc) {
FreeXid(xid);
return rc;
@@ -821,7 +820,7 @@
cifsFile = file->private_data;
if (cifsFile->srch_inf.endOfSearch) {
if (cifsFile->srch_inf.emptyDir) {
- cFYI(1, ("End of search, empty dir"));
+ cFYI(1, "End of search, empty dir");
rc = 0;
break;
}
@@ -833,16 +832,16 @@
rc = find_cifs_entry(xid, pTcon, file,
¤t_entry, &num_to_fill);
if (rc) {
- cFYI(1, ("fce error %d", rc));
+ cFYI(1, "fce error %d", rc);
goto rddir2_exit;
} else if (current_entry != NULL) {
- cFYI(1, ("entry %lld found", file->f_pos));
+ cFYI(1, "entry %lld found", file->f_pos);
} else {
- cFYI(1, ("could not find entry"));
+ cFYI(1, "could not find entry");
goto rddir2_exit;
}
- cFYI(1, ("loop through %d times filling dir for net buf %p",
- num_to_fill, cifsFile->srch_inf.ntwrk_buf_start));
+ cFYI(1, "loop through %d times filling dir for net buf %p",
+ num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
max_len = smbCalcSize((struct smb_hdr *)
cifsFile->srch_inf.ntwrk_buf_start);
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
@@ -851,8 +850,8 @@
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
if (current_entry == NULL) {
/* evaluate whether this case is an error */
- cERROR(1, ("past SMB end, num to fill %d i %d",
- num_to_fill, i));
+ cERROR(1, "past SMB end, num to fill %d i %d",
+ num_to_fill, i);
break;
}
/* if buggy server returns . and .. late do
@@ -867,8 +866,8 @@
file->f_pos++;
if (file->f_pos ==
cifsFile->srch_inf.index_of_last_entry) {
- cFYI(1, ("last entry in buf at pos %lld %s",
- file->f_pos, tmp_buf));
+ cFYI(1, "last entry in buf at pos %lld %s",
+ file->f_pos, tmp_buf);
cifs_save_resume_key(current_entry, cifsFile);
break;
} else
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7c3fd74..7707389 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -35,9 +35,11 @@
extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
unsigned char *p24);
-/* Checks if this is the first smb session to be reconnected after
- the socket has been reestablished (so we know whether to use vc 0).
- Called while holding the cifs_tcp_ses_lock, so do not block */
+/*
+ * Checks if this is the first smb session to be reconnected after
+ * the socket has been reestablished (so we know whether to use vc 0).
+ * Called while holding the cifs_tcp_ses_lock, so do not block
+ */
static bool is_first_ses_reconnect(struct cifsSesInfo *ses)
{
struct list_head *tmp;
@@ -284,7 +286,7 @@
int len;
char *data = *pbcc_area;
- cFYI(1, ("bleft %d", bleft));
+ cFYI(1, "bleft %d", bleft);
/*
* Windows servers do not always double null terminate their final
@@ -301,7 +303,7 @@
kfree(ses->serverOS);
ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
- cFYI(1, ("serverOS=%s", ses->serverOS));
+ cFYI(1, "serverOS=%s", ses->serverOS);
len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
data += len;
bleft -= len;
@@ -310,7 +312,7 @@
kfree(ses->serverNOS);
ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
- cFYI(1, ("serverNOS=%s", ses->serverNOS));
+ cFYI(1, "serverNOS=%s", ses->serverNOS);
len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
data += len;
bleft -= len;
@@ -319,7 +321,7 @@
kfree(ses->serverDomain);
ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
- cFYI(1, ("serverDomain=%s", ses->serverDomain));
+ cFYI(1, "serverDomain=%s", ses->serverDomain);
return;
}
@@ -332,7 +334,7 @@
int len;
char *bcc_ptr = *pbcc_area;
- cFYI(1, ("decode sessetup ascii. bleft %d", bleft));
+ cFYI(1, "decode sessetup ascii. bleft %d", bleft);
len = strnlen(bcc_ptr, bleft);
if (len >= bleft)
@@ -344,7 +346,7 @@
if (ses->serverOS)
strncpy(ses->serverOS, bcc_ptr, len);
if (strncmp(ses->serverOS, "OS/2", 4) == 0) {
- cFYI(1, ("OS/2 server"));
+ cFYI(1, "OS/2 server");
ses->flags |= CIFS_SES_OS2;
}
@@ -373,7 +375,7 @@
/* BB For newer servers which do not support Unicode,
but thus do return domain here we could add parsing
for it later, but it is not very important */
- cFYI(1, ("ascii: bytes left %d", bleft));
+ cFYI(1, "ascii: bytes left %d", bleft);
return rc;
}
@@ -384,16 +386,16 @@
CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
- cERROR(1, ("challenge blob len %d too small", blob_len));
+ cERROR(1, "challenge blob len %d too small", blob_len);
return -EINVAL;
}
if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
- cERROR(1, ("blob signature incorrect %s", pblob->Signature));
+ cERROR(1, "blob signature incorrect %s", pblob->Signature);
return -EINVAL;
}
if (pblob->MessageType != NtLmChallenge) {
- cERROR(1, ("Incorrect message type %d", pblob->MessageType));
+ cERROR(1, "Incorrect message type %d", pblob->MessageType);
return -EINVAL;
}
@@ -447,7 +449,7 @@
This function returns the length of the data in the blob */
static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
struct cifsSesInfo *ses,
- const struct nls_table *nls_cp, int first)
+ const struct nls_table *nls_cp, bool first)
{
AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
__u32 flags;
@@ -546,7 +548,7 @@
static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
struct cifsSesInfo *ses,
- const struct nls_table *nls, int first_time)
+ const struct nls_table *nls, bool first_time)
{
int bloblen;
@@ -559,8 +561,8 @@
#endif
int
-CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
- const struct nls_table *nls_cp)
+CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
+ const struct nls_table *nls_cp)
{
int rc = 0;
int wct;
@@ -577,13 +579,18 @@
int bytes_remaining;
struct key *spnego_key = NULL;
__le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
+ bool first_time;
if (ses == NULL)
return -EINVAL;
+ read_lock(&cifs_tcp_ses_lock);
+ first_time = is_first_ses_reconnect(ses);
+ read_unlock(&cifs_tcp_ses_lock);
+
type = ses->server->secType;
- cFYI(1, ("sess setup type %d", type));
+ cFYI(1, "sess setup type %d", type);
ssetup_ntlmssp_authenticate:
if (phase == NtLmChallenge)
phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
@@ -664,7 +671,7 @@
changed to do higher than lanman dialect and
we reconnected would we ever calc signing_key? */
- cFYI(1, ("Negotiating LANMAN setting up strings"));
+ cFYI(1, "Negotiating LANMAN setting up strings");
/* Unicode not allowed for LANMAN dialects */
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
#endif
@@ -744,7 +751,7 @@
unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
} else
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
- } else if (type == Kerberos || type == MSKerberos) {
+ } else if (type == Kerberos) {
#ifdef CONFIG_CIFS_UPCALL
struct cifs_spnego_msg *msg;
spnego_key = cifs_get_spnego_key(ses);
@@ -758,17 +765,17 @@
/* check version field to make sure that cifs.upcall is
sending us a response in an expected form */
if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
- cERROR(1, ("incorrect version of cifs.upcall (expected"
+ cERROR(1, "incorrect version of cifs.upcall (expected"
" %d but got %d)",
- CIFS_SPNEGO_UPCALL_VERSION, msg->version));
+ CIFS_SPNEGO_UPCALL_VERSION, msg->version);
rc = -EKEYREJECTED;
goto ssetup_exit;
}
/* bail out if key is too long */
if (msg->sesskey_len >
sizeof(ses->server->mac_signing_key.data.krb5)) {
- cERROR(1, ("Kerberos signing key too long (%u bytes)",
- msg->sesskey_len));
+ cERROR(1, "Kerberos signing key too long (%u bytes)",
+ msg->sesskey_len);
rc = -EOVERFLOW;
goto ssetup_exit;
}
@@ -796,7 +803,7 @@
/* BB: is this right? */
ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
#else /* ! CONFIG_CIFS_UPCALL */
- cERROR(1, ("Kerberos negotiated but upcall support disabled!"));
+ cERROR(1, "Kerberos negotiated but upcall support disabled!");
rc = -ENOSYS;
goto ssetup_exit;
#endif /* CONFIG_CIFS_UPCALL */
@@ -804,12 +811,12 @@
#ifdef CONFIG_CIFS_EXPERIMENTAL
if (type == RawNTLMSSP) {
if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
- cERROR(1, ("NTLMSSP requires Unicode support"));
+ cERROR(1, "NTLMSSP requires Unicode support");
rc = -ENOSYS;
goto ssetup_exit;
}
- cFYI(1, ("ntlmssp session setup phase %d", phase));
+ cFYI(1, "ntlmssp session setup phase %d", phase);
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
capabilities |= CAP_EXTENDED_SECURITY;
pSMB->req.Capabilities |= cpu_to_le32(capabilities);
@@ -827,7 +834,7 @@
on the response (challenge) */
smb_buf->Uid = ses->Suid;
} else {
- cERROR(1, ("invalid phase %d", phase));
+ cERROR(1, "invalid phase %d", phase);
rc = -ENOSYS;
goto ssetup_exit;
}
@@ -839,12 +846,12 @@
}
unicode_oslm_strings(&bcc_ptr, nls_cp);
} else {
- cERROR(1, ("secType %d not supported!", type));
+ cERROR(1, "secType %d not supported!", type);
rc = -ENOSYS;
goto ssetup_exit;
}
#else
- cERROR(1, ("secType %d not supported!", type));
+ cERROR(1, "secType %d not supported!", type);
rc = -ENOSYS;
goto ssetup_exit;
#endif
@@ -862,7 +869,7 @@
CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR);
/* SMB request buf freed in SendReceive2 */
- cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
+ cFYI(1, "ssetup rc from sendrecv2 is %d", rc);
pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
smb_buf = (struct smb_hdr *)iov[0].iov_base;
@@ -870,7 +877,7 @@
if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError ==
cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) {
if (phase != NtLmNegotiate) {
- cERROR(1, ("Unexpected more processing error"));
+ cERROR(1, "Unexpected more processing error");
goto ssetup_exit;
}
/* NTLMSSP Negotiate sent now processing challenge (response) */
@@ -882,14 +889,14 @@
if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
rc = -EIO;
- cERROR(1, ("bad word count %d", smb_buf->WordCount));
+ cERROR(1, "bad word count %d", smb_buf->WordCount);
goto ssetup_exit;
}
action = le16_to_cpu(pSMB->resp.Action);
if (action & GUEST_LOGIN)
- cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
+ cFYI(1, "Guest login"); /* BB mark SesInfo struct? */
ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
- cFYI(1, ("UID = %d ", ses->Suid));
+ cFYI(1, "UID = %d ", ses->Suid);
/* response can have either 3 or 4 word count - Samba sends 3 */
/* and lanman response is 3 */
bytes_remaining = BCC(smb_buf);
@@ -899,7 +906,7 @@
__u16 blob_len;
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
if (blob_len > bytes_remaining) {
- cERROR(1, ("bad security blob length %d", blob_len));
+ cERROR(1, "bad security blob length %d", blob_len);
rc = -EINVAL;
goto ssetup_exit;
}
@@ -933,7 +940,7 @@
}
kfree(str_area);
if (resp_buf_type == CIFS_SMALL_BUFFER) {
- cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base));
+ cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base);
cifs_small_buf_release(iov[0].iov_base);
} else if (resp_buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(iov[0].iov_base);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index ad081fe..82f78c4 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -35,7 +35,6 @@
#include "cifs_debug.h"
extern mempool_t *cifs_mid_poolp;
-extern struct kmem_cache *cifs_oplock_cachep;
static struct mid_q_entry *
AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
@@ -43,7 +42,7 @@
struct mid_q_entry *temp;
if (server == NULL) {
- cERROR(1, ("Null TCP session in AllocMidQEntry"));
+ cERROR(1, "Null TCP session in AllocMidQEntry");
return NULL;
}
@@ -55,7 +54,7 @@
temp->mid = smb_buffer->Mid; /* always LE */
temp->pid = current->pid;
temp->command = smb_buffer->Command;
- cFYI(1, ("For smb_command %d", temp->command));
+ cFYI(1, "For smb_command %d", temp->command);
/* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
/* when mid allocated can be before when sent */
temp->when_alloc = jiffies;
@@ -140,7 +139,7 @@
total_len += iov[i].iov_len;
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
- cFYI(1, ("Sending smb: total_len %d", total_len));
+ cFYI(1, "Sending smb: total_len %d", total_len);
dump_smb(smb_buffer, len);
i = 0;
@@ -168,9 +167,8 @@
reconnect which may clear the network problem.
*/
if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
- cERROR(1,
- ("sends on sock %p stuck for 15 seconds",
- ssocket));
+ cERROR(1, "sends on sock %p stuck for 15 seconds",
+ ssocket);
rc = -EAGAIN;
break;
}
@@ -184,13 +182,13 @@
total_len = 0;
break;
} else if (rc > total_len) {
- cERROR(1, ("sent %d requested %d", rc, total_len));
+ cERROR(1, "sent %d requested %d", rc, total_len);
break;
}
if (rc == 0) {
/* should never happen, letting socket clear before
retrying is our only obvious option here */
- cERROR(1, ("tcp sent no data"));
+ cERROR(1, "tcp sent no data");
msleep(500);
continue;
}
@@ -213,8 +211,8 @@
}
if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
- cFYI(1, ("partial send (%d remaining), terminating session",
- total_len));
+ cFYI(1, "partial send (%d remaining), terminating session",
+ total_len);
/* If we have only sent part of an SMB then the next SMB
could be taken as the remainder of this one. We need
to kill the socket so the server throws away the partial
@@ -223,7 +221,7 @@
}
if (rc < 0) {
- cERROR(1, ("Error %d sending data on socket to server", rc));
+ cERROR(1, "Error %d sending data on socket to server", rc);
} else
rc = 0;
@@ -296,7 +294,7 @@
}
if (ses->server->tcpStatus == CifsNeedReconnect) {
- cFYI(1, ("tcp session dead - return to caller to retry"));
+ cFYI(1, "tcp session dead - return to caller to retry");
return -EAGAIN;
}
@@ -348,7 +346,7 @@
lrt += time_to_wait;
if (time_after(jiffies, lrt)) {
/* No replies for time_to_wait. */
- cERROR(1, ("server not responding"));
+ cERROR(1, "server not responding");
return -1;
}
} else {
@@ -379,7 +377,7 @@
iov[0].iov_len = in_buf->smb_buf_length + 4;
flags |= CIFS_NO_RESP;
rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
- cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
+ cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
return rc;
}
@@ -402,7 +400,7 @@
if ((ses == NULL) || (ses->server == NULL)) {
cifs_small_buf_release(in_buf);
- cERROR(1, ("Null session"));
+ cERROR(1, "Null session");
return -EIO;
}
@@ -471,7 +469,7 @@
else if (long_op == CIFS_BLOCKING_OP)
timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
else {
- cERROR(1, ("unknown timeout flag %d", long_op));
+ cERROR(1, "unknown timeout flag %d", long_op);
rc = -EIO;
goto out;
}
@@ -490,8 +488,8 @@
spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf == NULL) {
- cERROR(1, ("No response to cmd %d mid %d",
- midQ->command, midQ->mid));
+ cERROR(1, "No response to cmd %d mid %d",
+ midQ->command, midQ->mid);
if (midQ->midState == MID_REQUEST_SUBMITTED) {
if (ses->server->tcpStatus == CifsExiting)
rc = -EHOSTDOWN;
@@ -504,7 +502,7 @@
if (rc != -EHOSTDOWN) {
if (midQ->midState == MID_RETRY_NEEDED) {
rc = -EAGAIN;
- cFYI(1, ("marking request for retry"));
+ cFYI(1, "marking request for retry");
} else {
rc = -EIO;
}
@@ -521,8 +519,8 @@
receive_len = midQ->resp_buf->smb_buf_length;
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
- cERROR(1, ("Frame too large received. Length: %d Xid: %d",
- receive_len, xid));
+ cERROR(1, "Frame too large received. Length: %d Xid: %d",
+ receive_len, xid);
rc = -EIO;
goto out;
}
@@ -548,7 +546,7 @@
&ses->server->mac_signing_key,
midQ->sequence_number+1);
if (rc) {
- cERROR(1, ("Unexpected SMB signature"));
+ cERROR(1, "Unexpected SMB signature");
/* BB FIXME add code to kill session */
}
}
@@ -569,7 +567,7 @@
DeleteMidQEntry */
} else {
rc = -EIO;
- cFYI(1, ("Bad MID state?"));
+ cFYI(1, "Bad MID state?");
}
out:
@@ -591,11 +589,11 @@
struct mid_q_entry *midQ;
if (ses == NULL) {
- cERROR(1, ("Null smb session"));
+ cERROR(1, "Null smb session");
return -EIO;
}
if (ses->server == NULL) {
- cERROR(1, ("Null tcp session"));
+ cERROR(1, "Null tcp session");
return -EIO;
}
@@ -607,8 +605,8 @@
use ses->maxReq */
if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
- cERROR(1, ("Illegal length, greater than maximum frame, %d",
- in_buf->smb_buf_length));
+ cERROR(1, "Illegal length, greater than maximum frame, %d",
+ in_buf->smb_buf_length);
return -EIO;
}
@@ -665,7 +663,7 @@
else if (long_op == CIFS_BLOCKING_OP)
timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
else {
- cERROR(1, ("unknown timeout flag %d", long_op));
+ cERROR(1, "unknown timeout flag %d", long_op);
rc = -EIO;
goto out;
}
@@ -681,8 +679,8 @@
spin_lock(&GlobalMid_Lock);
if (midQ->resp_buf == NULL) {
- cERROR(1, ("No response for cmd %d mid %d",
- midQ->command, midQ->mid));
+ cERROR(1, "No response for cmd %d mid %d",
+ midQ->command, midQ->mid);
if (midQ->midState == MID_REQUEST_SUBMITTED) {
if (ses->server->tcpStatus == CifsExiting)
rc = -EHOSTDOWN;
@@ -695,7 +693,7 @@
if (rc != -EHOSTDOWN) {
if (midQ->midState == MID_RETRY_NEEDED) {
rc = -EAGAIN;
- cFYI(1, ("marking request for retry"));
+ cFYI(1, "marking request for retry");
} else {
rc = -EIO;
}
@@ -712,8 +710,8 @@
receive_len = midQ->resp_buf->smb_buf_length;
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
- cERROR(1, ("Frame too large received. Length: %d Xid: %d",
- receive_len, xid));
+ cERROR(1, "Frame too large received. Length: %d Xid: %d",
+ receive_len, xid);
rc = -EIO;
goto out;
}
@@ -736,7 +734,7 @@
&ses->server->mac_signing_key,
midQ->sequence_number+1);
if (rc) {
- cERROR(1, ("Unexpected SMB signature"));
+ cERROR(1, "Unexpected SMB signature");
/* BB FIXME add code to kill session */
}
}
@@ -753,7 +751,7 @@
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else {
rc = -EIO;
- cERROR(1, ("Bad MID state?"));
+ cERROR(1, "Bad MID state?");
}
out:
@@ -824,13 +822,13 @@
struct cifsSesInfo *ses;
if (tcon == NULL || tcon->ses == NULL) {
- cERROR(1, ("Null smb session"));
+ cERROR(1, "Null smb session");
return -EIO;
}
ses = tcon->ses;
if (ses->server == NULL) {
- cERROR(1, ("Null tcp session"));
+ cERROR(1, "Null tcp session");
return -EIO;
}
@@ -842,8 +840,8 @@
use ses->maxReq */
if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
- cERROR(1, ("Illegal length, greater than maximum frame, %d",
- in_buf->smb_buf_length));
+ cERROR(1, "Illegal length, greater than maximum frame, %d",
+ in_buf->smb_buf_length);
return -EIO;
}
@@ -933,8 +931,8 @@
spin_unlock(&GlobalMid_Lock);
receive_len = midQ->resp_buf->smb_buf_length;
} else {
- cERROR(1, ("No response for cmd %d mid %d",
- midQ->command, midQ->mid));
+ cERROR(1, "No response for cmd %d mid %d",
+ midQ->command, midQ->mid);
if (midQ->midState == MID_REQUEST_SUBMITTED) {
if (ses->server->tcpStatus == CifsExiting)
rc = -EHOSTDOWN;
@@ -947,7 +945,7 @@
if (rc != -EHOSTDOWN) {
if (midQ->midState == MID_RETRY_NEEDED) {
rc = -EAGAIN;
- cFYI(1, ("marking request for retry"));
+ cFYI(1, "marking request for retry");
} else {
rc = -EIO;
}
@@ -958,8 +956,8 @@
}
if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
- cERROR(1, ("Frame too large received. Length: %d Xid: %d",
- receive_len, xid));
+ cERROR(1, "Frame too large received. Length: %d Xid: %d",
+ receive_len, xid);
rc = -EIO;
goto out;
}
@@ -968,7 +966,7 @@
if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
rc = -EIO;
- cERROR(1, ("Bad MID state?"));
+ cERROR(1, "Bad MID state?");
goto out;
}
@@ -986,7 +984,7 @@
&ses->server->mac_signing_key,
midQ->sequence_number+1);
if (rc) {
- cERROR(1, ("Unexpected SMB signature"));
+ cERROR(1, "Unexpected SMB signature");
/* BB FIXME add code to kill session */
}
}
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index f555ce0..a150920 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -70,12 +70,12 @@
return rc;
}
if (ea_name == NULL) {
- cFYI(1, ("Null xattr names not supported"));
+ cFYI(1, "Null xattr names not supported");
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
&& (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
cFYI(1,
- ("illegal xattr request %s (only user namespace supported)",
- ea_name));
+ "illegal xattr request %s (only user namespace supported)",
+ ea_name);
/* BB what if no namespace prefix? */
/* Should we just pass them to server, except for
system and perhaps security prefixes? */
@@ -131,19 +131,19 @@
search server for EAs or streams to
returns as xattrs */
if (value_size > MAX_EA_VALUE_SIZE) {
- cFYI(1, ("size of EA value too large"));
+ cFYI(1, "size of EA value too large");
kfree(full_path);
FreeXid(xid);
return -EOPNOTSUPP;
}
if (ea_name == NULL) {
- cFYI(1, ("Null xattr names not supported"));
+ cFYI(1, "Null xattr names not supported");
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
goto set_ea_exit;
if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0)
- cFYI(1, ("attempt to set cifs inode metadata"));
+ cFYI(1, "attempt to set cifs inode metadata");
ea_name += 5; /* skip past user. prefix */
rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
@@ -169,9 +169,9 @@
ACL_TYPE_ACCESS, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- cFYI(1, ("set POSIX ACL rc %d", rc));
+ cFYI(1, "set POSIX ACL rc %d", rc);
#else
- cFYI(1, ("set POSIX ACL not supported"));
+ cFYI(1, "set POSIX ACL not supported");
#endif
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
@@ -182,13 +182,13 @@
ACL_TYPE_DEFAULT, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- cFYI(1, ("set POSIX default ACL rc %d", rc));
+ cFYI(1, "set POSIX default ACL rc %d", rc);
#else
- cFYI(1, ("set default POSIX ACL not supported"));
+ cFYI(1, "set default POSIX ACL not supported");
#endif
} else {
- cFYI(1, ("illegal xattr request %s (only user namespace"
- " supported)", ea_name));
+ cFYI(1, "illegal xattr request %s (only user namespace"
+ " supported)", ea_name);
/* BB what if no namespace prefix? */
/* Should we just pass them to server, except for
system and perhaps security prefixes? */
@@ -235,13 +235,13 @@
/* return dos attributes as pseudo xattr */
/* return alt name if available as pseudo attr */
if (ea_name == NULL) {
- cFYI(1, ("Null xattr names not supported"));
+ cFYI(1, "Null xattr names not supported");
} else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
goto get_ea_exit;
if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
- cFYI(1, ("attempt to query cifs inode metadata"));
+ cFYI(1, "attempt to query cifs inode metadata");
/* revalidate/getattr then populate from inode */
} /* BB add else when above is implemented */
ea_name += 5; /* skip past user. prefix */
@@ -287,7 +287,7 @@
}
#endif /* EXPERIMENTAL */
#else
- cFYI(1, ("query POSIX ACL not supported yet"));
+ cFYI(1, "query POSIX ACL not supported yet");
#endif /* CONFIG_CIFS_POSIX */
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
@@ -299,18 +299,18 @@
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
#else
- cFYI(1, ("query POSIX default ACL not supported yet"));
+ cFYI(1, "query POSIX default ACL not supported yet");
#endif
} else if (strncmp(ea_name,
CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
- cFYI(1, ("Trusted xattr namespace not supported yet"));
+ cFYI(1, "Trusted xattr namespace not supported yet");
} else if (strncmp(ea_name,
CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
- cFYI(1, ("Security xattr namespace not supported yet"));
+ cFYI(1, "Security xattr namespace not supported yet");
} else
cFYI(1,
- ("illegal xattr request %s (only user namespace supported)",
- ea_name));
+ "illegal xattr request %s (only user namespace supported)",
+ ea_name);
/* We could add an additional check for streams ie
if proc/fs/cifs/streamstoxattr is set then
diff --git a/fs/compat.c b/fs/compat.c
index 4b6ed03..0544873 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1531,8 +1531,6 @@
if (retval < 0)
goto out;
- current->stack_start = current->mm->start_stack;
-
/* execve succeeded */
current->fs->in_exec = 0;
current->in_execve = 0;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 8e48b52..0b502f8 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -645,6 +645,7 @@
configfs_detach_group(sd->s_element);
child->d_inode->i_flags |= S_DEAD;
+ dont_mount(child);
mutex_unlock(&child->d_inode->i_mutex);
@@ -840,6 +841,7 @@
mutex_lock(&dentry->d_inode->i_mutex);
configfs_remove_dir(item);
dentry->d_inode->i_flags |= S_DEAD;
+ dont_mount(dentry);
mutex_unlock(&dentry->d_inode->i_mutex);
d_delete(dentry);
}
@@ -882,6 +884,7 @@
if (ret) {
configfs_detach_item(item);
dentry->d_inode->i_flags |= S_DEAD;
+ dont_mount(dentry);
}
configfs_adjust_dir_dirent_depth_after_populate(sd);
mutex_unlock(&dentry->d_inode->i_mutex);
@@ -1725,6 +1728,7 @@
mutex_unlock(&configfs_symlink_mutex);
configfs_detach_group(&group->cg_item);
dentry->d_inode->i_flags |= S_DEAD;
+ dont_mount(dentry);
mutex_unlock(&dentry->d_inode->i_mutex);
d_delete(dentry);
diff --git a/fs/exec.c b/fs/exec.c
index 49cdaa1..e6e94c6 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1387,8 +1387,6 @@
if (retval < 0)
goto out;
- current->stack_start = current->mm->start_stack;
-
/* execve succeeded */
current->fs->in_exec = 0;
current->in_execve = 0;
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 157382f..b66832a 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -446,10 +446,8 @@
/* initialize the mount flag and determine the default error handler */
flag = JFS_ERR_REMOUNT_RO;
- if (!parse_options((char *) data, sb, &newLVSize, &flag)) {
- kfree(sbi);
- return -EINVAL;
- }
+ if (!parse_options((char *) data, sb, &newLVSize, &flag))
+ goto out_kfree;
sbi->flag = flag;
#ifdef CONFIG_JFS_POSIX_ACL
@@ -458,7 +456,7 @@
if (newLVSize) {
printk(KERN_ERR "resize option for remount only\n");
- return -EINVAL;
+ goto out_kfree;
}
/*
@@ -478,7 +476,7 @@
inode = new_inode(sb);
if (inode == NULL) {
ret = -ENOMEM;
- goto out_kfree;
+ goto out_unload;
}
inode->i_ino = 0;
inode->i_nlink = 1;
@@ -550,9 +548,10 @@
make_bad_inode(sbi->direct_inode);
iput(sbi->direct_inode);
sbi->direct_inode = NULL;
-out_kfree:
+out_unload:
if (sbi->nls_tab)
unload_nls(sbi->nls_tab);
+out_kfree:
kfree(sbi);
return ret;
}
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
index 243c000..9bd2ce2 100644
--- a/fs/logfs/dev_bdev.c
+++ b/fs/logfs/dev_bdev.c
@@ -303,6 +303,11 @@
close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE);
}
+static int bdev_can_write_buf(struct super_block *sb, u64 ofs)
+{
+ return 0;
+}
+
static const struct logfs_device_ops bd_devops = {
.find_first_sb = bdev_find_first_sb,
.find_last_sb = bdev_find_last_sb,
@@ -310,6 +315,7 @@
.readpage = bdev_readpage,
.writeseg = bdev_writeseg,
.erase = bdev_erase,
+ .can_write_buf = bdev_can_write_buf,
.sync = bdev_sync,
.put_device = bdev_put_device,
};
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index cafb6ef..a85d47d 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -9,6 +9,7 @@
#include <linux/completion.h>
#include <linux/mount.h>
#include <linux/sched.h>
+#include <linux/slab.h>
#define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
@@ -126,7 +127,8 @@
err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE,
page_address(page));
- if (err == -EUCLEAN) {
+ if (err == -EUCLEAN || err == -EBADMSG) {
+ /* -EBADMSG happens regularly on power failures */
err = 0;
/* FIXME: force GC this segment */
}
@@ -233,12 +235,32 @@
put_mtd_device(logfs_super(sb)->s_mtd);
}
+static int mtd_can_write_buf(struct super_block *sb, u64 ofs)
+{
+ struct logfs_super *super = logfs_super(sb);
+ void *buf;
+ int err;
+
+ buf = kmalloc(super->s_writesize, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ err = mtd_read(sb, ofs, super->s_writesize, buf);
+ if (err)
+ goto out;
+ if (memchr_inv(buf, 0xff, super->s_writesize))
+ err = -EIO;
+ kfree(buf);
+out:
+ return err;
+}
+
static const struct logfs_device_ops mtd_devops = {
.find_first_sb = mtd_find_first_sb,
.find_last_sb = mtd_find_last_sb,
.readpage = mtd_readpage,
.writeseg = mtd_writeseg,
.erase = mtd_erase,
+ .can_write_buf = mtd_can_write_buf,
.sync = mtd_sync,
.put_device = mtd_put_device,
};
@@ -250,5 +272,7 @@
const struct logfs_device_ops *devops = &mtd_devops;
mtd = get_mtd_device(NULL, mtdnr);
+ if (IS_ERR(mtd))
+ return PTR_ERR(mtd);
return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt);
}
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
index 370f367..0de5240 100644
--- a/fs/logfs/file.c
+++ b/fs/logfs/file.c
@@ -161,7 +161,17 @@
static void logfs_invalidatepage(struct page *page, unsigned long offset)
{
- move_page_to_btree(page);
+ struct logfs_block *block = logfs_block(page);
+
+ if (block->reserved_bytes) {
+ struct super_block *sb = page->mapping->host->i_sb;
+ struct logfs_super *super = logfs_super(sb);
+
+ super->s_dirty_pages -= block->reserved_bytes;
+ block->ops->free_block(sb, block);
+ BUG_ON(bitmap_weight(block->alias_map, LOGFS_BLOCK_FACTOR));
+ } else
+ move_page_to_btree(page);
BUG_ON(PagePrivate(page) || page->private);
}
@@ -212,10 +222,8 @@
int logfs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
struct super_block *sb = dentry->d_inode->i_sb;
- struct logfs_super *super = logfs_super(sb);
- /* FIXME: write anchor */
- super->s_devops->sync(sb);
+ logfs_write_anchor(sb);
return 0;
}
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c
index 76c242f..caa4419 100644
--- a/fs/logfs/gc.c
+++ b/fs/logfs/gc.c
@@ -122,7 +122,7 @@
logfs_safe_iput(inode, cookie);
}
-static u32 logfs_gc_segment(struct super_block *sb, u32 segno, u8 dist)
+static u32 logfs_gc_segment(struct super_block *sb, u32 segno)
{
struct logfs_super *super = logfs_super(sb);
struct logfs_segment_header sh;
@@ -401,7 +401,7 @@
segno, (u64)segno << super->s_segshift,
dist, no_free_segments(sb), valid,
super->s_free_bytes);
- cleaned = logfs_gc_segment(sb, segno, dist);
+ cleaned = logfs_gc_segment(sb, segno);
log_gc("GC segment #%02x complete - now %x valid\n", segno,
valid - cleaned);
BUG_ON(cleaned != valid);
@@ -632,38 +632,31 @@
{
struct logfs_super *super = logfs_super(sb);
struct logfs_area *area = super->s_area[i];
- struct logfs_object_header oh;
+ gc_level_t gc_level;
+ u32 cleaned, valid, ec;
u32 segno = area->a_segno;
- u32 ofs = area->a_used_bytes;
- __be32 crc;
- int err;
+ u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
if (!area->a_is_open)
return 0;
- for (ofs = area->a_used_bytes;
- ofs <= super->s_segsize - sizeof(oh);
- ofs += (u32)be16_to_cpu(oh.len) + sizeof(oh)) {
- err = wbuf_read(sb, dev_ofs(sb, segno, ofs), sizeof(oh), &oh);
- if (err)
- return err;
+ if (super->s_devops->can_write_buf(sb, ofs) == 0)
+ return 0;
- if (!memchr_inv(&oh, 0xff, sizeof(oh)))
- break;
-
- crc = logfs_crc32(&oh, sizeof(oh) - 4, 4);
- if (crc != oh.crc) {
- printk(KERN_INFO "interrupted header at %llx\n",
- dev_ofs(sb, segno, ofs));
- return 0;
- }
- }
- if (ofs != area->a_used_bytes) {
- printk(KERN_INFO "%x bytes unaccounted data found at %llx\n",
- ofs - area->a_used_bytes,
- dev_ofs(sb, segno, area->a_used_bytes));
- area->a_used_bytes = ofs;
- }
+ printk(KERN_INFO"LogFS: Possibly incomplete write at %llx\n", ofs);
+ /*
+ * The device cannot write back the write buffer. Most likely the
+ * wbuf was already written out and the system crashed at some point
+ * before the journal commit happened. In that case we wouldn't have
+ * to do anything. But if the crash happened before the wbuf was
+ * written out correctly, we must GC this segment. So assume the
+ * worst and always do the GC run.
+ */
+ area->a_is_open = 0;
+ valid = logfs_valid_bytes(sb, segno, &ec, &gc_level);
+ cleaned = logfs_gc_segment(sb, segno);
+ if (cleaned != valid)
+ return -EIO;
return 0;
}
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index 14ed272..755a92e 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -193,6 +193,7 @@
inode->i_ctime = CURRENT_TIME;
inode->i_mtime = CURRENT_TIME;
inode->i_nlink = 1;
+ li->li_refcount = 1;
INIT_LIST_HEAD(&li->li_freeing_list);
for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
@@ -326,7 +327,7 @@
u64 ino;
mutex_lock(&super->s_journal_mutex);
- ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino);
+ ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino + 1);
super->s_last_ino = ino;
super->s_inos_till_wrap--;
if (super->s_inos_till_wrap < 0) {
@@ -386,8 +387,7 @@
static int logfs_sync_fs(struct super_block *sb, int wait)
{
- /* FIXME: write anchor */
- logfs_super(sb)->s_devops->sync(sb);
+ logfs_write_anchor(sb);
return 0;
}
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index fb0a613..4b0e061 100644
--- a/fs/logfs/journal.c
+++ b/fs/logfs/journal.c
@@ -132,10 +132,9 @@
ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
if (super->s_writesize > 1)
- logfs_buf_recover(area, ofs, a + 1, super->s_writesize);
+ return logfs_buf_recover(area, ofs, a + 1, super->s_writesize);
else
- logfs_buf_recover(area, ofs, NULL, 0);
- return 0;
+ return logfs_buf_recover(area, ofs, NULL, 0);
}
static void *unpack(void *from, void *to)
@@ -245,7 +244,7 @@
read_erasecount(sb, unpack(jh, scratch));
break;
case JE_AREA:
- read_area(sb, unpack(jh, scratch));
+ err = read_area(sb, unpack(jh, scratch));
break;
case JE_OBJ_ALIAS:
err = logfs_load_object_aliases(sb, unpack(jh, scratch),
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index 0a3df1a..93b55f3 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -144,6 +144,7 @@
* @erase: erase one segment
* @read: read from the device
* @erase: erase part of the device
+ * @can_write_buf: decide whether wbuf can be written to ofs
*/
struct logfs_device_ops {
struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs);
@@ -153,6 +154,7 @@
void (*writeseg)(struct super_block *sb, u64 ofs, size_t len);
int (*erase)(struct super_block *sb, loff_t ofs, size_t len,
int ensure_write);
+ int (*can_write_buf)(struct super_block *sb, u64 ofs);
void (*sync)(struct super_block *sb);
void (*put_device)(struct super_block *sb);
};
@@ -394,6 +396,7 @@
int s_lock_count;
mempool_t *s_block_pool; /* struct logfs_block pool */
mempool_t *s_shadow_pool; /* struct logfs_shadow pool */
+ struct list_head s_writeback_list; /* writeback pages */
/*
* Space accounting:
* - s_used_bytes specifies space used to store valid data objects.
@@ -598,19 +601,19 @@
int logfs_init_areas(struct super_block *sb);
void logfs_cleanup_areas(struct super_block *sb);
int logfs_open_area(struct logfs_area *area, size_t bytes);
-void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
+int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
int use_filler);
-static inline void logfs_buf_write(struct logfs_area *area, u64 ofs,
+static inline int logfs_buf_write(struct logfs_area *area, u64 ofs,
void *buf, size_t len)
{
- __logfs_buf_write(area, ofs, buf, len, 0);
+ return __logfs_buf_write(area, ofs, buf, len, 0);
}
-static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs,
+static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs,
void *buf, size_t len)
{
- __logfs_buf_write(area, ofs, buf, len, 1);
+ return __logfs_buf_write(area, ofs, buf, len, 1);
}
/* super.c */
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index 3159db6..0718d11 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -892,6 +892,8 @@
return bix;
else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED)
bix = maxbix(li->li_height);
+ else if (bix >= maxbix(li->li_height))
+ return bix;
else {
bix = seek_holedata_loop(inode, bix, 0);
if (bix < maxbix(li->li_height))
@@ -1093,17 +1095,25 @@
int get_page_reserve(struct inode *inode, struct page *page)
{
struct logfs_super *super = logfs_super(inode->i_sb);
+ struct logfs_block *block = logfs_block(page);
int ret;
- if (logfs_block(page) && logfs_block(page)->reserved_bytes)
+ if (block && block->reserved_bytes)
return 0;
logfs_get_wblocks(inode->i_sb, page, WF_LOCK);
- ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE);
+ while ((ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE)) &&
+ !list_empty(&super->s_writeback_list)) {
+ block = list_entry(super->s_writeback_list.next,
+ struct logfs_block, alias_list);
+ block->ops->write_block(block);
+ }
if (!ret) {
alloc_data_block(inode, page);
- logfs_block(page)->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE;
+ block = logfs_block(page);
+ block->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE;
super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE;
+ list_move_tail(&block->alias_list, &super->s_writeback_list);
}
logfs_put_wblocks(inode->i_sb, page, WF_LOCK);
return ret;
@@ -1861,7 +1871,7 @@
size = target;
logfs_get_wblocks(sb, NULL, 1);
- err = __logfs_truncate(inode, target);
+ err = __logfs_truncate(inode, size);
if (!err)
err = __logfs_write_inode(inode, 0);
logfs_put_wblocks(sb, NULL, 1);
@@ -2249,6 +2259,7 @@
int min_fill = 3 * super->s_no_blocks;
INIT_LIST_HEAD(&super->s_object_alias);
+ INIT_LIST_HEAD(&super->s_writeback_list);
mutex_init(&super->s_write_mutex);
super->s_block_pool = mempool_create_kmalloc_pool(min_fill,
sizeof(struct logfs_block));
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index f77ce2b..a9657af 100644
--- a/fs/logfs/segment.c
+++ b/fs/logfs/segment.c
@@ -67,7 +67,7 @@
return page;
}
-void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
+int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
int use_filler)
{
pgoff_t index = ofs >> PAGE_SHIFT;
@@ -81,8 +81,10 @@
copylen = min((ulong)len, PAGE_SIZE - offset);
page = get_mapping_page(area->a_sb, index, use_filler);
- SetPageUptodate(page);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
BUG_ON(!page); /* FIXME: reserve a pool */
+ SetPageUptodate(page);
memcpy(page_address(page) + offset, buf, copylen);
SetPagePrivate(page);
page_cache_release(page);
@@ -92,6 +94,7 @@
offset = 0;
index++;
} while (len);
+ return 0;
}
static void pad_partial_page(struct logfs_area *area)
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 5866ee6..d651e10 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -138,10 +138,14 @@
sb->s_fs_info = super;
sb->s_mtd = super->s_mtd;
sb->s_bdev = super->s_bdev;
+#ifdef CONFIG_BLOCK
if (sb->s_bdev)
sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info;
+#endif
+#ifdef CONFIG_MTD
if (sb->s_mtd)
sb->s_bdi = sb->s_mtd->backing_dev_info;
+#endif
return 0;
}
@@ -333,27 +337,27 @@
goto fail;
sb->s_root = d_alloc_root(rootdir);
- if (!sb->s_root)
- goto fail2;
+ if (!sb->s_root) {
+ iput(rootdir);
+ goto fail;
+ }
super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
if (!super->s_erase_page)
- goto fail2;
+ goto fail;
memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE);
/* FIXME: check for read-only mounts */
err = logfs_make_writeable(sb);
if (err)
- goto fail3;
+ goto fail1;
log_super("LogFS: Finished mounting\n");
simple_set_mnt(mnt, sb);
return 0;
-fail3:
+fail1:
__free_page(super->s_erase_page);
-fail2:
- iput(rootdir);
fail:
iput(logfs_super(sb)->s_master_inode);
return -EIO;
@@ -382,7 +386,7 @@
if (!first || IS_ERR(first))
return NULL;
last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]);
- if (!last || IS_ERR(first)) {
+ if (!last || IS_ERR(last)) {
page_cache_release(first);
return NULL;
}
@@ -413,7 +417,7 @@
page = find_super_block(sb);
if (!page)
- return -EIO;
+ return -EINVAL;
ds = page_address(page);
super->s_size = be64_to_cpu(ds->ds_filesystem_size);
diff --git a/fs/namei.c b/fs/namei.c
index a7dce91..b86b96f 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1641,7 +1641,7 @@
if (nd->last.name[nd->last.len]) {
if (open_flag & O_CREAT)
goto exit;
- nd->flags |= LOOKUP_DIRECTORY;
+ nd->flags |= LOOKUP_DIRECTORY | LOOKUP_FOLLOW;
}
/* just plain open? */
@@ -1830,6 +1830,8 @@
}
if (open_flag & O_DIRECTORY)
nd.flags |= LOOKUP_DIRECTORY;
+ if (!(open_flag & O_NOFOLLOW))
+ nd.flags |= LOOKUP_FOLLOW;
filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
while (unlikely(!filp)) { /* trailing symlink */
struct path holder;
@@ -1837,7 +1839,7 @@
void *cookie;
error = -ELOOP;
/* S_ISDIR part is a temporary automount kludge */
- if ((open_flag & O_NOFOLLOW) && !S_ISDIR(inode->i_mode))
+ if (!(nd.flags & LOOKUP_FOLLOW) && !S_ISDIR(inode->i_mode))
goto exit_dput;
if (count++ == 32)
goto exit_dput;
@@ -2174,8 +2176,10 @@
error = security_inode_rmdir(dir, dentry);
if (!error) {
error = dir->i_op->rmdir(dir, dentry);
- if (!error)
+ if (!error) {
dentry->d_inode->i_flags |= S_DEAD;
+ dont_mount(dentry);
+ }
}
}
mutex_unlock(&dentry->d_inode->i_mutex);
@@ -2259,7 +2263,7 @@
if (!error) {
error = dir->i_op->unlink(dir, dentry);
if (!error)
- dentry->d_inode->i_flags |= S_DEAD;
+ dont_mount(dentry);
}
}
mutex_unlock(&dentry->d_inode->i_mutex);
@@ -2570,17 +2574,20 @@
return error;
target = new_dentry->d_inode;
- if (target) {
+ if (target)
mutex_lock(&target->i_mutex);
- dentry_unhash(new_dentry);
- }
if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
error = -EBUSY;
- else
+ else {
+ if (target)
+ dentry_unhash(new_dentry);
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+ }
if (target) {
- if (!error)
+ if (!error) {
target->i_flags |= S_DEAD;
+ dont_mount(new_dentry);
+ }
mutex_unlock(&target->i_mutex);
if (d_unhashed(new_dentry))
d_rehash(new_dentry);
@@ -2612,7 +2619,7 @@
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
if (!error) {
if (target)
- target->i_flags |= S_DEAD;
+ dont_mount(new_dentry);
if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE))
d_move(old_dentry, new_dentry);
}
diff --git a/fs/namespace.c b/fs/namespace.c
index 8174c8a..f20cb57 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1432,7 +1432,7 @@
err = -ENOENT;
mutex_lock(&path->dentry->d_inode->i_mutex);
- if (IS_DEADDIR(path->dentry->d_inode))
+ if (cant_mount(path->dentry))
goto out_unlock;
err = security_sb_check_sb(mnt, path);
@@ -1623,7 +1623,7 @@
err = -ENOENT;
mutex_lock(&path->dentry->d_inode->i_mutex);
- if (IS_DEADDIR(path->dentry->d_inode))
+ if (cant_mount(path->dentry))
goto out1;
if (d_unlinked(path->dentry))
@@ -2234,7 +2234,7 @@
if (!check_mnt(root.mnt))
goto out2;
error = -ENOENT;
- if (IS_DEADDIR(new.dentry->d_inode))
+ if (cant_mount(old.dentry))
goto out2;
if (d_unlinked(new.dentry))
goto out2;
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 1567124..ea61d26 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -24,6 +24,8 @@
static void nfs_do_free_delegation(struct nfs_delegation *delegation)
{
+ if (delegation->cred)
+ put_rpccred(delegation->cred);
kfree(delegation);
}
@@ -36,13 +38,7 @@
static void nfs_free_delegation(struct nfs_delegation *delegation)
{
- struct rpc_cred *cred;
-
- cred = rcu_dereference(delegation->cred);
- rcu_assign_pointer(delegation->cred, NULL);
call_rcu(&delegation->rcu, nfs_free_delegation_callback);
- if (cred)
- put_rpccred(cred);
}
void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
@@ -129,21 +125,35 @@
*/
void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
{
- struct nfs_delegation *delegation = NFS_I(inode)->delegation;
- struct rpc_cred *oldcred;
+ struct nfs_delegation *delegation;
+ struct rpc_cred *oldcred = NULL;
- if (delegation == NULL)
- return;
- memcpy(delegation->stateid.data, res->delegation.data,
- sizeof(delegation->stateid.data));
- delegation->type = res->delegation_type;
- delegation->maxsize = res->maxsize;
- oldcred = delegation->cred;
- delegation->cred = get_rpccred(cred);
- clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
- NFS_I(inode)->delegation_state = delegation->type;
- smp_wmb();
- put_rpccred(oldcred);
+ rcu_read_lock();
+ delegation = rcu_dereference(NFS_I(inode)->delegation);
+ if (delegation != NULL) {
+ spin_lock(&delegation->lock);
+ if (delegation->inode != NULL) {
+ memcpy(delegation->stateid.data, res->delegation.data,
+ sizeof(delegation->stateid.data));
+ delegation->type = res->delegation_type;
+ delegation->maxsize = res->maxsize;
+ oldcred = delegation->cred;
+ delegation->cred = get_rpccred(cred);
+ clear_bit(NFS_DELEGATION_NEED_RECLAIM,
+ &delegation->flags);
+ NFS_I(inode)->delegation_state = delegation->type;
+ spin_unlock(&delegation->lock);
+ put_rpccred(oldcred);
+ rcu_read_unlock();
+ } else {
+ /* We appear to have raced with a delegation return. */
+ spin_unlock(&delegation->lock);
+ rcu_read_unlock();
+ nfs_inode_set_delegation(inode, cred, res);
+ }
+ } else {
+ rcu_read_unlock();
+ }
}
static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
@@ -166,9 +176,13 @@
return inode;
}
-static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
+static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi,
+ const nfs4_stateid *stateid,
+ struct nfs_client *clp)
{
- struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
+ struct nfs_delegation *delegation =
+ rcu_dereference_protected(nfsi->delegation,
+ lockdep_is_held(&clp->cl_lock));
if (delegation == NULL)
goto nomatch;
@@ -195,7 +209,7 @@
{
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
struct nfs_inode *nfsi = NFS_I(inode);
- struct nfs_delegation *delegation;
+ struct nfs_delegation *delegation, *old_delegation;
struct nfs_delegation *freeme = NULL;
int status = 0;
@@ -213,10 +227,12 @@
spin_lock_init(&delegation->lock);
spin_lock(&clp->cl_lock);
- if (rcu_dereference(nfsi->delegation) != NULL) {
- if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
- sizeof(delegation->stateid)) == 0 &&
- delegation->type == nfsi->delegation->type) {
+ old_delegation = rcu_dereference_protected(nfsi->delegation,
+ lockdep_is_held(&clp->cl_lock));
+ if (old_delegation != NULL) {
+ if (memcmp(&delegation->stateid, &old_delegation->stateid,
+ sizeof(old_delegation->stateid)) == 0 &&
+ delegation->type == old_delegation->type) {
goto out;
}
/*
@@ -226,12 +242,12 @@
dfprintk(FILE, "%s: server %s handed out "
"a duplicate delegation!\n",
__func__, clp->cl_hostname);
- if (delegation->type <= nfsi->delegation->type) {
+ if (delegation->type <= old_delegation->type) {
freeme = delegation;
delegation = NULL;
goto out;
}
- freeme = nfs_detach_delegation_locked(nfsi, NULL);
+ freeme = nfs_detach_delegation_locked(nfsi, NULL, clp);
}
list_add_rcu(&delegation->super_list, &clp->cl_delegations);
nfsi->delegation_state = delegation->type;
@@ -301,7 +317,7 @@
if (inode == NULL)
continue;
spin_lock(&clp->cl_lock);
- delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
+ delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp);
spin_unlock(&clp->cl_lock);
rcu_read_unlock();
if (delegation != NULL) {
@@ -330,9 +346,9 @@
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_delegation *delegation;
- if (rcu_dereference(nfsi->delegation) != NULL) {
+ if (rcu_access_pointer(nfsi->delegation) != NULL) {
spin_lock(&clp->cl_lock);
- delegation = nfs_detach_delegation_locked(nfsi, NULL);
+ delegation = nfs_detach_delegation_locked(nfsi, NULL, clp);
spin_unlock(&clp->cl_lock);
if (delegation != NULL)
nfs_do_return_delegation(inode, delegation, 0);
@@ -346,9 +362,9 @@
struct nfs_delegation *delegation;
int err = 0;
- if (rcu_dereference(nfsi->delegation) != NULL) {
+ if (rcu_access_pointer(nfsi->delegation) != NULL) {
spin_lock(&clp->cl_lock);
- delegation = nfs_detach_delegation_locked(nfsi, NULL);
+ delegation = nfs_detach_delegation_locked(nfsi, NULL, clp);
spin_unlock(&clp->cl_lock);
if (delegation != NULL) {
nfs_msync_inode(inode);
@@ -526,7 +542,7 @@
if (inode == NULL)
continue;
spin_lock(&clp->cl_lock);
- delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
+ delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL, clp);
spin_unlock(&clp->cl_lock);
rcu_read_unlock();
if (delegation != NULL)
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 1afb0a1..e27960c 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -28,6 +28,7 @@
#include <linux/path.h> /* struct path */
#include <linux/slab.h> /* kmem_* */
#include <linux/types.h>
+#include <linux/sched.h>
#include "inotify.h"
@@ -146,6 +147,7 @@
idr_for_each(&group->inotify_data.idr, idr_callback, group);
idr_remove_all(&group->inotify_data.idr);
idr_destroy(&group->inotify_data.idr);
+ free_uid(group->inotify_data.user);
}
void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv)
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 472cdf2..e46ca68 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -546,21 +546,24 @@
if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL)))
goto out_err;
+ /* we are putting the mark on the idr, take a reference */
+ fsnotify_get_mark(&tmp_ientry->fsn_entry);
+
spin_lock(&group->inotify_data.idr_lock);
ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry,
group->inotify_data.last_wd+1,
&tmp_ientry->wd);
spin_unlock(&group->inotify_data.idr_lock);
if (ret) {
+ /* we didn't get on the idr, drop the idr reference */
+ fsnotify_put_mark(&tmp_ientry->fsn_entry);
+
/* idr was out of memory allocate and try again */
if (ret == -EAGAIN)
goto retry;
goto out_err;
}
- /* we put the mark on the idr, take a reference */
- fsnotify_get_mark(&tmp_ientry->fsn_entry);
-
/* we are on the idr, now get on the inode */
ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode);
if (ret) {
@@ -578,16 +581,13 @@
/* return the watch descriptor for this new entry */
ret = tmp_ientry->wd;
- /* match the ref from fsnotify_init_markentry() */
- fsnotify_put_mark(&tmp_ientry->fsn_entry);
-
/* if this mark added a new event update the group mask */
if (mask & ~group->mask)
fsnotify_recalc_group_mask(group);
out_err:
- if (ret < 0)
- kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry);
+ /* match the ref from fsnotify_init_markentry() */
+ fsnotify_put_mark(&tmp_ientry->fsn_entry);
return ret;
}
diff --git a/fs/proc/array.c b/fs/proc/array.c
index e51f2ec..885ab55 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -81,7 +81,6 @@
#include <linux/pid_namespace.h>
#include <linux/ptrace.h>
#include <linux/tracehook.h>
-#include <linux/swapops.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
@@ -495,7 +494,7 @@
rsslim,
mm ? mm->start_code : 0,
mm ? mm->end_code : 0,
- (permitted && mm) ? task->stack_start : 0,
+ (permitted && mm) ? mm->start_stack : 0,
esp,
eip,
/* The signal information here is obsolete.
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 0705534..47f5b14 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -247,25 +247,6 @@
} else if (vma->vm_start <= mm->start_stack &&
vma->vm_end >= mm->start_stack) {
name = "[stack]";
- } else {
- unsigned long stack_start;
- struct proc_maps_private *pmp;
-
- pmp = m->private;
- stack_start = pmp->task->stack_start;
-
- if (vma->vm_start <= stack_start &&
- vma->vm_end >= stack_start) {
- pad_len_spaces(m, len);
- seq_printf(m,
- "[threadstack:%08lx]",
-#ifdef CONFIG_STACK_GROWSUP
- vma->vm_end - stack_start
-#else
- stack_start - vma->vm_start
-#endif
- );
- }
}
} else {
name = "[vdso]";
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 4e50286..1dabed2 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -164,8 +164,8 @@
name, de->name))
goto found;
}
+ dir_put_page(page);
}
- dir_put_page(page);
if (++n >= npages)
n = 0;
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
index c99c64d..c33749f 100644
--- a/include/asm-generic/atomic.h
+++ b/include/asm-generic/atomic.h
@@ -33,7 +33,7 @@
* Atomically reads the value of @v. Note that the guaranteed
* useful range of an atomic_t is only 24 bits.
*/
-#define atomic_read(v) ((v)->counter)
+#define atomic_read(v) (*(volatile int *)&(v)->counter)
/**
* atomic_set - set atomic variable
diff --git a/include/asm-generic/bitops/arch_hweight.h b/include/asm-generic/bitops/arch_hweight.h
new file mode 100644
index 0000000..6a211f4
--- /dev/null
+++ b/include/asm-generic/bitops/arch_hweight.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_
+#define _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_
+
+#include <asm/types.h>
+
+static inline unsigned int __arch_hweight32(unsigned int w)
+{
+ return __sw_hweight32(w);
+}
+
+static inline unsigned int __arch_hweight16(unsigned int w)
+{
+ return __sw_hweight16(w);
+}
+
+static inline unsigned int __arch_hweight8(unsigned int w)
+{
+ return __sw_hweight8(w);
+}
+
+static inline unsigned long __arch_hweight64(__u64 w)
+{
+ return __sw_hweight64(w);
+}
+#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
diff --git a/include/asm-generic/bitops/const_hweight.h b/include/asm-generic/bitops/const_hweight.h
new file mode 100644
index 0000000..fa2a50b
--- /dev/null
+++ b/include/asm-generic/bitops/const_hweight.h
@@ -0,0 +1,42 @@
+#ifndef _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_
+#define _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_
+
+/*
+ * Compile time versions of __arch_hweightN()
+ */
+#define __const_hweight8(w) \
+ ( (!!((w) & (1ULL << 0))) + \
+ (!!((w) & (1ULL << 1))) + \
+ (!!((w) & (1ULL << 2))) + \
+ (!!((w) & (1ULL << 3))) + \
+ (!!((w) & (1ULL << 4))) + \
+ (!!((w) & (1ULL << 5))) + \
+ (!!((w) & (1ULL << 6))) + \
+ (!!((w) & (1ULL << 7))) )
+
+#define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8 ))
+#define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
+#define __const_hweight64(w) (__const_hweight32(w) + __const_hweight32((w) >> 32))
+
+/*
+ * Generic interface.
+ */
+#define hweight8(w) (__builtin_constant_p(w) ? __const_hweight8(w) : __arch_hweight8(w))
+#define hweight16(w) (__builtin_constant_p(w) ? __const_hweight16(w) : __arch_hweight16(w))
+#define hweight32(w) (__builtin_constant_p(w) ? __const_hweight32(w) : __arch_hweight32(w))
+#define hweight64(w) (__builtin_constant_p(w) ? __const_hweight64(w) : __arch_hweight64(w))
+
+/*
+ * Interface for known constant arguments
+ */
+#define HWEIGHT8(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight8(w))
+#define HWEIGHT16(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight16(w))
+#define HWEIGHT32(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight32(w))
+#define HWEIGHT64(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight64(w))
+
+/*
+ * Type invariant interface to the compile time constant hweight functions.
+ */
+#define HWEIGHT(w) HWEIGHT64((u64)w)
+
+#endif /* _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_ */
diff --git a/include/asm-generic/bitops/hweight.h b/include/asm-generic/bitops/hweight.h
index fbbc383..a94d651 100644
--- a/include/asm-generic/bitops/hweight.h
+++ b/include/asm-generic/bitops/hweight.h
@@ -1,11 +1,7 @@
#ifndef _ASM_GENERIC_BITOPS_HWEIGHT_H_
#define _ASM_GENERIC_BITOPS_HWEIGHT_H_
-#include <asm/types.h>
-
-extern unsigned int hweight32(unsigned int w);
-extern unsigned int hweight16(unsigned int w);
-extern unsigned int hweight8(unsigned int w);
-extern unsigned long hweight64(__u64 w);
+#include <asm-generic/bitops/arch_hweight.h>
+#include <asm-generic/bitops/const_hweight.h>
#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h
index e694263..6920695 100644
--- a/include/asm-generic/dma-mapping-common.h
+++ b/include/asm-generic/dma-mapping-common.h
@@ -131,7 +131,7 @@
debug_dma_sync_single_range_for_cpu(dev, addr, offset, size, dir);
} else
- dma_sync_single_for_cpu(dev, addr, size, dir);
+ dma_sync_single_for_cpu(dev, addr + offset, size, dir);
}
static inline void dma_sync_single_range_for_device(struct device *dev,
@@ -148,7 +148,7 @@
debug_dma_sync_single_range_for_device(dev, addr, offset, size, dir);
} else
- dma_sync_single_for_device(dev, addr, size, dir);
+ dma_sync_single_for_device(dev, addr + offset, size, dir);
}
static inline void
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index e929c27..6b9db91 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -789,34 +789,6 @@
extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo,
bool interruptible);
-/**
- * ttm_bo_block_reservation
- *
- * @bo: A pointer to a struct ttm_buffer_object.
- * @interruptible: Use interruptible sleep when waiting.
- * @no_wait: Don't sleep, but rather return -EBUSY.
- *
- * Block reservation for validation by simply reserving the buffer.
- * This is intended for single buffer use only without eviction,
- * and thus needs no deadlock protection.
- *
- * Returns:
- * -EBUSY: If no_wait == 1 and the buffer is already reserved.
- * -ERESTARTSYS: If interruptible == 1 and the process received a signal
- * while sleeping.
- */
-extern int ttm_bo_block_reservation(struct ttm_buffer_object *bo,
- bool interruptible, bool no_wait);
-
-/**
- * ttm_bo_unblock_reservation
- *
- * @bo: A pointer to a struct ttm_buffer_object.
- *
- * Unblocks reservation leaving lru lists untouched.
- */
-extern void ttm_bo_unblock_reservation(struct ttm_buffer_object *bo);
-
/*
* ttm_bo_util.c
*/
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index b926afe..3da73f5 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -116,11 +116,12 @@
int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
+int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
#ifdef CONFIG_X86_IO_APIC
-extern int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity);
+extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
#else
-#define acpi_get_override_irq(bus, trigger, polarity) (-1)
+#define acpi_get_override_irq(gsi, trigger, polarity) (-1)
#endif
/*
* This function undoes the effect of one call to acpi_register_gsi().
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index b796eab..fc68053 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -10,6 +10,11 @@
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
#endif
+extern unsigned int __sw_hweight8(unsigned int w);
+extern unsigned int __sw_hweight16(unsigned int w);
+extern unsigned int __sw_hweight32(unsigned int w);
+extern unsigned long __sw_hweight64(__u64 w);
+
/*
* Include this here because some architectures need generic_ffs/fls in
* scope
@@ -44,31 +49,6 @@
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
}
-/*
- * Clearly slow versions of the hweightN() functions, their benefit is
- * of course compile time evaluation of constant arguments.
- */
-#define HWEIGHT8(w) \
- ( BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + \
- (!!((w) & (1ULL << 0))) + \
- (!!((w) & (1ULL << 1))) + \
- (!!((w) & (1ULL << 2))) + \
- (!!((w) & (1ULL << 3))) + \
- (!!((w) & (1ULL << 4))) + \
- (!!((w) & (1ULL << 5))) + \
- (!!((w) & (1ULL << 6))) + \
- (!!((w) & (1ULL << 7))) )
-
-#define HWEIGHT16(w) (HWEIGHT8(w) + HWEIGHT8((w) >> 8))
-#define HWEIGHT32(w) (HWEIGHT16(w) + HWEIGHT16((w) >> 16))
-#define HWEIGHT64(w) (HWEIGHT32(w) + HWEIGHT32((w) >> 32))
-
-/*
- * Type invariant version that simply casts things to the
- * largest type.
- */
-#define HWEIGHT(w) HWEIGHT64((u64)(w))
-
/**
* rol32 - rotate a 32-bit value left
* @word: value to rotate
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index b8ad1ea9..8f78073 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -530,6 +530,7 @@
{
return rcu_dereference_check(task->cgroups->subsys[subsys_id],
rcu_read_lock_held() ||
+ lockdep_is_held(&task->alloc_lock) ||
cgroup_lock_is_held());
}
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 4de02b1..9f15150 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -278,6 +278,27 @@
ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count);
};
+#define cpufreq_freq_attr_ro(_name) \
+static struct freq_attr _name = \
+__ATTR(_name, 0444, show_##_name, NULL)
+
+#define cpufreq_freq_attr_ro_perm(_name, _perm) \
+static struct freq_attr _name = \
+__ATTR(_name, _perm, show_##_name, NULL)
+
+#define cpufreq_freq_attr_ro_old(_name) \
+static struct freq_attr _name##_old = \
+__ATTR(_name, 0444, show_##_name##_old, NULL)
+
+#define cpufreq_freq_attr_rw(_name) \
+static struct freq_attr _name = \
+__ATTR(_name, 0644, show_##_name, store_##_name)
+
+#define cpufreq_freq_attr_rw_old(_name) \
+static struct freq_attr _name##_old = \
+__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old)
+
+
struct global_attr {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj,
@@ -286,6 +307,15 @@
const char *c, size_t count);
};
+#define define_one_global_ro(_name) \
+static struct global_attr _name = \
+__ATTR(_name, 0444, show_##_name, NULL)
+
+#define define_one_global_rw(_name) \
+static struct global_attr _name = \
+__ATTR(_name, 0644, show_##_name, store_##_name)
+
+
/*********************************************************************
* CPUFREQ 2.6. INTERFACE *
*********************************************************************/
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 30b93b2..eebb617 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -186,6 +186,8 @@
#define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 /* Parent inode is watched by some fsnotify listener */
+#define DCACHE_CANT_MOUNT 0x0100
+
extern spinlock_t dcache_lock;
extern seqlock_t rename_lock;
@@ -358,6 +360,18 @@
return d_unhashed(dentry) && !IS_ROOT(dentry);
}
+static inline int cant_mount(struct dentry *dentry)
+{
+ return (dentry->d_flags & DCACHE_CANT_MOUNT);
+}
+
+static inline void dont_mount(struct dentry *dentry)
+{
+ spin_lock(&dentry->d_lock);
+ dentry->d_flags |= DCACHE_CANT_MOUNT;
+ spin_unlock(&dentry->d_lock);
+}
+
static inline struct dentry *dget_parent(struct dentry *dentry)
{
struct dentry *ret;
diff --git a/include/linux/debugobjects.h b/include/linux/debugobjects.h
index 8c243aa..597692f 100644
--- a/include/linux/debugobjects.h
+++ b/include/linux/debugobjects.h
@@ -20,12 +20,14 @@
* struct debug_obj - representaion of an tracked object
* @node: hlist node to link the object into the tracker list
* @state: tracked object state
+ * @astate: current active state
* @object: pointer to the real object
* @descr: pointer to an object type specific debug description structure
*/
struct debug_obj {
struct hlist_node node;
enum debug_obj_state state;
+ unsigned int astate;
void *object;
struct debug_obj_descr *descr;
};
@@ -60,6 +62,15 @@
extern void debug_object_destroy (void *addr, struct debug_obj_descr *descr);
extern void debug_object_free (void *addr, struct debug_obj_descr *descr);
+/*
+ * Active state:
+ * - Set at 0 upon initialization.
+ * - Must return to 0 before deactivation.
+ */
+extern void
+debug_object_active_state(void *addr, struct debug_obj_descr *descr,
+ unsigned int expect, unsigned int next);
+
extern void debug_objects_early_init(void);
extern void debug_objects_mem_init(void);
#else
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index dc7fc64..ee8a841 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -180,7 +180,10 @@
*/
unsigned int flags;
+#ifdef CONFIG_PERF_EVENTS
int perf_refcount;
+ struct hlist_head *perf_events;
+#endif
};
#define PERF_MAX_TRACE_SIZE 2048
@@ -237,24 +240,22 @@
DECLARE_PER_CPU(struct pt_regs, perf_trace_regs);
-extern int perf_trace_enable(int event_id);
-extern void perf_trace_disable(int event_id);
-extern int ftrace_profile_set_filter(struct perf_event *event, int event_id,
+extern int perf_trace_init(struct perf_event *event);
+extern void perf_trace_destroy(struct perf_event *event);
+extern int perf_trace_enable(struct perf_event *event);
+extern void perf_trace_disable(struct perf_event *event);
+extern int ftrace_profile_set_filter(struct perf_event *event, int event_id,
char *filter_str);
extern void ftrace_profile_free_filter(struct perf_event *event);
-extern void *
-perf_trace_buf_prepare(int size, unsigned short type, int *rctxp,
- unsigned long *irq_flags);
+extern void *perf_trace_buf_prepare(int size, unsigned short type,
+ struct pt_regs *regs, int *rctxp);
static inline void
perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr,
- u64 count, unsigned long irq_flags, struct pt_regs *regs)
+ u64 count, struct pt_regs *regs, void *head)
{
- struct trace_entry *entry = raw_data;
-
- perf_tp_event(entry->type, addr, count, raw_data, size, regs);
+ perf_tp_event(addr, count, raw_data, size, regs, head);
perf_swevent_put_recursion_context(rctx);
- local_irq_restore(irq_flags);
}
#endif
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index c9bf92c..d94963b 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -79,10 +79,7 @@
IFLA_NET_NS_PID,
IFLA_IFALIAS,
IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */
- IFLA_VF_MAC, /* Hardware queue specific attributes */
- IFLA_VF_VLAN,
- IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */
- IFLA_VFINFO,
+ IFLA_VFINFO_LIST,
__IFLA_MAX
};
@@ -203,6 +200,24 @@
/* SR-IOV virtual function managment section */
+enum {
+ IFLA_VF_INFO_UNSPEC,
+ IFLA_VF_INFO,
+ __IFLA_VF_INFO_MAX,
+};
+
+#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1)
+
+enum {
+ IFLA_VF_UNSPEC,
+ IFLA_VF_MAC, /* Hardware queue specific attributes */
+ IFLA_VF_VLAN,
+ IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */
+ __IFLA_VF_MAX,
+};
+
+#define IFLA_VF_MAX (__IFLA_VF_MAX - 1)
+
struct ifla_vf_mac {
__u32 vf;
__u8 mac[32]; /* MAX_ADDR_LEN */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index b1ed1cd..7996fc2 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -49,7 +49,6 @@
{ .first = &init_task.pids[PIDTYPE_PGID].node }, \
{ .first = &init_task.pids[PIDTYPE_SID].node }, \
}, \
- .rcu = RCU_HEAD_INIT, \
.level = 0, \
.numbers = { { \
.nr = 0, \
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 3af4ffd..be22ad8 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -37,9 +37,9 @@
int (*attach_dev)(struct iommu_domain *domain, struct device *dev);
void (*detach_dev)(struct iommu_domain *domain, struct device *dev);
int (*map)(struct iommu_domain *domain, unsigned long iova,
- phys_addr_t paddr, size_t size, int prot);
- void (*unmap)(struct iommu_domain *domain, unsigned long iova,
- size_t size);
+ phys_addr_t paddr, int gfp_order, int prot);
+ int (*unmap)(struct iommu_domain *domain, unsigned long iova,
+ int gfp_order);
phys_addr_t (*iova_to_phys)(struct iommu_domain *domain,
unsigned long iova);
int (*domain_has_cap)(struct iommu_domain *domain,
@@ -56,10 +56,10 @@
struct device *dev);
extern void iommu_detach_device(struct iommu_domain *domain,
struct device *dev);
-extern int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
- phys_addr_t paddr, size_t size, int prot);
-extern void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
- size_t size);
+extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, int gfp_order, int prot);
+extern int iommu_unmap(struct iommu_domain *domain, unsigned long iova,
+ int gfp_order);
extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long iova);
extern int iommu_domain_has_cap(struct iommu_domain *domain,
@@ -96,16 +96,16 @@
{
}
-static inline int iommu_map_range(struct iommu_domain *domain,
- unsigned long iova, phys_addr_t paddr,
- size_t size, int prot)
+static inline int iommu_map(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, int gfp_order, int prot)
{
return -ENODEV;
}
-static inline void iommu_unmap_range(struct iommu_domain *domain,
- unsigned long iova, size_t size)
+static inline int iommu_unmap(struct iommu_domain *domain, unsigned long iova,
+ int gfp_order)
{
+ return -ENODEV;
}
static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index f58e9d83..56fde43 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -474,4 +474,13 @@
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
+struct zorro_device_id {
+ __u32 id; /* Device ID or ZORRO_WILDCARD */
+ kernel_ulong_t driver_data; /* Data private to the driver */
+};
+
+#define ZORRO_WILDCARD (0xffffffff) /* not official */
+
+#define ZORRO_DEVICE_MODALIAS_FMT "zorro:i%08X"
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 3fd5c82..fb6c91e 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -485,6 +485,7 @@
#include <linux/ftrace.h>
#include <linux/cpu.h>
#include <asm/atomic.h>
+#include <asm/local.h>
#define PERF_MAX_STACK_DEPTH 255
@@ -587,21 +588,19 @@
struct rcu_head rcu_head;
#ifdef CONFIG_PERF_USE_VMALLOC
struct work_struct work;
+ int page_order; /* allocation order */
#endif
- int data_order;
int nr_pages; /* nr of data pages */
int writable; /* are we writable */
int nr_locked; /* nr pages mlocked */
atomic_t poll; /* POLL_ for wakeups */
- atomic_t events; /* event_id limit */
- atomic_long_t head; /* write position */
- atomic_long_t done_head; /* completed head */
-
- atomic_t lock; /* concurrent writes */
- atomic_t wakeup; /* needs a wakeup */
- atomic_t lost; /* nr records lost */
+ local_t head; /* write position */
+ local_t nest; /* nested writers */
+ local_t events; /* event limit */
+ local_t wakeup; /* wakeup stamp */
+ local_t lost; /* nr records lost */
long watermark; /* wakeup watermark */
@@ -728,6 +727,7 @@
perf_overflow_handler_t overflow_handler;
#ifdef CONFIG_EVENT_TRACING
+ struct ftrace_event_call *tp_event;
struct event_filter *filter;
#endif
@@ -803,11 +803,12 @@
struct perf_output_handle {
struct perf_event *event;
struct perf_mmap_data *data;
- unsigned long head;
- unsigned long offset;
+ unsigned long wakeup;
+ unsigned long size;
+ void *addr;
+ int page;
int nmi;
int sample;
- int locked;
};
#ifdef CONFIG_PERF_EVENTS
@@ -993,8 +994,9 @@
}
extern void perf_event_init(void);
-extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
- int entry_size, struct pt_regs *regs);
+extern void perf_tp_event(u64 addr, u64 count, void *record,
+ int entry_size, struct pt_regs *regs,
+ struct hlist_head *head);
extern void perf_bp_event(struct perf_event *event, void *data);
#ifndef perf_misc_flags
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 212da17..5417944 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -44,12 +44,14 @@
extern int platform_add_devices(struct platform_device **, int);
extern struct platform_device *platform_device_register_simple(const char *, int id,
- struct resource *, unsigned int);
+ const struct resource *, unsigned int);
extern struct platform_device *platform_device_register_data(struct device *,
const char *, int, const void *, size_t);
extern struct platform_device *platform_device_alloc(const char *name, int id);
-extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
+extern int platform_device_add_resources(struct platform_device *pdev,
+ const struct resource *res,
+ unsigned int num);
extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size);
extern int platform_device_add(struct platform_device *pdev);
extern void platform_device_del(struct platform_device *pdev);
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index 5210a5c..fe1872e 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -110,6 +110,7 @@
struct rb_root
{
struct rb_node *rb_node;
+ void (*augment_cb)(struct rb_node *node);
};
@@ -129,7 +130,9 @@
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
-#define RB_ROOT (struct rb_root) { NULL, }
+#define RB_ROOT (struct rb_root) { NULL, NULL, }
+#define RB_AUGMENT_ROOT(x) (struct rb_root) { NULL, x}
+
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 07db2fe..b653b4a 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -56,8 +56,6 @@
};
/* Exported common interfaces */
-extern void synchronize_rcu_bh(void);
-extern void synchronize_sched(void);
extern void rcu_barrier(void);
extern void rcu_barrier_bh(void);
extern void rcu_barrier_sched(void);
@@ -66,8 +64,6 @@
/* Internal to kernel */
extern void rcu_init(void);
-extern int rcu_scheduler_active;
-extern void rcu_scheduler_starting(void);
#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
#include <linux/rcutree.h>
@@ -83,6 +79,14 @@
(ptr)->next = NULL; (ptr)->func = NULL; \
} while (0)
+static inline void init_rcu_head_on_stack(struct rcu_head *head)
+{
+}
+
+static inline void destroy_rcu_head_on_stack(struct rcu_head *head)
+{
+}
+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
extern struct lockdep_map rcu_lock_map;
@@ -106,12 +110,13 @@
/**
* rcu_read_lock_held - might we be in RCU read-side critical section?
*
- * If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in
- * an RCU read-side critical section. In absence of CONFIG_PROVE_LOCKING,
+ * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an RCU
+ * read-side critical section. In absence of CONFIG_DEBUG_LOCK_ALLOC,
* this assumes we are in an RCU read-side critical section unless it can
* prove otherwise.
*
- * Check rcu_scheduler_active to prevent false positives during boot.
+ * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
+ * and while lockdep is disabled.
*/
static inline int rcu_read_lock_held(void)
{
@@ -129,13 +134,15 @@
/**
* rcu_read_lock_sched_held - might we be in RCU-sched read-side critical section?
*
- * If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in an
- * RCU-sched read-side critical section. In absence of CONFIG_PROVE_LOCKING,
- * this assumes we are in an RCU-sched read-side critical section unless it
- * can prove otherwise. Note that disabling of preemption (including
- * disabling irqs) counts as an RCU-sched read-side critical section.
+ * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an
+ * RCU-sched read-side critical section. In absence of
+ * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side
+ * critical section unless it can prove otherwise. Note that disabling
+ * of preemption (including disabling irqs) counts as an RCU-sched
+ * read-side critical section.
*
- * Check rcu_scheduler_active to prevent false positives during boot.
+ * Check debug_lockdep_rcu_enabled() to prevent false positives during boot
+ * and while lockdep is disabled.
*/
#ifdef CONFIG_PREEMPT
static inline int rcu_read_lock_sched_held(void)
@@ -177,7 +184,7 @@
#ifdef CONFIG_PREEMPT
static inline int rcu_read_lock_sched_held(void)
{
- return !rcu_scheduler_active || preempt_count() != 0 || irqs_disabled();
+ return preempt_count() != 0 || irqs_disabled();
}
#else /* #ifdef CONFIG_PREEMPT */
static inline int rcu_read_lock_sched_held(void)
@@ -190,6 +197,17 @@
#ifdef CONFIG_PROVE_RCU
+extern int rcu_my_thread_group_empty(void);
+
+#define __do_rcu_dereference_check(c) \
+ do { \
+ static bool __warned; \
+ if (debug_lockdep_rcu_enabled() && !__warned && !(c)) { \
+ __warned = true; \
+ lockdep_rcu_dereference(__FILE__, __LINE__); \
+ } \
+ } while (0)
+
/**
* rcu_dereference_check - rcu_dereference with debug checking
* @p: The pointer to read, prior to dereferencing
@@ -219,8 +237,7 @@
*/
#define rcu_dereference_check(p, c) \
({ \
- if (debug_lockdep_rcu_enabled() && !(c)) \
- lockdep_rcu_dereference(__FILE__, __LINE__); \
+ __do_rcu_dereference_check(c); \
rcu_dereference_raw(p); \
})
@@ -237,8 +254,7 @@
*/
#define rcu_dereference_protected(p, c) \
({ \
- if (debug_lockdep_rcu_enabled() && !(c)) \
- lockdep_rcu_dereference(__FILE__, __LINE__); \
+ __do_rcu_dereference_check(c); \
(p); \
})
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index 0006b2d..e2e8931 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -29,6 +29,10 @@
void rcu_sched_qs(int cpu);
void rcu_bh_qs(int cpu);
+static inline void rcu_note_context_switch(int cpu)
+{
+ rcu_sched_qs(cpu);
+}
#define __rcu_read_lock() preempt_disable()
#define __rcu_read_unlock() preempt_enable()
@@ -72,7 +76,17 @@
{
}
-#define synchronize_rcu synchronize_sched
+extern void synchronize_sched(void);
+
+static inline void synchronize_rcu(void)
+{
+ synchronize_sched();
+}
+
+static inline void synchronize_rcu_bh(void)
+{
+ synchronize_sched();
+}
static inline void synchronize_rcu_expedited(void)
{
@@ -112,4 +126,17 @@
return 0;
}
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+
+extern int rcu_scheduler_active __read_mostly;
+extern void rcu_scheduler_starting(void);
+
+#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
+static inline void rcu_scheduler_starting(void)
+{
+}
+
+#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
#endif /* __LINUX_RCUTINY_H */
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 24e467e..c0ed1c0 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -34,6 +34,7 @@
extern void rcu_sched_qs(int cpu);
extern void rcu_bh_qs(int cpu);
+extern void rcu_note_context_switch(int cpu);
extern int rcu_needs_cpu(int cpu);
#ifdef CONFIG_TREE_PREEMPT_RCU
@@ -85,6 +86,8 @@
extern void call_rcu_sched(struct rcu_head *head,
void (*func)(struct rcu_head *rcu));
+extern void synchronize_rcu_bh(void);
+extern void synchronize_sched(void);
extern void synchronize_rcu_expedited(void);
static inline void synchronize_rcu_bh_expedited(void)
@@ -119,4 +122,7 @@
return num_online_cpus() == 1;
}
+extern void rcu_scheduler_starting(void);
+extern int rcu_scheduler_active __read_mostly;
+
#endif /* __LINUX_RCUTREE_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2a5b146..b55e988 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1493,7 +1493,6 @@
/* bitmask of trace recursion */
unsigned long trace_recursion;
#endif /* CONFIG_TRACING */
- unsigned long stack_start;
#ifdef CONFIG_CGROUP_MEM_RES_CTLR /* memcg uses this to do batch job */
struct memcg_batch_info {
int do_batch; /* incremented when batch uncharge started */
diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index 4d5ecb2..4d5d2f5 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -27,6 +27,8 @@
#ifndef _LINUX_SRCU_H
#define _LINUX_SRCU_H
+#include <linux/mutex.h>
+
struct srcu_struct_array {
int c[2];
};
@@ -84,8 +86,8 @@
/**
* srcu_read_lock_held - might we be in SRCU read-side critical section?
*
- * If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in
- * an SRCU read-side critical section. In absence of CONFIG_PROVE_LOCKING,
+ * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an SRCU
+ * read-side critical section. In absence of CONFIG_DEBUG_LOCK_ALLOC,
* this assumes we are in an SRCU read-side critical section unless it can
* prove otherwise.
*/
diff --git a/include/linux/types.h b/include/linux/types.h
index c42724f..23d237a 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -188,12 +188,12 @@
typedef phys_addr_t resource_size_t;
typedef struct {
- volatile int counter;
+ int counter;
} atomic_t;
#ifdef CONFIG_64BIT
typedef struct {
- volatile long counter;
+ long counter;
} atomic64_t;
#endif
diff --git a/include/linux/zorro.h b/include/linux/zorro.h
index 913bfc2..7bf9db5 100644
--- a/include/linux/zorro.h
+++ b/include/linux/zorro.h
@@ -38,8 +38,6 @@
typedef __u32 zorro_id;
-#define ZORRO_WILDCARD (0xffffffff) /* not official */
-
/* Include the ID list */
#include <linux/zorro_ids.h>
@@ -116,6 +114,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/mod_devicetable.h>
#include <asm/zorro.h>
@@ -142,29 +141,10 @@
* Zorro bus
*/
-struct zorro_bus {
- struct list_head devices; /* list of devices on this bus */
- unsigned int num_resources; /* number of resources */
- struct resource resources[4]; /* address space routed to this bus */
- struct device dev;
- char name[10];
-};
-
-extern struct zorro_bus zorro_bus; /* single Zorro bus */
extern struct bus_type zorro_bus_type;
/*
- * Zorro device IDs
- */
-
-struct zorro_device_id {
- zorro_id id; /* Device ID or ZORRO_WILDCARD */
- unsigned long driver_data; /* Data private to the driver */
-};
-
-
- /*
* Zorro device drivers
*/
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index b9da1f5..4aeff96 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -188,7 +188,6 @@
void saa7146_dma_free(struct saa7146_dev* dev,struct videobuf_queue *q,
struct saa7146_buf *buf);
-int saa7146_vv_devinit(struct saa7146_dev *dev);
int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv);
int saa7146_vv_release(struct saa7146_dev* dev);
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 851c813..61d73e3 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -279,6 +279,7 @@
/* 2nd level prototypes */
void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer);
+void sctp_generate_proto_unreach_event(unsigned long peer);
void sctp_ootb_pkt_free(struct sctp_packet *);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 597f8e2..219043a 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1010,6 +1010,9 @@
/* Heartbeat timer is per destination. */
struct timer_list hb_timer;
+ /* Timer to handle ICMP proto unreachable envets */
+ struct timer_list proto_unreach_timer;
+
/* Since we're using per-destination retransmission timers
* (see above), we're also using per-destination "transmitted"
* queues. This probably ought to be a private struct
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 75be5a2..aa04b9a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1197,30 +1197,15 @@
extern struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *);
extern void tcp_free_md5sig_pool(void);
-extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu);
-extern void __tcp_put_md5sig_pool(void);
+extern struct tcp_md5sig_pool *tcp_get_md5sig_pool(void);
+extern void tcp_put_md5sig_pool(void);
+
extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, struct tcphdr *);
extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, struct sk_buff *,
unsigned header_len);
extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
struct tcp_md5sig_key *key);
-static inline
-struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
-{
- int cpu = get_cpu();
- struct tcp_md5sig_pool *ret = __tcp_get_md5sig_pool(cpu);
- if (!ret)
- put_cpu();
- return ret;
-}
-
-static inline void tcp_put_md5sig_pool(void)
-{
- __tcp_put_md5sig_pool();
- put_cpu();
-}
-
/* write queue abstraction */
static inline void tcp_write_queue_purge(struct sock *sk)
{
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index e0e8daa..0152b86 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -695,14 +695,14 @@
struct ftrace_event_call *event_call = __data; \
struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
struct ftrace_raw_##call *entry; \
- struct pt_regs *__regs = &get_cpu_var(perf_trace_regs); \
+ struct pt_regs __regs; \
u64 __addr = 0, __count = 1; \
- unsigned long irq_flags; \
+ struct hlist_head *head; \
int __entry_size; \
int __data_size; \
int rctx; \
\
- perf_fetch_caller_regs(__regs, 1); \
+ perf_fetch_caller_regs(&__regs, 1); \
\
__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
__entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\
@@ -711,19 +711,20 @@
\
if (WARN_ONCE(__entry_size > PERF_MAX_TRACE_SIZE, \
"profile buffer not large enough")) \
- goto out; \
+ return; \
+ \
entry = (struct ftrace_raw_##call *)perf_trace_buf_prepare( \
- __entry_size, event_call->event.type, &rctx, &irq_flags); \
+ __entry_size, event_call->event.type, &__regs, &rctx); \
if (!entry) \
- goto out; \
+ return; \
+ \
tstruct \
\
{ assign; } \
\
+ head = per_cpu_ptr(event_call->perf_events, smp_processor_id());\
perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \
- __count, irq_flags, __regs); \
- out: \
- put_cpu_var(perf_trace_regs); \
+ __count, &__regs, head); \
}
/*
@@ -736,7 +737,6 @@
static inline void perf_test_probe_##call(void) \
{ \
check_trace_callback_type_##call(perf_trace_##template); \
- \
}
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 722b013..59a009d 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -158,7 +158,7 @@
u->mq_bytes + mq_bytes >
task_rlimit(p, RLIMIT_MSGQUEUE)) {
spin_unlock(&mq_lock);
- kfree(info->messages);
+ /* mqueue_delete_inode() releases info->messages */
goto out_inode;
}
u->mq_bytes += mq_bytes;
diff --git a/kernel/acct.c b/kernel/acct.c
index 24f8c81..e4c0e1f 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -353,17 +353,18 @@
void acct_exit_ns(struct pid_namespace *ns)
{
- struct bsd_acct_struct *acct;
+ struct bsd_acct_struct *acct = ns->bacct;
+ if (acct == NULL)
+ return;
+
+ del_timer_sync(&acct->timer);
spin_lock(&acct_lock);
- acct = ns->bacct;
- if (acct != NULL) {
- if (acct->file != NULL)
- acct_file_reopen(acct, NULL, NULL);
-
- kfree(acct);
- }
+ if (acct->file != NULL)
+ acct_file_reopen(acct, NULL, NULL);
spin_unlock(&acct_lock);
+
+ kfree(acct);
}
/*
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 4a07d05..e9ec642 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1646,7 +1646,9 @@
int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
{
char *start;
- struct dentry *dentry = rcu_dereference(cgrp->dentry);
+ struct dentry *dentry = rcu_dereference_check(cgrp->dentry,
+ rcu_read_lock_held() ||
+ cgroup_lock_is_held());
if (!dentry || cgrp == dummytop) {
/*
@@ -1662,13 +1664,17 @@
*--start = '\0';
for (;;) {
int len = dentry->d_name.len;
+
if ((start -= len) < buf)
return -ENAMETOOLONG;
- memcpy(start, cgrp->dentry->d_name.name, len);
+ memcpy(start, dentry->d_name.name, len);
cgrp = cgrp->parent;
if (!cgrp)
break;
- dentry = rcu_dereference(cgrp->dentry);
+
+ dentry = rcu_dereference_check(cgrp->dentry,
+ rcu_read_lock_held() ||
+ cgroup_lock_is_held());
if (!cgrp->parent)
continue;
if (--start < buf)
@@ -4429,7 +4435,15 @@
*/
unsigned short css_id(struct cgroup_subsys_state *css)
{
- struct css_id *cssid = rcu_dereference(css->id);
+ struct css_id *cssid;
+
+ /*
+ * This css_id() can return correct value when somone has refcnt
+ * on this or this is under rcu_read_lock(). Once css->id is allocated,
+ * it's unchanged until freed.
+ */
+ cssid = rcu_dereference_check(css->id,
+ rcu_read_lock_held() || atomic_read(&css->refcnt));
if (cssid)
return cssid->id;
@@ -4439,7 +4453,10 @@
unsigned short css_depth(struct cgroup_subsys_state *css)
{
- struct css_id *cssid = rcu_dereference(css->id);
+ struct css_id *cssid;
+
+ cssid = rcu_dereference_check(css->id,
+ rcu_read_lock_held() || atomic_read(&css->refcnt));
if (cssid)
return cssid->depth;
@@ -4447,15 +4464,36 @@
}
EXPORT_SYMBOL_GPL(css_depth);
+/**
+ * css_is_ancestor - test "root" css is an ancestor of "child"
+ * @child: the css to be tested.
+ * @root: the css supporsed to be an ancestor of the child.
+ *
+ * Returns true if "root" is an ancestor of "child" in its hierarchy. Because
+ * this function reads css->id, this use rcu_dereference() and rcu_read_lock().
+ * But, considering usual usage, the csses should be valid objects after test.
+ * Assuming that the caller will do some action to the child if this returns
+ * returns true, the caller must take "child";s reference count.
+ * If "child" is valid object and this returns true, "root" is valid, too.
+ */
+
bool css_is_ancestor(struct cgroup_subsys_state *child,
const struct cgroup_subsys_state *root)
{
- struct css_id *child_id = rcu_dereference(child->id);
- struct css_id *root_id = rcu_dereference(root->id);
+ struct css_id *child_id;
+ struct css_id *root_id;
+ bool ret = true;
- if (!child_id || !root_id || (child_id->depth < root_id->depth))
- return false;
- return child_id->stack[root_id->depth] == root_id->id;
+ rcu_read_lock();
+ child_id = rcu_dereference(child->id);
+ root_id = rcu_dereference(root->id);
+ if (!child_id
+ || !root_id
+ || (child_id->depth < root_id->depth)
+ || (child_id->stack[root_id->depth] != root_id->id))
+ ret = false;
+ rcu_read_unlock();
+ return ret;
}
static void __free_css_id_cb(struct rcu_head *head)
@@ -4555,13 +4593,13 @@
{
int subsys_id, i, depth = 0;
struct cgroup_subsys_state *parent_css, *child_css;
- struct css_id *child_id, *parent_id = NULL;
+ struct css_id *child_id, *parent_id;
subsys_id = ss->subsys_id;
parent_css = parent->subsys[subsys_id];
child_css = child->subsys[subsys_id];
- depth = css_depth(parent_css) + 1;
parent_id = parent_css->id;
+ depth = parent_id->depth;
child_id = get_new_cssid(ss, depth);
if (IS_ERR(child_id))
diff --git a/kernel/fork.c b/kernel/fork.c
index 5d3592de..4d57d9e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1111,7 +1111,6 @@
p->memcg_batch.do_batch = 0;
p->memcg_batch.memcg = NULL;
#endif
- p->stack_start = stack_start;
/* Perform scheduler related setup. Assign this task to a CPU. */
sched_fork(p, clone_flags);
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 87ebe8a..474a847 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1134,11 +1134,9 @@
free_reserved_phys_range(end, crashk_res.end);
- if (start == end) {
- crashk_res.end = end;
+ if (start == end)
release_resource(&crashk_res);
- } else
- crashk_res.end = end - 1;
+ crashk_res.end = end - 1;
unlock:
mutex_unlock(&kexec_mutex);
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index e9c759f..ec21304 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -431,20 +431,7 @@
/*
* Various lockdep statistics:
*/
-atomic_t chain_lookup_hits;
-atomic_t chain_lookup_misses;
-atomic_t hardirqs_on_events;
-atomic_t hardirqs_off_events;
-atomic_t redundant_hardirqs_on;
-atomic_t redundant_hardirqs_off;
-atomic_t softirqs_on_events;
-atomic_t softirqs_off_events;
-atomic_t redundant_softirqs_on;
-atomic_t redundant_softirqs_off;
-atomic_t nr_unused_locks;
-atomic_t nr_cyclic_checks;
-atomic_t nr_find_usage_forwards_checks;
-atomic_t nr_find_usage_backwards_checks;
+DEFINE_PER_CPU(struct lockdep_stats, lockdep_stats);
#endif
/*
@@ -748,7 +735,7 @@
return NULL;
}
class = lock_classes + nr_lock_classes++;
- debug_atomic_inc(&nr_unused_locks);
+ debug_atomic_inc(nr_unused_locks);
class->key = key;
class->name = lock->name;
class->subclass = subclass;
@@ -818,7 +805,8 @@
* Add a new dependency to the head of the list:
*/
static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
- struct list_head *head, unsigned long ip, int distance)
+ struct list_head *head, unsigned long ip,
+ int distance, struct stack_trace *trace)
{
struct lock_list *entry;
/*
@@ -829,11 +817,9 @@
if (!entry)
return 0;
- if (!save_trace(&entry->trace))
- return 0;
-
entry->class = this;
entry->distance = distance;
+ entry->trace = *trace;
/*
* Since we never remove from the dependency list, the list can
* be walked lockless by other CPUs, it's only allocation
@@ -1205,7 +1191,7 @@
{
int result;
- debug_atomic_inc(&nr_cyclic_checks);
+ debug_atomic_inc(nr_cyclic_checks);
result = __bfs_forwards(root, target, class_equal, target_entry);
@@ -1242,7 +1228,7 @@
{
int result;
- debug_atomic_inc(&nr_find_usage_forwards_checks);
+ debug_atomic_inc(nr_find_usage_forwards_checks);
result = __bfs_forwards(root, (void *)bit, usage_match, target_entry);
@@ -1265,7 +1251,7 @@
{
int result;
- debug_atomic_inc(&nr_find_usage_backwards_checks);
+ debug_atomic_inc(nr_find_usage_backwards_checks);
result = __bfs_backwards(root, (void *)bit, usage_match, target_entry);
@@ -1635,12 +1621,20 @@
*/
static int
check_prev_add(struct task_struct *curr, struct held_lock *prev,
- struct held_lock *next, int distance)
+ struct held_lock *next, int distance, int trylock_loop)
{
struct lock_list *entry;
int ret;
struct lock_list this;
struct lock_list *uninitialized_var(target_entry);
+ /*
+ * Static variable, serialized by the graph_lock().
+ *
+ * We use this static variable to save the stack trace in case
+ * we call into this function multiple times due to encountering
+ * trylocks in the held lock stack.
+ */
+ static struct stack_trace trace;
/*
* Prove that the new <prev> -> <next> dependency would not
@@ -1688,20 +1682,23 @@
}
}
+ if (!trylock_loop && !save_trace(&trace))
+ return 0;
+
/*
* Ok, all validations passed, add the new lock
* to the previous lock's dependency list:
*/
ret = add_lock_to_list(hlock_class(prev), hlock_class(next),
&hlock_class(prev)->locks_after,
- next->acquire_ip, distance);
+ next->acquire_ip, distance, &trace);
if (!ret)
return 0;
ret = add_lock_to_list(hlock_class(next), hlock_class(prev),
&hlock_class(next)->locks_before,
- next->acquire_ip, distance);
+ next->acquire_ip, distance, &trace);
if (!ret)
return 0;
@@ -1731,6 +1728,7 @@
check_prevs_add(struct task_struct *curr, struct held_lock *next)
{
int depth = curr->lockdep_depth;
+ int trylock_loop = 0;
struct held_lock *hlock;
/*
@@ -1756,7 +1754,8 @@
* added:
*/
if (hlock->read != 2) {
- if (!check_prev_add(curr, hlock, next, distance))
+ if (!check_prev_add(curr, hlock, next,
+ distance, trylock_loop))
return 0;
/*
* Stop after the first non-trylock entry,
@@ -1779,6 +1778,7 @@
if (curr->held_locks[depth].irq_context !=
curr->held_locks[depth-1].irq_context)
break;
+ trylock_loop = 1;
}
return 1;
out_bug:
@@ -1825,7 +1825,7 @@
list_for_each_entry(chain, hash_head, entry) {
if (chain->chain_key == chain_key) {
cache_hit:
- debug_atomic_inc(&chain_lookup_hits);
+ debug_atomic_inc(chain_lookup_hits);
if (very_verbose(class))
printk("\nhash chain already cached, key: "
"%016Lx tail class: [%p] %s\n",
@@ -1890,7 +1890,7 @@
chain_hlocks[chain->base + j] = class - lock_classes;
}
list_add_tail_rcu(&chain->entry, hash_head);
- debug_atomic_inc(&chain_lookup_misses);
+ debug_atomic_inc(chain_lookup_misses);
inc_chains();
return 1;
@@ -2311,7 +2311,12 @@
return;
if (unlikely(curr->hardirqs_enabled)) {
- debug_atomic_inc(&redundant_hardirqs_on);
+ /*
+ * Neither irq nor preemption are disabled here
+ * so this is racy by nature but loosing one hit
+ * in a stat is not a big deal.
+ */
+ __debug_atomic_inc(redundant_hardirqs_on);
return;
}
/* we'll do an OFF -> ON transition: */
@@ -2338,7 +2343,7 @@
curr->hardirq_enable_ip = ip;
curr->hardirq_enable_event = ++curr->irq_events;
- debug_atomic_inc(&hardirqs_on_events);
+ debug_atomic_inc(hardirqs_on_events);
}
EXPORT_SYMBOL(trace_hardirqs_on_caller);
@@ -2370,9 +2375,9 @@
curr->hardirqs_enabled = 0;
curr->hardirq_disable_ip = ip;
curr->hardirq_disable_event = ++curr->irq_events;
- debug_atomic_inc(&hardirqs_off_events);
+ debug_atomic_inc(hardirqs_off_events);
} else
- debug_atomic_inc(&redundant_hardirqs_off);
+ debug_atomic_inc(redundant_hardirqs_off);
}
EXPORT_SYMBOL(trace_hardirqs_off_caller);
@@ -2396,7 +2401,7 @@
return;
if (curr->softirqs_enabled) {
- debug_atomic_inc(&redundant_softirqs_on);
+ debug_atomic_inc(redundant_softirqs_on);
return;
}
@@ -2406,7 +2411,7 @@
curr->softirqs_enabled = 1;
curr->softirq_enable_ip = ip;
curr->softirq_enable_event = ++curr->irq_events;
- debug_atomic_inc(&softirqs_on_events);
+ debug_atomic_inc(softirqs_on_events);
/*
* We are going to turn softirqs on, so set the
* usage bit for all held locks, if hardirqs are
@@ -2436,10 +2441,10 @@
curr->softirqs_enabled = 0;
curr->softirq_disable_ip = ip;
curr->softirq_disable_event = ++curr->irq_events;
- debug_atomic_inc(&softirqs_off_events);
+ debug_atomic_inc(softirqs_off_events);
DEBUG_LOCKS_WARN_ON(!softirq_count());
} else
- debug_atomic_inc(&redundant_softirqs_off);
+ debug_atomic_inc(redundant_softirqs_off);
}
static void __lockdep_trace_alloc(gfp_t gfp_mask, unsigned long flags)
@@ -2644,7 +2649,7 @@
return 0;
break;
case LOCK_USED:
- debug_atomic_dec(&nr_unused_locks);
+ debug_atomic_dec(nr_unused_locks);
break;
default:
if (!debug_locks_off_graph_unlock())
@@ -2750,7 +2755,7 @@
if (!class)
return 0;
}
- debug_atomic_inc((atomic_t *)&class->ops);
+ atomic_inc((atomic_t *)&class->ops);
if (very_verbose(class)) {
printk("\nacquire class [%p] %s", class->key, class->name);
if (class->name_version > 1)
@@ -3801,8 +3806,11 @@
{
struct task_struct *curr = current;
+#ifndef CONFIG_PROVE_RCU_REPEATEDLY
if (!debug_locks_off())
return;
+#endif /* #ifdef CONFIG_PROVE_RCU_REPEATEDLY */
+ /* Note: the following can be executed concurrently, so be careful. */
printk("\n===================================================\n");
printk( "[ INFO: suspicious rcu_dereference_check() usage. ]\n");
printk( "---------------------------------------------------\n");
diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h
index a2ee95a..4f560cf 100644
--- a/kernel/lockdep_internals.h
+++ b/kernel/lockdep_internals.h
@@ -110,30 +110,60 @@
#endif
#ifdef CONFIG_DEBUG_LOCKDEP
+
+#include <asm/local.h>
/*
- * Various lockdep statistics:
+ * Various lockdep statistics.
+ * We want them per cpu as they are often accessed in fast path
+ * and we want to avoid too much cache bouncing.
*/
-extern atomic_t chain_lookup_hits;
-extern atomic_t chain_lookup_misses;
-extern atomic_t hardirqs_on_events;
-extern atomic_t hardirqs_off_events;
-extern atomic_t redundant_hardirqs_on;
-extern atomic_t redundant_hardirqs_off;
-extern atomic_t softirqs_on_events;
-extern atomic_t softirqs_off_events;
-extern atomic_t redundant_softirqs_on;
-extern atomic_t redundant_softirqs_off;
-extern atomic_t nr_unused_locks;
-extern atomic_t nr_cyclic_checks;
-extern atomic_t nr_cyclic_check_recursions;
-extern atomic_t nr_find_usage_forwards_checks;
-extern atomic_t nr_find_usage_forwards_recursions;
-extern atomic_t nr_find_usage_backwards_checks;
-extern atomic_t nr_find_usage_backwards_recursions;
-# define debug_atomic_inc(ptr) atomic_inc(ptr)
-# define debug_atomic_dec(ptr) atomic_dec(ptr)
-# define debug_atomic_read(ptr) atomic_read(ptr)
+struct lockdep_stats {
+ int chain_lookup_hits;
+ int chain_lookup_misses;
+ int hardirqs_on_events;
+ int hardirqs_off_events;
+ int redundant_hardirqs_on;
+ int redundant_hardirqs_off;
+ int softirqs_on_events;
+ int softirqs_off_events;
+ int redundant_softirqs_on;
+ int redundant_softirqs_off;
+ int nr_unused_locks;
+ int nr_cyclic_checks;
+ int nr_cyclic_check_recursions;
+ int nr_find_usage_forwards_checks;
+ int nr_find_usage_forwards_recursions;
+ int nr_find_usage_backwards_checks;
+ int nr_find_usage_backwards_recursions;
+};
+
+DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats);
+
+#define __debug_atomic_inc(ptr) \
+ this_cpu_inc(lockdep_stats.ptr);
+
+#define debug_atomic_inc(ptr) { \
+ WARN_ON_ONCE(!irqs_disabled()); \
+ __this_cpu_inc(lockdep_stats.ptr); \
+}
+
+#define debug_atomic_dec(ptr) { \
+ WARN_ON_ONCE(!irqs_disabled()); \
+ __this_cpu_dec(lockdep_stats.ptr); \
+}
+
+#define debug_atomic_read(ptr) ({ \
+ struct lockdep_stats *__cpu_lockdep_stats; \
+ unsigned long long __total = 0; \
+ int __cpu; \
+ for_each_possible_cpu(__cpu) { \
+ __cpu_lockdep_stats = &per_cpu(lockdep_stats, __cpu); \
+ __total += __cpu_lockdep_stats->ptr; \
+ } \
+ __total; \
+})
#else
+# define __debug_atomic_inc(ptr) do { } while (0)
# define debug_atomic_inc(ptr) do { } while (0)
# define debug_atomic_dec(ptr) do { } while (0)
# define debug_atomic_read(ptr) 0
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index d4aba4f..59b76c8 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -184,34 +184,34 @@
static void lockdep_stats_debug_show(struct seq_file *m)
{
#ifdef CONFIG_DEBUG_LOCKDEP
- unsigned int hi1 = debug_atomic_read(&hardirqs_on_events),
- hi2 = debug_atomic_read(&hardirqs_off_events),
- hr1 = debug_atomic_read(&redundant_hardirqs_on),
- hr2 = debug_atomic_read(&redundant_hardirqs_off),
- si1 = debug_atomic_read(&softirqs_on_events),
- si2 = debug_atomic_read(&softirqs_off_events),
- sr1 = debug_atomic_read(&redundant_softirqs_on),
- sr2 = debug_atomic_read(&redundant_softirqs_off);
+ unsigned long long hi1 = debug_atomic_read(hardirqs_on_events),
+ hi2 = debug_atomic_read(hardirqs_off_events),
+ hr1 = debug_atomic_read(redundant_hardirqs_on),
+ hr2 = debug_atomic_read(redundant_hardirqs_off),
+ si1 = debug_atomic_read(softirqs_on_events),
+ si2 = debug_atomic_read(softirqs_off_events),
+ sr1 = debug_atomic_read(redundant_softirqs_on),
+ sr2 = debug_atomic_read(redundant_softirqs_off);
- seq_printf(m, " chain lookup misses: %11u\n",
- debug_atomic_read(&chain_lookup_misses));
- seq_printf(m, " chain lookup hits: %11u\n",
- debug_atomic_read(&chain_lookup_hits));
- seq_printf(m, " cyclic checks: %11u\n",
- debug_atomic_read(&nr_cyclic_checks));
- seq_printf(m, " find-mask forwards checks: %11u\n",
- debug_atomic_read(&nr_find_usage_forwards_checks));
- seq_printf(m, " find-mask backwards checks: %11u\n",
- debug_atomic_read(&nr_find_usage_backwards_checks));
+ seq_printf(m, " chain lookup misses: %11llu\n",
+ debug_atomic_read(chain_lookup_misses));
+ seq_printf(m, " chain lookup hits: %11llu\n",
+ debug_atomic_read(chain_lookup_hits));
+ seq_printf(m, " cyclic checks: %11llu\n",
+ debug_atomic_read(nr_cyclic_checks));
+ seq_printf(m, " find-mask forwards checks: %11llu\n",
+ debug_atomic_read(nr_find_usage_forwards_checks));
+ seq_printf(m, " find-mask backwards checks: %11llu\n",
+ debug_atomic_read(nr_find_usage_backwards_checks));
- seq_printf(m, " hardirq on events: %11u\n", hi1);
- seq_printf(m, " hardirq off events: %11u\n", hi2);
- seq_printf(m, " redundant hardirq ons: %11u\n", hr1);
- seq_printf(m, " redundant hardirq offs: %11u\n", hr2);
- seq_printf(m, " softirq on events: %11u\n", si1);
- seq_printf(m, " softirq off events: %11u\n", si2);
- seq_printf(m, " redundant softirq ons: %11u\n", sr1);
- seq_printf(m, " redundant softirq offs: %11u\n", sr2);
+ seq_printf(m, " hardirq on events: %11llu\n", hi1);
+ seq_printf(m, " hardirq off events: %11llu\n", hi2);
+ seq_printf(m, " redundant hardirq ons: %11llu\n", hr1);
+ seq_printf(m, " redundant hardirq offs: %11llu\n", hr2);
+ seq_printf(m, " softirq on events: %11llu\n", si1);
+ seq_printf(m, " softirq off events: %11llu\n", si2);
+ seq_printf(m, " redundant softirq ons: %11llu\n", sr1);
+ seq_printf(m, " redundant softirq offs: %11llu\n", sr2);
#endif
}
@@ -263,7 +263,7 @@
#endif
}
#ifdef CONFIG_DEBUG_LOCKDEP
- DEBUG_LOCKS_WARN_ON(debug_atomic_read(&nr_unused_locks) != nr_unused);
+ DEBUG_LOCKS_WARN_ON(debug_atomic_read(nr_unused_locks) != nr_unused);
#endif
seq_printf(m, " lock-classes: %11lu [max: %lu]\n",
nr_lock_classes, MAX_LOCKDEP_KEYS);
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index a4fa381..e099650 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -2297,11 +2297,6 @@
rcu_read_unlock();
}
-static unsigned long perf_data_size(struct perf_mmap_data *data)
-{
- return data->nr_pages << (PAGE_SHIFT + data->data_order);
-}
-
#ifndef CONFIG_PERF_USE_VMALLOC
/*
@@ -2320,6 +2315,19 @@
return virt_to_page(data->data_pages[pgoff - 1]);
}
+static void *perf_mmap_alloc_page(int cpu)
+{
+ struct page *page;
+ int node;
+
+ node = (cpu == -1) ? cpu : cpu_to_node(cpu);
+ page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
+ if (!page)
+ return NULL;
+
+ return page_address(page);
+}
+
static struct perf_mmap_data *
perf_mmap_data_alloc(struct perf_event *event, int nr_pages)
{
@@ -2336,17 +2344,16 @@
if (!data)
goto fail;
- data->user_page = (void *)get_zeroed_page(GFP_KERNEL);
+ data->user_page = perf_mmap_alloc_page(event->cpu);
if (!data->user_page)
goto fail_user_page;
for (i = 0; i < nr_pages; i++) {
- data->data_pages[i] = (void *)get_zeroed_page(GFP_KERNEL);
+ data->data_pages[i] = perf_mmap_alloc_page(event->cpu);
if (!data->data_pages[i])
goto fail_data_pages;
}
- data->data_order = 0;
data->nr_pages = nr_pages;
return data;
@@ -2382,6 +2389,11 @@
kfree(data);
}
+static inline int page_order(struct perf_mmap_data *data)
+{
+ return 0;
+}
+
#else
/*
@@ -2390,10 +2402,15 @@
* Required for architectures that have d-cache aliasing issues.
*/
+static inline int page_order(struct perf_mmap_data *data)
+{
+ return data->page_order;
+}
+
static struct page *
perf_mmap_to_page(struct perf_mmap_data *data, unsigned long pgoff)
{
- if (pgoff > (1UL << data->data_order))
+ if (pgoff > (1UL << page_order(data)))
return NULL;
return vmalloc_to_page((void *)data->user_page + pgoff * PAGE_SIZE);
@@ -2413,7 +2430,7 @@
int i, nr;
data = container_of(work, struct perf_mmap_data, work);
- nr = 1 << data->data_order;
+ nr = 1 << page_order(data);
base = data->user_page;
for (i = 0; i < nr + 1; i++)
@@ -2452,7 +2469,7 @@
data->user_page = all_buf;
data->data_pages[0] = all_buf + PAGE_SIZE;
- data->data_order = ilog2(nr_pages);
+ data->page_order = ilog2(nr_pages);
data->nr_pages = 1;
return data;
@@ -2466,6 +2483,11 @@
#endif
+static unsigned long perf_data_size(struct perf_mmap_data *data)
+{
+ return data->nr_pages << (PAGE_SHIFT + page_order(data));
+}
+
static int perf_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct perf_event *event = vma->vm_file->private_data;
@@ -2506,8 +2528,6 @@
{
long max_size = perf_data_size(data);
- atomic_set(&data->lock, -1);
-
if (event->attr.watermark) {
data->watermark = min_t(long, max_size,
event->attr.wakeup_watermark);
@@ -2580,6 +2600,14 @@
long user_extra, extra;
int ret = 0;
+ /*
+ * Don't allow mmap() of inherited per-task counters. This would
+ * create a performance issue due to all children writing to the
+ * same buffer.
+ */
+ if (event->cpu == -1 && event->attr.inherit)
+ return -EINVAL;
+
if (!(vma->vm_flags & VM_SHARED))
return -EINVAL;
@@ -2885,120 +2913,80 @@
}
/*
- * Curious locking construct.
- *
* We need to ensure a later event_id doesn't publish a head when a former
- * event_id isn't done writing. However since we need to deal with NMIs we
+ * event isn't done writing. However since we need to deal with NMIs we
* cannot fully serialize things.
*
- * What we do is serialize between CPUs so we only have to deal with NMI
- * nesting on a single CPU.
- *
* We only publish the head (and generate a wakeup) when the outer-most
- * event_id completes.
+ * event completes.
*/
-static void perf_output_lock(struct perf_output_handle *handle)
+static void perf_output_get_handle(struct perf_output_handle *handle)
{
struct perf_mmap_data *data = handle->data;
- int cur, cpu = get_cpu();
- handle->locked = 0;
-
- for (;;) {
- cur = atomic_cmpxchg(&data->lock, -1, cpu);
- if (cur == -1) {
- handle->locked = 1;
- break;
- }
- if (cur == cpu)
- break;
-
- cpu_relax();
- }
+ preempt_disable();
+ local_inc(&data->nest);
+ handle->wakeup = local_read(&data->wakeup);
}
-static void perf_output_unlock(struct perf_output_handle *handle)
+static void perf_output_put_handle(struct perf_output_handle *handle)
{
struct perf_mmap_data *data = handle->data;
unsigned long head;
- int cpu;
-
- data->done_head = data->head;
-
- if (!handle->locked)
- goto out;
again:
- /*
- * The xchg implies a full barrier that ensures all writes are done
- * before we publish the new head, matched by a rmb() in userspace when
- * reading this position.
- */
- while ((head = atomic_long_xchg(&data->done_head, 0)))
- data->user_page->data_head = head;
+ head = local_read(&data->head);
/*
- * NMI can happen here, which means we can miss a done_head update.
+ * IRQ/NMI can happen here, which means we can miss a head update.
*/
- cpu = atomic_xchg(&data->lock, -1);
- WARN_ON_ONCE(cpu != smp_processor_id());
+ if (!local_dec_and_test(&data->nest))
+ goto out;
/*
- * Therefore we have to validate we did not indeed do so.
+ * Publish the known good head. Rely on the full barrier implied
+ * by atomic_dec_and_test() order the data->head read and this
+ * write.
*/
- if (unlikely(atomic_long_read(&data->done_head))) {
- /*
- * Since we had it locked, we can lock it again.
- */
- while (atomic_cmpxchg(&data->lock, -1, cpu) != -1)
- cpu_relax();
+ data->user_page->data_head = head;
+ /*
+ * Now check if we missed an update, rely on the (compiler)
+ * barrier in atomic_dec_and_test() to re-read data->head.
+ */
+ if (unlikely(head != local_read(&data->head))) {
+ local_inc(&data->nest);
goto again;
}
- if (atomic_xchg(&data->wakeup, 0))
+ if (handle->wakeup != local_read(&data->wakeup))
perf_output_wakeup(handle);
-out:
- put_cpu();
+
+ out:
+ preempt_enable();
}
-void perf_output_copy(struct perf_output_handle *handle,
+__always_inline void perf_output_copy(struct perf_output_handle *handle,
const void *buf, unsigned int len)
{
- unsigned int pages_mask;
- unsigned long offset;
- unsigned int size;
- void **pages;
-
- offset = handle->offset;
- pages_mask = handle->data->nr_pages - 1;
- pages = handle->data->data_pages;
-
do {
- unsigned long page_offset;
- unsigned long page_size;
- int nr;
+ unsigned long size = min_t(unsigned long, handle->size, len);
- nr = (offset >> PAGE_SHIFT) & pages_mask;
- page_size = 1UL << (handle->data->data_order + PAGE_SHIFT);
- page_offset = offset & (page_size - 1);
- size = min_t(unsigned int, page_size - page_offset, len);
+ memcpy(handle->addr, buf, size);
- memcpy(pages[nr] + page_offset, buf, size);
+ len -= size;
+ handle->addr += size;
+ handle->size -= size;
+ if (!handle->size) {
+ struct perf_mmap_data *data = handle->data;
- len -= size;
- buf += size;
- offset += size;
+ handle->page++;
+ handle->page &= data->nr_pages - 1;
+ handle->addr = data->data_pages[handle->page];
+ handle->size = PAGE_SIZE << page_order(data);
+ }
} while (len);
-
- handle->offset = offset;
-
- /*
- * Check we didn't copy past our reservation window, taking the
- * possible unsigned int wrap into account.
- */
- WARN_ON_ONCE(((long)(handle->head - handle->offset)) < 0);
}
int perf_output_begin(struct perf_output_handle *handle,
@@ -3036,13 +3024,13 @@
handle->sample = sample;
if (!data->nr_pages)
- goto fail;
+ goto out;
- have_lost = atomic_read(&data->lost);
+ have_lost = local_read(&data->lost);
if (have_lost)
size += sizeof(lost_event);
- perf_output_lock(handle);
+ perf_output_get_handle(handle);
do {
/*
@@ -3052,24 +3040,28 @@
*/
tail = ACCESS_ONCE(data->user_page->data_tail);
smp_rmb();
- offset = head = atomic_long_read(&data->head);
+ offset = head = local_read(&data->head);
head += size;
if (unlikely(!perf_output_space(data, tail, offset, head)))
goto fail;
- } while (atomic_long_cmpxchg(&data->head, offset, head) != offset);
+ } while (local_cmpxchg(&data->head, offset, head) != offset);
- handle->offset = offset;
- handle->head = head;
+ if (head - local_read(&data->wakeup) > data->watermark)
+ local_add(data->watermark, &data->wakeup);
- if (head - tail > data->watermark)
- atomic_set(&data->wakeup, 1);
+ handle->page = offset >> (PAGE_SHIFT + page_order(data));
+ handle->page &= data->nr_pages - 1;
+ handle->size = offset & ((PAGE_SIZE << page_order(data)) - 1);
+ handle->addr = data->data_pages[handle->page];
+ handle->addr += handle->size;
+ handle->size = (PAGE_SIZE << page_order(data)) - handle->size;
if (have_lost) {
lost_event.header.type = PERF_RECORD_LOST;
lost_event.header.misc = 0;
lost_event.header.size = sizeof(lost_event);
lost_event.id = event->id;
- lost_event.lost = atomic_xchg(&data->lost, 0);
+ lost_event.lost = local_xchg(&data->lost, 0);
perf_output_put(handle, lost_event);
}
@@ -3077,8 +3069,8 @@
return 0;
fail:
- atomic_inc(&data->lost);
- perf_output_unlock(handle);
+ local_inc(&data->lost);
+ perf_output_put_handle(handle);
out:
rcu_read_unlock();
@@ -3093,14 +3085,14 @@
int wakeup_events = event->attr.wakeup_events;
if (handle->sample && wakeup_events) {
- int events = atomic_inc_return(&data->events);
+ int events = local_inc_return(&data->events);
if (events >= wakeup_events) {
- atomic_sub(wakeup_events, &data->events);
- atomic_set(&data->wakeup, 1);
+ local_sub(wakeup_events, &data->events);
+ local_inc(&data->wakeup);
}
}
- perf_output_unlock(handle);
+ perf_output_put_handle(handle);
rcu_read_unlock();
}
@@ -3436,22 +3428,13 @@
{
struct perf_output_handle handle;
struct task_struct *task = task_event->task;
- unsigned long flags;
int size, ret;
- /*
- * If this CPU attempts to acquire an rq lock held by a CPU spinning
- * in perf_output_lock() from interrupt context, it's game over.
- */
- local_irq_save(flags);
-
size = task_event->event_id.header.size;
ret = perf_output_begin(&handle, event, size, 0, 0);
- if (ret) {
- local_irq_restore(flags);
+ if (ret)
return;
- }
task_event->event_id.pid = perf_event_pid(event, task);
task_event->event_id.ppid = perf_event_pid(event, current);
@@ -3462,7 +3445,6 @@
perf_output_put(&handle, task_event->event_id);
perf_output_end(&handle);
- local_irq_restore(flags);
}
static int perf_event_task_match(struct perf_event *event)
@@ -4020,9 +4002,6 @@
perf_swevent_overflow(event, 0, nmi, data, regs);
}
-static int perf_tp_event_match(struct perf_event *event,
- struct perf_sample_data *data);
-
static int perf_exclude_event(struct perf_event *event,
struct pt_regs *regs)
{
@@ -4052,10 +4031,6 @@
if (perf_exclude_event(event, regs))
return 0;
- if (event->attr.type == PERF_TYPE_TRACEPOINT &&
- !perf_tp_event_match(event, data))
- return 0;
-
return 1;
}
@@ -4066,19 +4041,46 @@
return hash_64(val, SWEVENT_HLIST_BITS);
}
-static struct hlist_head *
-find_swevent_head(struct perf_cpu_context *ctx, u64 type, u32 event_id)
+static inline struct hlist_head *
+__find_swevent_head(struct swevent_hlist *hlist, u64 type, u32 event_id)
{
- u64 hash;
- struct swevent_hlist *hlist;
+ u64 hash = swevent_hash(type, event_id);
- hash = swevent_hash(type, event_id);
+ return &hlist->heads[hash];
+}
+
+/* For the read side: events when they trigger */
+static inline struct hlist_head *
+find_swevent_head_rcu(struct perf_cpu_context *ctx, u64 type, u32 event_id)
+{
+ struct swevent_hlist *hlist;
hlist = rcu_dereference(ctx->swevent_hlist);
if (!hlist)
return NULL;
- return &hlist->heads[hash];
+ return __find_swevent_head(hlist, type, event_id);
+}
+
+/* For the event head insertion and removal in the hlist */
+static inline struct hlist_head *
+find_swevent_head(struct perf_cpu_context *ctx, struct perf_event *event)
+{
+ struct swevent_hlist *hlist;
+ u32 event_id = event->attr.config;
+ u64 type = event->attr.type;
+
+ /*
+ * Event scheduling is always serialized against hlist allocation
+ * and release. Which makes the protected version suitable here.
+ * The context lock guarantees that.
+ */
+ hlist = rcu_dereference_protected(ctx->swevent_hlist,
+ lockdep_is_held(&event->ctx->lock));
+ if (!hlist)
+ return NULL;
+
+ return __find_swevent_head(hlist, type, event_id);
}
static void do_perf_sw_event(enum perf_type_id type, u32 event_id,
@@ -4095,7 +4097,7 @@
rcu_read_lock();
- head = find_swevent_head(cpuctx, type, event_id);
+ head = find_swevent_head_rcu(cpuctx, type, event_id);
if (!head)
goto end;
@@ -4110,7 +4112,7 @@
int perf_swevent_get_recursion_context(void)
{
- struct perf_cpu_context *cpuctx = &get_cpu_var(perf_cpu_context);
+ struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
int rctx;
if (in_nmi())
@@ -4122,10 +4124,8 @@
else
rctx = 0;
- if (cpuctx->recursion[rctx]) {
- put_cpu_var(perf_cpu_context);
+ if (cpuctx->recursion[rctx])
return -1;
- }
cpuctx->recursion[rctx]++;
barrier();
@@ -4139,7 +4139,6 @@
struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
barrier();
cpuctx->recursion[rctx]--;
- put_cpu_var(perf_cpu_context);
}
EXPORT_SYMBOL_GPL(perf_swevent_put_recursion_context);
@@ -4150,6 +4149,7 @@
struct perf_sample_data data;
int rctx;
+ preempt_disable_notrace();
rctx = perf_swevent_get_recursion_context();
if (rctx < 0)
return;
@@ -4159,6 +4159,7 @@
do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, nmi, &data, regs);
perf_swevent_put_recursion_context(rctx);
+ preempt_enable_notrace();
}
static void perf_swevent_read(struct perf_event *event)
@@ -4178,7 +4179,7 @@
perf_swevent_set_period(event);
}
- head = find_swevent_head(cpuctx, event->attr.type, event->attr.config);
+ head = find_swevent_head(cpuctx, event);
if (WARN_ON_ONCE(!head))
return -EINVAL;
@@ -4366,6 +4367,14 @@
.read = task_clock_perf_event_read,
};
+/* Deref the hlist from the update side */
+static inline struct swevent_hlist *
+swevent_hlist_deref(struct perf_cpu_context *cpuctx)
+{
+ return rcu_dereference_protected(cpuctx->swevent_hlist,
+ lockdep_is_held(&cpuctx->hlist_mutex));
+}
+
static void swevent_hlist_release_rcu(struct rcu_head *rcu_head)
{
struct swevent_hlist *hlist;
@@ -4376,12 +4385,11 @@
static void swevent_hlist_release(struct perf_cpu_context *cpuctx)
{
- struct swevent_hlist *hlist;
+ struct swevent_hlist *hlist = swevent_hlist_deref(cpuctx);
- if (!cpuctx->swevent_hlist)
+ if (!hlist)
return;
- hlist = cpuctx->swevent_hlist;
rcu_assign_pointer(cpuctx->swevent_hlist, NULL);
call_rcu(&hlist->rcu_head, swevent_hlist_release_rcu);
}
@@ -4418,7 +4426,7 @@
mutex_lock(&cpuctx->hlist_mutex);
- if (!cpuctx->swevent_hlist && cpu_online(cpu)) {
+ if (!swevent_hlist_deref(cpuctx) && cpu_online(cpu)) {
struct swevent_hlist *hlist;
hlist = kzalloc(sizeof(*hlist), GFP_KERNEL);
@@ -4467,25 +4475,14 @@
#ifdef CONFIG_EVENT_TRACING
-void perf_tp_event(int event_id, u64 addr, u64 count, void *record,
- int entry_size, struct pt_regs *regs)
-{
- struct perf_sample_data data;
- struct perf_raw_record raw = {
- .size = entry_size,
- .data = record,
- };
+static const struct pmu perf_ops_tracepoint = {
+ .enable = perf_trace_enable,
+ .disable = perf_trace_disable,
+ .read = perf_swevent_read,
+ .unthrottle = perf_swevent_unthrottle,
+};
- perf_sample_data_init(&data, addr);
- data.raw = &raw;
-
- /* Trace events already protected against recursion */
- do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1,
- &data, regs);
-}
-EXPORT_SYMBOL_GPL(perf_tp_event);
-
-static int perf_tp_event_match(struct perf_event *event,
+static int perf_tp_filter_match(struct perf_event *event,
struct perf_sample_data *data)
{
void *record = data->raw->data;
@@ -4495,10 +4492,49 @@
return 0;
}
+static int perf_tp_event_match(struct perf_event *event,
+ struct perf_sample_data *data,
+ struct pt_regs *regs)
+{
+ /*
+ * All tracepoints are from kernel-space.
+ */
+ if (event->attr.exclude_kernel)
+ return 0;
+
+ if (!perf_tp_filter_match(event, data))
+ return 0;
+
+ return 1;
+}
+
+void perf_tp_event(u64 addr, u64 count, void *record, int entry_size,
+ struct pt_regs *regs, struct hlist_head *head)
+{
+ struct perf_sample_data data;
+ struct perf_event *event;
+ struct hlist_node *node;
+
+ struct perf_raw_record raw = {
+ .size = entry_size,
+ .data = record,
+ };
+
+ perf_sample_data_init(&data, addr);
+ data.raw = &raw;
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(event, node, head, hlist_entry) {
+ if (perf_tp_event_match(event, &data, regs))
+ perf_swevent_add(event, count, 1, &data, regs);
+ }
+ rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(perf_tp_event);
+
static void tp_perf_event_destroy(struct perf_event *event)
{
- perf_trace_disable(event->attr.config);
- swevent_hlist_put(event);
+ perf_trace_destroy(event);
}
static const struct pmu *tp_perf_event_init(struct perf_event *event)
@@ -4514,17 +4550,13 @@
!capable(CAP_SYS_ADMIN))
return ERR_PTR(-EPERM);
- if (perf_trace_enable(event->attr.config))
+ err = perf_trace_init(event);
+ if (err)
return NULL;
event->destroy = tp_perf_event_destroy;
- err = swevent_hlist_get(event);
- if (err) {
- perf_trace_disable(event->attr.config);
- return ERR_PTR(err);
- }
- return &perf_ops_generic;
+ return &perf_ops_tracepoint;
}
static int perf_event_set_filter(struct perf_event *event, void __user *arg)
@@ -4552,12 +4584,6 @@
#else
-static int perf_tp_event_match(struct perf_event *event,
- struct perf_sample_data *data)
-{
- return 1;
-}
-
static const struct pmu *tp_perf_event_init(struct perf_event *event)
{
return NULL;
@@ -4894,6 +4920,13 @@
int fput_needed = 0;
int ret = -EINVAL;
+ /*
+ * Don't allow output of inherited per-task events. This would
+ * create performance issues due to cross cpu access.
+ */
+ if (event->cpu == -1 && event->attr.inherit)
+ return -EINVAL;
+
if (!output_fd)
goto set;
@@ -4914,6 +4947,18 @@
if (event->data)
goto out;
+ /*
+ * Don't allow cross-cpu buffers
+ */
+ if (output_event->cpu != event->cpu)
+ goto out;
+
+ /*
+ * If its not a per-cpu buffer, it must be the same task.
+ */
+ if (output_event->cpu == -1 && output_event->ctx != event->ctx)
+ goto out;
+
atomic_long_inc(&output_file->f_count);
set:
diff --git a/kernel/profile.c b/kernel/profile.c
index a55d3a3..dfadc5b 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -127,8 +127,10 @@
return 0;
prof_buffer = vmalloc(buffer_bytes);
- if (prof_buffer)
+ if (prof_buffer) {
+ memset(prof_buffer, 0, buffer_bytes);
return 0;
+ }
free_cpumask_var(prof_cpu_mask);
return -ENOMEM;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 9fb5123..6af9cdd 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -14,7 +14,6 @@
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
#include <linux/ptrace.h>
#include <linux/security.h>
#include <linux/signal.h>
@@ -665,10 +664,6 @@
struct task_struct *child;
long ret;
- /*
- * This lock_kernel fixes a subtle race with suid exec
- */
- lock_kernel();
if (request == PTRACE_TRACEME) {
ret = ptrace_traceme();
if (!ret)
@@ -702,7 +697,6 @@
out_put_task_struct:
put_task_struct(child);
out:
- unlock_kernel();
return ret;
}
@@ -812,10 +806,6 @@
struct task_struct *child;
long ret;
- /*
- * This lock_kernel fixes a subtle race with suid exec
- */
- lock_kernel();
if (request == PTRACE_TRACEME) {
ret = ptrace_traceme();
goto out;
@@ -845,7 +835,6 @@
out_put_task_struct:
put_task_struct(child);
out:
- unlock_kernel();
return ret;
}
#endif /* CONFIG_COMPAT */
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 03a7ea1..72a8dc9 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -44,7 +44,6 @@
#include <linux/cpu.h>
#include <linux/mutex.h>
#include <linux/module.h>
-#include <linux/kernel_stat.h>
#include <linux/hardirq.h>
#ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -64,9 +63,6 @@
EXPORT_SYMBOL_GPL(rcu_sched_lock_map);
#endif
-int rcu_scheduler_active __read_mostly;
-EXPORT_SYMBOL_GPL(rcu_scheduler_active);
-
#ifdef CONFIG_DEBUG_LOCK_ALLOC
int debug_lockdep_rcu_enabled(void)
@@ -97,21 +93,6 @@
#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
/*
- * This function is invoked towards the end of the scheduler's initialization
- * process. Before this is called, the idle task might contain
- * RCU read-side critical sections (during which time, this idle
- * task is booting the system). After this function is called, the
- * idle tasks are prohibited from containing RCU read-side critical
- * sections.
- */
-void rcu_scheduler_starting(void)
-{
- WARN_ON(num_online_cpus() != 1);
- WARN_ON(nr_context_switches() > 0);
- rcu_scheduler_active = 1;
-}
-
-/*
* Awaken the corresponding synchronize_rcu() instance now that a
* grace period has elapsed.
*/
@@ -122,3 +103,14 @@
rcu = container_of(head, struct rcu_synchronize, head);
complete(&rcu->completion);
}
+
+#ifdef CONFIG_PROVE_RCU
+/*
+ * wrapper function to avoid #include problems.
+ */
+int rcu_my_thread_group_empty(void)
+{
+ return thread_group_empty(current);
+}
+EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty);
+#endif /* #ifdef CONFIG_PROVE_RCU */
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index 9f6d9ff..38729d3 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -44,9 +44,9 @@
};
/* Definition for rcupdate control block. */
-static struct rcu_ctrlblk rcu_ctrlblk = {
- .donetail = &rcu_ctrlblk.rcucblist,
- .curtail = &rcu_ctrlblk.rcucblist,
+static struct rcu_ctrlblk rcu_sched_ctrlblk = {
+ .donetail = &rcu_sched_ctrlblk.rcucblist,
+ .curtail = &rcu_sched_ctrlblk.rcucblist,
};
static struct rcu_ctrlblk rcu_bh_ctrlblk = {
@@ -54,6 +54,11 @@
.curtail = &rcu_bh_ctrlblk.rcucblist,
};
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+int rcu_scheduler_active __read_mostly;
+EXPORT_SYMBOL_GPL(rcu_scheduler_active);
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
#ifdef CONFIG_NO_HZ
static long rcu_dynticks_nesting = 1;
@@ -108,7 +113,8 @@
*/
void rcu_sched_qs(int cpu)
{
- if (rcu_qsctr_help(&rcu_ctrlblk) + rcu_qsctr_help(&rcu_bh_ctrlblk))
+ if (rcu_qsctr_help(&rcu_sched_ctrlblk) +
+ rcu_qsctr_help(&rcu_bh_ctrlblk))
raise_softirq(RCU_SOFTIRQ);
}
@@ -173,7 +179,7 @@
*/
static void rcu_process_callbacks(struct softirq_action *unused)
{
- __rcu_process_callbacks(&rcu_ctrlblk);
+ __rcu_process_callbacks(&rcu_sched_ctrlblk);
__rcu_process_callbacks(&rcu_bh_ctrlblk);
}
@@ -187,7 +193,8 @@
*
* Cool, huh? (Due to Josh Triplett.)
*
- * But we want to make this a static inline later.
+ * But we want to make this a static inline later. The cond_resched()
+ * currently makes this problematic.
*/
void synchronize_sched(void)
{
@@ -195,12 +202,6 @@
}
EXPORT_SYMBOL_GPL(synchronize_sched);
-void synchronize_rcu_bh(void)
-{
- synchronize_sched();
-}
-EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
-
/*
* Helper function for call_rcu() and call_rcu_bh().
*/
@@ -226,7 +227,7 @@
*/
void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
{
- __call_rcu(head, func, &rcu_ctrlblk);
+ __call_rcu(head, func, &rcu_sched_ctrlblk);
}
EXPORT_SYMBOL_GPL(call_rcu);
@@ -244,11 +245,13 @@
{
struct rcu_synchronize rcu;
+ init_rcu_head_on_stack(&rcu.head);
init_completion(&rcu.completion);
/* Will wake me after RCU finished. */
call_rcu(&rcu.head, wakeme_after_rcu);
/* Wait for it. */
wait_for_completion(&rcu.completion);
+ destroy_rcu_head_on_stack(&rcu.head);
}
EXPORT_SYMBOL_GPL(rcu_barrier);
@@ -256,11 +259,13 @@
{
struct rcu_synchronize rcu;
+ init_rcu_head_on_stack(&rcu.head);
init_completion(&rcu.completion);
/* Will wake me after RCU finished. */
call_rcu_bh(&rcu.head, wakeme_after_rcu);
/* Wait for it. */
wait_for_completion(&rcu.completion);
+ destroy_rcu_head_on_stack(&rcu.head);
}
EXPORT_SYMBOL_GPL(rcu_barrier_bh);
@@ -268,11 +273,13 @@
{
struct rcu_synchronize rcu;
+ init_rcu_head_on_stack(&rcu.head);
init_completion(&rcu.completion);
/* Will wake me after RCU finished. */
call_rcu_sched(&rcu.head, wakeme_after_rcu);
/* Wait for it. */
wait_for_completion(&rcu.completion);
+ destroy_rcu_head_on_stack(&rcu.head);
}
EXPORT_SYMBOL_GPL(rcu_barrier_sched);
@@ -280,3 +287,5 @@
{
open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
}
+
+#include "rcutiny_plugin.h"
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
new file mode 100644
index 0000000..d223a92bc
--- /dev/null
+++ b/kernel/rcutiny_plugin.h
@@ -0,0 +1,39 @@
+/*
+ * Read-Copy Update mechanism for mutual exclusion (tree-based version)
+ * Internal non-public definitions that provide either classic
+ * or preemptable semantics.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright IBM Corporation, 2009
+ *
+ * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+ */
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+
+#include <linux/kernel_stat.h>
+
+/*
+ * During boot, we forgive RCU lockdep issues. After this function is
+ * invoked, we start taking RCU lockdep issues seriously.
+ */
+void rcu_scheduler_starting(void)
+{
+ WARN_ON(nr_context_switches() > 0);
+ rcu_scheduler_active = 1;
+}
+
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 2b676f3..6535ac8 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -464,9 +464,11 @@
{
struct rcu_bh_torture_synchronize rcu;
+ init_rcu_head_on_stack(&rcu.head);
init_completion(&rcu.completion);
call_rcu_bh(&rcu.head, rcu_bh_torture_wakeme_after_cb);
wait_for_completion(&rcu.completion);
+ destroy_rcu_head_on_stack(&rcu.head);
}
static struct rcu_torture_ops rcu_bh_ops = {
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 3ec8160..d443734 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -46,6 +46,7 @@
#include <linux/cpu.h>
#include <linux/mutex.h>
#include <linux/time.h>
+#include <linux/kernel_stat.h>
#include "rcutree.h"
@@ -53,8 +54,8 @@
static struct lock_class_key rcu_node_class[NUM_RCU_LVLS];
-#define RCU_STATE_INITIALIZER(name) { \
- .level = { &name.node[0] }, \
+#define RCU_STATE_INITIALIZER(structname) { \
+ .level = { &structname.node[0] }, \
.levelcnt = { \
NUM_RCU_LVL_0, /* root of hierarchy. */ \
NUM_RCU_LVL_1, \
@@ -65,13 +66,14 @@
.signaled = RCU_GP_IDLE, \
.gpnum = -300, \
.completed = -300, \
- .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&name.onofflock), \
+ .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&structname.onofflock), \
.orphan_cbs_list = NULL, \
- .orphan_cbs_tail = &name.orphan_cbs_list, \
+ .orphan_cbs_tail = &structname.orphan_cbs_list, \
.orphan_qlen = 0, \
- .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&name.fqslock), \
+ .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&structname.fqslock), \
.n_force_qs = 0, \
.n_force_qs_ngp = 0, \
+ .name = #structname, \
}
struct rcu_state rcu_sched_state = RCU_STATE_INITIALIZER(rcu_sched_state);
@@ -80,6 +82,9 @@
struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state);
DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);
+int rcu_scheduler_active __read_mostly;
+EXPORT_SYMBOL_GPL(rcu_scheduler_active);
+
/*
* Return true if an RCU grace period is in progress. The ACCESS_ONCE()s
* permit this function to be invoked without holding the root rcu_node
@@ -97,25 +102,32 @@
*/
void rcu_sched_qs(int cpu)
{
- struct rcu_data *rdp;
+ struct rcu_data *rdp = &per_cpu(rcu_sched_data, cpu);
- rdp = &per_cpu(rcu_sched_data, cpu);
rdp->passed_quiesc_completed = rdp->gpnum - 1;
barrier();
rdp->passed_quiesc = 1;
- rcu_preempt_note_context_switch(cpu);
}
void rcu_bh_qs(int cpu)
{
- struct rcu_data *rdp;
+ struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu);
- rdp = &per_cpu(rcu_bh_data, cpu);
rdp->passed_quiesc_completed = rdp->gpnum - 1;
barrier();
rdp->passed_quiesc = 1;
}
+/*
+ * Note a context switch. This is a quiescent state for RCU-sched,
+ * and requires special handling for preemptible RCU.
+ */
+void rcu_note_context_switch(int cpu)
+{
+ rcu_sched_qs(cpu);
+ rcu_preempt_note_context_switch(cpu);
+}
+
#ifdef CONFIG_NO_HZ
DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
.dynticks_nesting = 1,
@@ -438,6 +450,8 @@
#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
+int rcu_cpu_stall_panicking __read_mostly;
+
static void record_gp_stall_check_time(struct rcu_state *rsp)
{
rsp->gp_start = jiffies;
@@ -470,7 +484,8 @@
/* OK, time to rat on our buddy... */
- printk(KERN_ERR "INFO: RCU detected CPU stalls:");
+ printk(KERN_ERR "INFO: %s detected stalls on CPUs/tasks: {",
+ rsp->name);
rcu_for_each_leaf_node(rsp, rnp) {
raw_spin_lock_irqsave(&rnp->lock, flags);
rcu_print_task_stall(rnp);
@@ -481,7 +496,7 @@
if (rnp->qsmask & (1UL << cpu))
printk(" %d", rnp->grplo + cpu);
}
- printk(" (detected by %d, t=%ld jiffies)\n",
+ printk("} (detected by %d, t=%ld jiffies)\n",
smp_processor_id(), (long)(jiffies - rsp->gp_start));
trigger_all_cpu_backtrace();
@@ -497,8 +512,8 @@
unsigned long flags;
struct rcu_node *rnp = rcu_get_root(rsp);
- printk(KERN_ERR "INFO: RCU detected CPU %d stall (t=%lu jiffies)\n",
- smp_processor_id(), jiffies - rsp->gp_start);
+ printk(KERN_ERR "INFO: %s detected stall on CPU %d (t=%lu jiffies)\n",
+ rsp->name, smp_processor_id(), jiffies - rsp->gp_start);
trigger_all_cpu_backtrace();
raw_spin_lock_irqsave(&rnp->lock, flags);
@@ -515,6 +530,8 @@
long delta;
struct rcu_node *rnp;
+ if (rcu_cpu_stall_panicking)
+ return;
delta = jiffies - rsp->jiffies_stall;
rnp = rdp->mynode;
if ((rnp->qsmask & rdp->grpmask) && delta >= 0) {
@@ -529,6 +546,21 @@
}
}
+static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
+{
+ rcu_cpu_stall_panicking = 1;
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block rcu_panic_block = {
+ .notifier_call = rcu_panic,
+};
+
+static void __init check_cpu_stall_init(void)
+{
+ atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block);
+}
+
#else /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
static void record_gp_stall_check_time(struct rcu_state *rsp)
@@ -539,6 +571,10 @@
{
}
+static void __init check_cpu_stall_init(void)
+{
+}
+
#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
/*
@@ -1125,8 +1161,6 @@
*/
void rcu_check_callbacks(int cpu, int user)
{
- if (!rcu_pending(cpu))
- return; /* if nothing for RCU to do. */
if (user ||
(idle_cpu(cpu) && rcu_scheduler_active &&
!in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
@@ -1158,7 +1192,8 @@
rcu_bh_qs(cpu);
}
rcu_preempt_check_callbacks(cpu);
- raise_softirq(RCU_SOFTIRQ);
+ if (rcu_pending(cpu))
+ raise_softirq(RCU_SOFTIRQ);
}
#ifdef CONFIG_SMP
@@ -1236,11 +1271,11 @@
break; /* grace period idle or initializing, ignore. */
case RCU_SAVE_DYNTICK:
-
- raw_spin_unlock(&rnp->lock); /* irqs remain disabled */
if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK)
break; /* So gcc recognizes the dead code. */
+ raw_spin_unlock(&rnp->lock); /* irqs remain disabled */
+
/* Record dyntick-idle state. */
force_qs_rnp(rsp, dyntick_save_progress_counter);
raw_spin_lock(&rnp->lock); /* irqs already disabled */
@@ -1449,11 +1484,13 @@
if (rcu_blocking_is_gp())
return;
+ init_rcu_head_on_stack(&rcu.head);
init_completion(&rcu.completion);
/* Will wake me after RCU finished. */
call_rcu_sched(&rcu.head, wakeme_after_rcu);
/* Wait for it. */
wait_for_completion(&rcu.completion);
+ destroy_rcu_head_on_stack(&rcu.head);
}
EXPORT_SYMBOL_GPL(synchronize_sched);
@@ -1473,11 +1510,13 @@
if (rcu_blocking_is_gp())
return;
+ init_rcu_head_on_stack(&rcu.head);
init_completion(&rcu.completion);
/* Will wake me after RCU finished. */
call_rcu_bh(&rcu.head, wakeme_after_rcu);
/* Wait for it. */
wait_for_completion(&rcu.completion);
+ destroy_rcu_head_on_stack(&rcu.head);
}
EXPORT_SYMBOL_GPL(synchronize_rcu_bh);
@@ -1498,8 +1537,20 @@
check_cpu_stall(rsp, rdp);
/* Is the RCU core waiting for a quiescent state from this CPU? */
- if (rdp->qs_pending) {
+ if (rdp->qs_pending && !rdp->passed_quiesc) {
+
+ /*
+ * If force_quiescent_state() coming soon and this CPU
+ * needs a quiescent state, and this is either RCU-sched
+ * or RCU-bh, force a local reschedule.
+ */
rdp->n_rp_qs_pending++;
+ if (!rdp->preemptable &&
+ ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs) - 1,
+ jiffies))
+ set_need_resched();
+ } else if (rdp->qs_pending && rdp->passed_quiesc) {
+ rdp->n_rp_report_qs++;
return 1;
}
@@ -1767,6 +1818,21 @@
}
/*
+ * This function is invoked towards the end of the scheduler's initialization
+ * process. Before this is called, the idle task might contain
+ * RCU read-side critical sections (during which time, this idle
+ * task is booting the system). After this function is called, the
+ * idle tasks are prohibited from containing RCU read-side critical
+ * sections. This function also enables RCU lockdep checking.
+ */
+void rcu_scheduler_starting(void)
+{
+ WARN_ON(num_online_cpus() != 1);
+ WARN_ON(nr_context_switches() > 0);
+ rcu_scheduler_active = 1;
+}
+
+/*
* Compute the per-level fanout, either using the exact fanout specified
* or balancing the tree, depending on CONFIG_RCU_FANOUT_EXACT.
*/
@@ -1849,6 +1915,14 @@
INIT_LIST_HEAD(&rnp->blocked_tasks[3]);
}
}
+
+ rnp = rsp->level[NUM_RCU_LVLS - 1];
+ for_each_possible_cpu(i) {
+ while (i > rnp->grphi)
+ rnp++;
+ rsp->rda[i]->mynode = rnp;
+ rcu_boot_init_percpu_data(i, rsp);
+ }
}
/*
@@ -1859,19 +1933,11 @@
#define RCU_INIT_FLAVOR(rsp, rcu_data) \
do { \
int i; \
- int j; \
- struct rcu_node *rnp; \
\
- rcu_init_one(rsp); \
- rnp = (rsp)->level[NUM_RCU_LVLS - 1]; \
- j = 0; \
for_each_possible_cpu(i) { \
- if (i > rnp[j].grphi) \
- j++; \
- per_cpu(rcu_data, i).mynode = &rnp[j]; \
(rsp)->rda[i] = &per_cpu(rcu_data, i); \
- rcu_boot_init_percpu_data(i, rsp); \
} \
+ rcu_init_one(rsp); \
} while (0)
void __init rcu_init(void)
@@ -1879,12 +1945,6 @@
int cpu;
rcu_bootup_announce();
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
- printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n");
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
-#if NUM_RCU_LVL_4 != 0
- printk(KERN_INFO "Experimental four-level hierarchy is enabled.\n");
-#endif /* #if NUM_RCU_LVL_4 != 0 */
RCU_INIT_FLAVOR(&rcu_sched_state, rcu_sched_data);
RCU_INIT_FLAVOR(&rcu_bh_state, rcu_bh_data);
__rcu_init_preempt();
@@ -1898,6 +1958,7 @@
cpu_notifier(rcu_cpu_notify, 0);
for_each_online_cpu(cpu)
rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
+ check_cpu_stall_init();
}
#include "rcutree_plugin.h"
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 4a525a3..14c040b 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -223,6 +223,7 @@
/* 5) __rcu_pending() statistics. */
unsigned long n_rcu_pending; /* rcu_pending() calls since boot. */
unsigned long n_rp_qs_pending;
+ unsigned long n_rp_report_qs;
unsigned long n_rp_cb_ready;
unsigned long n_rp_cpu_needs_gp;
unsigned long n_rp_gp_completed;
@@ -326,6 +327,7 @@
unsigned long jiffies_stall; /* Time at which to check */
/* for CPU stalls. */
#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
+ char *name; /* Name of structure. */
};
/* Return values for rcu_preempt_offline_tasks(). */
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 79b53bd..0e4f420 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -26,6 +26,45 @@
#include <linux/delay.h>
+/*
+ * Check the RCU kernel configuration parameters and print informative
+ * messages about anything out of the ordinary. If you like #ifdef, you
+ * will love this function.
+ */
+static void __init rcu_bootup_announce_oddness(void)
+{
+#ifdef CONFIG_RCU_TRACE
+ printk(KERN_INFO "\tRCU debugfs-based tracing is enabled.\n");
+#endif
+#if (defined(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 64) || (!defined(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 32)
+ printk(KERN_INFO "\tCONFIG_RCU_FANOUT set to non-default value of %d\n",
+ CONFIG_RCU_FANOUT);
+#endif
+#ifdef CONFIG_RCU_FANOUT_EXACT
+ printk(KERN_INFO "\tHierarchical RCU autobalancing is disabled.\n");
+#endif
+#ifdef CONFIG_RCU_FAST_NO_HZ
+ printk(KERN_INFO
+ "\tRCU dyntick-idle grace-period acceleration is enabled.\n");
+#endif
+#ifdef CONFIG_PROVE_RCU
+ printk(KERN_INFO "\tRCU lockdep checking is enabled.\n");
+#endif
+#ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE
+ printk(KERN_INFO "\tRCU torture testing starts during boot.\n");
+#endif
+#ifndef CONFIG_RCU_CPU_STALL_DETECTOR
+ printk(KERN_INFO
+ "\tRCU-based detection of stalled CPUs is disabled.\n");
+#endif
+#ifndef CONFIG_RCU_CPU_STALL_VERBOSE
+ printk(KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n");
+#endif
+#if NUM_RCU_LVL_4 != 0
+ printk(KERN_INFO "\tExperimental four-level hierarchy is enabled.\n");
+#endif
+}
+
#ifdef CONFIG_TREE_PREEMPT_RCU
struct rcu_state rcu_preempt_state = RCU_STATE_INITIALIZER(rcu_preempt_state);
@@ -38,8 +77,8 @@
*/
static void __init rcu_bootup_announce(void)
{
- printk(KERN_INFO
- "Experimental preemptable hierarchical RCU implementation.\n");
+ printk(KERN_INFO "Preemptable hierarchical RCU implementation.\n");
+ rcu_bootup_announce_oddness();
}
/*
@@ -75,13 +114,19 @@
* that this just means that the task currently running on the CPU is
* not in a quiescent state. There might be any number of tasks blocked
* while in an RCU read-side critical section.
+ *
+ * Unlike the other rcu_*_qs() functions, callers to this function
+ * must disable irqs in order to protect the assignment to
+ * ->rcu_read_unlock_special.
*/
static void rcu_preempt_qs(int cpu)
{
struct rcu_data *rdp = &per_cpu(rcu_preempt_data, cpu);
+
rdp->passed_quiesc_completed = rdp->gpnum - 1;
barrier();
rdp->passed_quiesc = 1;
+ current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
}
/*
@@ -144,9 +189,8 @@
* grace period, then the fact that the task has been enqueued
* means that we continue to block the current grace period.
*/
- rcu_preempt_qs(cpu);
local_irq_save(flags);
- t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
+ rcu_preempt_qs(cpu);
local_irq_restore(flags);
}
@@ -236,7 +280,6 @@
*/
special = t->rcu_read_unlock_special;
if (special & RCU_READ_UNLOCK_NEED_QS) {
- t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
rcu_preempt_qs(smp_processor_id());
}
@@ -473,7 +516,6 @@
struct task_struct *t = current;
if (t->rcu_read_lock_nesting == 0) {
- t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS;
rcu_preempt_qs(cpu);
return;
}
@@ -515,11 +557,13 @@
if (!rcu_scheduler_active)
return;
+ init_rcu_head_on_stack(&rcu.head);
init_completion(&rcu.completion);
/* Will wake me after RCU finished. */
call_rcu(&rcu.head, wakeme_after_rcu);
/* Wait for it. */
wait_for_completion(&rcu.completion);
+ destroy_rcu_head_on_stack(&rcu.head);
}
EXPORT_SYMBOL_GPL(synchronize_rcu);
@@ -754,6 +798,7 @@
static void __init rcu_bootup_announce(void)
{
printk(KERN_INFO "Hierarchical RCU implementation.\n");
+ rcu_bootup_announce_oddness();
}
/*
@@ -1008,6 +1053,8 @@
int rcu_needs_cpu(int cpu)
{
int c = 0;
+ int snap;
+ int snap_nmi;
int thatcpu;
/* Check for being in the holdoff period. */
@@ -1015,12 +1062,18 @@
return rcu_needs_cpu_quick_check(cpu);
/* Don't bother unless we are the last non-dyntick-idle CPU. */
- for_each_cpu_not(thatcpu, nohz_cpu_mask)
- if (thatcpu != cpu) {
+ for_each_online_cpu(thatcpu) {
+ if (thatcpu == cpu)
+ continue;
+ snap = per_cpu(rcu_dynticks, thatcpu).dynticks;
+ snap_nmi = per_cpu(rcu_dynticks, thatcpu).dynticks_nmi;
+ smp_mb(); /* Order sampling of snap with end of grace period. */
+ if (((snap & 0x1) != 0) || ((snap_nmi & 0x1) != 0)) {
per_cpu(rcu_dyntick_drain, cpu) = 0;
per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1;
return rcu_needs_cpu_quick_check(cpu);
}
+ }
/* Check and update the rcu_dyntick_drain sequencing. */
if (per_cpu(rcu_dyntick_drain, cpu) <= 0) {
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index d45db2e..36c95b4 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -241,11 +241,13 @@
static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
{
seq_printf(m, "%3d%cnp=%ld "
- "qsp=%ld cbr=%ld cng=%ld gpc=%ld gps=%ld nf=%ld nn=%ld\n",
+ "qsp=%ld rpq=%ld cbr=%ld cng=%ld "
+ "gpc=%ld gps=%ld nf=%ld nn=%ld\n",
rdp->cpu,
cpu_is_offline(rdp->cpu) ? '!' : ' ',
rdp->n_rcu_pending,
rdp->n_rp_qs_pending,
+ rdp->n_rp_report_qs,
rdp->n_rp_cb_ready,
rdp->n_rp_cpu_needs_gp,
rdp->n_rp_gp_completed,
diff --git a/kernel/sched.c b/kernel/sched.c
index 78554dd..1d93cd0 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3608,7 +3608,7 @@
preempt_disable();
cpu = smp_processor_id();
rq = cpu_rq(cpu);
- rcu_sched_qs(cpu);
+ rcu_note_context_switch(cpu);
prev = rq->curr;
switch_count = &prev->nivcsw;
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
index 9cf1baf..87a330a 100644
--- a/kernel/sched_debug.c
+++ b/kernel/sched_debug.c
@@ -114,7 +114,9 @@
{
char path[64];
+ rcu_read_lock();
cgroup_path(task_group(p)->css.cgroup, path, sizeof(path));
+ rcu_read_unlock();
SEQ_printf(m, " %s", path);
}
#endif
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 7c1a67e..0db913a 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -716,7 +716,7 @@
preempt_enable_no_resched();
cond_resched();
preempt_disable();
- rcu_sched_qs((long)__bind_cpu);
+ rcu_note_context_switch((long)__bind_cpu);
}
preempt_enable();
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index ef51d1f..b4e7431 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -294,7 +294,6 @@
struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
unsigned int cpu = (unsigned long)hcpu;
struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
- struct cpu_stop_work *work;
struct task_struct *p;
switch (action & ~CPU_TASKS_FROZEN) {
@@ -323,6 +322,9 @@
#ifdef CONFIG_HOTPLUG_CPU
case CPU_UP_CANCELED:
case CPU_DEAD:
+ {
+ struct cpu_stop_work *work;
+
/* kill the stopper */
kthread_stop(stopper->thread);
/* drain remaining works */
@@ -335,6 +337,7 @@
put_task_struct(stopper->thread);
stopper->thread = NULL;
break;
+ }
#endif
}
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 0a47e8d..26b8607 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -9,13 +9,9 @@
#include <linux/kprobes.h>
#include "trace.h"
-DEFINE_PER_CPU(struct pt_regs, perf_trace_regs);
-EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_regs);
-
EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs);
-static char *perf_trace_buf;
-static char *perf_trace_buf_nmi;
+static char *perf_trace_buf[4];
/*
* Force it to be aligned to unsigned long to avoid misaligned accesses
@@ -27,63 +23,82 @@
/* Count the events in use (per event id, not per instance) */
static int total_ref_count;
-static int perf_trace_event_enable(struct ftrace_event_call *event)
+static int perf_trace_event_init(struct ftrace_event_call *tp_event,
+ struct perf_event *p_event)
{
- char *buf;
+ struct hlist_head *list;
int ret = -ENOMEM;
+ int cpu;
- if (event->perf_refcount++ > 0)
+ p_event->tp_event = tp_event;
+ if (tp_event->perf_refcount++ > 0)
return 0;
+ list = alloc_percpu(struct hlist_head);
+ if (!list)
+ goto fail;
+
+ for_each_possible_cpu(cpu)
+ INIT_HLIST_HEAD(per_cpu_ptr(list, cpu));
+
+ tp_event->perf_events = list;
+
if (!total_ref_count) {
- buf = (char *)alloc_percpu(perf_trace_t);
- if (!buf)
- goto fail_buf;
+ char *buf;
+ int i;
- rcu_assign_pointer(perf_trace_buf, buf);
+ for (i = 0; i < 4; i++) {
+ buf = (char *)alloc_percpu(perf_trace_t);
+ if (!buf)
+ goto fail;
- buf = (char *)alloc_percpu(perf_trace_t);
- if (!buf)
- goto fail_buf_nmi;
-
- rcu_assign_pointer(perf_trace_buf_nmi, buf);
+ perf_trace_buf[i] = buf;
+ }
}
- if (event->class->reg)
- ret = event->class->reg(event, TRACE_REG_PERF_REGISTER);
+ if (tp_event->class->reg)
+ ret = tp_event->class->reg(tp_event, TRACE_REG_PERF_REGISTER);
else
- ret = tracepoint_probe_register(event->name,
- event->class->perf_probe,
- event);
- if (!ret) {
- total_ref_count++;
- return 0;
+ ret = tracepoint_probe_register(tp_event->name,
+ tp_event->class->perf_probe,
+ tp_event);
+
+ if (ret)
+ goto fail;
+
+ total_ref_count++;
+ return 0;
+
+fail:
+ if (!total_ref_count) {
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ free_percpu(perf_trace_buf[i]);
+ perf_trace_buf[i] = NULL;
+ }
}
-fail_buf_nmi:
- if (!total_ref_count) {
- free_percpu(perf_trace_buf_nmi);
- free_percpu(perf_trace_buf);
- perf_trace_buf_nmi = NULL;
- perf_trace_buf = NULL;
+ if (!--tp_event->perf_refcount) {
+ free_percpu(tp_event->perf_events);
+ tp_event->perf_events = NULL;
}
-fail_buf:
- event->perf_refcount--;
return ret;
}
-int perf_trace_enable(int event_id)
+int perf_trace_init(struct perf_event *p_event)
{
- struct ftrace_event_call *event;
+ struct ftrace_event_call *tp_event;
+ int event_id = p_event->attr.config;
int ret = -EINVAL;
mutex_lock(&event_mutex);
- list_for_each_entry(event, &ftrace_events, list) {
- if (event->event.type == event_id &&
- event->class && event->class->perf_probe &&
- try_module_get(event->mod)) {
- ret = perf_trace_event_enable(event);
+ list_for_each_entry(tp_event, &ftrace_events, list) {
+ if (tp_event->event.type == event_id &&
+ tp_event->class && tp_event->class->perf_probe &&
+ try_module_get(tp_event->mod)) {
+ ret = perf_trace_event_init(tp_event, p_event);
break;
}
}
@@ -92,93 +107,76 @@
return ret;
}
-static void perf_trace_event_disable(struct ftrace_event_call *event)
+int perf_trace_enable(struct perf_event *p_event)
{
- char *buf, *nmi_buf;
+ struct ftrace_event_call *tp_event = p_event->tp_event;
+ struct hlist_head *list;
- if (--event->perf_refcount > 0)
- return;
+ list = tp_event->perf_events;
+ if (WARN_ON_ONCE(!list))
+ return -EINVAL;
- if (event->class->reg)
- event->class->reg(event, TRACE_REG_PERF_UNREGISTER);
- else
- tracepoint_probe_unregister(event->name, event->class->perf_probe, event);
+ list = per_cpu_ptr(list, smp_processor_id());
+ hlist_add_head_rcu(&p_event->hlist_entry, list);
- if (!--total_ref_count) {
- buf = perf_trace_buf;
- rcu_assign_pointer(perf_trace_buf, NULL);
-
- nmi_buf = perf_trace_buf_nmi;
- rcu_assign_pointer(perf_trace_buf_nmi, NULL);
-
- /*
- * Ensure every events in profiling have finished before
- * releasing the buffers
- */
- synchronize_sched();
-
- free_percpu(buf);
- free_percpu(nmi_buf);
- }
+ return 0;
}
-void perf_trace_disable(int event_id)
+void perf_trace_disable(struct perf_event *p_event)
{
- struct ftrace_event_call *event;
+ hlist_del_rcu(&p_event->hlist_entry);
+}
- mutex_lock(&event_mutex);
- list_for_each_entry(event, &ftrace_events, list) {
- if (event->event.type == event_id) {
- perf_trace_event_disable(event);
- module_put(event->mod);
- break;
+void perf_trace_destroy(struct perf_event *p_event)
+{
+ struct ftrace_event_call *tp_event = p_event->tp_event;
+ int i;
+
+ if (--tp_event->perf_refcount > 0)
+ return;
+
+ if (tp_event->class->reg)
+ tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER);
+ else
+ tracepoint_probe_unregister(tp_event->name,
+ tp_event->class->perf_probe,
+ tp_event);
+
+ free_percpu(tp_event->perf_events);
+ tp_event->perf_events = NULL;
+
+ if (!--total_ref_count) {
+ for (i = 0; i < 4; i++) {
+ free_percpu(perf_trace_buf[i]);
+ perf_trace_buf[i] = NULL;
}
}
- mutex_unlock(&event_mutex);
}
__kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
- int *rctxp, unsigned long *irq_flags)
+ struct pt_regs *regs, int *rctxp)
{
struct trace_entry *entry;
- char *trace_buf, *raw_data;
- int pc, cpu;
+ char *raw_data;
+ int pc;
BUILD_BUG_ON(PERF_MAX_TRACE_SIZE % sizeof(unsigned long));
pc = preempt_count();
- /* Protect the per cpu buffer, begin the rcu read side */
- local_irq_save(*irq_flags);
-
*rctxp = perf_swevent_get_recursion_context();
if (*rctxp < 0)
- goto err_recursion;
+ return NULL;
- cpu = smp_processor_id();
-
- if (in_nmi())
- trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);
- else
- trace_buf = rcu_dereference_sched(perf_trace_buf);
-
- if (!trace_buf)
- goto err;
-
- raw_data = per_cpu_ptr(trace_buf, cpu);
+ raw_data = per_cpu_ptr(perf_trace_buf[*rctxp], smp_processor_id());
/* zero the dead bytes from align to not leak stack to user */
memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64));
entry = (struct trace_entry *)raw_data;
- tracing_generic_entry_update(entry, *irq_flags, pc);
+ tracing_generic_entry_update(entry, regs->flags, pc);
entry->type = type;
return raw_data;
-err:
- perf_swevent_put_recursion_context(*rctxp);
-err_recursion:
- local_irq_restore(*irq_flags);
- return NULL;
}
EXPORT_SYMBOL_GPL(perf_trace_buf_prepare);
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 9a082bb..faf7cef 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1338,9 +1338,9 @@
struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
struct ftrace_event_call *call = &tp->call;
struct kprobe_trace_entry_head *entry;
+ struct hlist_head *head;
u8 *data;
int size, __size, i;
- unsigned long irq_flags;
int rctx;
__size = sizeof(*entry) + tp->size;
@@ -1350,8 +1350,7 @@
"profile buffer not large enough"))
return;
- entry = perf_trace_buf_prepare(size, call->event.type,
- &rctx, &irq_flags);
+ entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
if (!entry)
return;
@@ -1360,7 +1359,8 @@
for (i = 0; i < tp->nr_args; i++)
call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
- perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs);
+ head = per_cpu_ptr(call->perf_events, smp_processor_id());
+ perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head);
}
/* Kretprobe profile handler */
@@ -1370,9 +1370,9 @@
struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
struct ftrace_event_call *call = &tp->call;
struct kretprobe_trace_entry_head *entry;
+ struct hlist_head *head;
u8 *data;
int size, __size, i;
- unsigned long irq_flags;
int rctx;
__size = sizeof(*entry) + tp->size;
@@ -1382,8 +1382,7 @@
"profile buffer not large enough"))
return;
- entry = perf_trace_buf_prepare(size, call->event.type,
- &rctx, &irq_flags);
+ entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
if (!entry)
return;
@@ -1393,8 +1392,8 @@
for (i = 0; i < tp->nr_args; i++)
call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset);
- perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1,
- irq_flags, regs);
+ head = per_cpu_ptr(call->perf_events, smp_processor_id());
+ perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head);
}
static int probe_perf_enable(struct ftrace_event_call *call)
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 9d35830..d2c859c 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -488,7 +488,7 @@
{
struct syscall_metadata *sys_data;
struct syscall_trace_enter *rec;
- unsigned long flags;
+ struct hlist_head *head;
int syscall_nr;
int rctx;
int size;
@@ -511,15 +511,16 @@
return;
rec = (struct syscall_trace_enter *)perf_trace_buf_prepare(size,
- sys_data->enter_event->event.type,
- &rctx, &flags);
+ sys_data->enter_event->event.type, regs, &rctx);
if (!rec)
return;
rec->nr = syscall_nr;
syscall_get_arguments(current, regs, 0, sys_data->nb_args,
(unsigned long *)&rec->args);
- perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs);
+
+ head = per_cpu_ptr(sys_data->enter_event->perf_events, smp_processor_id());
+ perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head);
}
int perf_sysenter_enable(struct ftrace_event_call *call)
@@ -561,7 +562,7 @@
{
struct syscall_metadata *sys_data;
struct syscall_trace_exit *rec;
- unsigned long flags;
+ struct hlist_head *head;
int syscall_nr;
int rctx;
int size;
@@ -587,15 +588,15 @@
return;
rec = (struct syscall_trace_exit *)perf_trace_buf_prepare(size,
- sys_data->exit_event->event.type,
- &rctx, &flags);
+ sys_data->exit_event->event.type, regs, &rctx);
if (!rec)
return;
rec->nr = syscall_nr;
rec->ret = syscall_get_return_value(current, regs);
- perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs);
+ head = per_cpu_ptr(sys_data->exit_event->perf_events, smp_processor_id());
+ perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head);
}
int perf_sysexit_enable(struct ftrace_event_call *call)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 935248b..d85be90 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -512,6 +512,18 @@
Say N if you are unsure.
+config PROVE_RCU_REPEATEDLY
+ bool "RCU debugging: don't disable PROVE_RCU on first splat"
+ depends on PROVE_RCU
+ default n
+ help
+ By itself, PROVE_RCU will disable checking upon issuing the
+ first warning (or "splat"). This feature prevents such
+ disabling, allowing multiple RCU-lockdep warnings to be printed
+ on a single reboot.
+
+ Say N if you are unsure.
+
config LOCKDEP
bool
depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
@@ -793,7 +805,7 @@
config RCU_CPU_STALL_VERBOSE
bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR"
depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU
- default n
+ default y
help
This option causes RCU to printk detailed per-task information
for any tasks that are stalling the current RCU grace period.
@@ -1086,6 +1098,13 @@
This option causes a performance degredation. Use only if you want
to debug device drivers. If unsure, say N.
+config ATOMIC64_SELFTEST
+ bool "Perform an atomic64_t self-test at boot"
+ help
+ Enable this option to test the atomic64_t functions at boot.
+
+ If unsure, say N.
+
source "samples/Kconfig"
source "lib/Kconfig.kgdb"
diff --git a/lib/Makefile b/lib/Makefile
index 0d40152..9e6d3c2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -39,7 +39,10 @@
lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o
lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
+
+CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
+
obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
obj-$(CONFIG_BTREE) += btree.o
obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
@@ -101,6 +104,8 @@
obj-$(CONFIG_GENERIC_ATOMIC64) += atomic64.o
+obj-$(CONFIG_ATOMIC64_SELFTEST) += atomic64_test.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/lib/atomic64.c b/lib/atomic64.c
index 8bee16e..a21c12b 100644
--- a/lib/atomic64.c
+++ b/lib/atomic64.c
@@ -162,12 +162,12 @@
{
unsigned long flags;
spinlock_t *lock = lock_addr(v);
- int ret = 1;
+ int ret = 0;
spin_lock_irqsave(lock, flags);
if (v->counter != u) {
v->counter += a;
- ret = 0;
+ ret = 1;
}
spin_unlock_irqrestore(lock, flags);
return ret;
diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c
new file mode 100644
index 0000000..65e482c
--- /dev/null
+++ b/lib/atomic64_test.c
@@ -0,0 +1,164 @@
+/*
+ * Testsuite for atomic64_t functions
+ *
+ * Copyright © 2010 Luca Barbieri
+ *
+ * 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.
+ */
+#include <linux/init.h>
+#include <asm/atomic.h>
+
+#define INIT(c) do { atomic64_set(&v, c); r = c; } while (0)
+static __init int test_atomic64(void)
+{
+ long long v0 = 0xaaa31337c001d00dLL;
+ long long v1 = 0xdeadbeefdeafcafeLL;
+ long long v2 = 0xfaceabadf00df001LL;
+ long long onestwos = 0x1111111122222222LL;
+ long long one = 1LL;
+
+ atomic64_t v = ATOMIC64_INIT(v0);
+ long long r = v0;
+ BUG_ON(v.counter != r);
+
+ atomic64_set(&v, v1);
+ r = v1;
+ BUG_ON(v.counter != r);
+ BUG_ON(atomic64_read(&v) != r);
+
+ INIT(v0);
+ atomic64_add(onestwos, &v);
+ r += onestwos;
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ atomic64_add(-one, &v);
+ r += -one;
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ r += onestwos;
+ BUG_ON(atomic64_add_return(onestwos, &v) != r);
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ r += -one;
+ BUG_ON(atomic64_add_return(-one, &v) != r);
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ atomic64_sub(onestwos, &v);
+ r -= onestwos;
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ atomic64_sub(-one, &v);
+ r -= -one;
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ r -= onestwos;
+ BUG_ON(atomic64_sub_return(onestwos, &v) != r);
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ r -= -one;
+ BUG_ON(atomic64_sub_return(-one, &v) != r);
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ atomic64_inc(&v);
+ r += one;
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ r += one;
+ BUG_ON(atomic64_inc_return(&v) != r);
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ atomic64_dec(&v);
+ r -= one;
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ r -= one;
+ BUG_ON(atomic64_dec_return(&v) != r);
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ BUG_ON(atomic64_xchg(&v, v1) != v0);
+ r = v1;
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ BUG_ON(atomic64_cmpxchg(&v, v0, v1) != v0);
+ r = v1;
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ BUG_ON(atomic64_cmpxchg(&v, v2, v1) != v0);
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ BUG_ON(atomic64_add_unless(&v, one, v0));
+ BUG_ON(v.counter != r);
+
+ INIT(v0);
+ BUG_ON(!atomic64_add_unless(&v, one, v1));
+ r += one;
+ BUG_ON(v.counter != r);
+
+#if defined(CONFIG_X86) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(_ASM_GENERIC_ATOMIC64_H)
+ INIT(onestwos);
+ BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1));
+ r -= one;
+ BUG_ON(v.counter != r);
+
+ INIT(0);
+ BUG_ON(atomic64_dec_if_positive(&v) != -one);
+ BUG_ON(v.counter != r);
+
+ INIT(-one);
+ BUG_ON(atomic64_dec_if_positive(&v) != (-one - one));
+ BUG_ON(v.counter != r);
+#else
+#warning Please implement atomic64_dec_if_positive for your architecture, and add it to the IF above
+#endif
+
+ INIT(onestwos);
+ BUG_ON(!atomic64_inc_not_zero(&v));
+ r += one;
+ BUG_ON(v.counter != r);
+
+ INIT(0);
+ BUG_ON(atomic64_inc_not_zero(&v));
+ BUG_ON(v.counter != r);
+
+ INIT(-one);
+ BUG_ON(!atomic64_inc_not_zero(&v));
+ r += one;
+ BUG_ON(v.counter != r);
+
+#ifdef CONFIG_X86
+ printk(KERN_INFO "atomic64 test passed for %s platform %s CX8 and %s SSE\n",
+#ifdef CONFIG_X86_64
+ "x86-64",
+#elif defined(CONFIG_X86_CMPXCHG64)
+ "i586+",
+#else
+ "i386+",
+#endif
+ boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without",
+ boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without");
+#else
+ printk(KERN_INFO "atomic64 test passed\n");
+#endif
+
+ return 0;
+}
+
+core_initcall(test_atomic64);
diff --git a/lib/btree.c b/lib/btree.c
index 41859a8..c9c6f03 100644
--- a/lib/btree.c
+++ b/lib/btree.c
@@ -95,7 +95,8 @@
unsigned long *node;
node = mempool_alloc(head->mempool, gfp);
- memset(node, 0, NODESIZE);
+ if (likely(node))
+ memset(node, 0, NODESIZE);
return node;
}
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index b862b30..deebcc5 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -141,6 +141,7 @@
obj->object = addr;
obj->descr = descr;
obj->state = ODEBUG_STATE_NONE;
+ obj->astate = 0;
hlist_del(&obj->node);
hlist_add_head(&obj->node, &b->list);
@@ -252,8 +253,10 @@
if (limit < 5 && obj->descr != descr_test) {
limit++;
- WARN(1, KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,
- obj_states[obj->state], obj->descr->name);
+ WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) "
+ "object type: %s\n",
+ msg, obj_states[obj->state], obj->astate,
+ obj->descr->name);
}
debug_objects_warnings++;
}
@@ -447,7 +450,10 @@
case ODEBUG_STATE_INIT:
case ODEBUG_STATE_INACTIVE:
case ODEBUG_STATE_ACTIVE:
- obj->state = ODEBUG_STATE_INACTIVE;
+ if (!obj->astate)
+ obj->state = ODEBUG_STATE_INACTIVE;
+ else
+ debug_print_object(obj, "deactivate");
break;
case ODEBUG_STATE_DESTROYED:
@@ -553,6 +559,53 @@
raw_spin_unlock_irqrestore(&db->lock, flags);
}
+/**
+ * debug_object_active_state - debug checks object usage state machine
+ * @addr: address of the object
+ * @descr: pointer to an object specific debug description structure
+ * @expect: expected state
+ * @next: state to move to if expected state is found
+ */
+void
+debug_object_active_state(void *addr, struct debug_obj_descr *descr,
+ unsigned int expect, unsigned int next)
+{
+ struct debug_bucket *db;
+ struct debug_obj *obj;
+ unsigned long flags;
+
+ if (!debug_objects_enabled)
+ return;
+
+ db = get_bucket((unsigned long) addr);
+
+ raw_spin_lock_irqsave(&db->lock, flags);
+
+ obj = lookup_object(addr, db);
+ if (obj) {
+ switch (obj->state) {
+ case ODEBUG_STATE_ACTIVE:
+ if (obj->astate == expect)
+ obj->astate = next;
+ else
+ debug_print_object(obj, "active_state");
+ break;
+
+ default:
+ debug_print_object(obj, "active_state");
+ break;
+ }
+ } else {
+ struct debug_obj o = { .object = addr,
+ .state = ODEBUG_STATE_NOTAVAILABLE,
+ .descr = descr };
+
+ debug_print_object(&o, "active_state");
+ }
+
+ raw_spin_unlock_irqrestore(&db->lock, flags);
+}
+
#ifdef CONFIG_DEBUG_OBJECTS_FREE
static void __debug_check_no_obj_freed(const void *address, unsigned long size)
{
@@ -774,7 +827,7 @@
}
}
-static int
+static int __init
check_results(void *addr, enum debug_obj_state state, int fixups, int warnings)
{
struct debug_bucket *db;
@@ -917,7 +970,7 @@
/*
* Convert the statically allocated objects to dynamic ones:
*/
-static int debug_objects_replace_static_objects(void)
+static int __init debug_objects_replace_static_objects(void)
{
struct debug_bucket *db = obj_hash;
struct hlist_node *node, *tmp;
diff --git a/lib/hweight.c b/lib/hweight.c
index 63ee4eb..3c79d50 100644
--- a/lib/hweight.c
+++ b/lib/hweight.c
@@ -9,7 +9,7 @@
* The Hamming Weight of a number is the total number of bits set in it.
*/
-unsigned int hweight32(unsigned int w)
+unsigned int __sw_hweight32(unsigned int w)
{
#ifdef ARCH_HAS_FAST_MULTIPLIER
w -= (w >> 1) & 0x55555555;
@@ -24,29 +24,30 @@
return (res + (res >> 16)) & 0x000000FF;
#endif
}
-EXPORT_SYMBOL(hweight32);
+EXPORT_SYMBOL(__sw_hweight32);
-unsigned int hweight16(unsigned int w)
+unsigned int __sw_hweight16(unsigned int w)
{
unsigned int res = w - ((w >> 1) & 0x5555);
res = (res & 0x3333) + ((res >> 2) & 0x3333);
res = (res + (res >> 4)) & 0x0F0F;
return (res + (res >> 8)) & 0x00FF;
}
-EXPORT_SYMBOL(hweight16);
+EXPORT_SYMBOL(__sw_hweight16);
-unsigned int hweight8(unsigned int w)
+unsigned int __sw_hweight8(unsigned int w)
{
unsigned int res = w - ((w >> 1) & 0x55);
res = (res & 0x33) + ((res >> 2) & 0x33);
return (res + (res >> 4)) & 0x0F;
}
-EXPORT_SYMBOL(hweight8);
+EXPORT_SYMBOL(__sw_hweight8);
-unsigned long hweight64(__u64 w)
+unsigned long __sw_hweight64(__u64 w)
{
#if BITS_PER_LONG == 32
- return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
+ return __sw_hweight32((unsigned int)(w >> 32)) +
+ __sw_hweight32((unsigned int)w);
#elif BITS_PER_LONG == 64
#ifdef ARCH_HAS_FAST_MULTIPLIER
w -= (w >> 1) & 0x5555555555555555ul;
@@ -63,4 +64,4 @@
#endif
#endif
}
-EXPORT_SYMBOL(hweight64);
+EXPORT_SYMBOL(__sw_hweight64);
diff --git a/lib/rbtree.c b/lib/rbtree.c
index e2aa3be..15e10b1 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -44,6 +44,11 @@
else
root->rb_node = right;
rb_set_parent(node, right);
+
+ if (root->augment_cb) {
+ root->augment_cb(node);
+ root->augment_cb(right);
+ }
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
@@ -67,12 +72,20 @@
else
root->rb_node = left;
rb_set_parent(node, left);
+
+ if (root->augment_cb) {
+ root->augment_cb(node);
+ root->augment_cb(left);
+ }
}
void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
+ if (root->augment_cb)
+ root->augment_cb(node);
+
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
@@ -227,12 +240,15 @@
else
{
struct rb_node *old = node, *left;
+ int old_parent_cb = 0;
+ int successor_parent_cb = 0;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (rb_parent(old)) {
+ old_parent_cb = 1;
if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node;
else
@@ -247,8 +263,10 @@
if (parent == old) {
parent = node;
} else {
+ successor_parent_cb = 1;
if (child)
rb_set_parent(child, parent);
+
parent->rb_left = child;
node->rb_right = old->rb_right;
@@ -259,6 +277,24 @@
node->rb_left = old->rb_left;
rb_set_parent(old->rb_left, node);
+ if (root->augment_cb) {
+ /*
+ * Here, three different nodes can have new children.
+ * The parent of the successor node that was selected
+ * to replace the node to be erased.
+ * The node that is getting erased and is now replaced
+ * by its successor.
+ * The parent of the node getting erased-replaced.
+ */
+ if (successor_parent_cb)
+ root->augment_cb(parent);
+
+ root->augment_cb(node);
+
+ if (old_parent_cb)
+ root->augment_cb(rb_parent(old));
+ }
+
goto color;
}
@@ -267,15 +303,19 @@
if (child)
rb_set_parent(child, parent);
- if (parent)
- {
+
+ if (parent) {
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
- }
- else
+
+ if (root->augment_cb)
+ root->augment_cb(parent);
+
+ } else {
root->rb_node = child;
+ }
color:
if (color == RB_BLACK)
diff --git a/lib/rwsem.c b/lib/rwsem.c
index 3e3365e..ceba8e2 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -136,9 +136,10 @@
out:
return sem;
- /* undo the change to count, but check for a transition 1->0 */
+ /* undo the change to the active count, but check for a transition
+ * 1->0 */
undo:
- if (rwsem_atomic_update(-RWSEM_ACTIVE_BIAS, sem) != 0)
+ if (rwsem_atomic_update(-RWSEM_ACTIVE_BIAS, sem) & RWSEM_ACTIVE_MASK)
goto out;
goto try_again;
}
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ffbdfc8..4c9e6bb 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1039,7 +1039,7 @@
page = alloc_buddy_huge_page(h, vma, addr);
if (!page) {
hugetlb_put_quota(inode->i_mapping, chg);
- return ERR_PTR(-VM_FAULT_OOM);
+ return ERR_PTR(-VM_FAULT_SIGBUS);
}
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 6c755de..8a79a6f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1601,7 +1601,6 @@
* There is a small race that "from" or "to" can be
* freed by rmdir, so we use css_tryget().
*/
- rcu_read_lock();
from = mc.from;
to = mc.to;
if (from && css_tryget(&from->css)) {
@@ -1622,7 +1621,6 @@
do_continue = (to == mem_over_limit);
css_put(&to->css);
}
- rcu_read_unlock();
if (do_continue) {
DEFINE_WAIT(wait);
prepare_to_wait(&mc.waitq, &wait,
diff --git a/mm/rmap.c b/mm/rmap.c
index 07fc947..0feeef8 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -336,14 +336,13 @@
/*
* At what user virtual address is page expected in vma?
- * checking that the page matches the vma.
+ * Caller should check the page is actually part of the vma.
*/
unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
{
- if (PageAnon(page)) {
- if (vma->anon_vma != page_anon_vma(page))
- return -EFAULT;
- } else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
+ if (PageAnon(page))
+ ;
+ else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
if (!vma->vm_file ||
vma->vm_file->f_mapping != page->mapping)
return -EFAULT;
diff --git a/net/core/dev.c b/net/core/dev.c
index f769098..264137f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1451,7 +1451,7 @@
*
* return values:
* NET_RX_SUCCESS (no congestion)
- * NET_RX_DROP (packet was dropped)
+ * NET_RX_DROP (packet was dropped, but freed)
*
* dev_forward_skb can be used for injecting an skb from the
* start_xmit function of one device into the receive queue
@@ -1465,12 +1465,11 @@
{
skb_orphan(skb);
- if (!(dev->flags & IFF_UP))
+ if (!(dev->flags & IFF_UP) ||
+ (skb->len > (dev->mtu + dev->hard_header_len))) {
+ kfree_skb(skb);
return NET_RX_DROP;
-
- if (skb->len > (dev->mtu + dev->hard_header_len))
- return NET_RX_DROP;
-
+ }
skb_set_dev(skb, dev);
skb->tstamp.tv64 = 0;
skb->pkt_type = PACKET_HOST;
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index fe776c9..31e85d3 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -602,12 +602,19 @@
a->tx_compressed = b->tx_compressed;
};
+/* All VF info */
static inline int rtnl_vfinfo_size(const struct net_device *dev)
{
- if (dev->dev.parent && dev_is_pci(dev->dev.parent))
- return dev_num_vf(dev->dev.parent) *
- sizeof(struct ifla_vf_info);
- else
+ if (dev->dev.parent && dev_is_pci(dev->dev.parent)) {
+
+ int num_vfs = dev_num_vf(dev->dev.parent);
+ size_t size = nlmsg_total_size(sizeof(struct nlattr));
+ size += nlmsg_total_size(num_vfs * sizeof(struct nlattr));
+ size += num_vfs * (sizeof(struct ifla_vf_mac) +
+ sizeof(struct ifla_vf_vlan) +
+ sizeof(struct ifla_vf_tx_rate));
+ return size;
+ } else
return 0;
}
@@ -629,7 +636,7 @@
+ nla_total_size(1) /* IFLA_OPERSTATE */
+ nla_total_size(1) /* IFLA_LINKMODE */
+ nla_total_size(4) /* IFLA_NUM_VF */
- + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */
+ + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */
+ rtnl_link_get_size(dev); /* IFLA_LINKINFO */
}
@@ -700,14 +707,37 @@
if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) {
int i;
- struct ifla_vf_info ivi;
- NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent));
- for (i = 0; i < dev_num_vf(dev->dev.parent); i++) {
+ struct nlattr *vfinfo, *vf;
+ int num_vfs = dev_num_vf(dev->dev.parent);
+
+ NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs);
+ vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST);
+ if (!vfinfo)
+ goto nla_put_failure;
+ for (i = 0; i < num_vfs; i++) {
+ struct ifla_vf_info ivi;
+ struct ifla_vf_mac vf_mac;
+ struct ifla_vf_vlan vf_vlan;
+ struct ifla_vf_tx_rate vf_tx_rate;
if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
break;
- NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi);
+ vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf;
+ memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac));
+ vf_vlan.vlan = ivi.vlan;
+ vf_vlan.qos = ivi.qos;
+ vf_tx_rate.rate = ivi.tx_rate;
+ vf = nla_nest_start(skb, IFLA_VF_INFO);
+ if (!vf) {
+ nla_nest_cancel(skb, vfinfo);
+ goto nla_put_failure;
+ }
+ NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac);
+ NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan);
+ NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate);
+ nla_nest_end(skb, vf);
}
+ nla_nest_end(skb, vfinfo);
}
if (dev->rtnl_link_ops) {
if (rtnl_link_fill(skb, dev) < 0)
@@ -769,12 +799,7 @@
[IFLA_LINKINFO] = { .type = NLA_NESTED },
[IFLA_NET_NS_PID] = { .type = NLA_U32 },
[IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 },
- [IFLA_VF_MAC] = { .type = NLA_BINARY,
- .len = sizeof(struct ifla_vf_mac) },
- [IFLA_VF_VLAN] = { .type = NLA_BINARY,
- .len = sizeof(struct ifla_vf_vlan) },
- [IFLA_VF_TX_RATE] = { .type = NLA_BINARY,
- .len = sizeof(struct ifla_vf_tx_rate) },
+ [IFLA_VFINFO_LIST] = {. type = NLA_NESTED },
};
EXPORT_SYMBOL(ifla_policy);
@@ -783,6 +808,19 @@
[IFLA_INFO_DATA] = { .type = NLA_NESTED },
};
+static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = {
+ [IFLA_VF_INFO] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = {
+ [IFLA_VF_MAC] = { .type = NLA_BINARY,
+ .len = sizeof(struct ifla_vf_mac) },
+ [IFLA_VF_VLAN] = { .type = NLA_BINARY,
+ .len = sizeof(struct ifla_vf_vlan) },
+ [IFLA_VF_TX_RATE] = { .type = NLA_BINARY,
+ .len = sizeof(struct ifla_vf_tx_rate) },
+};
+
struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
{
struct net *net;
@@ -812,6 +850,52 @@
return 0;
}
+static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
+{
+ int rem, err = -EINVAL;
+ struct nlattr *vf;
+ const struct net_device_ops *ops = dev->netdev_ops;
+
+ nla_for_each_nested(vf, attr, rem) {
+ switch (nla_type(vf)) {
+ case IFLA_VF_MAC: {
+ struct ifla_vf_mac *ivm;
+ ivm = nla_data(vf);
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_mac)
+ err = ops->ndo_set_vf_mac(dev, ivm->vf,
+ ivm->mac);
+ break;
+ }
+ case IFLA_VF_VLAN: {
+ struct ifla_vf_vlan *ivv;
+ ivv = nla_data(vf);
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_vlan)
+ err = ops->ndo_set_vf_vlan(dev, ivv->vf,
+ ivv->vlan,
+ ivv->qos);
+ break;
+ }
+ case IFLA_VF_TX_RATE: {
+ struct ifla_vf_tx_rate *ivt;
+ ivt = nla_data(vf);
+ err = -EOPNOTSUPP;
+ if (ops->ndo_set_vf_tx_rate)
+ err = ops->ndo_set_vf_tx_rate(dev, ivt->vf,
+ ivt->rate);
+ break;
+ }
+ default:
+ err = -EINVAL;
+ break;
+ }
+ if (err)
+ break;
+ }
+ return err;
+}
+
static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
struct nlattr **tb, char *ifname, int modified)
{
@@ -942,40 +1026,17 @@
write_unlock_bh(&dev_base_lock);
}
- if (tb[IFLA_VF_MAC]) {
- struct ifla_vf_mac *ivm;
- ivm = nla_data(tb[IFLA_VF_MAC]);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_mac)
- err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac);
- if (err < 0)
- goto errout;
- modified = 1;
- }
-
- if (tb[IFLA_VF_VLAN]) {
- struct ifla_vf_vlan *ivv;
- ivv = nla_data(tb[IFLA_VF_VLAN]);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_vlan)
- err = ops->ndo_set_vf_vlan(dev, ivv->vf,
- ivv->vlan,
- ivv->qos);
- if (err < 0)
- goto errout;
- modified = 1;
- }
- err = 0;
-
- if (tb[IFLA_VF_TX_RATE]) {
- struct ifla_vf_tx_rate *ivt;
- ivt = nla_data(tb[IFLA_VF_TX_RATE]);
- err = -EOPNOTSUPP;
- if (ops->ndo_set_vf_tx_rate)
- err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate);
- if (err < 0)
- goto errout;
- modified = 1;
+ if (tb[IFLA_VFINFO_LIST]) {
+ struct nlattr *attr;
+ int rem;
+ nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) {
+ if (nla_type(attr) != IFLA_VF_INFO)
+ goto errout;
+ err = do_setvfinfo(dev, attr);
+ if (err < 0)
+ goto errout;
+ modified = 1;
+ }
}
err = 0;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 6e74706..80769f1 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -661,13 +661,13 @@
#endif
#endif
-#ifdef CONFIG_FDDI
+#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)
case ARPHRD_FDDI:
arp->ar_hrd = htons(ARPHRD_ETHER);
arp->ar_pro = htons(ETH_P_IP);
break;
#endif
-#ifdef CONFIG_TR
+#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)
case ARPHRD_IEEE802_TR:
arp->ar_hrd = htons(ARPHRD_IEEE802);
arp->ar_pro = htons(ETH_P_IP);
@@ -1051,7 +1051,7 @@
return -EINVAL;
}
switch (dev->type) {
-#ifdef CONFIG_FDDI
+#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE)
case ARPHRD_FDDI:
/*
* According to RFC 1390, FDDI devices should accept ARP
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 9d4f6d1..ec19a89 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -754,7 +754,8 @@
c->next = mfc_unres_queue;
mfc_unres_queue = c;
- mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires);
+ if (atomic_read(&net->ipv4.cache_resolve_queue_len) == 1)
+ mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires);
}
/*
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 0f8caf6..296150b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2839,7 +2839,6 @@
if (p->md5_desc.tfm)
crypto_free_hash(p->md5_desc.tfm);
kfree(p);
- p = NULL;
}
}
free_percpu(pool);
@@ -2937,25 +2936,40 @@
EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
-struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu)
+
+/**
+ * tcp_get_md5sig_pool - get md5sig_pool for this user
+ *
+ * We use percpu structure, so if we succeed, we exit with preemption
+ * and BH disabled, to make sure another thread or softirq handling
+ * wont try to get same context.
+ */
+struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
{
struct tcp_md5sig_pool * __percpu *p;
- spin_lock_bh(&tcp_md5sig_pool_lock);
+
+ local_bh_disable();
+
+ spin_lock(&tcp_md5sig_pool_lock);
p = tcp_md5sig_pool;
if (p)
tcp_md5sig_users++;
- spin_unlock_bh(&tcp_md5sig_pool_lock);
- return (p ? *per_cpu_ptr(p, cpu) : NULL);
+ spin_unlock(&tcp_md5sig_pool_lock);
+
+ if (p)
+ return *per_cpu_ptr(p, smp_processor_id());
+
+ local_bh_enable();
+ return NULL;
}
+EXPORT_SYMBOL(tcp_get_md5sig_pool);
-EXPORT_SYMBOL(__tcp_get_md5sig_pool);
-
-void __tcp_put_md5sig_pool(void)
+void tcp_put_md5sig_pool(void)
{
+ local_bh_enable();
tcp_free_md5sig_pool();
}
-
-EXPORT_SYMBOL(__tcp_put_md5sig_pool);
+EXPORT_SYMBOL(tcp_put_md5sig_pool);
int tcp_md5_hash_header(struct tcp_md5sig_pool *hp,
struct tcphdr *th)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 8fef859..c36522a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1527,6 +1527,9 @@
uh = udp_hdr(skb);
ulen = ntohs(uh->len);
+ saddr = ip_hdr(skb)->saddr;
+ daddr = ip_hdr(skb)->daddr;
+
if (ulen > skb->len)
goto short_packet;
@@ -1540,9 +1543,6 @@
if (udp4_csum_init(skb, uh, proto))
goto csum_error;
- saddr = ip_hdr(skb)->saddr;
- daddr = ip_hdr(skb)->daddr;
-
if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
return __udp4_lib_mcast_deliver(net, skb, uh,
saddr, daddr, udptable);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 622dc79..6157388 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -222,6 +222,8 @@
if (!skb)
return;
+ skb->protocol = htons(ETH_P_IPV6);
+
serr = SKB_EXT_ERR(skb);
serr->ee.ee_errno = err;
serr->ee.ee_origin = SO_EE_ORIGIN_ICMP6;
@@ -255,6 +257,8 @@
if (!skb)
return;
+ skb->protocol = htons(ETH_P_IPV6);
+
skb_put(skb, sizeof(struct ipv6hdr));
skb_reset_network_header(skb);
iph = ipv6_hdr(skb);
@@ -319,7 +323,7 @@
sin->sin6_flowinfo = 0;
sin->sin6_port = serr->port;
sin->sin6_scope_id = 0;
- if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) {
+ if (skb->protocol == htons(ETH_P_IPV6)) {
ipv6_addr_copy(&sin->sin6_addr,
(struct in6_addr *)(nh + serr->addr_offset));
if (np->sndflow)
@@ -341,7 +345,7 @@
sin->sin6_family = AF_INET6;
sin->sin6_flowinfo = 0;
sin->sin6_scope_id = 0;
- if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) {
+ if (skb->protocol == htons(ETH_P_IPV6)) {
ipv6_addr_copy(&sin->sin6_addr, &ipv6_hdr(skb)->saddr);
if (np->rxopt.all)
datagram_recv_ctl(sk, msg, skb);
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index a432f0e..94e7fca 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -31,7 +31,7 @@
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK:
return sizeof(struct ethhdr);
-#ifdef CONFIG_TR
+#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE)
case ARPHRD_IEEE802_TR:
return sizeof(struct trh_hdr);
#endif
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 4aefa6d..875c8de 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2030,7 +2030,8 @@
continue;
if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
- wk->type != IEEE80211_WORK_AUTH)
+ wk->type != IEEE80211_WORK_AUTH &&
+ wk->type != IEEE80211_WORK_ASSOC)
continue;
if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 2a57018..ea21924 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -440,11 +440,25 @@
{
SCTP_DEBUG_PRINTK("%s\n", __func__);
- sctp_do_sm(SCTP_EVENT_T_OTHER,
- SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
- asoc->state, asoc->ep, asoc, t,
- GFP_ATOMIC);
+ if (sock_owned_by_user(sk)) {
+ if (timer_pending(&t->proto_unreach_timer))
+ return;
+ else {
+ if (!mod_timer(&t->proto_unreach_timer,
+ jiffies + (HZ/20)))
+ sctp_association_hold(asoc);
+ }
+
+ } else {
+ if (timer_pending(&t->proto_unreach_timer) &&
+ del_timer(&t->proto_unreach_timer))
+ sctp_association_put(asoc);
+ sctp_do_sm(SCTP_EVENT_T_OTHER,
+ SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
+ asoc->state, asoc->ep, asoc, t,
+ GFP_ATOMIC);
+ }
}
/* Common lookup code for icmp/icmpv6 error handler. */
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index d5ae450..eb1f42f 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -397,6 +397,41 @@
sctp_transport_put(transport);
}
+/* Handle the timeout of the ICMP protocol unreachable timer. Trigger
+ * the correct state machine transition that will close the association.
+ */
+void sctp_generate_proto_unreach_event(unsigned long data)
+{
+ struct sctp_transport *transport = (struct sctp_transport *) data;
+ struct sctp_association *asoc = transport->asoc;
+
+ sctp_bh_lock_sock(asoc->base.sk);
+ if (sock_owned_by_user(asoc->base.sk)) {
+ SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
+
+ /* Try again later. */
+ if (!mod_timer(&transport->proto_unreach_timer,
+ jiffies + (HZ/20)))
+ sctp_association_hold(asoc);
+ goto out_unlock;
+ }
+
+ /* Is this structure just waiting around for us to actually
+ * get destroyed?
+ */
+ if (asoc->base.dead)
+ goto out_unlock;
+
+ sctp_do_sm(SCTP_EVENT_T_OTHER,
+ SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
+ asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);
+
+out_unlock:
+ sctp_bh_unlock_sock(asoc->base.sk);
+ sctp_association_put(asoc);
+}
+
+
/* Inject a SACK Timeout event into the state machine. */
static void sctp_generate_sack_event(unsigned long data)
{
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index be4d63d..165d54e 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -108,6 +108,8 @@
(unsigned long)peer);
setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event,
(unsigned long)peer);
+ setup_timer(&peer->proto_unreach_timer,
+ sctp_generate_proto_unreach_event, (unsigned long)peer);
/* Initialize the 64-bit random nonce sent with heartbeat. */
get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));
@@ -171,6 +173,10 @@
del_timer(&transport->T3_rtx_timer))
sctp_transport_put(transport);
+ /* Delete the ICMP proto unreachable timer if it's active. */
+ if (timer_pending(&transport->proto_unreach_timer) &&
+ del_timer(&transport->proto_unreach_timer))
+ sctp_association_put(transport->asoc);
sctp_transport_put(transport);
}
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index f9bdf26..cbcd654 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -245,3 +245,7 @@
cmd_lzo = (cat $(filter-out FORCE,$^) | \
lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
(rm -f $@ ; false)
+
+# misc stuff
+# ---------------------------------------------------------------------------
+quote:="
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 220213e..df90f31 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -796,6 +796,16 @@
return 1;
}
+/* Looks like: zorro:iN. */
+static int do_zorro_entry(const char *filename, struct zorro_device_id *id,
+ char *alias)
+{
+ id->id = TO_NATIVE(id->id);
+ strcpy(alias, "zorro:");
+ ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id);
+ return 1;
+}
+
/* Ignore any prefix, eg. some architectures prepend _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -943,6 +953,10 @@
do_table(symval, sym->st_size,
sizeof(struct platform_device_id), "platform",
do_platform_entry, mod);
+ else if (sym_is(symname, "__mod_zorro_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct zorro_device_id), "zorro",
+ do_zorro_entry, mod);
free(zeros);
}
diff --git a/security/min_addr.c b/security/min_addr.c
index e86f297..f728728 100644
--- a/security/min_addr.c
+++ b/security/min_addr.c
@@ -33,7 +33,7 @@
{
int ret;
- if (!capable(CAP_SYS_RAWIO))
+ if (write && !capable(CAP_SYS_RAWIO))
return -EPERM;
ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 8728876..20b5982 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -36,6 +36,9 @@
#include <sound/timer.h>
#include <sound/minors.h>
#include <asm/io.h>
+#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
+#include <dma-coherence.h>
+#endif
/*
* Compatibility
@@ -3184,6 +3187,10 @@
substream->runtime->dma_area,
substream->runtime->dma_addr,
area->vm_end - area->vm_start);
+#elif defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT)
+ if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV &&
+ !plat_device_is_coherent(substream->dma_buffer.dev.dev))
+ area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
#endif /* ARCH_HAS_DMA_MMAP_COHERENT */
/* mmap with fault handler */
area->vm_ops = &snd_pcm_vm_ops_data_fault;
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
index 1e12307..4ff6c8c 100644
--- a/sound/drivers/pcsp/pcsp.h
+++ b/sound/drivers/pcsp/pcsp.h
@@ -16,7 +16,7 @@
#include <asm/i8253.h>
#else
#include <asm/8253pit.h>
-static DEFINE_SPINLOCK(i8253_lock);
+static DEFINE_RAW_SPINLOCK(i8253_lock);
#endif
#define PCSP_SOUND_VERSION 0x400 /* read 4.00 */
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
index 0444cde..b5e2b54 100644
--- a/sound/drivers/pcsp/pcsp_input.c
+++ b/sound/drivers/pcsp/pcsp_input.c
@@ -21,7 +21,7 @@
{
unsigned long flags;
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
if (count) {
/* set command for counter 2, 2 byte write */
@@ -36,7 +36,7 @@
outb(inb_p(0x61) & 0xFC, 0x61);
}
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
}
void pcspkr_stop_sound(void)
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index d77ffa9..ce9e7d1 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -66,7 +66,7 @@
timer_cnt = val * CUR_DIV() / 256;
if (timer_cnt && chip->enable) {
- spin_lock_irqsave(&i8253_lock, flags);
+ raw_spin_lock_irqsave(&i8253_lock, flags);
if (!nforce_wa) {
outb_p(chip->val61, 0x61);
outb_p(timer_cnt, 0x42);
@@ -75,7 +75,7 @@
outb(chip->val61 ^ 2, 0x61);
chip->thalf = 1;
}
- spin_unlock_irqrestore(&i8253_lock, flags);
+ raw_spin_unlock_irqrestore(&i8253_lock, flags);
}
chip->ns_rem = PCSP_PERIOD_NS();
@@ -159,10 +159,10 @@
return -EIO;
}
- spin_lock(&i8253_lock);
+ raw_spin_lock(&i8253_lock);
chip->val61 = inb(0x61) | 0x03;
outb_p(0x92, 0x43); /* binary, mode 1, LSB only, ch 2 */
- spin_unlock(&i8253_lock);
+ raw_spin_unlock(&i8253_lock);
atomic_set(&chip->timer_active, 1);
chip->thalf = 0;
@@ -179,11 +179,11 @@
return;
atomic_set(&chip->timer_active, 0);
- spin_lock(&i8253_lock);
+ raw_spin_lock(&i8253_lock);
/* restore the timer */
outb_p(0xb6, 0x43); /* binary, mode 3, LSB/MSB, ch 2 */
outb(chip->val61 & 0xFC, 0x61);
- spin_unlock(&i8253_lock);
+ raw_spin_unlock(&i8253_lock);
}
/*
diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
index bb14e4c..87910e9 100644
--- a/sound/oss/dmasound/dmasound_paula.c
+++ b/sound/oss/dmasound/dmasound_paula.c
@@ -21,6 +21,7 @@
#include <linux/ioport.h>
#include <linux/soundcard.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/setup.h>
@@ -710,31 +711,41 @@
/*** Config & Setup **********************************************************/
-static int __init dmasound_paula_init(void)
+static int __init amiga_audio_probe(struct platform_device *pdev)
{
- int err;
-
- if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) {
- if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40,
- "dmasound [Paula]"))
- return -EBUSY;
- dmasound.mach = machAmiga;
- dmasound.mach.default_hard = def_hard ;
- dmasound.mach.default_soft = def_soft ;
- err = dmasound_init();
- if (err)
- release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
- return err;
- } else
- return -ENODEV;
+ dmasound.mach = machAmiga;
+ dmasound.mach.default_hard = def_hard ;
+ dmasound.mach.default_soft = def_soft ;
+ return dmasound_init();
}
-static void __exit dmasound_paula_cleanup(void)
+static int __exit amiga_audio_remove(struct platform_device *pdev)
{
dmasound_deinit();
- release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
+ return 0;
}
-module_init(dmasound_paula_init);
-module_exit(dmasound_paula_cleanup);
+static struct platform_driver amiga_audio_driver = {
+ .remove = __exit_p(amiga_audio_remove),
+ .driver = {
+ .name = "amiga-audio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init amiga_audio_init(void)
+{
+ return platform_driver_probe(&amiga_audio_driver, amiga_audio_probe);
+}
+
+module_init(amiga_audio_init);
+
+static void __exit amiga_audio_exit(void)
+{
+ platform_driver_unregister(&amiga_audio_driver);
+}
+
+module_exit(amiga_audio_exit);
+
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:amiga-audio");
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 56e5207..feabb44 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -1197,9 +1197,10 @@
case 0x103c:
case 0x1631:
case 0x1734:
- /* HP, Packard Bell, & Fujitsu-Siemens laptops have really bad
- * sound over 0dB on NID 0x17. Fix max PCM level to 0 dB
- * (originally it has 0x2b steps with 0dB offset 0x14)
+ case 0x17aa:
+ /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
+ * really bad sound over 0dB on NID 0x17. Fix max PCM level to
+ * 0 dB (originally it has 0x2b steps with 0dB offset 0x14)
*/
snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
(0x14 << AC_AMPCAP_OFFSET_SHIFT) |
@@ -2846,6 +2847,7 @@
SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
+ SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
{}
};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 7404dba..886d8e4 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -17871,7 +17871,6 @@
ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
ALC663_ASUS_H13),
- SND_PCI_QUIRK(0x8086, 0xd604, "Intel mobo", ALC662_3ST_2ch_DIG),
{}
};
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 7fb7d01..a0e06d8 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -104,6 +104,7 @@
STAC_DELL_M4_2,
STAC_DELL_M4_3,
STAC_HP_M4,
+ STAC_HP_DV4,
STAC_HP_DV5,
STAC_HP_HDX,
STAC_HP_DV4_1222NR,
@@ -1544,11 +1545,9 @@
0x904601b0,
};
-static unsigned int intel_dg45id_pin_configs[14] = {
+static unsigned int intel_dg45id_pin_configs[13] = {
0x02214230, 0x02A19240, 0x01013214, 0x01014210,
- 0x01A19250, 0x01011212, 0x01016211, 0x40f000f0,
- 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0,
- 0x074510B0, 0x40f000f0
+ 0x01A19250, 0x01011212, 0x01016211
};
static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
@@ -1693,6 +1692,7 @@
[STAC_DELL_M4_2] = dell_m4_2_pin_configs,
[STAC_DELL_M4_3] = dell_m4_3_pin_configs,
[STAC_HP_M4] = NULL,
+ [STAC_HP_DV4] = NULL,
[STAC_HP_DV5] = NULL,
[STAC_HP_HDX] = NULL,
[STAC_HP_DV4_1222NR] = NULL,
@@ -1705,6 +1705,7 @@
[STAC_DELL_M4_2] = "dell-m4-2",
[STAC_DELL_M4_3] = "dell-m4-3",
[STAC_HP_M4] = "hp-m4",
+ [STAC_HP_DV4] = "hp-dv4",
[STAC_HP_DV5] = "hp-dv5",
[STAC_HP_HDX] = "hp-hdx",
[STAC_HP_DV4_1222NR] = "hp-dv4-1222nr",
@@ -1723,7 +1724,7 @@
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080,
"HP", STAC_HP_DV5),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0,
- "HP dv4-7", STAC_HP_DV5),
+ "HP dv4-7", STAC_HP_DV4),
SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600,
"HP dv4-7", STAC_HP_DV5),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610,
@@ -4768,6 +4769,9 @@
struct sigmatel_spec *spec = codec->spec;
unsigned int gpio;
+ if (spec->gpio_led)
+ return;
+
gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP);
gpio &= AC_GPIO_IO_COUNT;
if (gpio > 3)
@@ -5677,6 +5681,9 @@
spec->num_smuxes = 1;
spec->num_dmuxes = 1;
/* fallthrough */
+ case STAC_HP_DV4:
+ spec->gpio_led = 0x01;
+ /* fallthrough */
case STAC_HP_DV5:
snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN);
@@ -5690,6 +5697,7 @@
spec->num_dmics = 1;
spec->num_dmuxes = 1;
spec->num_smuxes = 1;
+ spec->gpio_led = 0x08;
break;
}
@@ -5746,7 +5754,8 @@
}
/* enable bass on HP dv7 */
- if (spec->board_config == STAC_HP_DV5) {
+ if (spec->board_config == STAC_HP_DV4 ||
+ spec->board_config == STAC_HP_DV5) {
unsigned int cap;
cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP);
cap &= AC_GPIO_IO_COUNT;
diff --git a/sound/pci/ice1712/maya44.c b/sound/pci/ice1712/maya44.c
index 3e1c20a..726fd4b 100644
--- a/sound/pci/ice1712/maya44.c
+++ b/sound/pci/ice1712/maya44.c
@@ -347,7 +347,7 @@
/* known working input slots (0-4) */
#define MAYA_LINE_IN 1 /* in-2 */
-#define MAYA_MIC_IN 4 /* in-5 */
+#define MAYA_MIC_IN 3 /* in-4 */
static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
{
@@ -393,8 +393,8 @@
int changed;
mutex_lock(&chip->mutex);
- changed = maya_set_gpio_bits(chip->ice, GPIO_MIC_RELAY,
- sel ? GPIO_MIC_RELAY : 0);
+ changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
+ sel ? (1 << GPIO_MIC_RELAY) : 0);
wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
mutex_unlock(&chip->mutex);
return changed;
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
index 16c226b..7c4986b 100644
--- a/sound/pci/oxygen/xonar_cs43xx.c
+++ b/sound/pci/oxygen/xonar_cs43xx.c
@@ -56,6 +56,7 @@
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#include "xonar.h"
+#include "cm9780.h"
#include "cs4398.h"
#include "cs4362a.h"
@@ -172,6 +173,8 @@
oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA,
GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE);
+ oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
+
xonar_init_cs53x1(chip);
xonar_enable_output(chip);
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 2cab8e8..909fa76 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -43,6 +43,9 @@
-c::
scale counter values
+-B::
+ print large numbers with thousands' separators according to locale
+
EXAMPLES
--------
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index a9281cc..3d8f31e 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -558,15 +558,19 @@
endif # PERF_HAVE_DWARF_REGS
endif # NO_DWARF
+ifdef NO_NEWT
+ BASIC_CFLAGS += -DNO_NEWT_SUPPORT
+else
ifneq ($(shell sh -c "(echo '\#include <newt.h>'; echo 'int main(void) { newtInit(); newtCls(); return newtFinished(); }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -lnewt -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
BASIC_CFLAGS += -DNO_NEWT_SUPPORT
else
# Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
BASIC_CFLAGS += -I/usr/include/slang
- EXTLIBS += -lnewt
+ EXTLIBS += -lnewt -lslang
LIB_OBJS += $(OUTPUT)util/newt.o
endif
+endif # NO_NEWT
ifndef NO_LIBPERL
PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null`
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index da1b2e9..d1d1b30 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -256,10 +256,8 @@
"Use pipe() instead of socketpair()"),
OPT_BOOLEAN('t', "thread", &thread_mode,
"Be multi thread instead of multi process"),
- OPT_INTEGER('g', "group", &num_groups,
- "Specify number of groups"),
- OPT_INTEGER('l', "loop", &loops,
- "Specify number of loops"),
+ OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"),
+ OPT_UINTEGER('l', "loop", &loops, "Specify number of loops"),
OPT_END()
};
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 4699677..fcb9626 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -95,7 +95,7 @@
return;
}
-static char *bench_format_str;
+static const char *bench_format_str;
int bench_format = BENCH_FORMAT_DEFAULT;
static const struct option bench_options[] = {
@@ -126,7 +126,7 @@
printf("\n");
}
-static int bench_str2int(char *str)
+static int bench_str2int(const char *str)
{
if (!str)
return BENCH_FORMAT_DEFAULT;
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 81e3ecc..6d5a8a7 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -33,10 +33,10 @@
static enum help_format help_format = HELP_FORMAT_MAN;
static struct option builtin_help_options[] = {
OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
- OPT_SET_INT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
- OPT_SET_INT('w', "web", &help_format, "show manual in web browser",
+ OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
+ OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
HELP_FORMAT_WEB),
- OPT_SET_INT('i', "info", &help_format, "show info page",
+ OPT_SET_UINT('i', "info", &help_format, "show info page",
HELP_FORMAT_INFO),
OPT_END(),
};
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index a4c7cae..34d1e85 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -19,11 +19,11 @@
#include <pthread.h>
#include <math.h>
-static char *file_name;
+static const char *file_name;
static char name_buffer[256];
-int perf_host = 1;
-int perf_guest;
+bool perf_host = 1;
+bool perf_guest;
static const char * const kvm_usage[] = {
"perf kvm [<options>] {top|record|report|diff|buildid-list}",
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index e18dfdc..821c158 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -792,8 +792,7 @@
print_bad_events(bad, total);
}
-static int info_threads;
-static int info_map;
+static bool info_threads, info_map;
static void dump_threads(void)
{
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 61c6d70..e4a4da3 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -65,8 +65,10 @@
int ret;
pr_debug("probe-definition(%d): %s\n", params.nevents, str);
- if (++params.nevents == MAX_PROBES)
- die("Too many probes (> %d) are specified.", MAX_PROBES);
+ if (++params.nevents == MAX_PROBES) {
+ pr_err("Too many probes (> %d) were specified.", MAX_PROBES);
+ return -1;
+ }
/* Parse a perf-probe command into event */
ret = parse_perf_probe_command(str, pev);
@@ -84,7 +86,9 @@
len = 0;
for (i = 0; i < argc; i++)
len += strlen(argv[i]) + 1;
- buf = xzalloc(len + 1);
+ buf = zalloc(len + 1);
+ if (buf == NULL)
+ return -ENOMEM;
len = 0;
for (i = 0; i < argc; i++)
len += sprintf(&buf[len], "%s ", argv[i]);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0f467cf..9bc8905 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -25,6 +25,7 @@
#include <unistd.h>
#include <sched.h>
+#include <sys/mman.h>
enum write_mode_t {
WRITE_FORCE,
@@ -33,8 +34,8 @@
static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
-static unsigned int user_interval = UINT_MAX;
-static long default_interval = 0;
+static u64 user_interval = ULLONG_MAX;
+static u64 default_interval = 0;
static int nr_cpus = 0;
static unsigned int page_size;
@@ -45,7 +46,7 @@
static int pipe_output = 0;
static const char *output_name = "perf.data";
static int group = 0;
-static unsigned int realtime_prio = 0;
+static int realtime_prio = 0;
static bool raw_samples = false;
static bool system_wide = false;
static int profile_cpu = -1;
@@ -60,13 +61,8 @@
static bool inherit_stat = false;
static bool no_samples = false;
static bool sample_address = false;
-static bool multiplex = false;
-static int multiplex_fd = -1;
static long samples = 0;
-static struct timeval last_read;
-static struct timeval this_read;
-
static u64 bytes_written = 0;
static struct pollfd *event_array;
@@ -86,7 +82,7 @@
unsigned int prev;
};
-static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
+static struct mmap_data mmap_array[MAX_NR_CPUS];
static unsigned long mmap_read_head(struct mmap_data *md)
{
@@ -146,8 +142,6 @@
void *buf;
int diff;
- gettimeofday(&this_read, NULL);
-
/*
* If we're further behind than half the buffer, there's a chance
* the writer will bite our tail and mess up the samples under us.
@@ -158,23 +152,13 @@
*/
diff = head - old;
if (diff < 0) {
- struct timeval iv;
- unsigned long msecs;
-
- timersub(&this_read, &last_read, &iv);
- msecs = iv.tv_sec*1000 + iv.tv_usec/1000;
-
- fprintf(stderr, "WARNING: failed to keep up with mmap data."
- " Last read %lu msecs ago.\n", msecs);
-
+ fprintf(stderr, "WARNING: failed to keep up with mmap data\n");
/*
* head points to a known good entry, start there.
*/
old = head;
}
- last_read = this_read;
-
if (old != head)
samples++;
@@ -268,7 +252,7 @@
* it a weak assumption overridable by the user.
*/
if (!attr->sample_period || (user_freq != UINT_MAX &&
- user_interval != UINT_MAX)) {
+ user_interval != ULLONG_MAX)) {
if (freq) {
attr->sample_type |= PERF_SAMPLE_PERIOD;
attr->freq = 1;
@@ -380,27 +364,30 @@
*/
if (group && group_fd == -1)
group_fd = fd[nr_cpu][counter][thread_index];
- if (multiplex && multiplex_fd == -1)
- multiplex_fd = fd[nr_cpu][counter][thread_index];
- if (multiplex && fd[nr_cpu][counter][thread_index] != multiplex_fd) {
-
- ret = ioctl(fd[nr_cpu][counter][thread_index], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd);
- assert(ret != -1);
+ if (counter || thread_index) {
+ ret = ioctl(fd[nr_cpu][counter][thread_index],
+ PERF_EVENT_IOC_SET_OUTPUT,
+ fd[nr_cpu][0][0]);
+ if (ret) {
+ error("failed to set output: %d (%s)\n", errno,
+ strerror(errno));
+ exit(-1);
+ }
} else {
- event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index];
- event_array[nr_poll].events = POLLIN;
- nr_poll++;
-
- mmap_array[nr_cpu][counter][thread_index].counter = counter;
- mmap_array[nr_cpu][counter][thread_index].prev = 0;
- mmap_array[nr_cpu][counter][thread_index].mask = mmap_pages*page_size - 1;
- mmap_array[nr_cpu][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size,
+ mmap_array[nr_cpu].counter = counter;
+ mmap_array[nr_cpu].prev = 0;
+ mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
+ mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size,
PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0);
- if (mmap_array[nr_cpu][counter][thread_index].base == MAP_FAILED) {
+ if (mmap_array[nr_cpu].base == MAP_FAILED) {
error("failed to mmap with %d (%s)\n", errno, strerror(errno));
exit(-1);
}
+
+ event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index];
+ event_array[nr_poll].events = POLLIN;
+ nr_poll++;
}
if (filter != NULL) {
@@ -501,16 +488,11 @@
static void mmap_read_all(void)
{
- int i, counter, thread;
+ int i;
for (i = 0; i < nr_cpu; i++) {
- for (counter = 0; counter < nr_counters; counter++) {
- for (thread = 0; thread < thread_num; thread++) {
- if (mmap_array[i][counter][thread].base)
- mmap_read(&mmap_array[i][counter][thread]);
- }
-
- }
+ if (mmap_array[i].base)
+ mmap_read(&mmap_array[i]);
}
if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
@@ -817,16 +799,13 @@
"CPU to profile on"),
OPT_BOOLEAN('f', "force", &force,
"overwrite existing data file (deprecated)"),
- OPT_LONG('c', "count", &user_interval,
- "event period to sample"),
+ OPT_U64('c', "count", &user_interval, "event period to sample"),
OPT_STRING('o', "output", &output_name, "file",
"output file name"),
OPT_BOOLEAN('i', "no-inherit", &no_inherit,
"child tasks do not inherit counters"),
- OPT_INTEGER('F', "freq", &user_freq,
- "profile at this frequency"),
- OPT_INTEGER('m', "mmap-pages", &mmap_pages,
- "number of mmap data pages"),
+ OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
+ OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
OPT_BOOLEAN('g', "call-graph", &call_graph,
"do call-graph (stack chain/backtrace) recording"),
OPT_INCR('v', "verbose", &verbose,
@@ -837,8 +816,6 @@
"Sample addresses"),
OPT_BOOLEAN('n', "no-samples", &no_samples,
"don't sample"),
- OPT_BOOLEAN('M', "multiplex", &multiplex,
- "multiplex counter output in a single channel"),
OPT_END()
};
@@ -890,9 +867,7 @@
for (i = 0; i < MAX_NR_CPUS; i++) {
for (j = 0; j < MAX_COUNTERS; j++) {
fd[i][j] = malloc(sizeof(int)*thread_num);
- mmap_array[i][j] = zalloc(
- sizeof(struct mmap_data)*thread_num);
- if (!fd[i][j] || !mmap_array[i][j])
+ if (!fd[i][j])
return -ENOMEM;
}
}
@@ -901,7 +876,7 @@
if (!event_array)
return -ENOMEM;
- if (user_interval != UINT_MAX)
+ if (user_interval != ULLONG_MAX)
default_interval = user_interval;
if (user_freq != UINT_MAX)
freq = user_freq;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 6826512..a7b8760 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -39,8 +39,8 @@
static bool show_threads;
static struct perf_read_values show_threads_values;
-static char default_pretty_printing_style[] = "normal";
-static char *pretty_printing_style = default_pretty_printing_style;
+static const char default_pretty_printing_style[] = "normal";
+static const char *pretty_printing_style = default_pretty_printing_style;
static char callchain_default_opt[] = "fractal,0.5";
@@ -116,7 +116,7 @@
* so we don't allocated the extra space needed because the stdio
* code will not use it.
*/
- if (use_browser)
+ if (use_browser > 0)
err = hist_entry__inc_addr_samples(he, al->addr);
out_free_syms:
free(syms);
@@ -330,7 +330,7 @@
hists = rb_entry(next, struct hists, rb_node);
hists__collapse_resort(hists);
hists__output_resort(hists);
- if (use_browser)
+ if (use_browser > 0)
hists__browse(hists, help, input_name);
else {
const char *evname = NULL;
@@ -347,7 +347,7 @@
next = rb_next(&hists->rb_node);
}
- if (!use_browser && sort_order == default_sort_order &&
+ if (use_browser <= 0 && sort_order == default_sort_order &&
parent_pattern == default_parent_pattern) {
fprintf(stdout, "#\n# (%s)\n#\n", help);
@@ -491,7 +491,7 @@
* so don't allocate extra space that won't be used in the stdio
* implementation.
*/
- if (use_browser)
+ if (use_browser > 0)
symbol_conf.priv_size = sizeof(struct sym_priv);
if (symbol__init() < 0)
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index be7bc92..f67bce2 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -22,7 +22,7 @@
static char const *input_name = "perf.data";
static char default_sort_order[] = "avg, max, switch, runtime";
-static char *sort_order = default_sort_order;
+static const char *sort_order = default_sort_order;
static int profile_cpu = -1;
@@ -105,7 +105,7 @@
static u64 sum_fluct;
static u64 run_avg;
-static unsigned long replay_repeat = 10;
+static unsigned int replay_repeat = 10;
static unsigned long nr_timestamps;
static unsigned long nr_unordered_timestamps;
static unsigned long nr_state_machine_bugs;
@@ -1816,8 +1816,8 @@
};
static const struct option replay_options[] = {
- OPT_INTEGER('r', "repeat", &replay_repeat,
- "repeat the workload replay N times (-1: infinite)"),
+ OPT_UINTEGER('r', "repeat", &replay_repeat,
+ "repeat the workload replay N times (-1: infinite)"),
OPT_INCR('v', "verbose", &verbose,
"be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index ff8c413..9a39ca3 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -50,6 +50,7 @@
#include <sys/prctl.h>
#include <math.h>
+#include <locale.h>
static struct perf_event_attr default_attrs[] = {
@@ -80,6 +81,8 @@
static int thread_num = 0;
static pid_t child_pid = -1;
static bool null_run = false;
+static bool big_num = false;
+
static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
@@ -377,7 +380,7 @@
{
double msecs = avg / 1e6;
- fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter));
+ fprintf(stderr, " %18.6f %-24s", msecs, event_name(counter));
if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) {
fprintf(stderr, " # %10.3f CPUs ",
@@ -389,7 +392,10 @@
{
double total, ratio = 0.0;
- fprintf(stderr, " %14.0f %-24s", avg, event_name(counter));
+ if (big_num)
+ fprintf(stderr, " %'18.0f %-24s", avg, event_name(counter));
+ else
+ fprintf(stderr, " %18.0f %-24s", avg, event_name(counter));
if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) {
total = avg_stats(&runtime_cycles_stats);
@@ -426,7 +432,7 @@
int scaled = event_scaled[counter];
if (scaled == -1) {
- fprintf(stderr, " %14s %-24s\n",
+ fprintf(stderr, " %18s %-24s\n",
"<not counted>", event_name(counter));
return;
}
@@ -477,7 +483,7 @@
print_counter(counter);
fprintf(stderr, "\n");
- fprintf(stderr, " %14.9f seconds time elapsed",
+ fprintf(stderr, " %18.9f seconds time elapsed",
avg_stats(&walltime_nsecs_stats)/1e9);
if (run_count > 1) {
fprintf(stderr, " ( +- %7.3f%% )",
@@ -534,6 +540,8 @@
"repeat command and print average + stddev (max: 100)"),
OPT_BOOLEAN('n', "null", &null_run,
"null run - dont start any counters"),
+ OPT_BOOLEAN('B', "big-num", &big_num,
+ "print large numbers with thousands\' separators"),
OPT_END()
};
@@ -542,6 +550,8 @@
int status;
int i,j;
+ setlocale(LC_ALL, "");
+
argc = parse_options(argc, argv, options, stat_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (!argc && target_pid == -1 && target_tid == -1)
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 0339612..035b9fa 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -257,7 +257,7 @@
};
static const struct option test_options[] = {
- OPT_BOOLEAN('v', "verbose", &verbose,
+ OPT_INTEGER('v', "verbose", &verbose,
"be more verbose (show symbol address, etc)"),
OPT_END()
};
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ed9b5b6..397290a 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -71,7 +71,7 @@
static bool inherit = false;
static int profile_cpu = -1;
static int nr_cpus = 0;
-static unsigned int realtime_prio = 0;
+static int realtime_prio = 0;
static bool group = false;
static unsigned int page_size;
static unsigned int mmap_pages = 16;
@@ -96,7 +96,7 @@
struct source_line *next;
};
-static char *sym_filter = NULL;
+static const char *sym_filter = NULL;
struct sym_entry *sym_filter_entry = NULL;
struct sym_entry *sym_filter_entry_sched = NULL;
static int sym_pcnt_filter = 5;
@@ -1357,8 +1357,7 @@
"file", "vmlinux pathname"),
OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols,
"hide kernel symbols"),
- OPT_INTEGER('m', "mmap-pages", &mmap_pages,
- "number of mmap data pages"),
+ OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
OPT_INTEGER('r', "realtime", &realtime_prio,
"collect data with this RT SCHED_FIFO priority"),
OPT_INTEGER('d', "delay", &delay_secs,
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 08e0e5d..6e48711 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -15,15 +15,15 @@
#include "util/parse-events.h"
#include "util/debugfs.h"
-bool use_browser;
-
const char perf_usage_string[] =
"perf [--version] [--help] COMMAND [ARGS]";
const char perf_more_info_string[] =
"See 'perf help COMMAND' for more information on a specific command.";
+int use_browser = -1;
static int use_pager = -1;
+
struct pager_config {
const char *cmd;
int val;
@@ -49,6 +49,24 @@
return c.val;
}
+static int tui_command_config(const char *var, const char *value, void *data)
+{
+ struct pager_config *c = data;
+ if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd))
+ c->val = perf_config_bool(var, value);
+ return 0;
+}
+
+/* returns 0 for "no tui", 1 for "use tui", and -1 for "not specified" */
+static int check_tui_config(const char *cmd)
+{
+ struct pager_config c;
+ c.cmd = cmd;
+ c.val = -1;
+ perf_config(tui_command_config, &c);
+ return c.val;
+}
+
static void commit_pager_choice(void)
{
switch (use_pager) {
@@ -255,6 +273,9 @@
if (p->option & RUN_SETUP)
prefix = NULL; /* setup_perf_directory(); */
+ if (use_browser == -1)
+ use_browser = check_tui_config(p->cmd);
+
if (use_pager == -1 && p->option & RUN_SETUP)
use_pager = check_pager_config(p->cmd);
if (use_pager == -1 && p->option & USE_PAGER)
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 02821fe..ef7aa0a 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -80,6 +80,7 @@
#include "../../include/linux/perf_event.h"
#include "util/types.h"
+#include <stdbool.h>
/*
* prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all
@@ -131,6 +132,6 @@
u64 ips[0];
};
-extern int perf_host, perf_guest;
+extern bool perf_host, perf_guest;
#endif
diff --git a/tools/perf/util/abspath.c b/tools/perf/util/abspath.c
index a791dd4..0e76aff 100644
--- a/tools/perf/util/abspath.c
+++ b/tools/perf/util/abspath.c
@@ -1,86 +1,5 @@
#include "cache.h"
-/*
- * Do not use this for inspecting *tracked* content. When path is a
- * symlink to a directory, we do not want to say it is a directory when
- * dealing with tracked content in the working tree.
- */
-static int is_directory(const char *path)
-{
- struct stat st;
- return (!stat(path, &st) && S_ISDIR(st.st_mode));
-}
-
-/* We allow "recursive" symbolic links. Only within reason, though. */
-#define MAXDEPTH 5
-
-const char *make_absolute_path(const char *path)
-{
- static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
- char cwd[1024] = "";
- int buf_index = 1, len;
-
- int depth = MAXDEPTH;
- char *last_elem = NULL;
- struct stat st;
-
- if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
- die ("Too long path: %.*s", 60, path);
-
- while (depth--) {
- if (!is_directory(buf)) {
- char *last_slash = strrchr(buf, '/');
- if (last_slash) {
- *last_slash = '\0';
- last_elem = xstrdup(last_slash + 1);
- } else {
- last_elem = xstrdup(buf);
- *buf = '\0';
- }
- }
-
- if (*buf) {
- if (!*cwd && !getcwd(cwd, sizeof(cwd)))
- die ("Could not get current working directory");
-
- if (chdir(buf))
- die ("Could not switch to '%s'", buf);
- }
- if (!getcwd(buf, PATH_MAX))
- die ("Could not get current working directory");
-
- if (last_elem) {
- len = strlen(buf);
-
- if (len + strlen(last_elem) + 2 > PATH_MAX)
- die ("Too long path name: '%s/%s'",
- buf, last_elem);
- buf[len] = '/';
- strcpy(buf + len + 1, last_elem);
- free(last_elem);
- last_elem = NULL;
- }
-
- if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
- len = readlink(buf, next_buf, PATH_MAX);
- if (len < 0)
- die ("Invalid symlink: %s", buf);
- if (PATH_MAX <= len)
- die("symbolic link too long: %s", buf);
- next_buf[len] = '\0';
- buf = next_buf;
- buf_index = 1 - buf_index;
- next_buf = bufs[buf_index];
- } else
- break;
- }
-
- if (*cwd && chdir(cwd))
- die ("Could not change back to '%s'", cwd);
-
- return buf;
-}
-
static const char *get_pwd_cwd(void)
{
static char cwd[PATH_MAX + 1];
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0f60a390..70c5cf8 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -6,6 +6,8 @@
* Copyright (C) 2009, 2010 Red Hat Inc.
* Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
*/
+#include "util.h"
+#include <stdio.h>
#include "build-id.h"
#include "event.h"
#include "symbol.h"
@@ -37,3 +39,23 @@
.mmap = event__process_mmap,
.fork = event__process_task,
};
+
+char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
+{
+ char build_id_hex[BUILD_ID_SIZE * 2 + 1];
+ const char *home;
+
+ if (!self->has_build_id)
+ return NULL;
+
+ build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex);
+ home = getenv("HOME");
+ if (bf == NULL) {
+ if (asprintf(&bf, "%s/%s/.build-id/%.2s/%s", home,
+ DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2) < 0)
+ return NULL;
+ } else
+ snprintf(bf, size, "%s/%s/.build-id/%.2s/%s", home,
+ DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2);
+ return bf;
+}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 1d981d6..5dafb00 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -5,4 +5,6 @@
extern struct perf_event_ops build_id__mark_dso_hit_ops;
+char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
+
#endif
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 4b9aab7..65fe664 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -13,56 +13,16 @@
#define PERF_DIR_ENVIRONMENT "PERF_DIR"
#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
-#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
-#define DB_ENVIRONMENT "PERF_OBJECT_DIRECTORY"
-#define INDEX_ENVIRONMENT "PERF_INDEX_FILE"
-#define GRAFT_ENVIRONMENT "PERF_GRAFT_FILE"
-#define TEMPLATE_DIR_ENVIRONMENT "PERF_TEMPLATE_DIR"
-#define CONFIG_ENVIRONMENT "PERF_CONFIG"
#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
-#define CEILING_DIRECTORIES_ENVIRONMENT "PERF_CEILING_DIRECTORIES"
-#define PERFATTRIBUTES_FILE ".perfattributes"
-#define INFOATTRIBUTES_FILE "info/attributes"
-#define ATTRIBUTE_MACRO_PREFIX "[attr]"
+#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
typedef int (*config_fn_t)(const char *, const char *, void *);
extern int perf_default_config(const char *, const char *, void *);
-extern int perf_config_from_file(config_fn_t fn, const char *, void *);
extern int perf_config(config_fn_t fn, void *);
-extern int perf_parse_ulong(const char *, unsigned long *);
extern int perf_config_int(const char *, const char *);
-extern unsigned long perf_config_ulong(const char *, const char *);
-extern int perf_config_bool_or_int(const char *, const char *, int *);
extern int perf_config_bool(const char *, const char *);
-extern int perf_config_string(const char **, const char *, const char *);
-extern int perf_config_set(const char *, const char *);
-extern int perf_config_set_multivar(const char *, const char *, const char *, int);
-extern int perf_config_rename_section(const char *, const char *);
-extern const char *perf_etc_perfconfig(void);
-extern int check_repository_format_version(const char *var, const char *value, void *cb);
-extern int perf_config_system(void);
-extern int perf_config_global(void);
extern int config_error_nonbool(const char *);
-extern const char *config_exclusive_filename;
-
-#define MAX_PERFNAME (1000)
-extern char perf_default_email[MAX_PERFNAME];
-extern char perf_default_name[MAX_PERFNAME];
-extern int user_ident_explicitly_given;
-
-extern const char *perf_log_output_encoding;
-extern const char *perf_mailmap_file;
-
-/* IO helper functions */
-extern void maybe_flush_or_die(FILE *, const char *);
-extern int copy_fd(int ifd, int ofd);
-extern int copy_file(const char *dst, const char *src, int mode);
-extern ssize_t write_in_full(int fd, const void *buf, size_t count);
-extern void write_or_die(int fd, const void *buf, size_t count);
-extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
-extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
-extern void fsync_or_die(int fd, const char *);
/* pager.c */
extern void setup_pager(void);
@@ -70,7 +30,7 @@
extern int pager_in_use(void);
extern int pager_use_color;
-extern bool use_browser;
+extern int use_browser;
#ifdef NO_NEWT_SUPPORT
static inline void setup_browser(void)
@@ -83,9 +43,6 @@
void exit_browser(bool wait_for_ok);
#endif
-extern const char *editor_program;
-extern const char *excludes_file;
-
char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv);
@@ -115,22 +72,12 @@
return path[0] == '/';
}
-const char *make_absolute_path(const char *path);
const char *make_nonrelative_path(const char *path);
-const char *make_relative_path(const char *abs, const char *base);
-int normalize_path_copy(char *dst, const char *src);
-int longest_ancestor_length(const char *path, const char *prefix_list);
char *strip_path_suffix(const char *path, const char *suffix);
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
-/* perf_mkstemp() - create tmp file honoring TMPDIR variable */
-extern int perf_mkstemp(char *path, size_t len, const char *template);
-extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
- __attribute__((format (printf, 3, 4)));
-extern char *perf_snpath(char *buf, size_t n, const char *fmt, ...)
- __attribute__((format (printf, 3, 4)));
extern char *perf_pathdup(const char *fmt, ...)
__attribute__((format (printf, 1, 2)));
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 21a52e0..62b69ad 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -15,6 +15,7 @@
#include <errno.h>
#include <math.h>
+#include "util.h"
#include "callchain.h"
bool ip_callchain__valid(struct ip_callchain *chain, event_t *event)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 1cba1f5..1ca73e4 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -5,7 +5,6 @@
#include <linux/list.h>
#include <linux/rbtree.h>
#include "event.h"
-#include "util.h"
#include "symbol.h"
enum chain_mode {
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 8784649..dabe892 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -16,7 +16,7 @@
static int config_linenr;
static int config_file_eof;
-const char *config_exclusive_filename = NULL;
+static const char *config_exclusive_filename;
static int get_next_char(void)
{
@@ -291,19 +291,6 @@
return 0;
}
-int perf_parse_ulong(const char *value, unsigned long *ret)
-{
- if (value && *value) {
- char *end;
- unsigned long val = strtoul(value, &end, 0);
- if (!parse_unit_factor(end, &val))
- return 0;
- *ret = val;
- return 1;
- }
- return 0;
-}
-
static void die_bad_config(const char *name)
{
if (config_file_name)
@@ -319,15 +306,7 @@
return ret;
}
-unsigned long perf_config_ulong(const char *name, const char *value)
-{
- unsigned long ret;
- if (!perf_parse_ulong(value, &ret))
- die_bad_config(name);
- return ret;
-}
-
-int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
+static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
{
*is_bool = 1;
if (!value)
@@ -348,14 +327,6 @@
return !!perf_config_bool_or_int(name, value, &discard);
}
-int perf_config_string(const char **dest, const char *var, const char *value)
-{
- if (!value)
- return config_error_nonbool(var);
- *dest = strdup(value);
- return 0;
-}
-
static int perf_default_core_config(const char *var __used, const char *value __used)
{
/* Add other config variables here and to Documentation/config.txt. */
@@ -371,7 +342,7 @@
return 0;
}
-int perf_config_from_file(config_fn_t fn, const char *filename, void *data)
+static int perf_config_from_file(config_fn_t fn, const char *filename, void *data)
{
int ret;
FILE *f = fopen(filename, "r");
@@ -389,7 +360,7 @@
return ret;
}
-const char *perf_etc_perfconfig(void)
+static const char *perf_etc_perfconfig(void)
{
static const char *system_wide;
if (!system_wide)
@@ -403,12 +374,12 @@
return v ? perf_config_bool(k, v) : def;
}
-int perf_config_system(void)
+static int perf_config_system(void)
{
return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0);
}
-int perf_config_global(void)
+static int perf_config_global(void)
{
return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0);
}
@@ -450,426 +421,6 @@
}
/*
- * Find all the stuff for perf_config_set() below.
- */
-
-#define MAX_MATCHES 512
-
-static struct {
- int baselen;
- char* key;
- int do_not_match;
- regex_t* value_regex;
- int multi_replace;
- size_t offset[MAX_MATCHES];
- enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
- int seen;
-} store;
-
-static int matches(const char* key, const char* value)
-{
- return !strcmp(key, store.key) &&
- (store.value_regex == NULL ||
- (store.do_not_match ^
- !regexec(store.value_regex, value, 0, NULL, 0)));
-}
-
-static int store_aux(const char* key, const char* value, void *cb __used)
-{
- int section_len;
- const char *ep;
-
- switch (store.state) {
- case KEY_SEEN:
- if (matches(key, value)) {
- if (store.seen == 1 && store.multi_replace == 0) {
- warning("%s has multiple values", key);
- } else if (store.seen >= MAX_MATCHES) {
- error("too many matches for %s", key);
- return 1;
- }
-
- store.offset[store.seen] = ftell(config_file);
- store.seen++;
- }
- break;
- case SECTION_SEEN:
- /*
- * What we are looking for is in store.key (both
- * section and var), and its section part is baselen
- * long. We found key (again, both section and var).
- * We would want to know if this key is in the same
- * section as what we are looking for. We already
- * know we are in the same section as what should
- * hold store.key.
- */
- ep = strrchr(key, '.');
- section_len = ep - key;
-
- if ((section_len != store.baselen) ||
- memcmp(key, store.key, section_len+1)) {
- store.state = SECTION_END_SEEN;
- break;
- }
-
- /*
- * Do not increment matches: this is no match, but we
- * just made sure we are in the desired section.
- */
- store.offset[store.seen] = ftell(config_file);
- /* fallthru */
- case SECTION_END_SEEN:
- case START:
- if (matches(key, value)) {
- store.offset[store.seen] = ftell(config_file);
- store.state = KEY_SEEN;
- store.seen++;
- } else {
- if (strrchr(key, '.') - key == store.baselen &&
- !strncmp(key, store.key, store.baselen)) {
- store.state = SECTION_SEEN;
- store.offset[store.seen] = ftell(config_file);
- }
- }
- default:
- break;
- }
- return 0;
-}
-
-static int store_write_section(int fd, const char* key)
-{
- const char *dot;
- int i, success;
- struct strbuf sb = STRBUF_INIT;
-
- dot = memchr(key, '.', store.baselen);
- if (dot) {
- strbuf_addf(&sb, "[%.*s \"", (int)(dot - key), key);
- for (i = dot - key + 1; i < store.baselen; i++) {
- if (key[i] == '"' || key[i] == '\\')
- strbuf_addch(&sb, '\\');
- strbuf_addch(&sb, key[i]);
- }
- strbuf_addstr(&sb, "\"]\n");
- } else {
- strbuf_addf(&sb, "[%.*s]\n", store.baselen, key);
- }
-
- success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
- strbuf_release(&sb);
-
- return success;
-}
-
-static int store_write_pair(int fd, const char* key, const char* value)
-{
- int i, success;
- int length = strlen(key + store.baselen + 1);
- const char *quote = "";
- struct strbuf sb = STRBUF_INIT;
-
- /*
- * Check to see if the value needs to be surrounded with a dq pair.
- * Note that problematic characters are always backslash-quoted; this
- * check is about not losing leading or trailing SP and strings that
- * follow beginning-of-comment characters (i.e. ';' and '#') by the
- * configuration parser.
- */
- if (value[0] == ' ')
- quote = "\"";
- for (i = 0; value[i]; i++)
- if (value[i] == ';' || value[i] == '#')
- quote = "\"";
- if (i && value[i - 1] == ' ')
- quote = "\"";
-
- strbuf_addf(&sb, "\t%.*s = %s",
- length, key + store.baselen + 1, quote);
-
- for (i = 0; value[i]; i++)
- switch (value[i]) {
- case '\n':
- strbuf_addstr(&sb, "\\n");
- break;
- case '\t':
- strbuf_addstr(&sb, "\\t");
- break;
- case '"':
- case '\\':
- strbuf_addch(&sb, '\\');
- default:
- strbuf_addch(&sb, value[i]);
- break;
- }
- strbuf_addf(&sb, "%s\n", quote);
-
- success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
- strbuf_release(&sb);
-
- return success;
-}
-
-static ssize_t find_beginning_of_line(const char* contents, size_t size,
- size_t offset_, int* found_bracket)
-{
- size_t equal_offset = size, bracket_offset = size;
- ssize_t offset;
-
-contline:
- for (offset = offset_-2; offset > 0
- && contents[offset] != '\n'; offset--)
- switch (contents[offset]) {
- case '=': equal_offset = offset; break;
- case ']': bracket_offset = offset; break;
- default: break;
- }
- if (offset > 0 && contents[offset-1] == '\\') {
- offset_ = offset;
- goto contline;
- }
- if (bracket_offset < equal_offset) {
- *found_bracket = 1;
- offset = bracket_offset+1;
- } else
- offset++;
-
- return offset;
-}
-
-int perf_config_set(const char* key, const char* value)
-{
- return perf_config_set_multivar(key, value, NULL, 0);
-}
-
-/*
- * If value==NULL, unset in (remove from) config,
- * if value_regex!=NULL, disregard key/value pairs where value does not match.
- * if multi_replace==0, nothing, or only one matching key/value is replaced,
- * else all matching key/values (regardless how many) are removed,
- * before the new pair is written.
- *
- * Returns 0 on success.
- *
- * This function does this:
- *
- * - it locks the config file by creating ".perf/config.lock"
- *
- * - it then parses the config using store_aux() as validator to find
- * the position on the key/value pair to replace. If it is to be unset,
- * it must be found exactly once.
- *
- * - the config file is mmap()ed and the part before the match (if any) is
- * written to the lock file, then the changed part and the rest.
- *
- * - the config file is removed and the lock file rename()d to it.
- *
- */
-int perf_config_set_multivar(const char* key, const char* value,
- const char* value_regex, int multi_replace)
-{
- int i, dot;
- int fd = -1, in_fd;
- int ret = 0;
- char* config_filename;
- const char* last_dot = strrchr(key, '.');
-
- if (config_exclusive_filename)
- config_filename = strdup(config_exclusive_filename);
- else
- config_filename = perf_pathdup("config");
-
- /*
- * Since "key" actually contains the section name and the real
- * key name separated by a dot, we have to know where the dot is.
- */
-
- if (last_dot == NULL) {
- error("key does not contain a section: %s", key);
- ret = 2;
- goto out_free;
- }
- store.baselen = last_dot - key;
-
- store.multi_replace = multi_replace;
-
- /*
- * Validate the key and while at it, lower case it for matching.
- */
- store.key = malloc(strlen(key) + 1);
- dot = 0;
- for (i = 0; key[i]; i++) {
- unsigned char c = key[i];
- if (c == '.')
- dot = 1;
- /* Leave the extended basename untouched.. */
- if (!dot || i > store.baselen) {
- if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) {
- error("invalid key: %s", key);
- free(store.key);
- ret = 1;
- goto out_free;
- }
- c = tolower(c);
- } else if (c == '\n') {
- error("invalid key (newline): %s", key);
- free(store.key);
- ret = 1;
- goto out_free;
- }
- store.key[i] = c;
- }
- store.key[i] = 0;
-
- /*
- * If .perf/config does not exist yet, write a minimal version.
- */
- in_fd = open(config_filename, O_RDONLY);
- if ( in_fd < 0 ) {
- free(store.key);
-
- if ( ENOENT != errno ) {
- error("opening %s: %s", config_filename,
- strerror(errno));
- ret = 3; /* same as "invalid config file" */
- goto out_free;
- }
- /* if nothing to unset, error out */
- if (value == NULL) {
- ret = 5;
- goto out_free;
- }
-
- store.key = (char*)key;
- if (!store_write_section(fd, key) ||
- !store_write_pair(fd, key, value))
- goto write_err_out;
- } else {
- struct stat st;
- char *contents;
- ssize_t contents_sz, copy_begin, copy_end;
- int new_line = 0;
-
- if (value_regex == NULL)
- store.value_regex = NULL;
- else {
- if (value_regex[0] == '!') {
- store.do_not_match = 1;
- value_regex++;
- } else
- store.do_not_match = 0;
-
- store.value_regex = (regex_t*)malloc(sizeof(regex_t));
- if (regcomp(store.value_regex, value_regex,
- REG_EXTENDED)) {
- error("invalid pattern: %s", value_regex);
- free(store.value_regex);
- ret = 6;
- goto out_free;
- }
- }
-
- store.offset[0] = 0;
- store.state = START;
- store.seen = 0;
-
- /*
- * After this, store.offset will contain the *end* offset
- * of the last match, or remain at 0 if no match was found.
- * As a side effect, we make sure to transform only a valid
- * existing config file.
- */
- if (perf_config_from_file(store_aux, config_filename, NULL)) {
- error("invalid config file %s", config_filename);
- free(store.key);
- if (store.value_regex != NULL) {
- regfree(store.value_regex);
- free(store.value_regex);
- }
- ret = 3;
- goto out_free;
- }
-
- free(store.key);
- if (store.value_regex != NULL) {
- regfree(store.value_regex);
- free(store.value_regex);
- }
-
- /* if nothing to unset, or too many matches, error out */
- if ((store.seen == 0 && value == NULL) ||
- (store.seen > 1 && multi_replace == 0)) {
- ret = 5;
- goto out_free;
- }
-
- fstat(in_fd, &st);
- contents_sz = xsize_t(st.st_size);
- contents = mmap(NULL, contents_sz, PROT_READ,
- MAP_PRIVATE, in_fd, 0);
- close(in_fd);
-
- if (store.seen == 0)
- store.seen = 1;
-
- for (i = 0, copy_begin = 0; i < store.seen; i++) {
- if (store.offset[i] == 0) {
- store.offset[i] = copy_end = contents_sz;
- } else if (store.state != KEY_SEEN) {
- copy_end = store.offset[i];
- } else
- copy_end = find_beginning_of_line(
- contents, contents_sz,
- store.offset[i]-2, &new_line);
-
- if (copy_end > 0 && contents[copy_end-1] != '\n')
- new_line = 1;
-
- /* write the first part of the config */
- if (copy_end > copy_begin) {
- if (write_in_full(fd, contents + copy_begin,
- copy_end - copy_begin) <
- copy_end - copy_begin)
- goto write_err_out;
- if (new_line &&
- write_in_full(fd, "\n", 1) != 1)
- goto write_err_out;
- }
- copy_begin = store.offset[i];
- }
-
- /* write the pair (value == NULL means unset) */
- if (value != NULL) {
- if (store.state == START) {
- if (!store_write_section(fd, key))
- goto write_err_out;
- }
- if (!store_write_pair(fd, key, value))
- goto write_err_out;
- }
-
- /* write the rest of the config */
- if (copy_begin < contents_sz)
- if (write_in_full(fd, contents + copy_begin,
- contents_sz - copy_begin) <
- contents_sz - copy_begin)
- goto write_err_out;
-
- munmap(contents, contents_sz);
- }
-
- ret = 0;
-
-out_free:
- free(config_filename);
- return ret;
-
-write_err_out:
- goto out_free;
-
-}
-
-/*
* Call this to report error for your variable that should not
* get a boolean value (i.e. "[my] var" means "true").
*/
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 2745605..67eeff5 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -53,8 +53,8 @@
slash--;
if (slash >= argv0) {
- argv0_path = xstrndup(argv0, slash - argv0);
- return slash + 1;
+ argv0_path = strndup(argv0, slash - argv0);
+ return argv0_path ? slash + 1 : NULL;
}
return argv0;
@@ -116,7 +116,7 @@
strbuf_release(&new_path);
}
-const char **prepare_perf_cmd(const char **argv)
+static const char **prepare_perf_cmd(const char **argv)
{
int argc;
const char **nargv;
diff --git a/tools/perf/util/exec_cmd.h b/tools/perf/util/exec_cmd.h
index 31647ac..bc4b915 100644
--- a/tools/perf/util/exec_cmd.h
+++ b/tools/perf/util/exec_cmd.h
@@ -5,7 +5,6 @@
extern const char *perf_extract_argv0_path(const char *path);
extern const char *perf_exec_path(void);
extern void setup_path(void);
-extern const char **prepare_perf_cmd(const char **argv);
extern int execv_perf_cmd(const char **argv); /* NULL terminated */
extern int execl_perf_cmd(const char *cmd, ...);
extern const char *system_path(const char *path);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 8847bec..1f62435 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -221,29 +221,38 @@
return 0;
}
+static int machine__write_buildid_table(struct machine *self, int fd)
+{
+ int err;
+ u16 kmisc = PERF_RECORD_MISC_KERNEL,
+ umisc = PERF_RECORD_MISC_USER;
+
+ if (!machine__is_host(self)) {
+ kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
+ umisc = PERF_RECORD_MISC_GUEST_USER;
+ }
+
+ err = __dsos__write_buildid_table(&self->kernel_dsos, self->pid,
+ kmisc, fd);
+ if (err == 0)
+ err = __dsos__write_buildid_table(&self->user_dsos,
+ self->pid, umisc, fd);
+ return err;
+}
+
static int dsos__write_buildid_table(struct perf_header *header, int fd)
{
struct perf_session *session = container_of(header,
struct perf_session, header);
struct rb_node *nd;
- int err = 0;
- u16 kmisc, umisc;
+ int err = machine__write_buildid_table(&session->host_machine, fd);
+
+ if (err)
+ return err;
for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
struct machine *pos = rb_entry(nd, struct machine, rb_node);
- if (machine__is_host(pos)) {
- kmisc = PERF_RECORD_MISC_KERNEL;
- umisc = PERF_RECORD_MISC_USER;
- } else {
- kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
- umisc = PERF_RECORD_MISC_GUEST_USER;
- }
-
- err = __dsos__write_buildid_table(&pos->kernel_dsos, pos->pid,
- kmisc, fd);
- if (err == 0)
- err = __dsos__write_buildid_table(&pos->user_dsos,
- pos->pid, umisc, fd);
+ err = machine__write_buildid_table(pos, fd);
if (err)
break;
}
@@ -363,12 +372,17 @@
return err;
}
-static int dsos__cache_build_ids(struct perf_header *self)
+static int machine__cache_build_ids(struct machine *self, const char *debugdir)
{
- struct perf_session *session = container_of(self,
- struct perf_session, header);
+ int ret = __dsos__cache_build_ids(&self->kernel_dsos, debugdir);
+ ret |= __dsos__cache_build_ids(&self->user_dsos, debugdir);
+ return ret;
+}
+
+static int perf_session__cache_build_ids(struct perf_session *self)
+{
struct rb_node *nd;
- int ret = 0;
+ int ret;
char debugdir[PATH_MAX];
snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"),
@@ -377,25 +391,30 @@
if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
return -1;
- for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
+ ret = machine__cache_build_ids(&self->host_machine, debugdir);
+
+ for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) {
struct machine *pos = rb_entry(nd, struct machine, rb_node);
- ret |= __dsos__cache_build_ids(&pos->kernel_dsos, debugdir);
- ret |= __dsos__cache_build_ids(&pos->user_dsos, debugdir);
+ ret |= machine__cache_build_ids(pos, debugdir);
}
return ret ? -1 : 0;
}
-static bool dsos__read_build_ids(struct perf_header *self, bool with_hits)
+static bool machine__read_build_ids(struct machine *self, bool with_hits)
{
- bool ret = false;
- struct perf_session *session = container_of(self,
- struct perf_session, header);
- struct rb_node *nd;
+ bool ret = __dsos__read_build_ids(&self->kernel_dsos, with_hits);
+ ret |= __dsos__read_build_ids(&self->user_dsos, with_hits);
+ return ret;
+}
- for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
+static bool perf_session__read_build_ids(struct perf_session *self, bool with_hits)
+{
+ struct rb_node *nd;
+ bool ret = machine__read_build_ids(&self->host_machine, with_hits);
+
+ for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) {
struct machine *pos = rb_entry(nd, struct machine, rb_node);
- ret |= __dsos__read_build_ids(&pos->kernel_dsos, with_hits);
- ret |= __dsos__read_build_ids(&pos->user_dsos, with_hits);
+ ret |= machine__read_build_ids(pos, with_hits);
}
return ret;
@@ -404,12 +423,14 @@
static int perf_header__adds_write(struct perf_header *self, int fd)
{
int nr_sections;
+ struct perf_session *session;
struct perf_file_section *feat_sec;
int sec_size;
u64 sec_start;
int idx = 0, err;
- if (dsos__read_build_ids(self, true))
+ session = container_of(self, struct perf_session, header);
+ if (perf_session__read_build_ids(session, true))
perf_header__set_feat(self, HEADER_BUILD_ID);
nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
@@ -450,7 +471,7 @@
}
buildid_sec->size = lseek(fd, 0, SEEK_CUR) -
buildid_sec->offset;
- dsos__cache_build_ids(self);
+ perf_session__cache_build_ids(session);
}
lseek(fd, sec_start, SEEK_SET);
@@ -490,7 +511,6 @@
lseek(fd, sizeof(f_header), SEEK_SET);
-
for (i = 0; i < self->attrs; i++) {
attr = self->attr[i];
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index fbb0097..6f2975a 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -4,28 +4,6 @@
#include "levenshtein.h"
#include "help.h"
-/* most GUI terminals set COLUMNS (although some don't export it) */
-static int term_columns(void)
-{
- char *col_string = getenv("COLUMNS");
- int n_cols;
-
- if (col_string && (n_cols = atoi(col_string)) > 0)
- return n_cols;
-
-#ifdef TIOCGWINSZ
- {
- struct winsize ws;
- if (!ioctl(1, TIOCGWINSZ, &ws)) {
- if (ws.ws_col)
- return ws.ws_col;
- }
- }
-#endif
-
- return 80;
-}
-
void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
{
struct cmdname *ent = malloc(sizeof(*ent) + len + 1);
@@ -96,9 +74,13 @@
{
int cols = 1, rows;
int space = longest + 1; /* min 1 SP between words */
- int max_cols = term_columns() - 1; /* don't print *on* the edge */
+ struct winsize win;
+ int max_cols;
int i, j;
+ get_term_dimensions(&win);
+ max_cols = win.ws_col - 1; /* don't print *on* the edge */
+
if (space < max_cols)
cols = max_cols / space;
rows = (cmds->cnt + cols - 1) / cols;
@@ -324,7 +306,7 @@
main_cmds.names[0] = NULL;
clean_cmdnames(&main_cmds);
- fprintf(stderr, "WARNING: You called a Git program named '%s', "
+ fprintf(stderr, "WARNING: You called a perf program named '%s', "
"which does not exist.\n"
"Continuing under the assumption that you meant '%s'\n",
cmd, assumed);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f75c5f6..739c39f 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,3 +1,4 @@
+#include "build-id.h"
#include "util.h"
#include "hist.h"
#include "session.h"
@@ -662,7 +663,7 @@
long displacement = 0;
unsigned int width;
const char *sep = symbol_conf.field_sep;
- char *col_width = symbol_conf.col_width_list_str;
+ const char *col_width = symbol_conf.col_width_list_str;
init_rem_hits();
@@ -988,22 +989,35 @@
struct symbol *sym = self->ms.sym;
struct map *map = self->ms.map;
struct dso *dso = map->dso;
- const char *filename = dso->long_name;
+ char *filename = dso__build_id_filename(dso, NULL, 0);
char command[PATH_MAX * 2];
FILE *file;
+ int err = -1;
u64 len;
- if (!filename)
- return -1;
+ if (filename == NULL) {
+ if (dso->has_build_id) {
+ pr_err("Can't annotate %s: not enough memory\n",
+ sym->name);
+ return -1;
+ }
+ /*
+ * If we don't have build-ids, well, lets hope that this
+ * DSO is the same as when 'perf record' ran.
+ */
+ filename = dso->long_name;
+ }
if (dso->origin == DSO__ORIG_KERNEL) {
- if (dso->annotate_warned)
- return 0;
+ if (dso->annotate_warned) {
+ err = 0;
+ goto out_free_filename;
+ }
dso->annotate_warned = 1;
pr_err("Can't annotate %s: No vmlinux file was found in the "
"path:\n", sym->name);
vmlinux_path__fprintf(stderr);
- return -1;
+ goto out_free_filename;
}
pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__,
@@ -1025,14 +1039,18 @@
file = popen(command, "r");
if (!file)
- return -1;
+ goto out_free_filename;
while (!feof(file))
if (hist_entry__parse_objdump_line(self, file, head) < 0)
break;
pclose(file);
- return 0;
+ err = 0;
+out_free_filename:
+ if (dso->has_build_id)
+ free(filename);
+ return err;
}
void hists__inc_nr_events(struct hists *self, u32 type)
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
index 388ab1b..1eb804f 100644
--- a/tools/perf/util/include/linux/kernel.h
+++ b/tools/perf/util/include/linux/kernel.h
@@ -28,6 +28,8 @@
(type *)((char *)__mptr - offsetof(type, member)); })
#endif
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
#ifndef max
#define max(x, y) ({ \
typeof(x) _max1 = (x); \
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 6974431..0b45658 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -1,7 +1,15 @@
#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
-
+/*
+ * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks
+ * the build if it isn't defined. Use the equivalent one that glibc
+ * has on features.h.
+ */
+#include <features.h>
+#ifndef HAVE_LONG_LONG
+#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
+#endif
#include <slang.h>
#include <stdlib.h>
#include <newt.h>
@@ -14,6 +22,17 @@
#include "sort.h"
#include "symbol.h"
+#if SLANG_VERSION < 20104
+#define slsmg_printf(msg, args...) SLsmg_printf((char *)msg, ##args)
+#define slsmg_write_nstring(msg, len) SLsmg_write_nstring((char *)msg, len)
+#define sltt_set_color(obj, name, fg, bg) SLtt_set_color(obj,(char *)name,\
+ (char *)fg, (char *)bg)
+#else
+#define slsmg_printf SLsmg_printf
+#define slsmg_write_nstring SLsmg_write_nstring
+#define sltt_set_color SLtt_set_color
+#endif
+
struct ui_progress {
newtComponent form, scale;
};
@@ -118,6 +137,7 @@
static void newt_form__set_exit_keys(newtComponent self)
{
+ newtFormAddHotKey(self, NEWT_KEY_LEFT);
newtFormAddHotKey(self, NEWT_KEY_ESCAPE);
newtFormAddHotKey(self, 'Q');
newtFormAddHotKey(self, 'q');
@@ -166,6 +186,48 @@
return rc;
}
+static int ui__help_window(const char *text)
+{
+ struct newtExitStruct es;
+ newtComponent tb, form = newt_form__new();
+ int rc = -1;
+ int max_len = 0, nr_lines = 0;
+ const char *t;
+
+ if (form == NULL)
+ return -1;
+
+ t = text;
+ while (1) {
+ const char *sep = strchr(t, '\n');
+ int len;
+
+ if (sep == NULL)
+ sep = strchr(t, '\0');
+ len = sep - t;
+ if (max_len < len)
+ max_len = len;
+ ++nr_lines;
+ if (*sep == '\0')
+ break;
+ t = sep + 1;
+ }
+
+ tb = newtTextbox(0, 0, max_len, nr_lines, 0);
+ if (tb == NULL)
+ goto out_destroy_form;
+
+ newtTextboxSetText(tb, text);
+ newtFormAddComponent(form, tb);
+ newtCenteredWindow(max_len, nr_lines, NULL);
+ newtFormRun(form, &es);
+ newtPopWindow();
+ rc = 0;
+out_destroy_form:
+ newtFormDestroy(form);
+ return rc;
+}
+
static bool dialog_yesno(const char *msg)
{
/* newtWinChoice should really be accepting const char pointers... */
@@ -249,21 +311,21 @@
color = ui_browser__percent_color(percent, current_entry);
SLsmg_set_color(color);
- SLsmg_printf(" %7.2f ", percent);
+ slsmg_printf(" %7.2f ", percent);
if (!current_entry)
SLsmg_set_color(HE_COLORSET_CODE);
} else {
int color = ui_browser__percent_color(0, current_entry);
SLsmg_set_color(color);
- SLsmg_write_nstring(" ", 9);
+ slsmg_write_nstring(" ", 9);
}
SLsmg_write_char(':');
- SLsmg_write_nstring(" ", 8);
+ slsmg_write_nstring(" ", 8);
if (!*self->line)
- SLsmg_write_nstring(" ", width - 18);
+ slsmg_write_nstring(" ", width - 18);
else
- SLsmg_write_nstring(self->line, width - 18);
+ slsmg_write_nstring(self->line, width - 18);
return 0;
}
@@ -321,9 +383,9 @@
newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
+ newtFormAddHotKey(self->form, ' ');
newtFormAddHotKey(self->form, NEWT_KEY_HOME);
newtFormAddHotKey(self->form, NEWT_KEY_END);
- newtFormAddHotKey(self->form, NEWT_KEY_LEFT);
if (ui_browser__refresh_entries(self) < 0)
return -1;
@@ -358,6 +420,7 @@
}
break;
case NEWT_KEY_PGDN:
+ case ' ':
if (self->first_visible_entry_idx + self->height > self->nr_entries - 1)
break;
@@ -756,8 +819,11 @@
newtFormAddHotKey(self->form, 'd');
newtFormAddHotKey(self->form, 'T');
newtFormAddHotKey(self->form, 't');
+ newtFormAddHotKey(self->form, '?');
+ newtFormAddHotKey(self->form, 'H');
+ newtFormAddHotKey(self->form, 'h');
+ newtFormAddHotKey(self->form, NEWT_KEY_F1);
newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
- newtFormAddHotKey(self->form, NEWT_KEY_LEFT);
newtFormAddComponents(self->form, self->tree, NULL);
self->selection = newt__symbol_tree_get_current(self->tree);
@@ -843,6 +909,9 @@
dso = browser->selection->map ? browser->selection->map->dso : NULL;
if (es.reason == NEWT_EXIT_HOTKEY) {
+ if (es.u.key == NEWT_KEY_F1)
+ goto do_help;
+
switch (toupper(es.u.key)) {
case 'A':
goto do_annotate;
@@ -850,6 +919,17 @@
goto zoom_dso;
case 'T':
goto zoom_thread;
+ case 'H':
+ case '?':
+do_help:
+ ui__help_window("-> Zoom into DSO/Threads & Annotate current symbol\n"
+ "<- Zoom out\n"
+ "a Annotate current symbol\n"
+ "h/?/F1 Show this window\n"
+ "d Zoom into current DSO\n"
+ "t Zoom into current Thread\n"
+ "q/CTRL+C Exit browser");
+ continue;
default:;
}
if (toupper(es.u.key) == 'Q' ||
@@ -988,23 +1068,26 @@
void setup_browser(void)
{
struct newtPercentTreeColors *c = &defaultPercentTreeColors;
- if (!isatty(1))
- return;
- use_browser = true;
+ if (!isatty(1) || !use_browser) {
+ setup_pager();
+ return;
+ }
+
+ use_browser = 1;
newtInit();
newtCls();
ui_helpline__puts(" ");
- SLtt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
- SLtt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
- SLtt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
- SLtt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
- SLtt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
+ sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
+ sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg);
+ sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg);
+ sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg);
+ sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg);
}
void exit_browser(bool wait_for_ok)
{
- if (use_browser) {
+ if (use_browser > 0) {
if (wait_for_ok) {
char title[] = "Fatal Error", ok[] = "Ok";
newtWinMessage(title, ok, browser__last_msg);
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index ed88764..99d02aa 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -51,7 +51,7 @@
case OPTION_BOOLEAN:
case OPTION_INCR:
case OPTION_BIT:
- case OPTION_SET_INT:
+ case OPTION_SET_UINT:
case OPTION_SET_PTR:
return opterror(opt, "takes no value", flags);
case OPTION_END:
@@ -59,7 +59,9 @@
case OPTION_GROUP:
case OPTION_STRING:
case OPTION_INTEGER:
+ case OPTION_UINTEGER:
case OPTION_LONG:
+ case OPTION_U64:
default:
break;
}
@@ -81,8 +83,8 @@
*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
return 0;
- case OPTION_SET_INT:
- *(int *)opt->value = unset ? 0 : opt->defval;
+ case OPTION_SET_UINT:
+ *(unsigned int *)opt->value = unset ? 0 : opt->defval;
return 0;
case OPTION_SET_PTR:
@@ -125,6 +127,22 @@
return opterror(opt, "expects a numerical value", flags);
return 0;
+ case OPTION_UINTEGER:
+ if (unset) {
+ *(unsigned int *)opt->value = 0;
+ return 0;
+ }
+ if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+ *(unsigned int *)opt->value = opt->defval;
+ return 0;
+ }
+ if (get_arg(p, opt, flags, &arg))
+ return -1;
+ *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
+ if (*s)
+ return opterror(opt, "expects a numerical value", flags);
+ return 0;
+
case OPTION_LONG:
if (unset) {
*(long *)opt->value = 0;
@@ -141,6 +159,22 @@
return opterror(opt, "expects a numerical value", flags);
return 0;
+ case OPTION_U64:
+ if (unset) {
+ *(u64 *)opt->value = 0;
+ return 0;
+ }
+ if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+ *(u64 *)opt->value = opt->defval;
+ return 0;
+ }
+ if (get_arg(p, opt, flags, &arg))
+ return -1;
+ *(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
+ if (*s)
+ return opterror(opt, "expects a numerical value", flags);
+ return 0;
+
case OPTION_END:
case OPTION_ARGUMENT:
case OPTION_GROUP:
@@ -446,7 +480,10 @@
switch (opts->type) {
case OPTION_ARGUMENT:
break;
+ case OPTION_LONG:
+ case OPTION_U64:
case OPTION_INTEGER:
+ case OPTION_UINTEGER:
if (opts->flags & PARSE_OPT_OPTARG)
if (opts->long_name)
pos += fprintf(stderr, "[=<n>]");
@@ -478,15 +515,14 @@
pos += fprintf(stderr, " ...");
}
break;
- default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
+ default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
case OPTION_END:
case OPTION_GROUP:
case OPTION_BIT:
case OPTION_BOOLEAN:
case OPTION_INCR:
- case OPTION_SET_INT:
+ case OPTION_SET_UINT:
case OPTION_SET_PTR:
- case OPTION_LONG:
break;
}
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index b2da725..c7d72dc 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -1,6 +1,9 @@
#ifndef __PERF_PARSE_OPTIONS_H
#define __PERF_PARSE_OPTIONS_H
+#include <linux/kernel.h>
+#include <stdbool.h>
+
enum parse_opt_type {
/* special types */
OPTION_END,
@@ -10,13 +13,15 @@
OPTION_BIT,
OPTION_BOOLEAN,
OPTION_INCR,
- OPTION_SET_INT,
+ OPTION_SET_UINT,
OPTION_SET_PTR,
/* options with arguments (usually) */
OPTION_STRING,
OPTION_INTEGER,
OPTION_LONG,
OPTION_CALLBACK,
+ OPTION_U64,
+ OPTION_UINTEGER,
};
enum parse_opt_flags {
@@ -74,7 +79,7 @@
*
* `defval`::
* default value to fill (*->value) with for PARSE_OPT_OPTARG.
- * OPTION_{BIT,SET_INT,SET_PTR} store the {mask,integer,pointer} to put in
+ * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
* the value when met.
* CALLBACKS can use it like they want.
*/
@@ -91,17 +96,21 @@
intptr_t defval;
};
+#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
+
#define OPT_END() { .type = OPTION_END }
#define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) }
#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) }
-#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) }
-#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
-#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
-#define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) }
+#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
+#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
+#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
+#define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) }
#define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
-#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
-#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
-#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) }
+#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
+#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
+#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
+#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
+#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
#define OPT_DATE(s, l, v, h) \
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
#define OPT_CALLBACK(s, l, v, a, h, f) \
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index fd1f2fa..58a470d 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -54,21 +54,6 @@
return path;
}
-char *mksnpath(char *buf, size_t n, const char *fmt, ...)
-{
- va_list args;
- unsigned len;
-
- va_start(args, fmt);
- len = vsnprintf(buf, n, fmt, args);
- va_end(args);
- if (len >= n) {
- strlcpy(buf, bad_path, n);
- return buf;
- }
- return cleanup_path(buf);
-}
-
static char *perf_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
{
const char *perf_dir = get_perf_dir();
@@ -89,15 +74,6 @@
return buf;
}
-char *perf_snpath(char *buf, size_t n, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- (void)perf_vsnpath(buf, n, fmt, args);
- va_end(args);
- return buf;
-}
-
char *perf_pathdup(const char *fmt, ...)
{
char path[PATH_MAX];
@@ -143,184 +119,6 @@
return cleanup_path(pathname);
}
-
-/* perf_mkstemp() - create tmp file honoring TMPDIR variable */
-int perf_mkstemp(char *path, size_t len, const char *template)
-{
- const char *tmp;
- size_t n;
-
- tmp = getenv("TMPDIR");
- if (!tmp)
- tmp = "/tmp";
- n = snprintf(path, len, "%s/%s", tmp, template);
- if (len <= n) {
- errno = ENAMETOOLONG;
- return -1;
- }
- return mkstemp(path);
-}
-
-
-const char *make_relative_path(const char *abs_path, const char *base)
-{
- static char buf[PATH_MAX + 1];
- int baselen;
-
- if (!base)
- return abs_path;
-
- baselen = strlen(base);
- if (prefixcmp(abs_path, base))
- return abs_path;
- if (abs_path[baselen] == '/')
- baselen++;
- else if (base[baselen - 1] != '/')
- return abs_path;
-
- strcpy(buf, abs_path + baselen);
-
- return buf;
-}
-
-/*
- * It is okay if dst == src, but they should not overlap otherwise.
- *
- * Performs the following normalizations on src, storing the result in dst:
- * - Ensures that components are separated by '/' (Windows only)
- * - Squashes sequences of '/'.
- * - Removes "." components.
- * - Removes ".." components, and the components the precede them.
- * Returns failure (non-zero) if a ".." component appears as first path
- * component anytime during the normalization. Otherwise, returns success (0).
- *
- * Note that this function is purely textual. It does not follow symlinks,
- * verify the existence of the path, or make any system calls.
- */
-int normalize_path_copy(char *dst, const char *src)
-{
- char *dst0;
-
- if (has_dos_drive_prefix(src)) {
- *dst++ = *src++;
- *dst++ = *src++;
- }
- dst0 = dst;
-
- if (is_dir_sep(*src)) {
- *dst++ = '/';
- while (is_dir_sep(*src))
- src++;
- }
-
- for (;;) {
- char c = *src;
-
- /*
- * A path component that begins with . could be
- * special:
- * (1) "." and ends -- ignore and terminate.
- * (2) "./" -- ignore them, eat slash and continue.
- * (3) ".." and ends -- strip one and terminate.
- * (4) "../" -- strip one, eat slash and continue.
- */
- if (c == '.') {
- if (!src[1]) {
- /* (1) */
- src++;
- } else if (is_dir_sep(src[1])) {
- /* (2) */
- src += 2;
- while (is_dir_sep(*src))
- src++;
- continue;
- } else if (src[1] == '.') {
- if (!src[2]) {
- /* (3) */
- src += 2;
- goto up_one;
- } else if (is_dir_sep(src[2])) {
- /* (4) */
- src += 3;
- while (is_dir_sep(*src))
- src++;
- goto up_one;
- }
- }
- }
-
- /* copy up to the next '/', and eat all '/' */
- while ((c = *src++) != '\0' && !is_dir_sep(c))
- *dst++ = c;
- if (is_dir_sep(c)) {
- *dst++ = '/';
- while (is_dir_sep(c))
- c = *src++;
- src--;
- } else if (!c)
- break;
- continue;
-
- up_one:
- /*
- * dst0..dst is prefix portion, and dst[-1] is '/';
- * go up one level.
- */
- dst--; /* go to trailing '/' */
- if (dst <= dst0)
- return -1;
- /* Windows: dst[-1] cannot be backslash anymore */
- while (dst0 < dst && dst[-1] != '/')
- dst--;
- }
- *dst = '\0';
- return 0;
-}
-
-/*
- * path = Canonical absolute path
- * prefix_list = Colon-separated list of absolute paths
- *
- * Determines, for each path in prefix_list, whether the "prefix" really
- * is an ancestor directory of path. Returns the length of the longest
- * ancestor directory, excluding any trailing slashes, or -1 if no prefix
- * is an ancestor. (Note that this means 0 is returned if prefix_list is
- * "/".) "/foo" is not considered an ancestor of "/foobar". Directories
- * are not considered to be their own ancestors. path must be in a
- * canonical form: empty components, or "." or ".." components are not
- * allowed. prefix_list may be null, which is like "".
- */
-int longest_ancestor_length(const char *path, const char *prefix_list)
-{
- char buf[PATH_MAX+1];
- const char *ceil, *colon;
- int len, max_len = -1;
-
- if (prefix_list == NULL || !strcmp(path, "/"))
- return -1;
-
- for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
- for (colon = ceil; *colon && *colon != PATH_SEP; colon++);
- len = colon - ceil;
- if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
- continue;
- strlcpy(buf, ceil, len+1);
- if (normalize_path_copy(buf, buf) < 0)
- continue;
- len = strlen(buf);
- if (len > 0 && buf[len-1] == '/')
- buf[--len] = '\0';
-
- if (!strncmp(path, buf, len) &&
- path[len] == '/' &&
- len > max_len) {
- max_len = len;
- }
- }
-
- return max_len;
-}
-
/* strip arbitrary amount of directory separators at end of path */
static inline int chomp_trailing_dir_sep(const char *path, int len)
{
@@ -354,5 +152,5 @@
if (path_len && !is_dir_sep(path[path_len - 1]))
return NULL;
- return xstrndup(path, chomp_trailing_dir_sep(path, path_len));
+ return strndup(path, chomp_trailing_dir_sep(path, path_len));
}
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 562b144..d964cb1 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -668,6 +668,7 @@
ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
if (ret <= 0 || nops == 0) {
pf->fb_ops = NULL;
+#if _ELFUTILS_PREREQ(0, 142)
} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
pf->cfi != NULL) {
Dwarf_Frame *frame;
@@ -677,6 +678,7 @@
(uintmax_t)pf->addr);
return -ENOENT;
}
+#endif
}
/* Find each argument */
@@ -741,32 +743,36 @@
const char *fname, const char *pat)
{
char *fbuf, *p1, *p2;
- int fd, ret, line, nlines = 0;
+ int fd, line, nlines = -1;
struct stat st;
fd = open(fname, O_RDONLY);
if (fd < 0) {
pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
- return fd;
+ return -errno;
}
- ret = fstat(fd, &st);
- if (ret < 0) {
+ if (fstat(fd, &st) < 0) {
pr_warning("Failed to get the size of %s: %s\n",
fname, strerror(errno));
- return ret;
+ nlines = -errno;
+ goto out_close;
}
- fbuf = xmalloc(st.st_size + 2);
- ret = read(fd, fbuf, st.st_size);
- if (ret < 0) {
+
+ nlines = -ENOMEM;
+ fbuf = malloc(st.st_size + 2);
+ if (fbuf == NULL)
+ goto out_close;
+ if (read(fd, fbuf, st.st_size) < 0) {
pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
- return ret;
+ nlines = -errno;
+ goto out_free_fbuf;
}
- close(fd);
fbuf[st.st_size] = '\n'; /* Dummy line */
fbuf[st.st_size + 1] = '\0';
p1 = fbuf;
line = 1;
+ nlines = 0;
while ((p2 = strchr(p1, '\n')) != NULL) {
*p2 = '\0';
if (strlazymatch(p1, pat)) {
@@ -776,7 +782,10 @@
line++;
p1 = p2 + 1;
}
+out_free_fbuf:
free(fbuf);
+out_close:
+ close(fd);
return nlines;
}
@@ -953,11 +962,15 @@
if (!dbg) {
pr_warning("No dwarf info found in the vmlinux - "
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
+ free(pf.tevs);
+ *tevs = NULL;
return -EBADF;
}
+#if _ELFUTILS_PREREQ(0, 142)
/* Get the call frame information from this dwarf */
pf.cfi = dwarf_getcfi(dbg);
+#endif
off = 0;
line_list__init(&pf.lcache);
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 66f1980..e1f61dc 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -29,6 +29,7 @@
#include <dwarf.h>
#include <libdw.h>
+#include <version.h>
struct probe_finder {
struct perf_probe_event *pev; /* Target probe event */
@@ -44,7 +45,9 @@
struct list_head lcache; /* Line cache for lazy match */
/* For variable searching */
+#if _ELFUTILS_PREREQ(0, 142)
Dwarf_CFI *cfi; /* Call Frame Information */
+#endif
Dwarf_Op *fb_ops; /* Frame base attribute */
struct perf_probe_arg *pvar; /* Current target variable */
struct kprobe_trace_arg *tvar; /* Current result variable */
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 2726fe4..01f0324 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -1,8 +1,6 @@
#include "cache.h"
#include "quote.h"
-int quote_path_fully = 1;
-
/* Help to copy the thing properly quoted for the shell safety.
* any single quote is replaced with '\'', any exclamation point
* is replaced with '\!', and the whole thing is enclosed in a
@@ -19,7 +17,7 @@
return (c == '\'' || c == '!');
}
-void sq_quote_buf(struct strbuf *dst, const char *src)
+static void sq_quote_buf(struct strbuf *dst, const char *src)
{
char *to_free = NULL;
@@ -41,23 +39,6 @@
free(to_free);
}
-void sq_quote_print(FILE *stream, const char *src)
-{
- char c;
-
- fputc('\'', stream);
- while ((c = *src++)) {
- if (need_bs_quote(c)) {
- fputs("'\\", stream);
- fputc(c, stream);
- fputc('\'', stream);
- } else {
- fputc(c, stream);
- }
- }
- fputc('\'', stream);
-}
-
void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
{
int i;
@@ -71,415 +52,3 @@
die("Too many or long arguments");
}
}
-
-char *sq_dequote_step(char *arg, char **next)
-{
- char *dst = arg;
- char *src = arg;
- char c;
-
- if (*src != '\'')
- return NULL;
- for (;;) {
- c = *++src;
- if (!c)
- return NULL;
- if (c != '\'') {
- *dst++ = c;
- continue;
- }
- /* We stepped out of sq */
- switch (*++src) {
- case '\0':
- *dst = 0;
- if (next)
- *next = NULL;
- return arg;
- case '\\':
- c = *++src;
- if (need_bs_quote(c) && *++src == '\'') {
- *dst++ = c;
- continue;
- }
- /* Fallthrough */
- default:
- if (!next || !isspace(*src))
- return NULL;
- do {
- c = *++src;
- } while (isspace(c));
- *dst = 0;
- *next = src;
- return arg;
- }
- }
-}
-
-char *sq_dequote(char *arg)
-{
- return sq_dequote_step(arg, NULL);
-}
-
-int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
-{
- char *next = arg;
-
- if (!*arg)
- return 0;
- do {
- char *dequoted = sq_dequote_step(next, &next);
- if (!dequoted)
- return -1;
- ALLOC_GROW(*argv, *nr + 1, *alloc);
- (*argv)[(*nr)++] = dequoted;
- } while (next);
-
- return 0;
-}
-
-/* 1 means: quote as octal
- * 0 means: quote as octal if (quote_path_fully)
- * -1 means: never quote
- * c: quote as "\\c"
- */
-#define X8(x) x, x, x, x, x, x, x, x
-#define X16(x) X8(x), X8(x)
-static signed char const sq_lookup[256] = {
- /* 0 1 2 3 4 5 6 7 */
- /* 0x00 */ 1, 1, 1, 1, 1, 1, 1, 'a',
- /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r', 1, 1,
- /* 0x10 */ X16(1),
- /* 0x20 */ -1, -1, '"', -1, -1, -1, -1, -1,
- /* 0x28 */ X16(-1), X16(-1), X16(-1),
- /* 0x58 */ -1, -1, -1, -1,'\\', -1, -1, -1,
- /* 0x60 */ X16(-1), X8(-1),
- /* 0x78 */ -1, -1, -1, -1, -1, -1, -1, 1,
- /* 0x80 */ /* set to 0 */
-};
-
-static inline int sq_must_quote(char c)
-{
- return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
-}
-
-/*
- * Returns the longest prefix not needing a quote up to maxlen if
- * positive.
- * This stops at the first \0 because it's marked as a character
- * needing an escape.
- */
-static ssize_t next_quote_pos(const char *s, ssize_t maxlen)
-{
- ssize_t len;
-
- if (maxlen < 0) {
- for (len = 0; !sq_must_quote(s[len]); len++);
- } else {
- for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++);
- }
- return len;
-}
-
-/*
- * C-style name quoting.
- *
- * (1) if sb and fp are both NULL, inspect the input name and counts the
- * number of bytes that are needed to hold c_style quoted version of name,
- * counting the double quotes around it but not terminating NUL, and
- * returns it.
- * However, if name does not need c_style quoting, it returns 0.
- *
- * (2) if sb or fp are not NULL, it emits the c_style quoted version
- * of name, enclosed with double quotes if asked and needed only.
- * Return value is the same as in (1).
- */
-static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
- struct strbuf *sb, FILE *fp, int no_dq)
-{
-#define EMIT(c) \
- do { \
- if (sb) strbuf_addch(sb, (c)); \
- if (fp) fputc((c), fp); \
- count++; \
- } while (0)
-
-#define EMITBUF(s, l) \
- do { \
- int __ret; \
- if (sb) strbuf_add(sb, (s), (l)); \
- if (fp) __ret = fwrite((s), (l), 1, fp); \
- count += (l); \
- } while (0)
-
- ssize_t len, count = 0;
- const char *p = name;
-
- for (;;) {
- int ch;
-
- len = next_quote_pos(p, maxlen);
- if (len == maxlen || !p[len])
- break;
-
- if (!no_dq && p == name)
- EMIT('"');
-
- EMITBUF(p, len);
- EMIT('\\');
- p += len;
- ch = (unsigned char)*p++;
- if (sq_lookup[ch] >= ' ') {
- EMIT(sq_lookup[ch]);
- } else {
- EMIT(((ch >> 6) & 03) + '0');
- EMIT(((ch >> 3) & 07) + '0');
- EMIT(((ch >> 0) & 07) + '0');
- }
- }
-
- EMITBUF(p, len);
- if (p == name) /* no ending quote needed */
- return 0;
-
- if (!no_dq)
- EMIT('"');
- return count;
-}
-
-size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq)
-{
- return quote_c_style_counted(name, -1, sb, fp, nodq);
-}
-
-void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq)
-{
- if (quote_c_style(prefix, NULL, NULL, 0) ||
- quote_c_style(path, NULL, NULL, 0)) {
- if (!nodq)
- strbuf_addch(sb, '"');
- quote_c_style(prefix, sb, NULL, 1);
- quote_c_style(path, sb, NULL, 1);
- if (!nodq)
- strbuf_addch(sb, '"');
- } else {
- strbuf_addstr(sb, prefix);
- strbuf_addstr(sb, path);
- }
-}
-
-void write_name_quoted(const char *name, FILE *fp, int terminator)
-{
- if (terminator) {
- quote_c_style(name, NULL, fp, 0);
- } else {
- fputs(name, fp);
- }
- fputc(terminator, fp);
-}
-
-void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
- const char *name, FILE *fp, int terminator)
-{
- int needquote = 0;
-
- if (terminator) {
- needquote = next_quote_pos(pfx, pfxlen) < pfxlen
- || name[next_quote_pos(name, -1)];
- }
- if (needquote) {
- fputc('"', fp);
- quote_c_style_counted(pfx, pfxlen, NULL, fp, 1);
- quote_c_style(name, NULL, fp, 1);
- fputc('"', fp);
- } else {
- int ret;
-
- ret = fwrite(pfx, pfxlen, 1, fp);
- fputs(name, fp);
- }
- fputc(terminator, fp);
-}
-
-/* quote path as relative to the given prefix */
-char *quote_path_relative(const char *in, int len,
- struct strbuf *out, const char *prefix)
-{
- int needquote;
-
- if (len < 0)
- len = strlen(in);
-
- /* "../" prefix itself does not need quoting, but "in" might. */
- needquote = (next_quote_pos(in, len) < len);
- strbuf_setlen(out, 0);
- strbuf_grow(out, len);
-
- if (needquote)
- strbuf_addch(out, '"');
- if (prefix) {
- int off = 0;
- while (off < len && prefix[off] && prefix[off] == in[off])
- if (prefix[off] == '/') {
- prefix += off + 1;
- in += off + 1;
- len -= off + 1;
- off = 0;
- } else
- off++;
-
- for (; *prefix; prefix++)
- if (*prefix == '/')
- strbuf_addstr(out, "../");
- }
-
- quote_c_style_counted (in, len, out, NULL, 1);
-
- if (needquote)
- strbuf_addch(out, '"');
- if (!out->len)
- strbuf_addstr(out, "./");
-
- return out->buf;
-}
-
-/*
- * C-style name unquoting.
- *
- * Quoted should point at the opening double quote.
- * + Returns 0 if it was able to unquote the string properly, and appends the
- * result in the strbuf `sb'.
- * + Returns -1 in case of error, and doesn't touch the strbuf. Though note
- * that this function will allocate memory in the strbuf, so calling
- * strbuf_release is mandatory whichever result unquote_c_style returns.
- *
- * Updates endp pointer to point at one past the ending double quote if given.
- */
-int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp)
-{
- size_t oldlen = sb->len, len;
- int ch, ac;
-
- if (*quoted++ != '"')
- return -1;
-
- for (;;) {
- len = strcspn(quoted, "\"\\");
- strbuf_add(sb, quoted, len);
- quoted += len;
-
- switch (*quoted++) {
- case '"':
- if (endp)
- *endp = quoted;
- return 0;
- case '\\':
- break;
- default:
- goto error;
- }
-
- switch ((ch = *quoted++)) {
- case 'a': ch = '\a'; break;
- case 'b': ch = '\b'; break;
- case 'f': ch = '\f'; break;
- case 'n': ch = '\n'; break;
- case 'r': ch = '\r'; break;
- case 't': ch = '\t'; break;
- case 'v': ch = '\v'; break;
-
- case '\\': case '"':
- break; /* verbatim */
-
- /* octal values with first digit over 4 overflow */
- case '0': case '1': case '2': case '3':
- ac = ((ch - '0') << 6);
- if ((ch = *quoted++) < '0' || '7' < ch)
- goto error;
- ac |= ((ch - '0') << 3);
- if ((ch = *quoted++) < '0' || '7' < ch)
- goto error;
- ac |= (ch - '0');
- ch = ac;
- break;
- default:
- goto error;
- }
- strbuf_addch(sb, ch);
- }
-
- error:
- strbuf_setlen(sb, oldlen);
- return -1;
-}
-
-/* quoting as a string literal for other languages */
-
-void perl_quote_print(FILE *stream, const char *src)
-{
- const char sq = '\'';
- const char bq = '\\';
- char c;
-
- fputc(sq, stream);
- while ((c = *src++)) {
- if (c == sq || c == bq)
- fputc(bq, stream);
- fputc(c, stream);
- }
- fputc(sq, stream);
-}
-
-void python_quote_print(FILE *stream, const char *src)
-{
- const char sq = '\'';
- const char bq = '\\';
- const char nl = '\n';
- char c;
-
- fputc(sq, stream);
- while ((c = *src++)) {
- if (c == nl) {
- fputc(bq, stream);
- fputc('n', stream);
- continue;
- }
- if (c == sq || c == bq)
- fputc(bq, stream);
- fputc(c, stream);
- }
- fputc(sq, stream);
-}
-
-void tcl_quote_print(FILE *stream, const char *src)
-{
- char c;
-
- fputc('"', stream);
- while ((c = *src++)) {
- switch (c) {
- case '[': case ']':
- case '{': case '}':
- case '$': case '\\': case '"':
- fputc('\\', stream);
- default:
- fputc(c, stream);
- break;
- case '\f':
- fputs("\\f", stream);
- break;
- case '\r':
- fputs("\\r", stream);
- break;
- case '\n':
- fputs("\\n", stream);
- break;
- case '\t':
- fputs("\\t", stream);
- break;
- case '\v':
- fputs("\\v", stream);
- break;
- }
- }
- fputc('"', stream);
-}
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index b6a0197..172889e 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -22,47 +22,8 @@
*
* Note that the above examples leak memory! Remember to free result from
* sq_quote() in a real application.
- *
- * sq_quote_buf() writes to an existing buffer of specified size; it
- * will return the number of characters that would have been written
- * excluding the final null regardless of the buffer size.
*/
-extern void sq_quote_print(FILE *stream, const char *src);
-
-extern void sq_quote_buf(struct strbuf *, const char *src);
extern void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
-/* This unwraps what sq_quote() produces in place, but returns
- * NULL if the input does not look like what sq_quote would have
- * produced.
- */
-extern char *sq_dequote(char *);
-
-/*
- * Same as the above, but can be used to unwrap many arguments in the
- * same string separated by space. "next" is changed to point to the
- * next argument that should be passed as first parameter. When there
- * is no more argument to be dequoted, "next" is updated to point to NULL.
- */
-extern char *sq_dequote_step(char *arg, char **next);
-extern int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc);
-
-extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
-extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
-extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
-
-extern void write_name_quoted(const char *name, FILE *, int terminator);
-extern void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
- const char *name, FILE *, int terminator);
-
-/* quote path as relative to the given prefix */
-char *quote_path_relative(const char *in, int len,
- struct strbuf *out, const char *prefix);
-
-/* quoting as a string literal for other languages */
-extern void perl_quote_print(FILE *stream, const char *src);
-extern void python_quote_print(FILE *stream, const char *src);
-extern void tcl_quote_print(FILE *stream, const char *src);
-
#endif /* __PERF_QUOTE_H */
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index 2b615ac..da8e9b2 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -212,93 +212,3 @@
prepare_run_command_v_opt(&cmd, argv, opt);
return run_command(&cmd);
}
-
-int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env)
-{
- struct child_process cmd;
- prepare_run_command_v_opt(&cmd, argv, opt);
- cmd.dir = dir;
- cmd.env = env;
- return run_command(&cmd);
-}
-
-int start_async(struct async *async)
-{
- int pipe_out[2];
-
- if (pipe(pipe_out) < 0)
- return error("cannot create pipe: %s", strerror(errno));
- async->out = pipe_out[0];
-
- /* Flush stdio before fork() to avoid cloning buffers */
- fflush(NULL);
-
- async->pid = fork();
- if (async->pid < 0) {
- error("fork (async) failed: %s", strerror(errno));
- close_pair(pipe_out);
- return -1;
- }
- if (!async->pid) {
- close(pipe_out[0]);
- exit(!!async->proc(pipe_out[1], async->data));
- }
- close(pipe_out[1]);
-
- return 0;
-}
-
-int finish_async(struct async *async)
-{
- int ret = 0;
-
- if (wait_or_whine(async->pid))
- ret = error("waitpid (async) failed");
-
- return ret;
-}
-
-int run_hook(const char *index_file, const char *name, ...)
-{
- struct child_process hook;
- const char **argv = NULL, *env[2];
- char idx[PATH_MAX];
- va_list args;
- int ret;
- size_t i = 0, alloc = 0;
-
- if (access(perf_path("hooks/%s", name), X_OK) < 0)
- return 0;
-
- va_start(args, name);
- ALLOC_GROW(argv, i + 1, alloc);
- argv[i++] = perf_path("hooks/%s", name);
- while (argv[i-1]) {
- ALLOC_GROW(argv, i + 1, alloc);
- argv[i++] = va_arg(args, const char *);
- }
- va_end(args);
-
- memset(&hook, 0, sizeof(hook));
- hook.argv = argv;
- hook.no_stdin = 1;
- hook.stdout_to_stderr = 1;
- if (index_file) {
- snprintf(idx, sizeof(idx), "PERF_INDEX_FILE=%s", index_file);
- env[0] = idx;
- env[1] = NULL;
- hook.env = env;
- }
-
- ret = start_command(&hook);
- free(argv);
- if (ret) {
- warning("Could not spawn %s", argv[0]);
- return ret;
- }
- ret = finish_command(&hook);
- if (ret == -ERR_RUN_COMMAND_WAITPID_SIGNAL)
- warning("%s exited due to uncaught signal", argv[0]);
-
- return ret;
-}
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
index d790287..1ef264d 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/perf/util/run-command.h
@@ -50,39 +50,9 @@
int finish_command(struct child_process *);
int run_command(struct child_process *);
-extern int run_hook(const char *index_file, const char *name, ...);
-
#define RUN_COMMAND_NO_STDIN 1
#define RUN_PERF_CMD 2 /*If this is to be perf sub-command */
#define RUN_COMMAND_STDOUT_TO_STDERR 4
int run_command_v_opt(const char **argv, int opt);
-/*
- * env (the environment) is to be formatted like environ: "VAR=VALUE".
- * To unset an environment variable use just "VAR".
- */
-int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env);
-
-/*
- * The purpose of the following functions is to feed a pipe by running
- * a function asynchronously and providing output that the caller reads.
- *
- * It is expected that no synchronization and mutual exclusion between
- * the caller and the feed function is necessary so that the function
- * can run in a thread without interfering with the caller.
- */
-struct async {
- /*
- * proc writes to fd and closes it;
- * returns 0 on success, non-zero on failure
- */
- int (*proc)(int fd, void *data);
- void *data;
- int out; /* caller reads from here and closes it */
- pid_t pid;
-};
-
-int start_async(struct async *async);
-int finish_async(struct async *async);
-
#endif /* __PERF_RUN_COMMAND_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 25bfca4..8f83a18 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -5,6 +5,7 @@
#include <byteswap.h>
#include <unistd.h>
#include <sys/types.h>
+#include <sys/mman.h>
#include "session.h"
#include "sort.h"
@@ -894,3 +895,10 @@
__dsos__fprintf(&self->host_machine.user_dsos, fp) +
machines__fprintf_dsos(&self->machines, fp);
}
+
+size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
+ bool with_hits)
+{
+ size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits);
+ return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits);
+}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index e7fce48..55c6881 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -132,12 +132,8 @@
size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
-static inline
-size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
- bool with_hits)
-{
- return machines__fprintf_dsos_buildid(&self->machines, fp, with_hits);
-}
+size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
+ FILE *fp, bool with_hits);
static inline
size_t perf_session__fprintf_nr_events(struct perf_session *self, FILE *fp)
diff --git a/tools/perf/util/sigchain.c b/tools/perf/util/sigchain.c
index 1118b99..ba785e9 100644
--- a/tools/perf/util/sigchain.c
+++ b/tools/perf/util/sigchain.c
@@ -16,7 +16,7 @@
die("BUG: signal out of range: %d", sig);
}
-int sigchain_push(int sig, sigchain_fun f)
+static int sigchain_push(int sig, sigchain_fun f)
{
struct sigchain_signal *s = signals + sig;
check_signum(sig);
diff --git a/tools/perf/util/sigchain.h b/tools/perf/util/sigchain.h
index 1a53c11..959d64e 100644
--- a/tools/perf/util/sigchain.h
+++ b/tools/perf/util/sigchain.h
@@ -3,7 +3,6 @@
typedef void (*sigchain_fun)(int);
-int sigchain_push(int sig, sigchain_fun f);
int sigchain_pop(int sig);
void sigchain_push_common(sigchain_fun f);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index da30b30..2316cb5 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,10 +1,10 @@
#include "sort.h"
regex_t parent_regex;
-char default_parent_pattern[] = "^sys_|^do_page_fault";
-char *parent_pattern = default_parent_pattern;
-char default_sort_order[] = "comm,dso,symbol";
-char *sort_order = default_sort_order;
+const char default_parent_pattern[] = "^sys_|^do_page_fault";
+const char *parent_pattern = default_parent_pattern;
+const char default_sort_order[] = "comm,dso,symbol";
+const char *sort_order = default_sort_order;
int sort__need_collapse = 0;
int sort__has_parent = 0;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index eab2e0b3..0d61c40 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -25,10 +25,10 @@
#include "sort.h"
extern regex_t parent_regex;
-extern char *sort_order;
-extern char default_parent_pattern[];
-extern char *parent_pattern;
-extern char default_sort_order[];
+extern const char *sort_order;
+extern const char default_parent_pattern[];
+extern const char *parent_pattern;
+extern const char default_sort_order[];
extern int sort__need_collapse;
extern int sort__has_parent;
extern char *field_sep;
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 5249d5a..92e0685 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -41,16 +41,6 @@
return res;
}
-void strbuf_attach(struct strbuf *sb, void *buf, size_t len, size_t alloc)
-{
- strbuf_release(sb);
- sb->buf = buf;
- sb->len = len;
- sb->alloc = alloc;
- strbuf_grow(sb, 0);
- sb->buf[sb->len] = '\0';
-}
-
void strbuf_grow(struct strbuf *sb, size_t extra)
{
if (sb->len + extra + 1 <= sb->len)
@@ -60,94 +50,7 @@
ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
}
-void strbuf_trim(struct strbuf *sb)
-{
- char *b = sb->buf;
- while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
- sb->len--;
- while (sb->len > 0 && isspace(*b)) {
- b++;
- sb->len--;
- }
- memmove(sb->buf, b, sb->len);
- sb->buf[sb->len] = '\0';
-}
-void strbuf_rtrim(struct strbuf *sb)
-{
- while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
- sb->len--;
- sb->buf[sb->len] = '\0';
-}
-
-void strbuf_ltrim(struct strbuf *sb)
-{
- char *b = sb->buf;
- while (sb->len > 0 && isspace(*b)) {
- b++;
- sb->len--;
- }
- memmove(sb->buf, b, sb->len);
- sb->buf[sb->len] = '\0';
-}
-
-void strbuf_tolower(struct strbuf *sb)
-{
- unsigned int i;
-
- for (i = 0; i < sb->len; i++)
- sb->buf[i] = tolower(sb->buf[i]);
-}
-
-struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
-{
- int alloc = 2, pos = 0;
- char *n, *p;
- struct strbuf **ret;
- struct strbuf *t;
-
- ret = calloc(alloc, sizeof(struct strbuf *));
- p = n = sb->buf;
- while (n < sb->buf + sb->len) {
- int len;
- n = memchr(n, delim, sb->len - (n - sb->buf));
- if (pos + 1 >= alloc) {
- alloc = alloc * 2;
- ret = realloc(ret, sizeof(struct strbuf *) * alloc);
- }
- if (!n)
- n = sb->buf + sb->len - 1;
- len = n - p + 1;
- t = malloc(sizeof(struct strbuf));
- strbuf_init(t, len);
- strbuf_add(t, p, len);
- ret[pos] = t;
- ret[++pos] = NULL;
- p = ++n;
- }
- return ret;
-}
-
-void strbuf_list_free(struct strbuf **sbs)
-{
- struct strbuf **s = sbs;
-
- while (*s) {
- strbuf_release(*s);
- free(*s++);
- }
- free(sbs);
-}
-
-int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
-{
- int len = a->len < b->len ? a->len: b->len;
- int cmp = memcmp(a->buf, b->buf, len);
- if (cmp)
- return cmp;
- return a->len < b->len ? -1: a->len != b->len;
-}
-
-void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
+static void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
const void *data, size_t dlen)
{
if (pos + len < pos)
@@ -166,11 +69,6 @@
strbuf_setlen(sb, sb->len + dlen - len);
}
-void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
-{
- strbuf_splice(sb, pos, 0, data, len);
-}
-
void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
{
strbuf_splice(sb, pos, len, NULL, 0);
@@ -183,13 +81,6 @@
strbuf_setlen(sb, sb->len + len);
}
-void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
-{
- strbuf_grow(sb, len);
- memcpy(sb->buf + sb->len, sb->buf + pos, len);
- strbuf_setlen(sb, sb->len + len);
-}
-
void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
{
int len;
@@ -214,57 +105,6 @@
strbuf_setlen(sb, sb->len + len);
}
-void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
- void *context)
-{
- for (;;) {
- const char *percent;
- size_t consumed;
-
- percent = strchrnul(format, '%');
- strbuf_add(sb, format, percent - format);
- if (!*percent)
- break;
- format = percent + 1;
-
- consumed = fn(sb, format, context);
- if (consumed)
- format += consumed;
- else
- strbuf_addch(sb, '%');
- }
-}
-
-size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
- void *context)
-{
- struct strbuf_expand_dict_entry *e = context;
- size_t len;
-
- for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
- if (!strncmp(placeholder, e->placeholder, len)) {
- if (e->value)
- strbuf_addstr(sb, e->value);
- return len;
- }
- }
- return 0;
-}
-
-size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
-{
- size_t res;
- size_t oldalloc = sb->alloc;
-
- strbuf_grow(sb, size);
- res = fread(sb->buf + sb->len, 1, size, f);
- if (res > 0)
- strbuf_setlen(sb, sb->len + res);
- else if (oldalloc == 0)
- strbuf_release(sb);
- return res;
-}
-
ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
{
size_t oldlen = sb->len;
@@ -291,70 +131,3 @@
sb->buf[sb->len] = '\0';
return sb->len - oldlen;
}
-
-#define STRBUF_MAXLINK (2*PATH_MAX)
-
-int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint)
-{
- size_t oldalloc = sb->alloc;
-
- if (hint < 32)
- hint = 32;
-
- while (hint < STRBUF_MAXLINK) {
- ssize_t len;
-
- strbuf_grow(sb, hint);
- len = readlink(path, sb->buf, hint);
- if (len < 0) {
- if (errno != ERANGE)
- break;
- } else if (len < hint) {
- strbuf_setlen(sb, len);
- return 0;
- }
-
- /* .. the buffer was too small - try again */
- hint *= 2;
- }
- if (oldalloc == 0)
- strbuf_release(sb);
- return -1;
-}
-
-int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
-{
- int ch;
-
- strbuf_grow(sb, 0);
- if (feof(fp))
- return EOF;
-
- strbuf_reset(sb);
- while ((ch = fgetc(fp)) != EOF) {
- if (ch == term)
- break;
- strbuf_grow(sb, 1);
- sb->buf[sb->len++] = ch;
- }
- if (ch == EOF && sb->len == 0)
- return EOF;
-
- sb->buf[sb->len] = '\0';
- return 0;
-}
-
-int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint)
-{
- int fd, len;
-
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -1;
- len = strbuf_read(sb, fd, hint);
- close(fd);
- if (len < 0)
- return -1;
-
- return len;
-}
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index a3d121d..436ac31 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -53,12 +53,6 @@
extern void strbuf_init(struct strbuf *buf, ssize_t hint);
extern void strbuf_release(struct strbuf *);
extern char *strbuf_detach(struct strbuf *, size_t *);
-extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
-static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
- struct strbuf tmp = *a;
- *a = *b;
- *b = tmp;
-}
/*----- strbuf size related -----*/
static inline ssize_t strbuf_avail(const struct strbuf *sb) {
@@ -74,17 +68,6 @@
sb->len = len;
sb->buf[len] = '\0';
}
-#define strbuf_reset(sb) strbuf_setlen(sb, 0)
-
-/*----- content related -----*/
-extern void strbuf_trim(struct strbuf *);
-extern void strbuf_rtrim(struct strbuf *);
-extern void strbuf_ltrim(struct strbuf *);
-extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
-extern void strbuf_tolower(struct strbuf *);
-
-extern struct strbuf **strbuf_split(const struct strbuf *, int delim);
-extern void strbuf_list_free(struct strbuf **);
/*----- add data in your buffer -----*/
static inline void strbuf_addch(struct strbuf *sb, int c) {
@@ -93,45 +76,17 @@
sb->buf[sb->len] = '\0';
}
-extern void strbuf_insert(struct strbuf *, size_t pos, const void *, size_t);
extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);
-/* splice pos..pos+len with given data */
-extern void strbuf_splice(struct strbuf *, size_t pos, size_t len,
- const void *, size_t);
-
extern void strbuf_add(struct strbuf *, const void *, size_t);
static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
strbuf_add(sb, s, strlen(s));
}
-static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) {
- strbuf_add(sb, sb2->buf, sb2->len);
-}
-extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
-
-typedef size_t (*expand_fn_t) (struct strbuf *sb, const char *placeholder, void *context);
-extern void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn, void *context);
-struct strbuf_expand_dict_entry {
- const char *placeholder;
- const char *value;
-};
-extern size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, void *context);
__attribute__((format(printf,2,3)))
extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
-extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
/* XXX: if read fails, any partial read is undone */
extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
-extern int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint);
-extern int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint);
-
-extern int strbuf_getline(struct strbuf *, FILE *, int);
-
-extern void stripspace(struct strbuf *buf, int skip_comments);
-extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);
-
-extern int strbuf_branchname(struct strbuf *sb, const char *name);
-extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);
#endif /* __PERF_STRBUF_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index ecccc8d..aaa51ba 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -11,6 +11,7 @@
#include <sys/param.h>
#include <fcntl.h>
#include <unistd.h>
+#include "build-id.h"
#include "symbol.h"
#include "strlist.h"
@@ -525,7 +526,7 @@
curr_map = map_groups__find_by_name(kmaps,
map->type, module);
if (curr_map == NULL) {
- pr_err("%s/proc/{kallsyms,modules} "
+ pr_debug("%s/proc/{kallsyms,modules} "
"inconsistency while looking "
"for \"%s\" module!\n",
machine->root_dir, module);
@@ -1131,6 +1132,10 @@
list_for_each_entry(pos, head, node) {
if (with_hits && !pos->hit)
continue;
+ if (pos->has_build_id) {
+ have_build_id = true;
+ continue;
+ }
if (filename__read_build_id(pos->long_name, pos->build_id,
sizeof(pos->build_id)) > 0) {
have_build_id = true;
@@ -1289,7 +1294,6 @@
int size = PATH_MAX;
char *name;
u8 build_id[BUILD_ID_SIZE];
- char build_id_hex[BUILD_ID_SIZE * 2 + 1];
int ret = -1;
int fd;
struct machine *machine;
@@ -1321,15 +1325,8 @@
}
self->origin = DSO__ORIG_BUILD_ID_CACHE;
-
- if (self->has_build_id) {
- build_id__sprintf(self->build_id, sizeof(self->build_id),
- build_id_hex);
- snprintf(name, size, "%s/%s/.build-id/%.2s/%s",
- getenv("HOME"), DEBUG_CACHE_DIR,
- build_id_hex, build_id_hex + 2);
+ if (dso__build_id_filename(self, name, size) != NULL)
goto open_file;
- }
more:
do {
self->origin++;
@@ -1345,6 +1342,7 @@
case DSO__ORIG_BUILDID:
if (filename__read_build_id(self->long_name, build_id,
sizeof(build_id))) {
+ char build_id_hex[BUILD_ID_SIZE * 2 + 1];
build_id__sprintf(build_id, sizeof(build_id),
build_id_hex);
snprintf(name, size,
@@ -1933,6 +1931,12 @@
return ret;
}
+size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits)
+{
+ return __dsos__fprintf_buildid(&self->kernel_dsos, fp, with_hits) +
+ __dsos__fprintf_buildid(&self->user_dsos, fp, with_hits);
+}
+
size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits)
{
struct rb_node *nd;
@@ -1940,8 +1944,7 @@
for (nd = rb_first(self); nd; nd = rb_next(nd)) {
struct machine *pos = rb_entry(nd, struct machine, rb_node);
- ret += __dsos__fprintf_buildid(&pos->kernel_dsos, fp, with_hits);
- ret += __dsos__fprintf_buildid(&pos->user_dsos, fp, with_hits);
+ ret += machine__fprintf_dsos_buildid(pos, fp, with_hits);
}
return ret;
}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6389d1a..5d25b5e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -78,7 +78,7 @@
*default_guest_kallsyms,
*default_guest_modules;
const char *guestmount;
- char *dso_list_str,
+ const char *dso_list_str,
*comm_list_str,
*sym_list_str,
*col_width_list_str;
@@ -170,6 +170,7 @@
size_t __dsos__fprintf(struct list_head *head, FILE *fp);
+size_t machine__fprintf_dsos_buildid(struct machine *self, FILE *fp, bool with_hits);
size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp);
size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits);
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 069f261..73a0222 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -1937,7 +1937,7 @@
if (!field)
return NULL;
- if (field->flags & FIELD_IS_STRING) {
+ if (field->flags & FIELD_IS_DYNAMIC) {
int offset;
offset = *(int *)(data + field->offset);
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index cb54cd0..f55cc3a 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -53,12 +53,6 @@
static ssize_t calc_data_size;
static bool repipe;
-/* If it fails, the next read will report it */
-static void skip(int size)
-{
- lseek(input_fd, size, SEEK_CUR);
-}
-
static int do_read(int fd, void *buf, int size)
{
int rsize = size;
@@ -98,6 +92,19 @@
return r;
}
+/* If it fails, the next read will report it */
+static void skip(int size)
+{
+ char buf[BUFSIZ];
+ int r;
+
+ while (size) {
+ r = size > BUFSIZ ? BUFSIZ : size;
+ read_or_die(buf, r);
+ size -= r;
+ };
+}
+
static unsigned int read4(void)
{
unsigned int data;
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 406d452..b3e86b1 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -233,7 +233,12 @@
#define data2host2(ptr) __data2host2(*(unsigned short *)ptr)
#define data2host4(ptr) __data2host4(*(unsigned int *)ptr)
-#define data2host8(ptr) __data2host8(*(unsigned long long *)ptr)
+#define data2host8(ptr) ({ \
+ unsigned long long __val; \
+ \
+ memcpy(&__val, (ptr), sizeof(unsigned long long)); \
+ __data2host8(__val); \
+})
extern int header_page_ts_offset;
extern int header_page_ts_size;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0795bf30..45b9655 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -152,7 +152,6 @@
extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
extern int prefixcmp(const char *str, const char *prefix);
-extern time_t tm_to_time_t(const struct tm *tm);
static inline const char *skip_prefix(const char *str, const char *prefix)
{
@@ -160,119 +159,6 @@
return strncmp(str, prefix, len) ? NULL : str + len;
}
-#if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
-
-#ifndef PROT_READ
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define MAP_PRIVATE 1
-#define MAP_FAILED ((void*)-1)
-#endif
-
-#define mmap git_mmap
-#define munmap git_munmap
-extern void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
-extern int git_munmap(void *start, size_t length);
-
-#else /* NO_MMAP || USE_WIN32_MMAP */
-
-#include <sys/mman.h>
-
-#endif /* NO_MMAP || USE_WIN32_MMAP */
-
-#ifdef NO_MMAP
-
-/* This value must be multiple of (pagesize * 2) */
-#define DEFAULT_PACKED_GIT_WINDOW_SIZE (1 * 1024 * 1024)
-
-#else /* NO_MMAP */
-
-/* This value must be multiple of (pagesize * 2) */
-#define DEFAULT_PACKED_GIT_WINDOW_SIZE \
- (sizeof(void*) >= 8 \
- ? 1 * 1024 * 1024 * 1024 \
- : 32 * 1024 * 1024)
-
-#endif /* NO_MMAP */
-
-#ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
-#define on_disk_bytes(st) ((st).st_size)
-#else
-#define on_disk_bytes(st) ((st).st_blocks * 512)
-#endif
-
-#define DEFAULT_PACKED_GIT_LIMIT \
- ((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256))
-
-#ifdef NO_PREAD
-#define pread git_pread
-extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
-#endif
-/*
- * Forward decl that will remind us if its twin in cache.h changes.
- * This function is used in compat/pread.c. But we can't include
- * cache.h there.
- */
-extern ssize_t read_in_full(int fd, void *buf, size_t count);
-
-#ifdef NO_SETENV
-#define setenv gitsetenv
-extern int gitsetenv(const char *, const char *, int);
-#endif
-
-#ifdef NO_MKDTEMP
-#define mkdtemp gitmkdtemp
-extern char *gitmkdtemp(char *);
-#endif
-
-#ifdef NO_UNSETENV
-#define unsetenv gitunsetenv
-extern void gitunsetenv(const char *);
-#endif
-
-#ifdef NO_STRCASESTR
-#define strcasestr gitstrcasestr
-extern char *gitstrcasestr(const char *haystack, const char *needle);
-#endif
-
-#ifdef NO_STRLCPY
-#define strlcpy gitstrlcpy
-extern size_t gitstrlcpy(char *, const char *, size_t);
-#endif
-
-#ifdef NO_STRTOUMAX
-#define strtoumax gitstrtoumax
-extern uintmax_t gitstrtoumax(const char *, char **, int);
-#endif
-
-#ifdef NO_HSTRERROR
-#define hstrerror githstrerror
-extern const char *githstrerror(int herror);
-#endif
-
-#ifdef NO_MEMMEM
-#define memmem gitmemmem
-void *gitmemmem(const void *haystack, size_t haystacklen,
- const void *needle, size_t needlelen);
-#endif
-
-#ifdef FREAD_READS_DIRECTORIES
-#ifdef fopen
-#undef fopen
-#endif
-#define fopen(a,b) git_fopen(a,b)
-extern FILE *git_fopen(const char*, const char*);
-#endif
-
-#ifdef SNPRINTF_RETURNS_BOGUS
-#define snprintf git_snprintf
-extern int git_snprintf(char *str, size_t maxsize,
- const char *format, ...);
-#define vsnprintf git_vsnprintf
-extern int git_vsnprintf(char *str, size_t maxsize,
- const char *format, va_list ap);
-#endif
-
#ifdef __GLIBC_PREREQ
#if __GLIBC_PREREQ(2, 1)
#define HAVE_STRCHRNUL
@@ -293,28 +179,14 @@
* Wrappers:
*/
extern char *xstrdup(const char *str);
-extern void *xmalloc(size_t size) __attribute__((weak));
-extern void *xmemdupz(const void *data, size_t len);
-extern char *xstrndup(const char *str, size_t len);
extern void *xrealloc(void *ptr, size_t size) __attribute__((weak));
-static inline void *xzalloc(size_t size)
-{
- void *buf = xmalloc(size);
-
- return memset(buf, 0, size);
-}
static inline void *zalloc(size_t size)
{
return calloc(1, size);
}
-static inline size_t xsize_t(off_t len)
-{
- return (size_t)len;
-}
-
static inline int has_extension(const char *filename, const char *ext)
{
size_t len = strlen(filename);
@@ -351,8 +223,6 @@
#define isalpha(x) sane_istest(x,GIT_ALPHA)
#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
#define isprint(x) sane_istest(x,GIT_PRINT)
-#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
-#define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL)
#define tolower(x) sane_case((unsigned char)(x), 0x20)
#define toupper(x) sane_case((unsigned char)(x), 0)
@@ -363,38 +233,6 @@
return x;
}
-static inline int strtoul_ui(char const *s, int base, unsigned int *result)
-{
- unsigned long ul;
- char *p;
-
- errno = 0;
- ul = strtoul(s, &p, base);
- if (errno || *p || p == s || (unsigned int) ul != ul)
- return -1;
- *result = ul;
- return 0;
-}
-
-static inline int strtol_i(char const *s, int base, int *result)
-{
- long ul;
- char *p;
-
- errno = 0;
- ul = strtol(s, &p, base);
- if (errno || *p || p == s || (int) ul != ul)
- return -1;
- *result = ul;
- return 0;
-}
-
-#ifdef INTERNAL_QSORT
-void git_qsort(void *base, size_t nmemb, size_t size,
- int(*compar)(const void *, const void *));
-#define qsort git_qsort
-#endif
-
#ifndef DIR_HAS_BSD_GROUP_SEMANTICS
# define FORCE_DIR_SET_GID S_ISGID
#else
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
index bf44ca8..73e900e 100644
--- a/tools/perf/util/wrapper.c
+++ b/tools/perf/util/wrapper.c
@@ -23,46 +23,6 @@
return ret;
}
-void *xmalloc(size_t size)
-{
- void *ret = malloc(size);
- if (!ret && !size)
- ret = malloc(1);
- if (!ret) {
- release_pack_memory(size, -1);
- ret = malloc(size);
- if (!ret && !size)
- ret = malloc(1);
- if (!ret)
- die("Out of memory, malloc failed");
- }
-#ifdef XMALLOC_POISON
- memset(ret, 0xA5, size);
-#endif
- return ret;
-}
-
-/*
- * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
- * "data" to the allocated memory, zero terminates the allocated memory,
- * and returns a pointer to the allocated memory. If the allocation fails,
- * the program dies.
- */
-void *xmemdupz(const void *data, size_t len)
-{
- char *p = xmalloc(len + 1);
- memcpy(p, data, len);
- p[len] = '\0';
- return p;
-}
-
-char *xstrndup(const char *str, size_t len)
-{
- char *p = memchr(str, '\0', len);
-
- return xmemdupz(str, p ? (size_t)(p - str) : len);
-}
-
void *xrealloc(void *ptr, size_t size)
{
void *ret = realloc(ptr, size);
@@ -78,73 +38,3 @@
}
return ret;
}
-
-/*
- * xread() is the same a read(), but it automatically restarts read()
- * operations with a recoverable error (EAGAIN and EINTR). xread()
- * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
- */
-static ssize_t xread(int fd, void *buf, size_t len)
-{
- ssize_t nr;
- while (1) {
- nr = read(fd, buf, len);
- if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
- continue;
- return nr;
- }
-}
-
-/*
- * xwrite() is the same a write(), but it automatically restarts write()
- * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
- * GUARANTEE that "len" bytes is written even if the operation is successful.
- */
-static ssize_t xwrite(int fd, const void *buf, size_t len)
-{
- ssize_t nr;
- while (1) {
- nr = write(fd, buf, len);
- if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
- continue;
- return nr;
- }
-}
-
-ssize_t read_in_full(int fd, void *buf, size_t count)
-{
- char *p = buf;
- ssize_t total = 0;
-
- while (count > 0) {
- ssize_t loaded = xread(fd, p, count);
- if (loaded <= 0)
- return total ? total : loaded;
- count -= loaded;
- p += loaded;
- total += loaded;
- }
-
- return total;
-}
-
-ssize_t write_in_full(int fd, const void *buf, size_t count)
-{
- const char *p = buf;
- ssize_t total = 0;
-
- while (count > 0) {
- ssize_t written = xwrite(fd, p, count);
- if (written < 0)
- return -1;
- if (!written) {
- errno = ENOSPC;
- return -1;
- }
- count -= written;
- p += written;
- total += written;
- }
-
- return total;
-}
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 03a5eb2..7c79c1d 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -197,7 +197,7 @@
union kvm_ioapic_redirect_entry entry;
int ret = 1;
- mutex_lock(&ioapic->lock);
+ spin_lock(&ioapic->lock);
if (irq >= 0 && irq < IOAPIC_NUM_PINS) {
entry = ioapic->redirtbl[irq];
level ^= entry.fields.polarity;
@@ -214,7 +214,7 @@
}
trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0);
}
- mutex_unlock(&ioapic->lock);
+ spin_unlock(&ioapic->lock);
return ret;
}
@@ -238,9 +238,9 @@
* is dropped it will be put into irr and will be delivered
* after ack notifier returns.
*/
- mutex_unlock(&ioapic->lock);
+ spin_unlock(&ioapic->lock);
kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i);
- mutex_lock(&ioapic->lock);
+ spin_lock(&ioapic->lock);
if (trigger_mode != IOAPIC_LEVEL_TRIG)
continue;
@@ -259,9 +259,9 @@
smp_rmb();
if (!test_bit(vector, ioapic->handled_vectors))
return;
- mutex_lock(&ioapic->lock);
+ spin_lock(&ioapic->lock);
__kvm_ioapic_update_eoi(ioapic, vector, trigger_mode);
- mutex_unlock(&ioapic->lock);
+ spin_unlock(&ioapic->lock);
}
static inline struct kvm_ioapic *to_ioapic(struct kvm_io_device *dev)
@@ -287,7 +287,7 @@
ASSERT(!(addr & 0xf)); /* check alignment */
addr &= 0xff;
- mutex_lock(&ioapic->lock);
+ spin_lock(&ioapic->lock);
switch (addr) {
case IOAPIC_REG_SELECT:
result = ioapic->ioregsel;
@@ -301,7 +301,7 @@
result = 0;
break;
}
- mutex_unlock(&ioapic->lock);
+ spin_unlock(&ioapic->lock);
switch (len) {
case 8:
@@ -338,7 +338,7 @@
}
addr &= 0xff;
- mutex_lock(&ioapic->lock);
+ spin_lock(&ioapic->lock);
switch (addr) {
case IOAPIC_REG_SELECT:
ioapic->ioregsel = data;
@@ -356,7 +356,7 @@
default:
break;
}
- mutex_unlock(&ioapic->lock);
+ spin_unlock(&ioapic->lock);
return 0;
}
@@ -386,7 +386,7 @@
ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL);
if (!ioapic)
return -ENOMEM;
- mutex_init(&ioapic->lock);
+ spin_lock_init(&ioapic->lock);
kvm->arch.vioapic = ioapic;
kvm_ioapic_reset(ioapic);
kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops);
@@ -419,9 +419,9 @@
if (!ioapic)
return -EINVAL;
- mutex_lock(&ioapic->lock);
+ spin_lock(&ioapic->lock);
memcpy(state, ioapic, sizeof(struct kvm_ioapic_state));
- mutex_unlock(&ioapic->lock);
+ spin_unlock(&ioapic->lock);
return 0;
}
@@ -431,9 +431,9 @@
if (!ioapic)
return -EINVAL;
- mutex_lock(&ioapic->lock);
+ spin_lock(&ioapic->lock);
memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
update_handled_vectors(ioapic);
- mutex_unlock(&ioapic->lock);
+ spin_unlock(&ioapic->lock);
return 0;
}
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index 8a751b7..0b190c3 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -45,7 +45,7 @@
struct kvm_io_device dev;
struct kvm *kvm;
void (*ack_notifier)(void *opaque, int irq);
- struct mutex lock;
+ spinlock_t lock;
DECLARE_BITMAP(handled_vectors, 256);
};
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index 80fd3ad..11692b9 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -32,12 +32,30 @@
static void kvm_iommu_put_pages(struct kvm *kvm,
gfn_t base_gfn, unsigned long npages);
+static pfn_t kvm_pin_pages(struct kvm *kvm, struct kvm_memory_slot *slot,
+ gfn_t gfn, unsigned long size)
+{
+ gfn_t end_gfn;
+ pfn_t pfn;
+
+ pfn = gfn_to_pfn_memslot(kvm, slot, gfn);
+ end_gfn = gfn + (size >> PAGE_SHIFT);
+ gfn += 1;
+
+ if (is_error_pfn(pfn))
+ return pfn;
+
+ while (gfn < end_gfn)
+ gfn_to_pfn_memslot(kvm, slot, gfn++);
+
+ return pfn;
+}
+
int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
{
- gfn_t gfn = slot->base_gfn;
- unsigned long npages = slot->npages;
+ gfn_t gfn, end_gfn;
pfn_t pfn;
- int i, r = 0;
+ int r = 0;
struct iommu_domain *domain = kvm->arch.iommu_domain;
int flags;
@@ -45,31 +63,62 @@
if (!domain)
return 0;
+ gfn = slot->base_gfn;
+ end_gfn = gfn + slot->npages;
+
flags = IOMMU_READ | IOMMU_WRITE;
if (kvm->arch.iommu_flags & KVM_IOMMU_CACHE_COHERENCY)
flags |= IOMMU_CACHE;
- for (i = 0; i < npages; i++) {
- /* check if already mapped */
- if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn)))
- continue;
- pfn = gfn_to_pfn_memslot(kvm, slot, gfn);
- r = iommu_map_range(domain,
- gfn_to_gpa(gfn),
- pfn_to_hpa(pfn),
- PAGE_SIZE, flags);
+ while (gfn < end_gfn) {
+ unsigned long page_size;
+
+ /* Check if already mapped */
+ if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn))) {
+ gfn += 1;
+ continue;
+ }
+
+ /* Get the page size we could use to map */
+ page_size = kvm_host_page_size(kvm, gfn);
+
+ /* Make sure the page_size does not exceed the memslot */
+ while ((gfn + (page_size >> PAGE_SHIFT)) > end_gfn)
+ page_size >>= 1;
+
+ /* Make sure gfn is aligned to the page size we want to map */
+ while ((gfn << PAGE_SHIFT) & (page_size - 1))
+ page_size >>= 1;
+
+ /*
+ * Pin all pages we are about to map in memory. This is
+ * important because we unmap and unpin in 4kb steps later.
+ */
+ pfn = kvm_pin_pages(kvm, slot, gfn, page_size);
+ if (is_error_pfn(pfn)) {
+ gfn += 1;
+ continue;
+ }
+
+ /* Map into IO address space */
+ r = iommu_map(domain, gfn_to_gpa(gfn), pfn_to_hpa(pfn),
+ get_order(page_size), flags);
if (r) {
printk(KERN_ERR "kvm_iommu_map_address:"
"iommu failed to map pfn=%lx\n", pfn);
goto unmap_pages;
}
- gfn++;
+
+ gfn += page_size >> PAGE_SHIFT;
+
+
}
+
return 0;
unmap_pages:
- kvm_iommu_put_pages(kvm, slot->base_gfn, i);
+ kvm_iommu_put_pages(kvm, slot->base_gfn, gfn);
return r;
}
@@ -189,27 +238,47 @@
return r;
}
+static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages)
+{
+ unsigned long i;
+
+ for (i = 0; i < npages; ++i)
+ kvm_release_pfn_clean(pfn + i);
+}
+
static void kvm_iommu_put_pages(struct kvm *kvm,
gfn_t base_gfn, unsigned long npages)
{
- gfn_t gfn = base_gfn;
+ struct iommu_domain *domain;
+ gfn_t end_gfn, gfn;
pfn_t pfn;
- struct iommu_domain *domain = kvm->arch.iommu_domain;
- unsigned long i;
u64 phys;
+ domain = kvm->arch.iommu_domain;
+ end_gfn = base_gfn + npages;
+ gfn = base_gfn;
+
/* check if iommu exists and in use */
if (!domain)
return;
- for (i = 0; i < npages; i++) {
- phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn));
- pfn = phys >> PAGE_SHIFT;
- kvm_release_pfn_clean(pfn);
- gfn++;
- }
+ while (gfn < end_gfn) {
+ unsigned long unmap_pages;
+ int order;
- iommu_unmap_range(domain, gfn_to_gpa(base_gfn), PAGE_SIZE * npages);
+ /* Get physical address */
+ phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn));
+ pfn = phys >> PAGE_SHIFT;
+
+ /* Unmap address from IO address space */
+ order = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE);
+ unmap_pages = 1ULL << order;
+
+ /* Unpin all pages we just unmapped to not leak any memory */
+ kvm_unpin_pages(kvm, pfn, unmap_pages);
+
+ gfn += unmap_pages;
+ }
}
static int kvm_iommu_unmap_memslots(struct kvm *kvm)