The real-time-latency response requirements are such that the
traditional approach of disabling preemption across RCU
read-side critical sections is inappropriate.
-Kernels built with CONFIG_PREEMPT=y therefore
+Kernels built with CONFIG_PREEMPTION=y therefore
use an RCU implementation that allows RCU read-side critical
sections to be preempted.
This requirement made its presence known after users made it
@@ -3064,7 +3064,7 @@
rcu_barrier_bh() , and
rcu_read_lock_bh_held() .
However, the update-side APIs are now simple wrappers for other RCU
-flavors, namely RCU-sched in CONFIG_PREEMPT=n kernels and RCU-preempt
+flavors, namely RCU-sched in CONFIG_PREEMPTION=n kernels and RCU-preempt
otherwise.
@@ -3088,12 +3088,12 @@
Therefore, RCU-sched was created, which follows “classic”
RCU in that an RCU-sched grace period waits for for pre-existing
interrupt and NMI handlers.
-In kernels built with CONFIG_PREEMPT=n , the RCU and RCU-sched
+In kernels built with CONFIG_PREEMPTION=n , the RCU and RCU-sched
APIs have identical implementations, while kernels built with
-CONFIG_PREEMPT=y provide a separate implementation for each.
+CONFIG_PREEMPTION=y provide a separate implementation for each.
-Note well that in CONFIG_PREEMPT=y kernels,
+Note well that in CONFIG_PREEMPTION=y kernels,
rcu_read_lock_sched() and rcu_read_unlock_sched()
disable and re-enable preemption, respectively.
This means that if there was a preemption attempt during the
@@ -3302,12 +3302,12 @@
call_rcu_tasks() ,
synchronize_rcu_tasks() , and
rcu_barrier_tasks() .
-In CONFIG_PREEMPT=n kernels, trampolines cannot be preempted,
+In CONFIG_PREEMPTION=n kernels, trampolines cannot be preempted,
so these APIs map to
call_rcu() ,
synchronize_rcu() , and
rcu_barrier() , respectively.
-In CONFIG_PREEMPT=y kernels, trampolines can be preempted,
+In CONFIG_PREEMPTION=y kernels, trampolines can be preempted,
and these three APIs are therefore implemented by separate functions
that check for voluntary context switches.
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index e98ff261a438b..087dc6c22c37c 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -210,8 +210,8 @@ over a rather long period of time, but improvements are always welcome!
the rest of the system.
7. As of v4.20, a given kernel implements only one RCU flavor,
- which is RCU-sched for PREEMPT=n and RCU-preempt for PREEMPT=y.
- If the updater uses call_rcu() or synchronize_rcu(),
+ which is RCU-sched for PREEMPTION=n and RCU-preempt for
+ PREEMPTION=y. If the updater uses call_rcu() or synchronize_rcu(),
then the corresponding readers my use rcu_read_lock() and
rcu_read_unlock(), rcu_read_lock_bh() and rcu_read_unlock_bh(),
or any pair of primitives that disables and re-enables preemption,
diff --git a/Documentation/RCU/rcubarrier.txt b/Documentation/RCU/rcubarrier.txt
index a2782df697328..5aa93c215af46 100644
--- a/Documentation/RCU/rcubarrier.txt
+++ b/Documentation/RCU/rcubarrier.txt
@@ -6,8 +6,8 @@ RCU (read-copy update) is a synchronization mechanism that can be thought
of as a replacement for read-writer locking (among other things), but with
very low-overhead readers that are immune to deadlock, priority inversion,
and unbounded latency. RCU read-side critical sections are delimited
-by rcu_read_lock() and rcu_read_unlock(), which, in non-CONFIG_PREEMPT
-kernels, generate no code whatsoever.
+by rcu_read_lock() and rcu_read_unlock(), which, in
+non-CONFIG_PREEMPTION kernels, generate no code whatsoever.
This means that RCU writers are unaware of the presence of concurrent
readers, so that RCU updates to shared data must be undertaken quite
@@ -303,10 +303,10 @@ Answer: This cannot happen. The reason is that on_each_cpu() has its last
to smp_call_function() and further to smp_call_function_on_cpu(),
causing this latter to spin until the cross-CPU invocation of
rcu_barrier_func() has completed. This by itself would prevent
- a grace period from completing on non-CONFIG_PREEMPT kernels,
+ a grace period from completing on non-CONFIG_PREEMPTION kernels,
since each CPU must undergo a context switch (or other quiescent
state) before the grace period can complete. However, this is
- of no use in CONFIG_PREEMPT kernels.
+ of no use in CONFIG_PREEMPTION kernels.
Therefore, on_each_cpu() disables preemption across its call
to smp_call_function() and also across the local call to
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index f48f4621ccbc2..bd510771b75ec 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -20,7 +20,7 @@ o A CPU looping with preemption disabled.
o A CPU looping with bottom halves disabled.
-o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel
+o For !CONFIG_PREEMPTION kernels, a CPU looping anywhere in the kernel
without invoking schedule(). If the looping in the kernel is
really expected and desirable behavior, you might need to add
some calls to cond_resched().
@@ -39,7 +39,7 @@ o Anything that prevents RCU's grace-period kthreads from running.
result in the "rcu_.*kthread starved for" console-log message,
which will include additional debugging information.
-o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might
+o A CPU-bound real-time task in a CONFIG_PREEMPTION kernel, which might
happen to preempt a low-priority task in the middle of an RCU
read-side critical section. This is especially damaging if
that low-priority task is not permitted to run on any other CPU,
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 7e1a8721637ab..7e03e8f80b293 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -648,9 +648,10 @@ Quick Quiz #1: Why is this argument naive? How could a deadlock
This section presents a "toy" RCU implementation that is based on
"classic RCU". It is also short on performance (but only for updates) and
-on features such as hotplug CPU and the ability to run in CONFIG_PREEMPT
-kernels. The definitions of rcu_dereference() and rcu_assign_pointer()
-are the same as those shown in the preceding section, so they are omitted.
+on features such as hotplug CPU and the ability to run in
+CONFIG_PREEMPTION kernels. The definitions of rcu_dereference() and
+rcu_assign_pointer() are the same as those shown in the preceding
+section, so they are omitted.
void rcu_read_lock(void) { }
diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
index b9b50553bfc56..b89c88168d6a3 100644
--- a/Documentation/kbuild/makefiles.rst
+++ b/Documentation/kbuild/makefiles.rst
@@ -1115,6 +1115,23 @@ When kbuild executes, the following steps are followed (roughly):
In this example, extra-y is used to list object files that
shall be built, but shall not be linked as part of built-in.a.
+ header-test-y
+
+ header-test-y specifies headers (`*.h`) in the current directory that
+ should be compile tested to ensure they are self-contained,
+ i.e. compilable as standalone units. If CONFIG_HEADER_TEST is enabled,
+ this builds them as part of extra-y.
+
+ header-test-pattern-y
+
+ This works as a weaker version of header-test-y, and accepts wildcard
+ patterns. The typical usage is::
+
+ header-test-pattern-y += *.h
+
+ This specifies all the files that matches to `*.h` in the current
+ directory, but the files in 'header-test-' are excluded.
+
6.7 Commands useful for building a boot image
---------------------------------------------
diff --git a/Documentation/printk-ringbuffer.txt b/Documentation/printk-ringbuffer.txt
new file mode 100644
index 0000000000000..6bde5dbd8545b
--- /dev/null
+++ b/Documentation/printk-ringbuffer.txt
@@ -0,0 +1,377 @@
+struct printk_ringbuffer
+------------------------
+John Ogness
+
+Overview
+~~~~~~~~
+As the name suggests, this ring buffer was implemented specifically to serve
+the needs of the printk() infrastructure. The ring buffer itself is not
+specific to printk and could be used for other purposes. _However_, the
+requirements and semantics of printk are rather unique. If you intend to use
+this ring buffer for anything other than printk, you need to be very clear on
+its features, behavior, and pitfalls.
+
+Features
+^^^^^^^^
+The printk ring buffer has the following features:
+
+- single global buffer
+- resides in initialized data section (available at early boot)
+- lockless readers
+- supports multiple writers
+- supports multiple non-consuming readers
+- safe from any context (including NMI)
+- groups bytes into variable length blocks (referenced by entries)
+- entries tagged with sequence numbers
+
+Behavior
+^^^^^^^^
+Since the printk ring buffer readers are lockless, there exists no
+synchronization between readers and writers. Basically writers are the tasks
+in control and may overwrite any and all committed data at any time and from
+any context. For this reason readers can miss entries if they are overwritten
+before the reader was able to access the data. The reader API implementation
+is such that reader access to entries is atomic, so there is no risk of
+readers having to deal with partial or corrupt data. Also, entries are
+tagged with sequence numbers so readers can recognize if entries were missed.
+
+Writing to the ring buffer consists of 2 steps. First a writer must reserve
+an entry of desired size. After this step the writer has exclusive access
+to the memory region. Once the data has been written to memory, it needs to
+be committed to the ring buffer. After this step the entry has been inserted
+into the ring buffer and assigned an appropriate sequence number.
+
+Once committed, a writer must no longer access the data directly. This is
+because the data may have been overwritten and no longer exists. If a
+writer must access the data, it should either keep a private copy before
+committing the entry or use the reader API to gain access to the data.
+
+Because of how the data backend is implemented, entries that have been
+reserved but not yet committed act as barriers, preventing future writers
+from filling the ring buffer beyond the location of the reserved but not
+yet committed entry region. For this reason it is *important* that writers
+perform both reserve and commit as quickly as possible. Also, be aware that
+preemption and local interrupts are disabled and writing to the ring buffer
+is processor-reentrant locked during the reserve/commit window. Writers in
+NMI contexts can still preempt any other writers, but as long as these
+writers do not write a large amount of data with respect to the ring buffer
+size, this should not become an issue.
+
+API
+~~~
+
+Declaration
+^^^^^^^^^^^
+The printk ring buffer can be instantiated as a static structure:
+
+ /* declare a static struct printk_ringbuffer */
+ #define DECLARE_STATIC_PRINTKRB(name, szbits, cpulockptr)
+
+The value of szbits specifies the size of the ring buffer in bits. The
+cpulockptr field is a pointer to a prb_cpulock struct that is used to
+perform processor-reentrant spin locking for the writers. It is specified
+externally because it may be used for multiple ring buffers (or other
+code) to synchronize writers without risk of deadlock.
+
+Here is an example of a declaration of a printk ring buffer specifying a
+32KB (2^15) ring buffer:
+
+....
+DECLARE_STATIC_PRINTKRB_CPULOCK(rb_cpulock);
+DECLARE_STATIC_PRINTKRB(rb, 15, &rb_cpulock);
+....
+
+If writers will be using multiple ring buffers and the ordering of that usage
+is not clear, the same prb_cpulock should be used for both ring buffers.
+
+Writer API
+^^^^^^^^^^
+The writer API consists of 2 functions. The first is to reserve an entry in
+the ring buffer, the second is to commit that data to the ring buffer. The
+reserved entry information is stored within a provided `struct prb_handle`.
+
+ /* reserve an entry */
+ char *prb_reserve(struct prb_handle *h, struct printk_ringbuffer *rb,
+ unsigned int size);
+
+ /* commit a reserved entry to the ring buffer */
+ void prb_commit(struct prb_handle *h);
+
+Here is an example of a function to write data to a ring buffer:
+
+....
+int write_data(struct printk_ringbuffer *rb, char *data, int size)
+{
+ struct prb_handle h;
+ char *buf;
+
+ buf = prb_reserve(&h, rb, size);
+ if (!buf)
+ return -1;
+ memcpy(buf, data, size);
+ prb_commit(&h);
+
+ return 0;
+}
+....
+
+Pitfalls
+++++++++
+Be aware that prb_reserve() can fail. A retry might be successful, but it
+depends entirely on whether or not the next part of the ring buffer to
+overwrite belongs to reserved but not yet committed entries of other writers.
+Writers can use the prb_inc_lost() function to allow readers to notice that a
+message was lost.
+
+Reader API
+^^^^^^^^^^
+The reader API utilizes a `struct prb_iterator` to track the reader's
+position in the ring buffer.
+
+ /* declare a pre-initialized static iterator for a ring buffer */
+ #define DECLARE_STATIC_PRINTKRB_ITER(name, rbaddr)
+
+ /* initialize iterator for a ring buffer (if static macro NOT used) */
+ void prb_iter_init(struct prb_iterator *iter,
+ struct printk_ringbuffer *rb, u64 *seq);
+
+ /* make a deep copy of an iterator */
+ void prb_iter_copy(struct prb_iterator *dest,
+ struct prb_iterator *src);
+
+ /* non-blocking, advance to next entry (and read the data) */
+ int prb_iter_next(struct prb_iterator *iter, char *buf,
+ int size, u64 *seq);
+
+ /* blocking, advance to next entry (and read the data) */
+ int prb_iter_wait_next(struct prb_iterator *iter, char *buf,
+ int size, u64 *seq);
+
+ /* position iterator at the entry seq */
+ int prb_iter_seek(struct prb_iterator *iter, u64 seq);
+
+ /* read data at current position */
+ int prb_iter_data(struct prb_iterator *iter, char *buf,
+ int size, u64 *seq);
+
+Typically prb_iter_data() is not needed because the data can be retrieved
+directly with prb_iter_next().
+
+Here is an example of a non-blocking function that will read all the data in
+a ring buffer:
+
+....
+void read_all_data(struct printk_ringbuffer *rb, char *buf, int size)
+{
+ struct prb_iterator iter;
+ u64 prev_seq = 0;
+ u64 seq;
+ int ret;
+
+ prb_iter_init(&iter, rb, NULL);
+
+ for (;;) {
+ ret = prb_iter_next(&iter, buf, size, &seq);
+ if (ret > 0) {
+ if (seq != ++prev_seq) {
+ /* "seq - prev_seq" entries missed */
+ prev_seq = seq;
+ }
+ /* process buf here */
+ } else if (ret == 0) {
+ /* hit the end, done */
+ break;
+ } else if (ret < 0) {
+ /*
+ * iterator is invalid, a writer overtook us, reset the
+ * iterator and keep going, entries were missed
+ */
+ prb_iter_init(&iter, rb, NULL);
+ }
+ }
+}
+....
+
+Pitfalls
+++++++++
+The reader's iterator can become invalid at any time because the reader was
+overtaken by a writer. Typically the reader should reset the iterator back
+to the current oldest entry (which will be newer than the entry the reader
+was at) and continue, noting the number of entries that were missed.
+
+Utility API
+^^^^^^^^^^^
+Several functions are available as convenience for external code.
+
+ /* query the size of the data buffer */
+ int prb_buffer_size(struct printk_ringbuffer *rb);
+
+ /* skip a seq number to signify a lost record */
+ void prb_inc_lost(struct printk_ringbuffer *rb);
+
+ /* processor-reentrant spin lock */
+ void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store);
+
+ /* processor-reentrant spin unlock */
+ void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store);
+
+Pitfalls
+++++++++
+Although the value returned by prb_buffer_size() does represent an absolute
+upper bound, the amount of data that can be stored within the ring buffer
+is actually less because of the additional storage space of a header for each
+entry.
+
+The prb_lock() and prb_unlock() functions can be used to synchronize between
+ring buffer writers and other external activities. The function of a
+processor-reentrant spin lock is to disable preemption and local interrupts
+and synchronize against other processors. It does *not* protect against
+multiple contexts of a single processor, i.e NMI.
+
+Implementation
+~~~~~~~~~~~~~~
+This section describes several of the implementation concepts and details to
+help developers better understand the code.
+
+Entries
+^^^^^^^
+All ring buffer data is stored within a single static byte array. The reason
+for this is to ensure that any pointers to the data (past and present) will
+always point to valid memory. This is important because the lockless readers
+may be preempted for long periods of time and when they resume may be working
+with expired pointers.
+
+Entries are identified by start index and size. (The start index plus size
+is the start index of the next entry.) The start index is not simply an
+offset into the byte array, but rather a logical position (lpos) that maps
+directly to byte array offsets.
+
+For example, for a byte array of 1000, an entry may have have a start index
+of 100. Another entry may have a start index of 1100. And yet another 2100.
+All of these entry are pointing to the same memory region, but only the most
+recent entry is valid. The other entries are pointing to valid memory, but
+represent entries that have been overwritten.
+
+Note that due to overflowing, the most recent entry is not necessarily the one
+with the highest lpos value. Indeed, the printk ring buffer initializes its
+data such that an overflow happens relatively quickly in order to validate the
+handling of this situation. The implementation assumes that an lpos (unsigned
+long) will never completely wrap while a reader is preempted. If this were to
+become an issue, the seq number (which never wraps) could be used to increase
+the robustness of handling this situation.
+
+Buffer Wrapping
+^^^^^^^^^^^^^^^
+If an entry starts near the end of the byte array but would extend beyond it,
+a special terminating entry (size = -1) is inserted into the byte array and
+the real entry is placed at the beginning of the byte array. This can waste
+space at the end of the byte array, but simplifies the implementation by
+allowing writers to always work with contiguous buffers.
+
+Note that the size field is the first 4 bytes of the entry header. Also note
+that calc_next() always ensures that there are at least 4 bytes left at the
+end of the byte array to allow room for a terminating entry.
+
+Ring Buffer Pointers
+^^^^^^^^^^^^^^^^^^^^
+Three pointers (lpos values) are used to manage the ring buffer:
+
+ - _tail_: points to the oldest entry
+ - _head_: points to where the next new committed entry will be
+ - _reserve_: points to where the next new reserved entry will be
+
+These pointers always maintain a logical ordering:
+
+ tail <= head <= reserve
+
+The reserve pointer moves forward when a writer reserves a new entry. The
+head pointer moves forward when a writer commits a new entry.
+
+The reserve pointer cannot overwrite the tail pointer in a wrap situation. In
+such a situation, the tail pointer must be "pushed forward", thus
+invalidating that oldest entry. Readers identify if they are accessing a
+valid entry by ensuring their entry pointer is `>= tail && < head`.
+
+If the tail pointer is equal to the head pointer, it cannot be pushed and any
+reserve operation will fail. The only resolution is for writers to commit
+their reserved entries.
+
+Processor-Reentrant Locking
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The purpose of the processor-reentrant locking is to limit the interruption
+scenarios of writers to 2 contexts. This allows for a simplified
+implementation where:
+
+- The reserve/commit window only exists on 1 processor at a time. A reserve
+ can never fail due to uncommitted entries of other processors.
+
+- When committing entries, it is trivial to handle the situation when
+ subsequent entries have already been committed, i.e. managing the head
+ pointer.
+
+Performance
+~~~~~~~~~~~
+Some basic tests were performed on a quad Intel(R) Xeon(R) CPU E5-2697 v4 at
+2.30GHz (36 cores / 72 threads). All tests involved writing a total of
+32,000,000 records at an average of 33 bytes each. Each writer was pinned to
+its own CPU and would write as fast as it could until a total of 32,000,000
+records were written. All tests involved 2 readers that were both pinned
+together to another CPU. Each reader would read as fast as it could and track
+how many of the 32,000,000 records it could read. All tests used a ring buffer
+of 16KB in size, which holds around 350 records (header + data for each
+entry).
+
+The only difference between the tests is the number of writers (and thus also
+the number of records per writer). As more writers are added, the time to
+write a record increases. This is because data pointers, modified via cmpxchg,
+and global data access in general become more contended.
+
+1 writer
+^^^^^^^^
+ runtime: 0m 18s
+ reader1: 16219900/32000000 (50%) records
+ reader2: 16141582/32000000 (50%) records
+
+2 writers
+^^^^^^^^^
+ runtime: 0m 32s
+ reader1: 16327957/32000000 (51%) records
+ reader2: 16313988/32000000 (50%) records
+
+4 writers
+^^^^^^^^^
+ runtime: 0m 42s
+ reader1: 16421642/32000000 (51%) records
+ reader2: 16417224/32000000 (51%) records
+
+8 writers
+^^^^^^^^^
+ runtime: 0m 43s
+ reader1: 16418300/32000000 (51%) records
+ reader2: 16432222/32000000 (51%) records
+
+16 writers
+^^^^^^^^^^
+ runtime: 0m 54s
+ reader1: 16539189/32000000 (51%) records
+ reader2: 16542711/32000000 (51%) records
+
+32 writers
+^^^^^^^^^^
+ runtime: 1m 13s
+ reader1: 16731808/32000000 (52%) records
+ reader2: 16735119/32000000 (52%) records
+
+Comments
+^^^^^^^^
+It is particularly interesting to compare/contrast the 1-writer and 32-writer
+tests. Despite the writing of the 32,000,000 records taking over 4 times
+longer, the readers (which perform no cmpxchg) were still unable to keep up.
+This shows that the memory contention between the increasing number of CPUs
+also has a dramatic effect on readers.
+
+It should also be noted that in all cases each reader was able to read >=50%
+of the records. This means that a single reader would have been able to keep
+up with the writer(s) in all cases, becoming slightly easier as more writers
+are added. This was the purpose of pinning 2 readers to 1 CPU: to observe how
+maximum reader performance changes.
diff --git a/Documentation/trace/ftrace-uses.rst b/Documentation/trace/ftrace-uses.rst
index 1fbc69894eed0..1e0020b0bc745 100644
--- a/Documentation/trace/ftrace-uses.rst
+++ b/Documentation/trace/ftrace-uses.rst
@@ -146,7 +146,7 @@ FTRACE_OPS_FL_RECURSION_SAFE
itself or any nested functions that those functions call.
If this flag is set, it is possible that the callback will also
- be called with preemption enabled (when CONFIG_PREEMPT is set),
+ be called with preemption enabled (when CONFIG_PREEMPTION is set),
but this is not guaranteed.
FTRACE_OPS_FL_IPMODIFY
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000000000..1e73bc717e366
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,11 @@
+pipeline {
+ agent any
+
+ stages {
+ stage('Build') {
+ steps {
+ sh '/bin/bash ./jenkins_build.sh'
+ }
+ }
+ }
+}
diff --git a/Makefile b/Makefile
index 6d61c77c06320..d24221fbd04ee 100644
--- a/Makefile
+++ b/Makefile
@@ -618,6 +618,7 @@ ifeq ($(KBUILD_EXTMOD),)
init-y := init/
drivers-y := drivers/ sound/
drivers-$(CONFIG_SAMPLES) += samples/
+drivers-$(CONFIG_KERNEL_HEADER_TEST) += include/
net-y := net/
libs-y := lib/
core-y := usr/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000..a35e1f064aa79
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+| kernel | normal | rt |
+|:---------:|:--------:|:-------:|
+|4.4 | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/4.4/) | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/4.4-rt/) |
+|4.9 | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/4.9/) | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/4.9-rt/) |
+|4.14 | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/4.14/) | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/4.14-rt/) |
+|4.19 | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/4.19/) | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/4.19-rt/) |
+|5.4 | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/5.4/) | [](http://gfnd.rcn-ee.org:8080/job/beagleboard_kernel_builder/job/5.4-rt/) |
diff --git a/arch/Kconfig b/arch/Kconfig
index 43102756304c1..746735396a7ce 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -31,6 +31,7 @@ config OPROFILE
tristate "OProfile system profiling"
depends on PROFILING
depends on HAVE_OPROFILE
+ depends on !PREEMPT_RT
select RING_BUFFER
select RING_BUFFER_ALLOW_SWAP
help
diff --git a/arch/alpha/include/asm/spinlock_types.h b/arch/alpha/include/asm/spinlock_types.h
index 1d5716bc060be..6883bc952d224 100644
--- a/arch/alpha/include/asm/spinlock_types.h
+++ b/arch/alpha/include/asm/spinlock_types.h
@@ -2,10 +2,6 @@
#ifndef _ALPHA_SPINLOCK_TYPES_H
#define _ALPHA_SPINLOCK_TYPES_H
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
typedef struct {
volatile unsigned int lock;
} arch_spinlock_t;
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 72be01270e246..1f6bb184a44db 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -337,11 +337,11 @@ resume_user_mode_begin:
resume_kernel_mode:
; Disable Interrupts from this point on
- ; CONFIG_PREEMPT: This is a must for preempt_schedule_irq()
- ; !CONFIG_PREEMPT: To ensure restore_regs is intr safe
+ ; CONFIG_PREEMPTION: This is a must for preempt_schedule_irq()
+ ; !CONFIG_PREEMPTION: To ensure restore_regs is intr safe
IRQ_DISABLE r9
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
; Can't preempt if preemption disabled
GET_CURR_THR_INFO_FROM_SP r10
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4c47f51268c81..d862614181f39 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -31,6 +31,7 @@ config ARM
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_RT
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
@@ -63,7 +64,7 @@ config ARM
select HARDIRQS_SW_RESEND
select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
+ select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU && !PREEMPT_RT
select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU
select HAVE_ARCH_MMAP_RND_BITS if MMU
select HAVE_ARCH_SECCOMP_FILTER if AEABI && !OABI_COMPAT
@@ -102,6 +103,7 @@ config ARM
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_LAZY
select HAVE_RCU_TABLE_FREE if SMP && ARM_LPAE
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RSEQ
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 0b3cd7a33a264..87a8b8db3411b 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -29,6 +29,10 @@ export ZRELADDR INITRD_PHYS PARAMS_PHYS
targets := Image zImage xipImage bootpImage uImage
+ifeq ($(CONFIG_OF_OVERLAY),y)
+DTC_FLAGS += -@
+endif
+
ifeq ($(CONFIG_XIP_KERNEL),y)
cmd_deflate_xip_data = $(CONFIG_SHELL) -c \
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 6237122f63020..0a55eba8d78b0 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -1,4 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
+
+ifeq ($(CONFIG_OF_OVERLAY),y)
+DTC_FLAGS += -@
+endif
+
dtb-$(CONFIG_ARCH_ALPINE) += \
alpine-db.dtb
dtb-$(CONFIG_MACH_ARTPEC6) += \
@@ -740,6 +745,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \
am335x-base0033.dtb \
am335x-bone.dtb \
am335x-boneblack.dtb \
+ am335x-bonegreen-gateway.dtb \
am335x-boneblack-wireless.dtb \
am335x-boneblack-prusuart.dtb \
am335x-boneblue.dtb \
diff --git a/arch/arm/boot/dts/am335x-bonegreen-gateway.dts b/arch/arm/boot/dts/am335x-bonegreen-gateway.dts
new file mode 100644
index 0000000000000..83f48fb3c759a
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bonegreen-gateway.dts
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include "am335x-bonegreen-common.dtsi"
+#include
+
+/ {
+ model = "SeeedStudio BeagleBone Green Gateway";
+ compatible = "ti,am335x-bone-green-gateway", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+ aliases {
+ rtc0 = &extrtc;
+ rtc1 = &rtc;
+ };
+
+ chosen {
+ base_dtb = "am335x-bonegreen-gateway.dts";
+ base_dtb_timestamp = __TIMESTAMP__;
+ };
+
+ wlan_en_reg: fixedregulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "wlan-en-regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ startup-delay-us= <70000>;
+
+ /* WL_EN */
+ gpio = <&gpio3 9 0>;
+ enable-active-high;
+ };
+
+ leds {
+ led6 {
+ label = "beaglebone:green:usr4";
+ gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "netdev";
+ default-state = "off";
+ };
+ };
+};
+
+&cpu0_opp_table {
+ /*
+ * Octavo Systems:
+ * The EFUSE_SMA register is not programmed for any of the AM335x wafers
+ * we get and we are not programming them during our production test.
+ * Therefore, from a DEVICE_ID revision point of view, the silicon looks
+ * like it is Revision 2.1. However, from an EFUSE_SMA point of view for
+ * the HW OPP table, the silicon looks like it is Revision 1.0 (ie the
+ * EFUSE_SMA register reads as all zeros).
+ */
+ oppnitro-1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+&am33xx_pinmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usbhost_pins>;
+
+ bt_pins: pinmux_bt_pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_txd0.gpio0_28 - BT_EN */
+ >;
+ };
+
+ mmc3_pins: pinmux_mmc3_pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+ AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+ >;
+ };
+
+ uart2_grove_pins: pinmux_uart2_grove_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x90c, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)
+ AM33XX_IOPAD(0x910, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)
+ >;
+ };
+
+ uart3_pins: pinmux_uart3_pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gmii1_rxd3.uart3_rxd */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* gmii1_rxd2.uart3_txd */
+ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3) /* mdio_data.uart3_ctsn */
+ AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* mdio_clk.uart3_rtsn */
+ >;
+ };
+
+ wl18xx_pins: pinmux_wl18xx_pins {
+ pinctrl-single,pins = <
+ AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gmii1_txclk.gpio3_9 WL_EN */
+ AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_refclk.gpio0_29 WL_IRQ */
+ AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_rxclk.gpio3_10 LS_BUF_EN */
+ >;
+ };
+
+ usbhost_pins: pinmux_usbhost_pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gmii1_txd1.gpio0[21] */
+ >;
+ };
+};
+
+&mac {
+ status = "disabled";
+};
+
+&mmc3 {
+ dmas = <&edma_xbar 12 0 1
+ &edma_xbar 13 0 2>;
+ dma-names = "tx", "rx";
+ status = "okay";
+ vmmc-supply = <&wlan_en_reg>;
+ bus-width = <4>;
+ non-removable;
+ cap-power-off-card;
+ ti,needs-special-hs-handling;
+ keep-power-in-suspend;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc3_pins &wl18xx_pins>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wlcore: wlcore@2 {
+ compatible = "ti,wl1835";
+ reg = <2>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <29 IRQ_TYPE_EDGE_RISING>;
+ };
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_grove_pins>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pins &bt_pins>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "ti,wl1835-st";
+ enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&i2c0 {
+ extrtc: rtc@68 {
+ compatible = "dallas,ds1340";
+ reg = <0x68>;
+ };
+};
+
+// (K16) gmii1_txd1.gpio0[21]
+&gpio0 {
+ usb_reset {
+ gpio-hog;
+ gpios = <21 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "usb_reset";
+ };
+};
+
+&gpio3 {
+ ls_buf_en {
+ gpio-hog;
+ gpios = <10 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "LS_BUF_EN";
+ };
+};
+
+&usb1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hub@1 {
+ compatible = "usb424,9512";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet: ethernet@1 {
+ compatible = "usb424,ec00";
+ reg = <1>;
+ };
+ };
+};
diff --git a/arch/arm/configs/bb.org_defconfig b/arch/arm/configs/bb.org_defconfig
new file mode 100644
index 0000000000000..3a4f3ade466ad
--- /dev/null
+++ b/arch/arm/configs/bb.org_defconfig
@@ -0,0 +1,2613 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT_RT=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_PSI=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_IKHEADERS=m
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_SYSFS_SYSCALL is not set
+CONFIG_USERFAULTFD=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
+CONFIG_PROFILING=y
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_SOC_OMAP5=y
+CONFIG_SOC_AM33XX=y
+CONFIG_SOC_AM43XX=y
+CONFIG_SOC_DRA7XX=y
+CONFIG_SOC_HAS_OMAP2_SDRC=y
+CONFIG_OMAP5_ERRATA_801819=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_PL310_ERRATA_727915=y
+CONFIG_PL310_ERRATA_753970=y
+CONFIG_PL310_ERRATA_769419=y
+CONFIG_ARM_ERRATA_430973=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_ARM_ERRATA_754327=y
+CONFIG_ARM_ERRATA_764369=y
+CONFIG_ARM_ERRATA_773022=y
+CONFIG_ARM_ERRATA_814220=y
+CONFIG_SMP=y
+CONFIG_MCPM=y
+CONFIG_NR_CPUS=2
+CONFIG_ARM_PSCI=y
+CONFIG_HZ_250=y
+CONFIG_SECCOMP=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_KEXEC=y
+CONFIG_EFI=y
+# CONFIG_DMI is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=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_CPUFREQ_DT=y
+# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
+CONFIG_ARM_TI_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+CONFIG_APM_EMULATION=y
+CONFIG_ENERGY_MODEL=y
+CONFIG_EFI_VARS=m
+# CONFIG_EFI_ARMSTUB_DTB_LOADER is not set
+CONFIG_ARM_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM_NEON=m
+CONFIG_CRYPTO_SHA256_ARM=m
+CONFIG_CRYPTO_SHA512_ARM=m
+CONFIG_CRYPTO_AES_ARM=m
+CONFIG_CRYPTO_AES_ARM_BS=m
+CONFIG_CRYPTO_CHACHA20_NEON=m
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_COMPRESS=y
+CONFIG_MODULE_COMPRESS_XZ=y
+CONFIG_BLK_DEV_ZONED=y
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_BLK_WBT=y
+CONFIG_BLK_SED_OPAL=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_MQ_IOSCHED_KYBER=m
+CONFIG_IOSCHED_BFQ=m
+CONFIG_BFQ_GROUP_IOSCHED=y
+CONFIG_BINFMT_MISC=m
+CONFIG_KSM=y
+CONFIG_FRONTSWAP=y
+CONFIG_ZSWAP=y
+CONFIG_ZBUD=y
+CONFIG_Z3FOLD=m
+CONFIG_ZSMALLOC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_INTERFACE=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_WIREGUARD=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_FIB_TRIE_STATS=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_NET_IPVTI=m
+CONFIG_NET_FOU_IP_TUNNELS=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_ESP_OFFLOAD=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
+CONFIG_INET_RAW_DIAG=m
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_NV=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_TCP_CONG_DCTCP=m
+CONFIG_TCP_CONG_CDG=m
+CONFIG_TCP_CONG_BBR=m
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_ESP_OFFLOAD=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_ILA=m
+CONFIG_IPV6_VTI=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_IPV6_SEG6_LWTUNNEL=y
+CONFIG_IPV6_SEG6_HMAC=y
+CONFIG_NETLABEL=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_LOG_NETDEV=m
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NF_CT_NETLINK_TIMEOUT=m
+CONFIG_NF_CT_NETLINK_HELPER=m
+CONFIG_NETFILTER_NETLINK_GLUE_CT=y
+CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_SET=m
+CONFIG_NF_TABLES_INET=y
+CONFIG_NF_TABLES_NETDEV=y
+CONFIG_NFT_NUMGEN=m
+CONFIG_NFT_CT=m
+CONFIG_NFT_FLOW_OFFLOAD=m
+CONFIG_NFT_COUNTER=m
+CONFIG_NFT_CONNLIMIT=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_MASQ=m
+CONFIG_NFT_REDIR=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_TUNNEL=m
+CONFIG_NFT_OBJREF=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_QUOTA=m
+CONFIG_NFT_REJECT=m
+CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
+CONFIG_NFT_FIB_INET=m
+CONFIG_NFT_XFRM=m
+CONFIG_NFT_SOCKET=m
+CONFIG_NFT_OSF=m
+CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
+CONFIG_NFT_FIB_NETDEV=m
+CONFIG_NF_FLOW_TABLE_INET=m
+CONFIG_NF_FLOW_TABLE=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_AUDIT=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_CGROUP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_IPMAC=m
+CONFIG_IP_SET_HASH_MAC=m
+CONFIG_IP_SET_HASH_NETPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETNET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_FO=m
+CONFIG_IP_VS_OVF=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_MH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_PE_SIP=m
+CONFIG_NFT_DUP_IPV4=m
+CONFIG_NFT_FIB_IPV4=m
+CONFIG_NF_TABLES_ARP=y
+CONFIG_NF_FLOW_TABLE_IPV4=m
+CONFIG_NF_LOG_ARP=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_NFT_DUP_IPV6=m
+CONFIG_NFT_FIB_IPV6=m
+CONFIG_NF_FLOW_TABLE_IPV6=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_SRH=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_IP6_NF_NAT=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
+CONFIG_NFT_BRIDGE_REJECT=m
+CONFIG_NF_LOG_BRIDGE=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_TIPC=m
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+CONFIG_LLC2=m
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_PHONET=m
+CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
+CONFIG_IEEE802154=m
+CONFIG_IEEE802154_6LOWPAN=m
+CONFIG_MAC802154=m
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFB=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_CBS=m
+CONFIG_NET_SCH_ETF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_SKBPRIO=m
+CONFIG_NET_SCH_CHOKE=m
+CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=m
+CONFIG_NET_SCH_CAKE=m
+CONFIG_NET_SCH_FQ=m
+CONFIG_NET_SCH_HHF=m
+CONFIG_NET_SCH_PIE=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_CLS_CGROUP=m
+CONFIG_NET_CLS_BPF=m
+CONFIG_NET_CLS_FLOWER=m
+CONFIG_NET_CLS_MATCHALL=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_EMATCH_CANID=m
+CONFIG_NET_EMATCH_IPSET=m
+CONFIG_NET_EMATCH_IPT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_SAMPLE=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+CONFIG_NET_ACT_VLAN=m
+CONFIG_NET_ACT_BPF=m
+CONFIG_NET_ACT_CONNMARK=m
+CONFIG_NET_ACT_SKBMOD=m
+CONFIG_NET_ACT_IFE=m
+CONFIG_NET_ACT_TUNNEL_KEY=m
+CONFIG_NET_IFE_SKBMARK=m
+CONFIG_NET_IFE_SKBPRIO=m
+CONFIG_NET_IFE_SKBTCINDEX=m
+CONFIG_DCB=y
+CONFIG_BATMAN_ADV=m
+# CONFIG_BATMAN_ADV_BATMAN_V is not set
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_DEBUGFS=y
+CONFIG_OPENVSWITCH=m
+CONFIG_VSOCKETS=m
+CONFIG_VIRTIO_VSOCKETS=m
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=y
+CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
+CONFIG_NET_SWITCHDEV=y
+CONFIG_CGROUP_NET_PRIO=y
+CONFIG_BPF_JIT=y
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_DROP_MONITOR=y
+CONFIG_HAMRADIO=y
+CONFIG_AX25=m
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_YAM=m
+CONFIG_CAN=m
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_C_CAN=m
+CONFIG_CAN_C_CAN_PLATFORM=m
+CONFIG_CAN_HI311X=m
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_8DEV_USB=m
+CONFIG_CAN_EMS_USB=m
+CONFIG_CAN_ESD_USB2=m
+CONFIG_CAN_GS_USB=m
+CONFIG_CAN_KVASER_USB=m
+CONFIG_CAN_MCBA_USB=m
+CONFIG_CAN_PEAK_USB=m
+CONFIG_CAN_UCAN=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_6LOWPAN=m
+CONFIG_BT_LEDS=y
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_BT_ATH3K=m
+CONFIG_BT_WILINK=m
+CONFIG_BT_MTKUART=m
+CONFIG_AF_RXRPC_IPV6=y
+CONFIG_RXKAD=y
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_DEFAULT_PS is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_WIMAX=m
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NFC=m
+CONFIG_NFC_DIGITAL=m
+CONFIG_NFC_NCI=m
+CONFIG_NFC_NCI_SPI=m
+CONFIG_NFC_NCI_UART=m
+CONFIG_NFC_TRF7970A=m
+CONFIG_NFC_SIM=m
+CONFIG_NFC_PORT100=m
+CONFIG_NFC_PN533_USB=m
+CONFIG_NFC_PN533_I2C=m
+CONFIG_NFC_ST_NCI_I2C=m
+CONFIG_NFC_ST_NCI_SPI=m
+CONFIG_NFC_NXP_NCI=m
+CONFIG_NFC_NXP_NCI_I2C=m
+CONFIG_NFC_ST95HF=m
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_EXTRA_FIRMWARE="am335x-pm-firmware.elf am335x-bone-scale-data.bin am335x-evm-scale-data.bin am43x-evm-scale-data.bin"
+CONFIG_EXTRA_FIRMWARE_DIR="firmware"
+CONFIG_OMAP_OCP2SCP=y
+CONFIG_SIMPLE_PM_BUS=y
+CONFIG_CONNECTOR=y
+CONFIG_GNSS=m
+CONFIG_GNSS_MTK_SERIAL=m
+CONFIG_GNSS_SIRF_SERIAL=m
+CONFIG_GNSS_UBX_SERIAL=m
+CONFIG_MTD=y
+CONFIG_MTD_AR7_PARTS=m
+CONFIG_MTD_OF_PARTS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_RFD_FTL=m
+CONFIG_SSFDC=m
+CONFIG_MTD_OOPS=m
+CONFIG_MTD_SWAP=m
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PLATRAM=m
+CONFIG_MTD_DATAFLASH=m
+CONFIG_MTD_SST25L=m
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+CONFIG_MTD_ONENAND_2X_PROGRAM=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_ECC_SW_BCH=y
+CONFIG_MTD_NAND_OMAP2=m
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_LPDDR=m
+CONFIG_MTD_SPI_NOR=m
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_OF_OVERLAY=y
+CONFIG_BLK_DEV_NULL_BLK=m
+CONFIG_ZRAM=m
+CONFIG_ZRAM_WRITEBACK=y
+CONFIG_ZRAM_MEMORY_TRACKING=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_DRBD=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=m
+CONFIG_BLK_DEV_RBD=m
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_AD525X_DPOT_SPI=m
+CONFIG_ICS932S401=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_SRAM=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93XX46=m
+CONFIG_TI_ST=m
+CONFIG_RAID_ATTRS=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
+CONFIG_SCSI_UFSHCD=m
+CONFIG_LIBFC=m
+CONFIG_LIBFCOE=m
+CONFIG_SCSI_VIRTIO=m
+CONFIG_SCSI_DH=y
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_MD_CLUSTER=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_UNSTRIPED=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
+CONFIG_DM_WRITECACHE=m
+CONFIG_DM_ERA=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=m
+CONFIG_DM_VERITY=m
+CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
+CONFIG_DM_SWITCH=m
+CONFIG_DM_LOG_WRITES=m
+CONFIG_DM_INTEGRITY=m
+CONFIG_DM_ZONED=m
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
+CONFIG_TCM_USER2=m
+CONFIG_LOOPBACK_TARGET=m
+CONFIG_TCM_FC=m
+CONFIG_ISCSI_TARGET=m
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_EQUALIZER=m
+CONFIG_IFB=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_IPVLAN=m
+CONFIG_IPVTAP=m
+CONFIG_VXLAN=m
+CONFIG_GENEVE=m
+CONFIG_GTP=m
+CONFIG_MACSEC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=m
+CONFIG_NLMON=m
+CONFIG_NET_VRF=m
+CONFIG_ATM_DUMMY=m
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+CONFIG_ENC28J60=y
+CONFIG_ENCX24J600=y
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_PENSANDO is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
+CONFIG_SMC91X=m
+CONFIG_SMC911X=m
+CONFIG_SMSC911X=m
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+CONFIG_TI_CPSW_PHY_SEL=y
+CONFIG_TI_CPSW=y
+CONFIG_TI_CPTS=y
+# CONFIG_NET_VENDOR_VIA is not set
+CONFIG_WIZNET_W5100=y
+CONFIG_WIZNET_W5100_SPI=y
+# CONFIG_NET_VENDOR_XILINX is not set
+CONFIG_MDIO_BCM_UNIMAC=m
+CONFIG_LED_TRIGGER_PHY=y
+CONFIG_AT803X_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_MICROCHIP_PHY=y
+CONFIG_MICROSEMI_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOATM=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_LAN78XX=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_AX88179_178A=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_HUAWEI_CDC_NCM=m
+CONFIG_USB_NET_CDC_MBIM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SR9700=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_NET_KALMIA=m
+CONFIG_USB_NET_QMI_WWAN=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_CDC_PHONET=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
+CONFIG_USB_NET_CH9200=m
+CONFIG_ATH9K=m
+CONFIG_ATH9K_CHANNEL_CONTEXT=y
+CONFIG_ATH9K_HTC=m
+CONFIG_CARL9170=m
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_SDIO=m
+CONFIG_ATH6KL_USB=m
+CONFIG_AR5523=m
+CONFIG_ATH10K=m
+CONFIG_ATH10K_USB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_BRCMFMAC=m
+CONFIG_BRCMFMAC_USB=y
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_MESH=y
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_MT7601U=m
+CONFIG_MT76x0U=m
+CONFIG_MT76x2U=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT3573=y
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_RT55XX=y
+CONFIG_RTL8187=m
+CONFIG_RTL8192CU=m
+# CONFIG_RTLWIFI_DEBUG is not set
+CONFIG_RTL8XXXU=m
+CONFIG_RTW88=m
+CONFIG_RSI_91X=m
+# CONFIG_RSI_SDIO is not set
+CONFIG_WL1251=m
+CONFIG_WL1251_SPI=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX=m
+CONFIG_WL18XX=m
+CONFIG_WLCORE_SPI=m
+CONFIG_WLCORE_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_WIMAX_I2400M_USB=m
+CONFIG_IEEE802154_FAKELB=m
+CONFIG_IEEE802154_AT86RF230=m
+CONFIG_IEEE802154_MRF24J40=m
+CONFIG_IEEE802154_CC2520=m
+CONFIG_IEEE802154_ATUSB=m
+CONFIG_IEEE802154_ADF7242=m
+CONFIG_IEEE802154_HWSIM=m
+CONFIG_INPUT_SPARSEKMAP=m
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_KEYBOARD_ADP5588=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_LM8323=m
+CONFIG_KEYBOARD_MAX7359=m
+CONFIG_KEYBOARD_STOWAWAY=m
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_ELAN_I2C=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+CONFIG_MOUSE_SYNAPTICS_USB=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=m
+CONFIG_JOYSTICK_IFORCE_232=m
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_JOYSTICK_AS5011=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_JOYSTICK_PSXPAD_SPI=y
+CONFIG_JOYSTICK_PSXPAD_SPI_FF=y
+CONFIG_JOYSTICK_PXRC=m
+CONFIG_JOYSTICK_FSIA6B=m
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=m
+CONFIG_TABLET_USB_AIPTEK=m
+CONFIG_TABLET_USB_GTCO=m
+CONFIG_TABLET_USB_HANWANG=m
+CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_PEGASUS=m
+CONFIG_TABLET_SERIAL_WACOM4=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_AD7877=m
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_AR1021_I2C=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GOODIX=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+CONFIG_TOUCHSCREEN_MCS5000=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_EDT_FT5X06=y
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_TSC2005=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_SILEAD=y
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_TPS65218_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_PALMAS_PWRBUTTON=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_N_GSM=m
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_DMA is not set
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
+CONFIG_SERIAL_8250_OMAP=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_MAX3100=m
+CONFIG_SERIAL_MAX310X=m
+CONFIG_SERIAL_PRU_SUART=m
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_TTY_PRINTK=m
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_TCG_TPM=y
+CONFIG_TCG_TIS_I2C_ATMEL=y
+CONFIG_RANDOM_TRUST_BOOTLOADER=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=m
+CONFIG_I2C_MUX_GPIO=y
+CONFIG_I2C_MUX_PCA954x=m
+CONFIG_I2C_MUX_PINCTRL=y
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_DIOLAN_U2C=m
+CONFIG_I2C_ROBOTFUZZ_OSIF=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+CONFIG_I2C_SLAVE=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_OMAP24XX=y
+CONFIG_SPI_TI_QSPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_SLAVE=y
+CONFIG_SPI_SLAVE_TIME=m
+CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PPS_CLIENT_GPIO=m
+CONFIG_PINCTRL_MCP23S08=m
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_PINCTRL_PALMAS=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_SYSCON=y
+CONFIG_GPIO_ADP5588=m
+CONFIG_GPIO_ADNP=m
+CONFIG_GPIO_MAX7300=m
+CONFIG_GPIO_MAX732X=m
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_TPIC2810=m
+CONFIG_GPIO_PALMAS=y
+CONFIG_GPIO_STMPE=y
+CONFIG_GPIO_TPS65218=y
+CONFIG_GPIO_74X164=m
+CONFIG_GPIO_MAX3191X=m
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MC33880=m
+CONFIG_GPIO_PISOSR=m
+CONFIG_GPIO_XRA1403=m
+CONFIG_W1=y
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2405=m
+CONFIG_W1_SLAVE_DS2408=m
+CONFIG_W1_SLAVE_DS2413=m
+CONFIG_W1_SLAVE_DS2406=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2805=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+CONFIG_W1_SLAVE_DS2438=m
+CONFIG_W1_SLAVE_DS2780=m
+CONFIG_W1_SLAVE_DS2781=m
+CONFIG_W1_SLAVE_DS28E04=m
+CONFIG_W1_SLAVE_DS28E17=m
+CONFIG_POWER_AVS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_RESTART=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_GENERIC_ADC_BATTERY=m
+CONFIG_CHARGER_GPIO=m
+CONFIG_SENSORS_AD7314=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7310=m
+CONFIG_SENSORS_ADT7410=m
+CONFIG_SENSORS_ADT7411=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7475=m
+CONFIG_SENSORS_AS370=m
+CONFIG_SENSORS_ASC7621=m
+CONFIG_SENSORS_ASPEED=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS620=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FTSTEUTATES=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_G760A=m
+CONFIG_SENSORS_G762=m
+CONFIG_SENSORS_GPIO_FAN=y
+CONFIG_SENSORS_HIH6130=m
+CONFIG_SENSORS_IIO_HWMON=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_JC42=m
+CONFIG_SENSORS_POWR1220=m
+CONFIG_SENSORS_LINEAGE=m
+CONFIG_SENSORS_LTC2945=m
+CONFIG_SENSORS_LTC2990=m
+CONFIG_SENSORS_LTC4151=m
+CONFIG_SENSORS_LTC4215=m
+CONFIG_SENSORS_LTC4222=m
+CONFIG_SENSORS_LTC4245=m
+CONFIG_SENSORS_LTC4260=m
+CONFIG_SENSORS_LTC4261=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX16065=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX1668=m
+CONFIG_SENSORS_MAX197=m
+CONFIG_SENSORS_MAX31722=m
+CONFIG_SENSORS_MAX6621=m
+CONFIG_SENSORS_MAX6639=m
+CONFIG_SENSORS_MAX6642=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_MAX6697=m
+CONFIG_SENSORS_MAX31790=m
+CONFIG_SENSORS_MCP3021=m
+CONFIG_SENSORS_TC654=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LM95234=m
+CONFIG_SENSORS_LM95241=m
+CONFIG_SENSORS_LM95245=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_NTC_THERMISTOR=m
+CONFIG_SENSORS_NCT6683=m
+CONFIG_SENSORS_NCT6775=m
+CONFIG_SENSORS_NCT7802=m
+CONFIG_SENSORS_NCT7904=m
+CONFIG_SENSORS_NPCM7XX=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_PMBUS=m
+CONFIG_SENSORS_ADM1275=m
+CONFIG_SENSORS_IBM_CFFPS=m
+CONFIG_SENSORS_INSPUR_IPSPS=m
+CONFIG_SENSORS_IR35221=m
+CONFIG_SENSORS_IR38064=m
+CONFIG_SENSORS_IRPS5401=m
+CONFIG_SENSORS_ISL68137=m
+CONFIG_SENSORS_LM25066=m
+CONFIG_SENSORS_LTC2978=m
+CONFIG_SENSORS_LTC2978_REGULATOR=y
+CONFIG_SENSORS_LTC3815=m
+CONFIG_SENSORS_MAX16064=m
+CONFIG_SENSORS_MAX20751=m
+CONFIG_SENSORS_MAX31785=m
+CONFIG_SENSORS_MAX34440=m
+CONFIG_SENSORS_MAX8688=m
+CONFIG_SENSORS_PXE1610=m
+CONFIG_SENSORS_TPS40422=m
+CONFIG_SENSORS_TPS53679=m
+CONFIG_SENSORS_UCD9000=m
+CONFIG_SENSORS_UCD9200=m
+CONFIG_SENSORS_ZL6100=m
+CONFIG_SENSORS_PWM_FAN=m
+CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SHT21=m
+CONFIG_SENSORS_SHT3x=m
+CONFIG_SENSORS_SHTC1=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
+CONFIG_SENSORS_EMC2103=m
+CONFIG_SENSORS_EMC6W201=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_SCH5627=m
+CONFIG_SENSORS_SCH5636=m
+CONFIG_SENSORS_STTS751=m
+CONFIG_SENSORS_SMM665=m
+CONFIG_SENSORS_ADC128D818=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_ADS7871=m
+CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_INA209=m
+CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_INA3221=m
+CONFIG_SENSORS_TC74=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=y
+CONFIG_SENSORS_TMP103=m
+CONFIG_SENSORS_TMP108=m
+CONFIG_SENSORS_TMP401=m
+CONFIG_SENSORS_TMP421=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_W83773G=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83795=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_THERMAL_STATISTICS=y
+CONFIG_THERMAL_GOV_FAIR_SHARE=y
+CONFIG_THERMAL_GOV_BANG_BANG=y
+CONFIG_CPU_THERMAL=y
+CONFIG_CLOCK_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_TI_THERMAL=y
+CONFIG_OMAP5_THERMAL=y
+CONFIG_DRA752_THERMAL=y
+CONFIG_GENERIC_ADC_THERMAL=m
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_WATCHDOG_PRETIMEOUT_GOV=y
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=m
+CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP=y
+CONFIG_SOFT_WATCHDOG=y
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_MFD_STMPE=y
+CONFIG_MFD_TI_AM335X_TSCADC=y
+CONFIG_MFD_PALMAS=y
+CONFIG_MFD_TPS65217=y
+CONFIG_MFD_TPS65218=y
+CONFIG_MFD_WL1273_CORE=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_PALMAS=y
+CONFIG_REGULATOR_PBIAS=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_TI_ABB=y
+CONFIG_REGULATOR_TPS65217=y
+CONFIG_REGULATOR_TPS65218=y
+CONFIG_RC_CORE=m
+CONFIG_LIRC=y
+CONFIG_RC_DECODERS=y
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_SANYO_DECODER=m
+CONFIG_IR_SHARP_DECODER=m
+CONFIG_IR_MCE_KBD_DECODER=m
+CONFIG_IR_XMP_DECODER=m
+CONFIG_IR_IMON_DECODER=m
+CONFIG_RC_DEVICES=y
+CONFIG_RC_ATI_REMOTE=m
+CONFIG_IR_IMON=m
+CONFIG_IR_IMON_RAW=m
+CONFIG_IR_MCEUSB=m
+CONFIG_IR_REDRAT3=m
+CONFIG_IR_STREAMZAP=m
+CONFIG_IR_IGORPLUGUSB=m
+CONFIG_IR_IGUANA=m
+CONFIG_IR_TTUSBIR=m
+CONFIG_RC_LOOPBACK=m
+CONFIG_IR_GPIO_CIR=m
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+CONFIG_MEDIA_SDR_SUPPORT=y
+CONFIG_MEDIA_CEC_SUPPORT=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_DTCS033=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+CONFIG_USB_GSPCA_JL2005BCD=m
+CONFIG_USB_GSPCA_KINECT=m
+CONFIG_USB_GSPCA_KONICA=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_NW80X=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SE401=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SPCA1528=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STK1135=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TOPRO=m
+CONFIG_USB_GSPCA_TOUPTEK=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_VICAM=m
+CONFIG_USB_GSPCA_XIRLINK_CIT=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_USB_PWC=m
+CONFIG_VIDEO_CPIA2=m
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_VIDEO_USBTV=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_STK1160_COMMON=m
+CONFIG_VIDEO_GO7007=m
+CONFIG_VIDEO_GO7007_USB=m
+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_AU0828_RC=y
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_DVB_USB=m
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_PCTV452E=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AZ6027=m
+CONFIG_DVB_USB_TECHNISAT_USB2=m
+CONFIG_DVB_USB_V2=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_AF9035=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_AZ6007=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_LME2510=m
+CONFIG_DVB_USB_MXL111SF=m
+CONFIG_DVB_USB_RTL28XXU=m
+CONFIG_DVB_USB_DVBSKY=m
+CONFIG_DVB_USB_ZD1301=m
+CONFIG_SMS_USB_DRV=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+CONFIG_DVB_AS102=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_V4L2=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_USB_AIRSPY=m
+CONFIG_USB_HACKRF=m
+CONFIG_USB_MSI2500=m
+CONFIG_USB_PULSE8_CEC=m
+CONFIG_USB_RAINSHADOW_CEC=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_SMS_SDIO_DRV=m
+CONFIG_RADIO_SI470X=y
+CONFIG_USB_SI470X=m
+CONFIG_RADIO_SI4713=m
+CONFIG_I2C_SI4713=m
+CONFIG_USB_MR800=m
+CONFIG_RADIO_SHARK=m
+CONFIG_RADIO_SHARK2=m
+CONFIG_USB_KEENE=m
+CONFIG_USB_RAREMONO=m
+CONFIG_USB_MA901=m
+CONFIG_RADIO_WL128X=m
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_CS3308=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_VPX3220=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_SR030PC30=m
+CONFIG_VIDEO_NOON010PC30=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+CONFIG_VIDEO_SAA6752HS=m
+CONFIG_VIDEO_M52790=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_M88RS6000T=m
+CONFIG_MEDIA_TUNER_MXL301RF=m
+CONFIG_MEDIA_TUNER_QM1D1B0004=m
+CONFIG_DVB_STV0910=m
+CONFIG_DVB_STV6111=m
+CONFIG_DVB_MXL5XX=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_ZL10036=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24117=m
+CONFIG_DVB_MB86A16=m
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_STV0367=m
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_LNBH25=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_TDA665x=m
+CONFIG_DVB_HORUS3A=m
+CONFIG_DVB_ASCOT2E=m
+CONFIG_DVB_HELENE=m
+CONFIG_DVB_CXD2099=m
+CONFIG_DVB_DUMMY_FE=m
+CONFIG_DRM=y
+CONFIG_DRM_DP_AUX_CHARDEV=y
+CONFIG_DRM_LOAD_EDID_FIRMWARE=y
+CONFIG_DRM_I2C_NXP_TDA998X=y
+CONFIG_DRM_VGEM=m
+CONFIG_DRM_UDL=m
+CONFIG_DRM_OMAP=y
+CONFIG_OMAP5_DSS_HDMI=y
+CONFIG_DRM_OMAP_ENCODER_TPD12S015=y
+CONFIG_DRM_OMAP_CONNECTOR_HDMI=y
+CONFIG_DRM_TILCDC=y
+CONFIG_DRM_PANEL_SIMPLE=y
+CONFIG_DRM_PANEL_SONY_ACX565AKM=m
+CONFIG_DRM_PANEL_TPO_TD028TTEC1=m
+CONFIG_DRM_PANEL_TPO_TD043MTEA1=m
+CONFIG_DRM_SII902X=y
+CONFIG_DRM_TI_TFP410=y
+CONFIG_DRM_I2C_ADV7511=y
+CONFIG_DRM_I2C_ADV7511_AUDIO=y
+CONFIG_DRM_ETNAVIV=y
+CONFIG_TINYDRM_HX8357D=m
+CONFIG_TINYDRM_ILI9225=m
+CONFIG_TINYDRM_ILI9341=m
+CONFIG_TINYDRM_MI0283QT=m
+CONFIG_TINYDRM_REPAPER=m
+CONFIG_TINYDRM_ST7586=m
+CONFIG_TINYDRM_ST7735R=m
+CONFIG_DRM_LEGACY=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_SMSCUFX=m
+CONFIG_FB_UDL=m
+CONFIG_FB_SIMPLE=y
+CONFIG_FB_SSD1307=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_GPIO=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set
+CONFIG_SND=y
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_ALOOP=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_HDA_PREALLOC_SIZE=2048
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SND_USB_HIFACE=m
+CONFIG_SND_BCD2000=m
+CONFIG_SND_USB_POD=m
+CONFIG_SND_USB_PODHD=m
+CONFIG_SND_USB_TONEPORT=m
+CONFIG_SND_USB_VARIAX=m
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_DAVINCI_MCASP=y
+CONFIG_SND_SOC_OMAP_DMIC=y
+CONFIG_SND_SOC_OMAP_MCBSP=y
+CONFIG_SND_SOC_OMAP_MCPDM=y
+CONFIG_SND_SOC_OMAP_HDMI=y
+CONFIG_SND_SOC_ADAU1701=m
+CONFIG_SND_SOC_ADAU7002=m
+CONFIG_SND_SOC_AK4554=m
+CONFIG_SND_SOC_CS4265=m
+CONFIG_SND_SOC_CS4271_I2C=m
+CONFIG_SND_SOC_PCM512x_I2C=m
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_TLV320AIC23_I2C=m
+CONFIG_SND_SOC_TLV320AIC31XX=m
+CONFIG_SND_SOC_TLV320AIC3X=m
+CONFIG_SND_SOC_TS3A227E=m
+CONFIG_SND_SOC_WM8753=m
+CONFIG_SND_SOC_WM8804_I2C=m
+CONFIG_SND_SOC_WM8903=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SIMPLE_CARD=y
+CONFIG_SND_AUDIO_GRAPH_CARD=y
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACCUTOUCH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=m
+CONFIG_HID_ASUS=m
+CONFIG_HID_AUREAL=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BETOP_FF=m
+CONFIG_HID_BIGBEN_FF=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CORSAIR=m
+CONFIG_HID_COUGAR=m
+CONFIG_HID_MACALLY=m
+CONFIG_HID_PRODIKEYS=m
+CONFIG_HID_CMEDIA=m
+CONFIG_HID_CP2112=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELAN=m
+CONFIG_HID_ELECOM=m
+CONFIG_HID_ELO=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GEMBIRD=m
+CONFIG_HID_GFRM=m
+CONFIG_HID_HOLTEK=m
+CONFIG_HOLTEK_FF=y
+CONFIG_HID_GT683R=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KYE=m
+CONFIG_HID_UCLOGIC=m
+CONFIG_HID_WALTOP=m
+CONFIG_HID_VIEWSONIC=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_ICADE=m
+CONFIG_HID_ITE=m
+CONFIG_HID_JABRA=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LCPOWER=m
+CONFIG_HID_LENOVO=m
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MALTRON=m
+CONFIG_HID_MAYFLASH=m
+CONFIG_HID_REDRAGON=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
+CONFIG_HID_NTI=m
+CONFIG_HID_NTRIG=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PENMOUNT=m
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_PICOLCD_CIR=y
+CONFIG_HID_PLANTRONICS=m
+CONFIG_HID_PRIMAX=m
+CONFIG_HID_RETRODE=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_SAITEK=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_SONY_FF=y
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_STEAM=m
+CONFIG_HID_STEELSERIES=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_RMI=m
+CONFIG_HID_GREENASIA=m
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THINGM=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_UDRAW_PS3=m
+CONFIG_HID_U2FZERO=m
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_XINMO=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_ZEROPLUS_FF=y
+CONFIG_HID_ZYDACRON=m
+CONFIG_HID_SENSOR_HUB=m
+CONFIG_HID_SENSOR_CUSTOM_SENSOR=m
+CONFIG_HID_ALPS=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_I2C_HID=y
+CONFIG_USB_LED_TRIG=y
+CONFIG_USB_ULPI_BUS=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_OTG=y
+CONFIG_USB_LEDS_TRIGGER_USBPORT=m
+CONFIG_USB_MON=m
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_PRINTER=m
+CONFIG_USB_TMC=m
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_REALTEK=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_USB_UAS=y
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USBIP_CORE=m
+CONFIG_USBIP_VHCI_HCD=m
+CONFIG_USBIP_VHCI_HC_PORTS=15
+CONFIG_USBIP_VHCI_NR_HCS=8
+CONFIG_USBIP_HOST=m
+CONFIG_USBIP_VUDC=m
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_DSPS=y
+CONFIG_MUSB_PIO_ONLY=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_F8153X=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MXUPORT=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+CONFIG_USB_SERIAL_UPD78F0730=m
+CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_EHSET_TEST_FIXTURE=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
+CONFIG_USB_HSIC_USB3503=m
+CONFIG_USB_CHAOSKEY=m
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_AM335X_PHY_USB=y
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_DUMMY_HCD=m
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_PHONET=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_UVC=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_NOKIA=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+CONFIG_USB_ROLE_SWITCH=m
+CONFIG_MMC=y
+CONFIG_PWRSEQ_SD8787=m
+CONFIG_MMC_BLOCK_MINORS=256
+CONFIG_SDIO_UART=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=y
+CONFIG_MMC_VUB300=m
+CONFIG_MMC_USHC=m
+CONFIG_MMC_SDHCI_OMAP=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_LP3944=m
+CONFIG_LEDS_LP5523=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_PWM=m
+CONFIG_LEDS_REGULATOR=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_LT3593=m
+CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_DISK=y
+CONFIG_LEDS_TRIGGER_MTD=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_ACTIVITY=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=m
+CONFIG_LEDS_TRIGGER_CAMERA=m
+CONFIG_LEDS_TRIGGER_PANIC=y
+CONFIG_LEDS_TRIGGER_NETDEV=y
+CONFIG_ACCESSIBILITY=y
+CONFIG_A11Y_BRAILLE_CONSOLE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_ABB5ZES3=y
+CONFIG_RTC_DRV_ABEOZ9=y
+CONFIG_RTC_DRV_ABX80X=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS1374_WDT=y
+CONFIG_RTC_DRV_DS1672=y
+CONFIG_RTC_DRV_HYM8563=y
+CONFIG_RTC_DRV_MAX6900=y
+CONFIG_RTC_DRV_RS5C372=y
+CONFIG_RTC_DRV_ISL1208=y
+CONFIG_RTC_DRV_ISL12022=y
+CONFIG_RTC_DRV_ISL12026=y
+CONFIG_RTC_DRV_X1205=y
+CONFIG_RTC_DRV_PCF8523=y
+CONFIG_RTC_DRV_PCF85063=y
+CONFIG_RTC_DRV_PCF85363=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_PCF8583=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=y
+CONFIG_RTC_DRV_PALMAS=y
+CONFIG_RTC_DRV_S35390A=y
+CONFIG_RTC_DRV_FM3130=y
+CONFIG_RTC_DRV_RX8010=y
+CONFIG_RTC_DRV_RX8581=y
+CONFIG_RTC_DRV_RX8025=y
+CONFIG_RTC_DRV_EM3027=y
+CONFIG_RTC_DRV_RV8803=y
+CONFIG_RTC_DRV_M41T93=y
+CONFIG_RTC_DRV_M41T94=y
+CONFIG_RTC_DRV_DS1302=y
+CONFIG_RTC_DRV_DS1305=y
+CONFIG_RTC_DRV_DS1343=y
+CONFIG_RTC_DRV_DS1347=y
+CONFIG_RTC_DRV_DS1390=y
+CONFIG_RTC_DRV_MAX6916=y
+CONFIG_RTC_DRV_R9701=y
+CONFIG_RTC_DRV_RX4581=y
+CONFIG_RTC_DRV_RX6110=y
+CONFIG_RTC_DRV_RS5C348=y
+CONFIG_RTC_DRV_MAX6902=y
+CONFIG_RTC_DRV_PCF2123=y
+CONFIG_RTC_DRV_MCP795=y
+CONFIG_RTC_DRV_DS3232=y
+CONFIG_RTC_DRV_PCF2127=y
+CONFIG_RTC_DRV_RV3029C2=y
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1685_FAMILY=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_DS2404=m
+CONFIG_RTC_DRV_EFI=y
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_OMAP=y
+CONFIG_RTC_DRV_HID_SENSOR_TIME=m
+CONFIG_DMADEVICES=y
+CONFIG_TI_CPPI41=y
+CONFIG_ASYNC_TX_DMA=y
+CONFIG_AUXDISPLAY=y
+CONFIG_HD44780=m
+CONFIG_IMG_ASCII_LCD=m
+CONFIG_HT16K33=m
+CONFIG_UIO=m
+CONFIG_VIRT_DRIVERS=y
+CONFIG_VIRTIO_BALLOON=m
+CONFIG_VIRTIO_INPUT=m
+CONFIG_VIRTIO_MMIO=m
+CONFIG_GREYBUS=m
+CONFIG_GREYBUS_ES2=m
+CONFIG_STAGING=y
+CONFIG_RTLLIB=m
+CONFIG_RTL8723BS=m
+CONFIG_R8712U=m
+CONFIG_R8188EU=m
+CONFIG_ADIS16203=m
+CONFIG_ADIS16240=m
+CONFIG_AD7816=m
+CONFIG_AD7192=m
+CONFIG_AD7280=m
+CONFIG_ADT7316=m
+CONFIG_ADT7316_I2C=m
+CONFIG_AD7150=m
+CONFIG_AD7746=m
+CONFIG_AD9832=m
+CONFIG_AD9834=m
+CONFIG_AD5933=m
+CONFIG_ADE7854=m
+CONFIG_AD2S1210=m
+CONFIG_FB_TFT=m
+CONFIG_FB_TFT_AGM1264K_FL=m
+CONFIG_FB_TFT_BD663474=m
+CONFIG_FB_TFT_HX8340BN=m
+CONFIG_FB_TFT_HX8347D=m
+CONFIG_FB_TFT_HX8353D=m
+CONFIG_FB_TFT_HX8357D=m
+CONFIG_FB_TFT_ILI9163=m
+CONFIG_FB_TFT_ILI9320=m
+CONFIG_FB_TFT_ILI9325=m
+CONFIG_FB_TFT_ILI9340=m
+CONFIG_FB_TFT_ILI9341=m
+CONFIG_FB_TFT_ILI9481=m
+CONFIG_FB_TFT_ILI9486=m
+CONFIG_FB_TFT_PCD8544=m
+CONFIG_FB_TFT_RA8875=m
+CONFIG_FB_TFT_S6D02A1=m
+CONFIG_FB_TFT_S6D1121=m
+CONFIG_FB_TFT_SH1106=m
+CONFIG_FB_TFT_SSD1289=m
+CONFIG_FB_TFT_SSD1305=m
+CONFIG_FB_TFT_SSD1306=m
+CONFIG_FB_TFT_SSD1331=m
+CONFIG_FB_TFT_SSD1351=m
+CONFIG_FB_TFT_ST7735R=m
+CONFIG_FB_TFT_ST7789V=m
+CONFIG_FB_TFT_TINYLCD=m
+CONFIG_FB_TFT_TLS8204=m
+CONFIG_FB_TFT_UC1611=m
+CONFIG_FB_TFT_UC1701=m
+CONFIG_FB_TFT_UPD161704=m
+CONFIG_FB_TFT_WATTEROTT=m
+CONFIG_GREYBUS_AUDIO=m
+CONFIG_GREYBUS_BOOTROM=m
+CONFIG_GREYBUS_FIRMWARE=m
+CONFIG_GREYBUS_HID=m
+CONFIG_GREYBUS_LIGHT=m
+CONFIG_GREYBUS_LOG=m
+CONFIG_GREYBUS_LOOPBACK=m
+CONFIG_GREYBUS_POWER=m
+CONFIG_GREYBUS_RAW=m
+CONFIG_GREYBUS_VIBRATOR=m
+CONFIG_GREYBUS_BRIDGED_PHY=m
+CONFIG_GREYBUS_GPIO=m
+CONFIG_GREYBUS_I2C=m
+CONFIG_GREYBUS_PWM=m
+CONFIG_GREYBUS_SDIO=m
+CONFIG_GREYBUS_SPI=m
+CONFIG_GREYBUS_UART=m
+CONFIG_GREYBUS_USB=m
+CONFIG_USB_WUSB_CBAF=m
+CONFIG_STAGING_EXFAT_FS=m
+CONFIG_COMMON_CLK_PALMAS=y
+CONFIG_COMMON_CLK_TI_ADPLL=y
+CONFIG_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_OMAP=y
+CONFIG_OMAP_IOMMU=y
+CONFIG_REMOTEPROC=y
+CONFIG_OMAP_REMOTEPROC=y
+CONFIG_OMAP_REMOTEPROC_WATCHDOG=y
+CONFIG_WKUP_M3_RPROC=y
+CONFIG_RPMSG_CHAR=y
+CONFIG_RPMSG_VIRTIO=y
+CONFIG_RPMSG_PRU=y
+CONFIG_SOC_TI=y
+CONFIG_AMX3_PM=y
+CONFIG_WKUP_M3_IPC=y
+CONFIG_TI_PRUSS=y
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_DEVFREQ_GOV_PERFORMANCE=y
+CONFIG_DEVFREQ_GOV_POWERSAVE=y
+CONFIG_DEVFREQ_GOV_USERSPACE=y
+CONFIG_DEVFREQ_GOV_PASSIVE=y
+CONFIG_PM_DEVFREQ_EVENT=y
+CONFIG_EXTCON_GPIO=y
+CONFIG_EXTCON_PALMAS=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_TI_EMIF=y
+CONFIG_TI_EMIF_SRAM=y
+CONFIG_IIO=y
+CONFIG_IIO_SW_DEVICE=m
+CONFIG_IIO_SW_TRIGGER=m
+CONFIG_ADIS16201=m
+CONFIG_ADIS16209=m
+CONFIG_ADXL345_I2C=m
+CONFIG_ADXL345_SPI=m
+CONFIG_ADXL372_SPI=m
+CONFIG_ADXL372_I2C=m
+CONFIG_BMA180=m
+CONFIG_BMA220=m
+CONFIG_BMC150_ACCEL=m
+CONFIG_DA280=m
+CONFIG_DA311=m
+CONFIG_DMARD06=m
+CONFIG_DMARD09=m
+CONFIG_DMARD10=m
+CONFIG_HID_SENSOR_ACCEL_3D=m
+CONFIG_IIO_ST_ACCEL_3AXIS=m
+CONFIG_KXSD9=m
+CONFIG_KXCJK1013=m
+CONFIG_MC3230=m
+CONFIG_MMA7455_I2C=m
+CONFIG_MMA7455_SPI=m
+CONFIG_MMA7660=m
+CONFIG_MMA8452=m
+CONFIG_MMA9551=m
+CONFIG_MMA9553=m
+CONFIG_MXC4005=m
+CONFIG_MXC6255=m
+CONFIG_SCA3000=m
+CONFIG_STK8312=m
+CONFIG_STK8BA50=m
+CONFIG_AD7124=m
+CONFIG_AD7266=m
+CONFIG_AD7291=m
+CONFIG_AD7298=m
+CONFIG_AD7476=m
+CONFIG_AD7606_IFACE_SPI=m
+CONFIG_AD7766=m
+CONFIG_AD7768_1=m
+CONFIG_AD7780=m
+CONFIG_AD7791=m
+CONFIG_AD7793=m
+CONFIG_AD7887=m
+CONFIG_AD7923=m
+CONFIG_AD7949=m
+CONFIG_AD799X=m
+CONFIG_CC10001_ADC=m
+CONFIG_ENVELOPE_DETECTOR=m
+CONFIG_HI8435=m
+CONFIG_HX711=m
+CONFIG_INA2XX_ADC=m
+CONFIG_LTC2471=m
+CONFIG_LTC2485=m
+CONFIG_LTC2497=m
+CONFIG_MAX1027=m
+CONFIG_MAX11100=m
+CONFIG_MAX1118=m
+CONFIG_MAX1363=m
+CONFIG_MAX9611=m
+CONFIG_MCP320X=m
+CONFIG_MCP3422=m
+CONFIG_MCP3911=m
+CONFIG_NAU7802=m
+CONFIG_PALMAS_GPADC=m
+CONFIG_SD_ADC_MODULATOR=m
+CONFIG_STMPE_ADC=m
+CONFIG_TI_ADC081C=m
+CONFIG_TI_ADC0832=m
+CONFIG_TI_ADC084S021=m
+CONFIG_TI_ADC12138=m
+CONFIG_TI_ADC108S102=m
+CONFIG_TI_ADC128S052=m
+CONFIG_TI_ADC161S626=m
+CONFIG_TI_ADS1015=m
+CONFIG_TI_ADS7950=m
+CONFIG_TI_ADS8344=m
+CONFIG_TI_ADS8688=m
+CONFIG_TI_ADS124S08=m
+CONFIG_TI_AM335X_ADC=y
+CONFIG_TI_TLC4541=m
+CONFIG_IIO_RESCALE=m
+CONFIG_AD8366=m
+CONFIG_ATLAS_PH_SENSOR=m
+CONFIG_BME680=m
+CONFIG_CCS811=m
+CONFIG_IAQCORE=m
+CONFIG_PMS7003=m
+CONFIG_SENSIRION_SGP30=m
+CONFIG_SPS30=m
+CONFIG_VZ89X=m
+CONFIG_AD5064=m
+CONFIG_AD5360=m
+CONFIG_AD5380=m
+CONFIG_AD5421=m
+CONFIG_AD5446=m
+CONFIG_AD5449=m
+CONFIG_AD5592R=m
+CONFIG_AD5593R=m
+CONFIG_AD5504=m
+CONFIG_AD5624R_SPI=m
+CONFIG_LTC1660=m
+CONFIG_LTC2632=m
+CONFIG_AD5686_SPI=m
+CONFIG_AD5696_I2C=m
+CONFIG_AD5755=m
+CONFIG_AD5758=m
+CONFIG_AD5761=m
+CONFIG_AD5764=m
+CONFIG_AD5791=m
+CONFIG_AD7303=m
+CONFIG_AD8801=m
+CONFIG_DPOT_DAC=m
+CONFIG_DS4424=m
+CONFIG_M62332=m
+CONFIG_MAX517=m
+CONFIG_MAX5821=m
+CONFIG_MCP4725=m
+CONFIG_MCP4922=m
+CONFIG_TI_DAC082S085=m
+CONFIG_TI_DAC5571=m
+CONFIG_TI_DAC7311=m
+CONFIG_TI_DAC7612=m
+CONFIG_AD9523=m
+CONFIG_ADF4350=m
+CONFIG_ADF4371=m
+CONFIG_ADIS16080=m
+CONFIG_ADIS16130=m
+CONFIG_ADIS16136=m
+CONFIG_ADIS16260=m
+CONFIG_ADXRS450=m
+CONFIG_BMG160=m
+CONFIG_FXAS21002C=m
+CONFIG_HID_SENSOR_GYRO_3D=m
+CONFIG_MPU3050_I2C=m
+CONFIG_IIO_ST_GYRO_3AXIS=m
+CONFIG_ITG3200=m
+CONFIG_AFE4403=m
+CONFIG_AFE4404=m
+CONFIG_MAX30100=m
+CONFIG_MAX30102=m
+CONFIG_AM2315=m
+CONFIG_DHT11=m
+CONFIG_HDC100X=m
+CONFIG_HID_SENSOR_HUMIDITY=m
+CONFIG_HTS221=m
+CONFIG_HTU21=m
+CONFIG_SI7005=m
+CONFIG_SI7020=m
+CONFIG_ADIS16400=m
+CONFIG_ADIS16460=m
+CONFIG_ADIS16480=m
+CONFIG_BMI160_I2C=m
+CONFIG_BMI160_SPI=m
+CONFIG_KMX61=m
+CONFIG_INV_MPU6050_I2C=m
+CONFIG_INV_MPU6050_SPI=m
+CONFIG_IIO_ST_LSM6DSX=m
+CONFIG_ADJD_S311=m
+CONFIG_AL3320A=m
+CONFIG_APDS9300=m
+CONFIG_APDS9960=m
+CONFIG_BH1750=m
+CONFIG_BH1780=m
+CONFIG_CM32181=m
+CONFIG_CM3232=m
+CONFIG_CM3323=m
+CONFIG_CM3605=m
+CONFIG_CM36651=m
+CONFIG_GP2AP020A00F=m
+CONFIG_SENSORS_ISL29018=m
+CONFIG_SENSORS_ISL29028=m
+CONFIG_ISL29125=m
+CONFIG_HID_SENSOR_ALS=m
+CONFIG_HID_SENSOR_PROX=m
+CONFIG_JSA1212=m
+CONFIG_RPR0521=m
+CONFIG_LTR501=m
+CONFIG_LV0104CS=m
+CONFIG_MAX44000=m
+CONFIG_MAX44009=m
+CONFIG_NOA1305=m
+CONFIG_OPT3001=m
+CONFIG_PA12203001=m
+CONFIG_SI1133=m
+CONFIG_SI1145=m
+CONFIG_STK3310=m
+CONFIG_ST_UVIS25=m
+CONFIG_TCS3414=m
+CONFIG_TCS3472=m
+CONFIG_SENSORS_TSL2563=m
+CONFIG_TSL2583=m
+CONFIG_TSL2772=m
+CONFIG_TSL4531=m
+CONFIG_US5182D=m
+CONFIG_VCNL4000=m
+CONFIG_VCNL4035=m
+CONFIG_VEML6070=m
+CONFIG_VL6180=m
+CONFIG_ZOPT2201=m
+CONFIG_AK8974=m
+CONFIG_AK09911=m
+CONFIG_BMC150_MAGN_I2C=m
+CONFIG_BMC150_MAGN_SPI=m
+CONFIG_MAG3110=m
+CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
+CONFIG_MMC35240=m
+CONFIG_IIO_ST_MAGN_3AXIS=m
+CONFIG_SENSORS_HMC5843_I2C=m
+CONFIG_SENSORS_HMC5843_SPI=m
+CONFIG_SENSORS_RM3100_I2C=m
+CONFIG_SENSORS_RM3100_SPI=m
+CONFIG_HID_SENSOR_INCLINOMETER_3D=m
+CONFIG_HID_SENSOR_DEVICE_ROTATION=m
+CONFIG_IIO_HRTIMER_TRIGGER=m
+CONFIG_IIO_INTERRUPT_TRIGGER=m
+CONFIG_IIO_TIGHTLOOP_TRIGGER=m
+CONFIG_IIO_SYSFS_TRIGGER=m
+CONFIG_AD5272=m
+CONFIG_DS1803=m
+CONFIG_MAX5432=m
+CONFIG_MAX5481=m
+CONFIG_MAX5487=m
+CONFIG_MCP4018=m
+CONFIG_MCP4131=m
+CONFIG_MCP4531=m
+CONFIG_MCP41010=m
+CONFIG_TPL0102=m
+CONFIG_LMP91000=m
+CONFIG_ABP060MG=m
+CONFIG_BMP280=m
+CONFIG_DPS310=m
+CONFIG_HID_SENSOR_PRESS=m
+CONFIG_HP03=m
+CONFIG_MPL115_I2C=m
+CONFIG_MPL115_SPI=m
+CONFIG_MPL3115=m
+CONFIG_MS5611=m
+CONFIG_MS5611_I2C=m
+CONFIG_MS5611_SPI=m
+CONFIG_MS5637=m
+CONFIG_IIO_ST_PRESS=m
+CONFIG_T5403=m
+CONFIG_HP206C=m
+CONFIG_ZPA2326=m
+CONFIG_AS3935=m
+CONFIG_ISL29501=m
+CONFIG_LIDAR_LITE_V2=m
+CONFIG_MB1232=m
+CONFIG_RFD77402=m
+CONFIG_SRF04=m
+CONFIG_SX9500=m
+CONFIG_SRF08=m
+CONFIG_VL53L0X_I2C=m
+CONFIG_AD2S90=m
+CONFIG_AD2S1200=m
+CONFIG_MAXIM_THERMOCOUPLE=m
+CONFIG_HID_SENSOR_TEMP=m
+CONFIG_MLX90614=m
+CONFIG_MLX90632=m
+CONFIG_TMP006=m
+CONFIG_TMP007=m
+CONFIG_TSYS01=m
+CONFIG_TSYS02D=m
+CONFIG_MAX31856=m
+CONFIG_PWM_OMAP_DMTIMER=y
+CONFIG_PWM_PCA9685=y
+CONFIG_PWM_STMPE=y
+CONFIG_PWM_TIECAP=y
+CONFIG_PWM_TIEHRPWM=y
+CONFIG_TI_PRUSS_INTC=y
+CONFIG_RESET_TI_SYSCON=y
+CONFIG_OMAP_USB2=y
+CONFIG_TI_PIPE3=y
+CONFIG_RAS=y
+CONFIG_FPGA=m
+CONFIG_ALTERA_PR_IP_CORE=m
+CONFIG_ALTERA_PR_IP_CORE_PLAT=m
+CONFIG_FPGA_MGR_ALTERA_PS_SPI=m
+CONFIG_FPGA_MGR_XILINX_SPI=m
+CONFIG_FPGA_MGR_ICE40_SPI=m
+CONFIG_FPGA_MGR_MACHXO2_SPI=m
+CONFIG_FPGA_BRIDGE=m
+CONFIG_ALTERA_FREEZE_BRIDGE=m
+CONFIG_XILINX_PR_DECOUPLER=m
+CONFIG_FPGA_REGION=m
+CONFIG_OF_FPGA_REGION=m
+CONFIG_COUNTER=y
+CONFIG_VALIDATE_FS_PARSER=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_BTRFS_FS=y
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_FS_ENCRYPTION=y
+CONFIG_FS_VERITY=y
+CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=m
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=m
+CONFIG_VIRTIO_FS=m
+CONFIG_OVERLAY_FS=y
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_CACHEFILES=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_NTFS_FS=m
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+CONFIG_EROFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_BLOCKLAYOUT=y
+CONFIG_NFSD_V4_SECURITY_LABEL=y
+CONFIG_SUNRPC_DEBUG=y
+CONFIG_CEPH_FS=m
+CONFIG_CEPH_FSCACHE=y
+CONFIG_CEPH_FS_POSIX_ACL=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_CIFS_FSCACHE=y
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+CONFIG_AFS_FSCACHE=y
+CONFIG_9P_FS=m
+CONFIG_9P_FSCACHE=y
+CONFIG_9P_FS_POSIX_ACL=y
+CONFIG_9P_FS_SECURITY=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+CONFIG_DLM_DEBUG=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK_XFRM=y
+CONFIG_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY_FALLBACK is not set
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_TOMOYO=y
+CONFIG_SECURITY_APPARMOR=y
+CONFIG_SECURITY_YAMA=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_DEFAULT_SECURITY_APPARMOR=y
+CONFIG_CRYPTO_USER=m
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_DH=y
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
+CONFIG_CRYPTO_DEV_OMAP=y
+CONFIG_CRYPTO_DEV_OMAP_SHAM=y
+CONFIG_CRYPTO_DEV_OMAP_AES=y
+CONFIG_CRYPTO_DEV_OMAP_DES=y
+CONFIG_PKCS8_PRIVATE_KEY_PARSER=m
+# CONFIG_RAID6_PQ_BENCHMARK is not set
+CONFIG_CORDIC=m
+CONFIG_CRC64=m
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_SPARC is not set
+CONFIG_CMA_SIZE_MBYTES=48
+CONFIG_IRQ_POLL=y
+CONFIG_PRINTK_TIME=y
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x01b6
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_NOTIFIER_ERROR_INJECTION=m
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_TRACER_SNAPSHOT=y
+CONFIG_STACK_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_BUG_ON_DATA_CORRUPTION=y
+# CONFIG_STRICT_DEVMEM is not set
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 46d41140df27d..c421b5b81946e 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -23,6 +23,8 @@
#endif
#ifndef __ASSEMBLY__
+#include
+
struct irqaction;
struct pt_regs;
diff --git a/arch/arm/include/asm/spinlock_types.h b/arch/arm/include/asm/spinlock_types.h
index 5976958647fe1..a37c0803954ba 100644
--- a/arch/arm/include/asm/spinlock_types.h
+++ b/arch/arm/include/asm/spinlock_types.h
@@ -2,10 +2,6 @@
#ifndef __ASM_SPINLOCK_TYPES_H
#define __ASM_SPINLOCK_TYPES_H
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
#define TICKET_SHIFT 16
typedef struct {
diff --git a/arch/arm/include/asm/switch_to.h b/arch/arm/include/asm/switch_to.h
index d3e937dcee4d0..285e6248454fc 100644
--- a/arch/arm/include/asm/switch_to.h
+++ b/arch/arm/include/asm/switch_to.h
@@ -4,13 +4,20 @@
#include
+#if defined CONFIG_PREEMPT_RT && defined CONFIG_HIGHMEM
+void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p);
+#else
+static inline void
+switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p) { }
+#endif
+
/*
* For v7 SMP cores running a preemptible kernel we may be pre-empted
* during a TLB maintenance operation, so execute an inner-shareable dsb
* to ensure that the maintenance completes in case we migrate to another
* CPU.
*/
-#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP) && defined(CONFIG_CPU_V7)
+#if defined(CONFIG_PREEMPTION) && defined(CONFIG_SMP) && defined(CONFIG_CPU_V7)
#define __complete_pending_tlbi() dsb(ish)
#else
#define __complete_pending_tlbi()
@@ -26,6 +33,7 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info
#define switch_to(prev,next,last) \
do { \
__complete_pending_tlbi(); \
+ switch_kmaps(prev, next); \
last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
} while (0)
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 0d0d5178e2c32..13be9c2137e26 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -46,6 +46,7 @@ struct cpu_context_save {
struct thread_info {
unsigned long flags; /* low level flags */
int preempt_count; /* 0 => preemptable, <0 => bug */
+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
mm_segment_t addr_limit; /* address limit */
struct task_struct *task; /* main task structure */
__u32 cpu; /* cpu */
@@ -139,7 +140,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
#define TIF_SYSCALL_TRACE 4 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
-#define TIF_SECCOMP 7 /* seccomp syscall filtering active */
+#define TIF_SECCOMP 8 /* seccomp syscall filtering active */
+#define TIF_NEED_RESCHED_LAZY 7
#define TIF_NOHZ 12 /* in adaptive nohz mode */
#define TIF_USING_IWMMXT 17
@@ -149,6 +151,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
#define _TIF_UPROBE (1 << TIF_UPROBE)
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
@@ -164,7 +167,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
* Change these and you break ASM code in entry-common.S
*/
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
- _TIF_NOTIFY_RESUME | _TIF_UPROBE)
+ _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
+ _TIF_NEED_RESCHED_LAZY)
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_THREAD_INFO_H */
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index c773b829ee8ee..f3a0e1cd1f048 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -53,6 +53,7 @@ int main(void)
BLANK();
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count));
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 858d4e5415326..e917b3da4b28a 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -211,13 +211,20 @@ __irq_svc:
svc_entry
irq_handler
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
- ldr r0, [tsk, #TI_FLAGS] @ get flags
teq r8, #0 @ if preempt count != 0
+ bne 1f @ return from exeption
+ ldr r0, [tsk, #TI_FLAGS] @ get flags
+ tst r0, #_TIF_NEED_RESCHED @ if NEED_RESCHED is set
+ blne svc_preempt @ preempt!
+
+ ldr r8, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
+ teq r8, #0 @ if preempt lazy count != 0
movne r0, #0 @ force flags to 0
- tst r0, #_TIF_NEED_RESCHED
+ tst r0, #_TIF_NEED_RESCHED_LAZY
blne svc_preempt
+1:
#endif
svc_exit r5, irq = 1 @ return from exception
@@ -226,14 +233,20 @@ ENDPROC(__irq_svc)
.ltorg
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
svc_preempt:
mov r8, lr
1: bl preempt_schedule_irq @ irq en/disable is done inside
ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
tst r0, #_TIF_NEED_RESCHED
+ bne 1b
+ tst r0, #_TIF_NEED_RESCHED_LAZY
reteq r8 @ go again
- b 1b
+ ldr r0, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
+ teq r0, #0 @ if preempt lazy count != 0
+ beq 1b
+ ret r8 @ go again
+
#endif
__und_fault:
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 271cb8a1eba1e..fd039b1b37319 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -53,7 +53,9 @@ __ret_fast_syscall:
cmp r2, #TASK_SIZE
blne addr_limit_check_failed
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
- tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
+ tst r1, #((_TIF_SYSCALL_WORK | _TIF_WORK_MASK) & ~_TIF_SECCOMP)
+ bne fast_work_pending
+ tst r1, #_TIF_SECCOMP
bne fast_work_pending
@@ -90,8 +92,11 @@ __ret_fast_syscall:
cmp r2, #TASK_SIZE
blne addr_limit_check_failed
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
- tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
+ tst r1, #((_TIF_SYSCALL_WORK | _TIF_WORK_MASK) & ~_TIF_SECCOMP)
+ bne do_slower_path
+ tst r1, #_TIF_SECCOMP
beq no_work_pending
+do_slower_path:
UNWIND(.fnend )
ENDPROC(ret_fast_syscall)
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index ab2568996ddb0..50d43ce823bfb 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -649,7 +649,8 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
*/
trace_hardirqs_off();
do {
- if (likely(thread_flags & _TIF_NEED_RESCHED)) {
+ if (likely(thread_flags & (_TIF_NEED_RESCHED |
+ _TIF_NEED_RESCHED_LAZY))) {
schedule();
} else {
if (unlikely(!user_mode(regs)))
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 46e1be9e57a81..581caf6493a94 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -682,11 +682,9 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
break;
case IPI_CPU_BACKTRACE:
- printk_nmi_enter();
irq_enter();
nmi_cpu_backtrace(regs);
irq_exit();
- printk_nmi_exit();
break;
default:
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index c053abd1fb539..abb7dd7e656fd 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -248,6 +248,8 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
#ifdef CONFIG_PREEMPT
#define S_PREEMPT " PREEMPT"
+#elif defined(CONFIG_PREEMPT_RT)
+#define S_PREEMPT " PREEMPT_RT"
#else
#define S_PREEMPT ""
#endif
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 0ee8fc4b4672c..dc8f152f35566 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -135,13 +135,13 @@ flush_levels:
and r1, r1, #7 @ mask of the bits for current cache only
cmp r1, #2 @ see what cache we have at this level
blt skip @ skip if no cache, or just i-cache
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
save_and_disable_irqs_notrace r9 @ make cssr&csidr read atomic
#endif
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
isb @ isb to sych the new cssr&csidr
mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
restore_irqs_notrace r9
#endif
and r2, r1, #7 @ extract the length of the cache lines
diff --git a/arch/arm/mm/cache-v7m.S b/arch/arm/mm/cache-v7m.S
index a0035c426ce63..1bc3a0a507539 100644
--- a/arch/arm/mm/cache-v7m.S
+++ b/arch/arm/mm/cache-v7m.S
@@ -183,13 +183,13 @@ flush_levels:
and r1, r1, #7 @ mask of the bits for current cache only
cmp r1, #2 @ see what cache we have at this level
blt skip @ skip if no cache, or just i-cache
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
save_and_disable_irqs_notrace r9 @ make cssr&csidr read atomic
#endif
write_csselr r10, r1 @ set current cache level
isb @ isb to sych the new cssr&csidr
read_ccsidr r1 @ read the new csidr
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
restore_irqs_notrace r9
#endif
and r2, r1, #7 @ extract the length of the cache lines
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index bd0f4821f7e11..865fd8fbfe59c 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -414,6 +414,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
if (addr < TASK_SIZE)
return do_page_fault(addr, fsr, regs);
+ if (interrupts_enabled(regs))
+ local_irq_enable();
+
if (user_mode(regs))
goto bad_area;
@@ -481,6 +484,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
static int
do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
+ if (interrupts_enabled(regs))
+ local_irq_enable();
+
do_bad_area(addr, fsr, regs);
return 0;
}
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index a76f8ace9ce66..eb4a361d47d7b 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -31,6 +31,11 @@ static inline pte_t get_fixmap_pte(unsigned long vaddr)
return *ptep;
}
+static unsigned int fixmap_idx(int type)
+{
+ return FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
+}
+
void *kmap(struct page *page)
{
might_sleep();
@@ -51,12 +56,13 @@ EXPORT_SYMBOL(kunmap);
void *kmap_atomic(struct page *page)
{
+ pte_t pte = mk_pte(page, kmap_prot);
unsigned int idx;
unsigned long vaddr;
void *kmap;
int type;
- preempt_disable();
+ preempt_disable_nort();
pagefault_disable();
if (!PageHighMem(page))
return page_address(page);
@@ -76,7 +82,7 @@ void *kmap_atomic(struct page *page)
type = kmap_atomic_idx_push();
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
+ idx = fixmap_idx(type);
vaddr = __fix_to_virt(idx);
#ifdef CONFIG_DEBUG_HIGHMEM
/*
@@ -90,7 +96,10 @@ void *kmap_atomic(struct page *page)
* in place, so the contained TLB flush ensures the TLB is updated
* with the new mapping.
*/
- set_fixmap_pte(idx, mk_pte(page, kmap_prot));
+#ifdef CONFIG_PREEMPT_RT
+ current->kmap_pte[type] = pte;
+#endif
+ set_fixmap_pte(idx, pte);
return (void *)vaddr;
}
@@ -103,44 +112,75 @@ void __kunmap_atomic(void *kvaddr)
if (kvaddr >= (void *)FIXADDR_START) {
type = kmap_atomic_idx();
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
+ idx = fixmap_idx(type);
if (cache_is_vivt())
__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
+#ifdef CONFIG_PREEMPT_RT
+ current->kmap_pte[type] = __pte(0);
+#endif
#ifdef CONFIG_DEBUG_HIGHMEM
BUG_ON(vaddr != __fix_to_virt(idx));
- set_fixmap_pte(idx, __pte(0));
#else
(void) idx; /* to kill a warning */
#endif
+ set_fixmap_pte(idx, __pte(0));
kmap_atomic_idx_pop();
} else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) {
/* this address was obtained through kmap_high_get() */
kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)]));
}
pagefault_enable();
- preempt_enable();
+ preempt_enable_nort();
}
EXPORT_SYMBOL(__kunmap_atomic);
void *kmap_atomic_pfn(unsigned long pfn)
{
+ pte_t pte = pfn_pte(pfn, kmap_prot);
unsigned long vaddr;
int idx, type;
struct page *page = pfn_to_page(pfn);
- preempt_disable();
+ preempt_disable_nort();
pagefault_disable();
if (!PageHighMem(page))
return page_address(page);
type = kmap_atomic_idx_push();
- idx = FIX_KMAP_BEGIN + type + KM_TYPE_NR * smp_processor_id();
+ idx = fixmap_idx(type);
vaddr = __fix_to_virt(idx);
#ifdef CONFIG_DEBUG_HIGHMEM
BUG_ON(!pte_none(get_fixmap_pte(vaddr)));
#endif
- set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot));
+#ifdef CONFIG_PREEMPT_RT
+ current->kmap_pte[type] = pte;
+#endif
+ set_fixmap_pte(idx, pte);
return (void *)vaddr;
}
+#if defined CONFIG_PREEMPT_RT
+void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p)
+{
+ int i;
+
+ /*
+ * Clear @prev's kmap_atomic mappings
+ */
+ for (i = 0; i < prev_p->kmap_idx; i++) {
+ int idx = fixmap_idx(i);
+
+ set_fixmap_pte(idx, __pte(0));
+ }
+ /*
+ * Restore @next_p's kmap_atomic mappings
+ */
+ for (i = 0; i < next_p->kmap_idx; i++) {
+ int idx = fixmap_idx(i);
+
+ if (!pte_none(next_p->kmap_pte[i]))
+ set_fixmap_pte(idx, next_p->kmap_pte[i]);
+ }
+}
+#endif
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index f8157e9228ca9..b1bf607fcf6ac 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -34,32 +34,32 @@ config ARM64
select ARCH_HAS_TEARDOWN_DMA_OPS if IOMMU_SUPPORT
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAVE_NMI_SAFE_CMPXCHG
- select ARCH_INLINE_READ_LOCK if !PREEMPT
- select ARCH_INLINE_READ_LOCK_BH if !PREEMPT
- select ARCH_INLINE_READ_LOCK_IRQ if !PREEMPT
- select ARCH_INLINE_READ_LOCK_IRQSAVE if !PREEMPT
- select ARCH_INLINE_READ_UNLOCK if !PREEMPT
- select ARCH_INLINE_READ_UNLOCK_BH if !PREEMPT
- select ARCH_INLINE_READ_UNLOCK_IRQ if !PREEMPT
- select ARCH_INLINE_READ_UNLOCK_IRQRESTORE if !PREEMPT
- select ARCH_INLINE_WRITE_LOCK if !PREEMPT
- select ARCH_INLINE_WRITE_LOCK_BH if !PREEMPT
- select ARCH_INLINE_WRITE_LOCK_IRQ if !PREEMPT
- select ARCH_INLINE_WRITE_LOCK_IRQSAVE if !PREEMPT
- select ARCH_INLINE_WRITE_UNLOCK if !PREEMPT
- select ARCH_INLINE_WRITE_UNLOCK_BH if !PREEMPT
- select ARCH_INLINE_WRITE_UNLOCK_IRQ if !PREEMPT
- select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE if !PREEMPT
- select ARCH_INLINE_SPIN_TRYLOCK if !PREEMPT
- select ARCH_INLINE_SPIN_TRYLOCK_BH if !PREEMPT
- select ARCH_INLINE_SPIN_LOCK if !PREEMPT
- select ARCH_INLINE_SPIN_LOCK_BH if !PREEMPT
- select ARCH_INLINE_SPIN_LOCK_IRQ if !PREEMPT
- select ARCH_INLINE_SPIN_LOCK_IRQSAVE if !PREEMPT
- select ARCH_INLINE_SPIN_UNLOCK if !PREEMPT
- select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPT
- select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPT
- select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPT
+ select ARCH_INLINE_READ_LOCK if !PREEMPTION
+ select ARCH_INLINE_READ_LOCK_BH if !PREEMPTION
+ select ARCH_INLINE_READ_LOCK_IRQ if !PREEMPTION
+ select ARCH_INLINE_READ_LOCK_IRQSAVE if !PREEMPTION
+ select ARCH_INLINE_READ_UNLOCK if !PREEMPTION
+ select ARCH_INLINE_READ_UNLOCK_BH if !PREEMPTION
+ select ARCH_INLINE_READ_UNLOCK_IRQ if !PREEMPTION
+ select ARCH_INLINE_READ_UNLOCK_IRQRESTORE if !PREEMPTION
+ select ARCH_INLINE_WRITE_LOCK if !PREEMPTION
+ select ARCH_INLINE_WRITE_LOCK_BH if !PREEMPTION
+ select ARCH_INLINE_WRITE_LOCK_IRQ if !PREEMPTION
+ select ARCH_INLINE_WRITE_LOCK_IRQSAVE if !PREEMPTION
+ select ARCH_INLINE_WRITE_UNLOCK if !PREEMPTION
+ select ARCH_INLINE_WRITE_UNLOCK_BH if !PREEMPTION
+ select ARCH_INLINE_WRITE_UNLOCK_IRQ if !PREEMPTION
+ select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE if !PREEMPTION
+ select ARCH_INLINE_SPIN_TRYLOCK if !PREEMPTION
+ select ARCH_INLINE_SPIN_TRYLOCK_BH if !PREEMPTION
+ select ARCH_INLINE_SPIN_LOCK if !PREEMPTION
+ select ARCH_INLINE_SPIN_LOCK_BH if !PREEMPTION
+ select ARCH_INLINE_SPIN_LOCK_IRQ if !PREEMPTION
+ select ARCH_INLINE_SPIN_LOCK_IRQSAVE if !PREEMPTION
+ select ARCH_INLINE_SPIN_UNLOCK if !PREEMPTION
+ select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPTION
+ select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPTION
+ select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
select ARCH_KEEP_MEMBLOCK
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_USE_QUEUED_RWLOCKS
@@ -68,6 +68,7 @@ config ARM64
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_INT128 if GCC_VERSION >= 50000 || CC_IS_CLANG
select ARCH_SUPPORTS_NUMA_BALANCING
+ select ARCH_SUPPORTS_RT
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select ARCH_WANT_FRAME_POINTERS
@@ -158,6 +159,7 @@ config ARM64
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_LAZY
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_FUNCTION_ARG_ACCESS_API
select HAVE_RCU_TABLE_FREE
diff --git a/arch/arm64/crypto/sha256-glue.c b/arch/arm64/crypto/sha256-glue.c
index e273faca924f9..999da59f03a9d 100644
--- a/arch/arm64/crypto/sha256-glue.c
+++ b/arch/arm64/crypto/sha256-glue.c
@@ -97,7 +97,7 @@ static int sha256_update_neon(struct shash_desc *desc, const u8 *data,
* input when running on a preemptible kernel, but process the
* data block by block instead.
*/
- if (IS_ENABLED(CONFIG_PREEMPT) &&
+ if (IS_ENABLED(CONFIG_PREEMPTION) &&
chunk + sctx->count % SHA256_BLOCK_SIZE > SHA256_BLOCK_SIZE)
chunk = SHA256_BLOCK_SIZE -
sctx->count % SHA256_BLOCK_SIZE;
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index b8cf7c85ffa2a..2cc0dd8bd9f78 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -699,8 +699,8 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
* where is optional, and marks the point where execution will resume
* after a yield has been performed. If omitted, execution resumes right after
* the endif_yield_neon invocation. Note that the entire sequence, including
- * the provided patchup code, will be omitted from the image if CONFIG_PREEMPT
- * is not defined.
+ * the provided patchup code, will be omitted from the image if
+ * CONFIG_PREEMPTION is not defined.
*
* As a convenience, in the case where no patchup code is required, the above
* sequence may be abbreviated to
@@ -728,7 +728,7 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
.endm
.macro if_will_cond_yield_neon
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
get_current_task x0
ldr x0, [x0, #TSK_TI_PREEMPT]
sub x0, x0, #PREEMPT_DISABLE_OFFSET
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index befe37d4bc0e5..53d846f1bfe70 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -91,6 +91,7 @@ alternative_cb_end
void kvm_update_va_mask(struct alt_instr *alt,
__le32 *origptr, __le32 *updptr, int nr_inst);
+void kvm_compute_layout(void);
static inline unsigned long __kern_hyp_va(unsigned long v)
{
diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h
index d499516470149..3b19db2db1ed0 100644
--- a/arch/arm64/include/asm/preempt.h
+++ b/arch/arm64/include/asm/preempt.h
@@ -70,20 +70,43 @@ static inline bool __preempt_count_dec_and_test(void)
* interrupt occurring between the non-atomic READ_ONCE/WRITE_ONCE
* pair.
*/
- return !pc || !READ_ONCE(ti->preempt_count);
+ if (!pc || !READ_ONCE(ti->preempt_count))
+ return true;
+#ifdef CONFIG_PREEMPT_LAZY
+ if ((pc & ~PREEMPT_NEED_RESCHED))
+ return false;
+ if (current_thread_info()->preempt_lazy_count)
+ return false;
+ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
+#else
+ return false;
+#endif
}
static inline bool should_resched(int preempt_offset)
{
+#ifdef CONFIG_PREEMPT_LAZY
+ u64 pc = READ_ONCE(current_thread_info()->preempt_count);
+ if (pc == preempt_offset)
+ return true;
+
+ if ((pc & ~PREEMPT_NEED_RESCHED) != preempt_offset)
+ return false;
+
+ if (current_thread_info()->preempt_lazy_count)
+ return false;
+ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
+#else
u64 pc = READ_ONCE(current_thread_info()->preempt_count);
return pc == preempt_offset;
+#endif
}
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
void preempt_schedule(void);
#define __preempt_schedule() preempt_schedule()
void preempt_schedule_notrace(void);
#define __preempt_schedule_notrace() preempt_schedule_notrace()
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
#endif /* __ASM_PREEMPT_H */
diff --git a/arch/arm64/include/asm/spinlock_types.h b/arch/arm64/include/asm/spinlock_types.h
index 18782f0c47212..6672b05350b4e 100644
--- a/arch/arm64/include/asm/spinlock_types.h
+++ b/arch/arm64/include/asm/spinlock_types.h
@@ -5,10 +5,6 @@
#ifndef __ASM_SPINLOCK_TYPES_H
#define __ASM_SPINLOCK_TYPES_H
-#if !defined(__LINUX_SPINLOCK_TYPES_H) && !defined(__ASM_SPINLOCK_H)
-# error "please don't include this file directly"
-#endif
-
#include
#include
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index f0cec4160136e..33328454d531e 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -29,6 +29,7 @@ struct thread_info {
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
u64 ttbr0; /* saved TTBR0_EL1 */
#endif
+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
union {
u64 preempt_count; /* 0 => preemptible, <0 => bug */
struct {
@@ -63,6 +64,7 @@ void arch_release_task_struct(struct task_struct *tsk);
#define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */
#define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */
#define TIF_FSCHECK 5 /* Check FS is USER_DS on return */
+#define TIF_NEED_RESCHED_LAZY 6
#define TIF_NOHZ 7
#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
@@ -83,6 +85,7 @@ void arch_release_task_struct(struct task_struct *tsk);
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_FOREIGN_FPSTATE (1 << TIF_FOREIGN_FPSTATE)
+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
#define _TIF_NOHZ (1 << TIF_NOHZ)
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
@@ -96,8 +99,9 @@ void arch_release_task_struct(struct task_struct *tsk);
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
_TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
- _TIF_UPROBE | _TIF_FSCHECK)
+ _TIF_UPROBE | _TIF_FSCHECK | _TIF_NEED_RESCHED_LAZY)
+#define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
_TIF_NOHZ | _TIF_SYSCALL_EMU)
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 214685760e1c3..f7975b079551e 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -30,6 +30,7 @@ int main(void)
BLANK();
DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags));
DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count));
+ DEFINE(TSK_TI_PREEMPT_LAZY, offsetof(struct task_struct, thread_info.preempt_lazy_count));
DEFINE(TSK_TI_ADDR_LIMIT, offsetof(struct task_struct, thread_info.addr_limit));
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
DEFINE(TSK_TI_TTBR0, offsetof(struct task_struct, thread_info.ttbr0));
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index cf3bd2976e574..b25f633650809 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -669,7 +669,7 @@ el1_irq:
irq_handler
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count
alternative_if ARM64_HAS_IRQ_PRIO_MASKING
/*
@@ -679,9 +679,18 @@ alternative_if ARM64_HAS_IRQ_PRIO_MASKING
mrs x0, daif
orr x24, x24, x0
alternative_else_nop_endif
- cbnz x24, 1f // preempt count != 0 || NMI return path
- bl arm64_preempt_schedule_irq // irq en/disable is done inside
+
+ cbz x24, 1f // (need_resched + count) == 0
+ cbnz w24, 2f // count != 0
+
+ ldr w24, [tsk, #TSK_TI_PREEMPT_LAZY] // get preempt lazy count
+ cbnz w24, 2f // preempt lazy count != 0
+
+ ldr x0, [tsk, #TSK_TI_FLAGS] // get flags
+ tbz x0, #TIF_NEED_RESCHED_LAZY, 2f // needs rescheduling?
1:
+ bl arm64_preempt_schedule_irq // irq en/disable is done inside
+2:
#endif
#ifdef CONFIG_ARM64_PSEUDO_NMI
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 1765e5284994f..3cc477c729236 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -213,6 +213,16 @@ static void sve_free(struct task_struct *task)
__sve_free(task);
}
+static void *sve_free_atomic(struct task_struct *task)
+{
+ void *sve_state = task->thread.sve_state;
+
+ WARN_ON(test_tsk_thread_flag(task, TIF_SVE));
+
+ task->thread.sve_state = NULL;
+ return sve_state;
+}
+
/*
* TIF_SVE controls whether a task can use SVE without trapping while
* in userspace, and also the way a task's FPSIMD/SVE state is stored
@@ -1010,6 +1020,7 @@ void fpsimd_thread_switch(struct task_struct *next)
void fpsimd_flush_thread(void)
{
int vl, supported_vl;
+ void *mem = NULL;
if (!system_supports_fpsimd())
return;
@@ -1022,7 +1033,7 @@ void fpsimd_flush_thread(void)
if (system_supports_sve()) {
clear_thread_flag(TIF_SVE);
- sve_free(current);
+ mem = sve_free_atomic(current);
/*
* Reset the task vector length as required.
@@ -1056,6 +1067,7 @@ void fpsimd_flush_thread(void)
}
put_cpu_fpsimd_context();
+ kfree(mem);
}
/*
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index dd2cdc0d5be20..94dbce6b27195 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -910,7 +910,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs,
/* Check valid user FS if needed */
addr_limit_user_check();
- if (thread_flags & _TIF_NEED_RESCHED) {
+ if (thread_flags & _TIF_NEED_RESCHED_MASK) {
/* Unmask Debug and SError for the next task */
local_daif_restore(DAIF_PROCCTX_NOIRQ);
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index dc9fe879c2793..02d41eae3da86 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include
#include
@@ -39,6 +40,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -408,6 +410,8 @@ static void __init hyp_mode_check(void)
"CPU: CPUs started in inconsistent modes");
else
pr_info("CPU: All CPU(s) started at EL1\n");
+ if (IS_ENABLED(CONFIG_KVM_ARM_HOST))
+ kvm_compute_layout();
}
void __init smp_cpus_done(unsigned int max_cpus)
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 34739e80211bc..0bf934257744d 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -143,9 +143,12 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
#ifdef CONFIG_PREEMPT
#define S_PREEMPT " PREEMPT"
+#elif defined(CONFIG_PREEMPT_RT)
+#define S_PREEMPT " PREEMPT_RT"
#else
#define S_PREEMPT ""
#endif
+
#define S_SMP " SMP"
static int __die(const char *str, int err, struct pt_regs *regs)
diff --git a/arch/arm64/kvm/va_layout.c b/arch/arm64/kvm/va_layout.c
index 2cf7d4b606c38..dab1fea4752aa 100644
--- a/arch/arm64/kvm/va_layout.c
+++ b/arch/arm64/kvm/va_layout.c
@@ -22,7 +22,7 @@ static u8 tag_lsb;
static u64 tag_val;
static u64 va_mask;
-static void compute_layout(void)
+__init void kvm_compute_layout(void)
{
phys_addr_t idmap_addr = __pa_symbol(__hyp_idmap_text_start);
u64 hyp_va_msb;
@@ -110,9 +110,6 @@ void __init kvm_update_va_mask(struct alt_instr *alt,
BUG_ON(nr_inst != 5);
- if (!has_vhe() && !va_mask)
- compute_layout();
-
for (i = 0; i < nr_inst; i++) {
u32 rd, rn, insn, oinsn;
@@ -156,9 +153,6 @@ void kvm_patch_vector_branch(struct alt_instr *alt,
return;
}
- if (!va_mask)
- compute_layout();
-
/*
* Compute HYP VA by using the same computation as kern_hyp_va()
*/
diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S
index 4332a10aec6c7..fb154d19625bc 100644
--- a/arch/c6x/kernel/entry.S
+++ b/arch/c6x/kernel/entry.S
@@ -18,7 +18,7 @@
#define DP B14
#define SP B15
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
#define resume_kernel restore_all
#endif
@@ -287,7 +287,7 @@ work_notifysig:
;; is a little bit different
;;
ENTRY(ret_from_exception)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
MASK_INT B2
#endif
@@ -557,7 +557,7 @@ ENDPROC(_nmi_handler)
;;
;; Jump to schedule() then return to ret_from_isr
;;
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
resume_kernel:
GET_THREAD_INFO A12
LDW .D1T1 *+A12(THREAD_INFO_PREEMPT_COUNT),A1
@@ -582,7 +582,7 @@ preempt_schedule:
B .S2 preempt_schedule_irq
#endif
ADDKPC .S2 preempt_schedule,B3,4
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
ENTRY(enable_exception)
DINT
diff --git a/arch/csky/kernel/entry.S b/arch/csky/kernel/entry.S
index a7a5b67df8989..0077063280000 100644
--- a/arch/csky/kernel/entry.S
+++ b/arch/csky/kernel/entry.S
@@ -277,7 +277,7 @@ ENTRY(csky_irq)
zero_fp
psrset ee
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
mov r9, sp /* Get current stack pointer */
bmaski r10, THREAD_SHIFT
andn r9, r10 /* Get thread_info */
@@ -294,7 +294,7 @@ ENTRY(csky_irq)
mov a0, sp
jbsr csky_do_IRQ
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
subi r12, 1
stw r12, (r9, TINFO_PREEMPT)
cmpnei r12, 0
diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S
index 4ade5f8299bae..c6e289b5f1f28 100644
--- a/arch/h8300/kernel/entry.S
+++ b/arch/h8300/kernel/entry.S
@@ -284,12 +284,12 @@ badsys:
mov.l er0,@(LER0:16,sp)
bra resume_userspace
-#if !defined(CONFIG_PREEMPT)
+#if !defined(CONFIG_PREEMPTION)
#define resume_kernel restore_all
#endif
ret_from_exception:
-#if defined(CONFIG_PREEMPT)
+#if defined(CONFIG_PREEMPTION)
orc #0xc0,ccr
#endif
ret_from_interrupt:
@@ -319,7 +319,7 @@ work_resched:
restore_all:
RESTORE_ALL /* Does RTE */
-#if defined(CONFIG_PREEMPT)
+#if defined(CONFIG_PREEMPTION)
resume_kernel:
mov.l @(TI_PRE_COUNT:16,er4),er0
bne restore_all:8
diff --git a/arch/hexagon/include/asm/spinlock_types.h b/arch/hexagon/include/asm/spinlock_types.h
index 19d233497ba52..de72fb23016dc 100644
--- a/arch/hexagon/include/asm/spinlock_types.h
+++ b/arch/hexagon/include/asm/spinlock_types.h
@@ -8,10 +8,6 @@
#ifndef _ASM_SPINLOCK_TYPES_H
#define _ASM_SPINLOCK_TYPES_H
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
typedef struct {
volatile unsigned int lock;
} arch_spinlock_t;
diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S
index 4023fdbea4902..554371d92bed6 100644
--- a/arch/hexagon/kernel/vm_entry.S
+++ b/arch/hexagon/kernel/vm_entry.S
@@ -265,12 +265,12 @@ event_dispatch:
* should be in the designated register (usually R19)
*
* If we were in kernel mode, we don't need to check scheduler
- * or signals if CONFIG_PREEMPT is not set. If set, then it has
+ * or signals if CONFIG_PREEMPTION is not set. If set, then it has
* to jump to a need_resched kind of block.
- * BTW, CONFIG_PREEMPT is not supported yet.
+ * BTW, CONFIG_PREEMPTION is not supported yet.
*/
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
R0 = #VM_INT_DISABLE
trap1(#HVM_TRAP1_VMSETIE)
#endif
diff --git a/arch/ia64/include/asm/spinlock_types.h b/arch/ia64/include/asm/spinlock_types.h
index 6e345fefcdcab..681408d6816fb 100644
--- a/arch/ia64/include/asm/spinlock_types.h
+++ b/arch/ia64/include/asm/spinlock_types.h
@@ -2,10 +2,6 @@
#ifndef _ASM_IA64_SPINLOCK_TYPES_H
#define _ASM_IA64_SPINLOCK_TYPES_H
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
typedef struct {
volatile unsigned int lock;
} arch_spinlock_t;
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index a9992be5718b8..2ac9263315000 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -670,12 +670,12 @@ GLOBAL_ENTRY(ia64_leave_syscall)
*
* p6 controls whether current_thread_info()->flags needs to be check for
* extra work. We always check for extra work when returning to user-level.
- * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
+ * With CONFIG_PREEMPTION, we also check for extra work when the preempt_count
* is 0. After extra work processing has been completed, execution
* resumes at ia64_work_processed_syscall with p6 set to 1 if the extra-work-check
* needs to be redone.
*/
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
RSM_PSR_I(p0, r2, r18) // disable interrupts
cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
@@ -685,7 +685,7 @@ GLOBAL_ENTRY(ia64_leave_syscall)
(pUStk) mov r21=0 // r21 <- 0
;;
cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
-#else /* !CONFIG_PREEMPT */
+#else /* !CONFIG_PREEMPTION */
RSM_PSR_I(pUStk, r2, r18)
cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
@@ -814,12 +814,12 @@ GLOBAL_ENTRY(ia64_leave_kernel)
*
* p6 controls whether current_thread_info()->flags needs to be check for
* extra work. We always check for extra work when returning to user-level.
- * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
+ * With CONFIG_PREEMPTION, we also check for extra work when the preempt_count
* is 0. After extra work processing has been completed, execution
* resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
* needs to be redone.
*/
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
RSM_PSR_I(p0, r17, r31) // disable interrupts
cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
@@ -1120,7 +1120,7 @@ skip_rbs_switch:
/*
* On entry:
- * r20 = ¤t->thread_info->pre_count (if CONFIG_PREEMPT)
+ * r20 = ¤t->thread_info->pre_count (if CONFIG_PREEMPTION)
* r31 = current->thread_info->flags
* On exit:
* p6 = TRUE if work-pending-check needs to be redone
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index b8356edbde659..a6d6a0556f089 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -841,7 +841,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
return 1;
}
-#if !defined(CONFIG_PREEMPT)
+#if !defined(CONFIG_PREEMPTION)
if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) {
/* Boost up -- we can execute copied instructions directly */
ia64_psr(regs)->ri = p->ainsn.slot;
diff --git a/arch/m68k/coldfire/entry.S b/arch/m68k/coldfire/entry.S
index 52d312d5b4d4f..d43a02795a4a4 100644
--- a/arch/m68k/coldfire/entry.S
+++ b/arch/m68k/coldfire/entry.S
@@ -108,7 +108,7 @@ ret_from_exception:
btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel */
jeq Luser_return /* if so, skip resched, signals */
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
movel %sp,%d1 /* get thread_info pointer */
andl #-THREAD_SIZE,%d1 /* at base of kernel stack */
movel %d1,%a0
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index 4e1b567becd6a..253f2b702b4c0 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -728,7 +728,7 @@ no_intr_resched:
bri 6f;
/* MS: Return to kernel state. */
2:
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
lwi r11, CURRENT_TASK, TS_THREAD_INFO;
/* MS: get preempt_count from thread info */
lwi r5, r11, TI_PREEMPT_COUNT;
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c1c3da4fc6674..31ed84ffcd05c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2586,7 +2586,7 @@ config MIPS_CRC_SUPPORT
#
config HIGHMEM
bool "High Memory Support"
- depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA
+ depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA && !PREEMPT_RT
config CPU_SUPPORTS_HIGHMEM
bool
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index feb069cbf44e8..655f40ddb6d1e 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -63,7 +63,7 @@
.endm
.macro local_irq_disable reg=t0
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
lw \reg, TI_PRE_COUNT($28)
addi \reg, \reg, 1
sw \reg, TI_PRE_COUNT($28)
@@ -73,7 +73,7 @@
xori \reg, \reg, 1
mtc0 \reg, CP0_STATUS
irq_disable_hazard
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
lw \reg, TI_PRE_COUNT($28)
addi \reg, \reg, -1
sw \reg, TI_PRE_COUNT($28)
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 5469d43b69668..4849a48afc0f8 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -19,7 +19,7 @@
#include
#include
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
#define resume_kernel restore_all
#else
#define __ret_from_irq ret_from_exception
@@ -27,7 +27,7 @@
.text
.align 5
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
FEXPORT(ret_from_exception)
local_irq_disable # preempt stop
b __ret_from_irq
@@ -53,7 +53,7 @@ resume_userspace:
bnez t0, work_pending
j restore_all
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
resume_kernel:
local_irq_disable
lw t0, TI_PRE_COUNT($28)
diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
index fbd68329737f4..abbb74e46f054 100644
--- a/arch/nds32/Kconfig
+++ b/arch/nds32/Kconfig
@@ -61,7 +61,7 @@ config GENERIC_HWEIGHT
config GENERIC_LOCKBREAK
def_bool y
- depends on PREEMPT
+ depends on PREEMPTION
config TRACE_IRQFLAGS_SUPPORT
def_bool y
diff --git a/arch/nds32/kernel/ex-exit.S b/arch/nds32/kernel/ex-exit.S
index 1df02a7933641..6a2966c2d8c8f 100644
--- a/arch/nds32/kernel/ex-exit.S
+++ b/arch/nds32/kernel/ex-exit.S
@@ -72,7 +72,7 @@
restore_user_regs_last
.endm
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
.macro preempt_stop
.endm
#else
@@ -158,7 +158,7 @@ no_work_pending:
/*
* preemptive kernel
*/
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
resume_kernel:
gie_disable
lwi $t0, [tsk+#TSK_TI_PREEMPT]
diff --git a/arch/nios2/kernel/entry.S b/arch/nios2/kernel/entry.S
index 1e515ccd698e3..3d8d1d0bcb64b 100644
--- a/arch/nios2/kernel/entry.S
+++ b/arch/nios2/kernel/entry.S
@@ -365,7 +365,7 @@ ENTRY(ret_from_interrupt)
ldw r1, PT_ESTATUS(sp) /* check if returning to kernel */
TSTBNZ r1, r1, ESTATUS_EU, Luser_return
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
GET_THREAD_INFO r1
ldw r4, TI_PREEMPT_COUNT(r1)
bne r4, r0, restore_all
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 0c29d6cb2c8df..9b44f06b263ef 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -82,7 +82,7 @@ config STACK_GROWSUP
config GENERIC_LOCKBREAK
bool
default y
- depends on SMP && PREEMPT
+ depends on SMP && PREEMPTION
config ARCH_HAS_ILOG2_U32
bool
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index b96d744969779..9a03e29c87330 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -940,14 +940,14 @@ intr_restore:
rfi
nop
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
# define intr_do_preempt intr_restore
-#endif /* !CONFIG_PREEMPT */
+#endif /* !CONFIG_PREEMPTION */
.import schedule,code
intr_do_resched:
/* Only call schedule on return to userspace. If we're returning
- * to kernel space, we may schedule if CONFIG_PREEMPT, otherwise
+ * to kernel space, we may schedule if CONFIG_PREEMPTION, otherwise
* we jump back to intr_restore.
*/
LDREG PT_IASQ0(%r16), %r20
@@ -979,7 +979,7 @@ intr_do_resched:
* and preempt_count is 0. otherwise, we continue on
* our merry way back to the current running task.
*/
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
.import preempt_schedule_irq,code
intr_do_preempt:
rsm PSW_SM_I, %r0 /* disable interrupts */
@@ -999,7 +999,7 @@ intr_do_preempt:
nop
b,n intr_restore /* ssm PSW_SM_I done by intr_restore */
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
/*
* External interrupts.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2b1033f132109..74c8114b190b0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -106,7 +106,7 @@ config LOCKDEP_SUPPORT
config GENERIC_LOCKBREAK
bool
default y
- depends on SMP && PREEMPT
+ depends on SMP && PREEMPTION
config GENERIC_HWEIGHT
bool
@@ -144,6 +144,7 @@ config PPC
select ARCH_MIGHT_HAVE_PC_SERIO
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_RT
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
select ARCH_WANT_IPC_PARSE_VERSION
@@ -221,6 +222,7 @@ config PPC
select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_LAZY
select HAVE_RCU_TABLE_FREE
select HAVE_MMU_GATHER_PAGE_SIZE
select HAVE_REGS_AND_STACK_ACCESS_API
@@ -398,7 +400,7 @@ menu "Kernel options"
config HIGHMEM
bool "High memory support"
- depends on PPC32
+ depends on PPC32 && !PREEMPT_RT
source "kernel/Kconfig.hz"
diff --git a/arch/powerpc/include/asm/spinlock_types.h b/arch/powerpc/include/asm/spinlock_types.h
index 87adaf13b7e84..7305cb6a53e47 100644
--- a/arch/powerpc/include/asm/spinlock_types.h
+++ b/arch/powerpc/include/asm/spinlock_types.h
@@ -2,10 +2,6 @@
#ifndef _ASM_POWERPC_SPINLOCK_TYPES_H
#define _ASM_POWERPC_SPINLOCK_TYPES_H
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
typedef struct {
volatile unsigned int slock;
} arch_spinlock_t;
diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h
index 1c8460e235838..b1653c160bab9 100644
--- a/arch/powerpc/include/asm/stackprotector.h
+++ b/arch/powerpc/include/asm/stackprotector.h
@@ -24,7 +24,11 @@ static __always_inline void boot_init_stack_canary(void)
unsigned long canary;
/* Try to get a semi random initial value. */
+#ifdef CONFIG_PREEMPT_RT
+ canary = (unsigned long)&canary;
+#else
canary = get_random_canary();
+#endif
canary ^= mftb();
canary ^= LINUX_VERSION_CODE;
canary &= CANARY_MASK;
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 8e1d0195ac366..594fdb569e540 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -30,6 +30,8 @@
struct thread_info {
int preempt_count; /* 0 => preemptable,
<0 => BUG */
+ int preempt_lazy_count; /* 0 => preemptable,
+ <0 => BUG */
unsigned long local_flags; /* private flags for thread */
#ifdef CONFIG_LIVEPATCH
unsigned long *livepatch_sp;
@@ -80,11 +82,12 @@ void arch_setup_new_exec(void);
#define TIF_SINGLESTEP 8 /* singlestepping active */
#define TIF_NOHZ 9 /* in adaptive nohz mode */
#define TIF_SECCOMP 10 /* secure computing */
-#define TIF_RESTOREALL 11 /* Restore all regs (implies NOERROR) */
-#define TIF_NOERROR 12 /* Force successful syscall return */
+
+#define TIF_NEED_RESCHED_LAZY 11 /* lazy rescheduling necessary */
+#define TIF_SYSCALL_TRACEPOINT 12 /* syscall tracepoint instrumentation */
+
#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */
#define TIF_UPROBE 14 /* breakpointed or single-stepping */
-#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */
#define TIF_EMULATE_STACK_STORE 16 /* Is an instruction emulation
for stack store? */
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
@@ -93,6 +96,9 @@ void arch_setup_new_exec(void);
#endif
#define TIF_POLLING_NRFLAG 19 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_32BIT 20 /* 32 bit binary */
+#define TIF_RESTOREALL 21 /* Restore all regs (implies NOERROR) */
+#define TIF_NOERROR 22 /* Force successful syscall return */
+
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<preempt_count */
lwz r0,TI_PREEMPT(r2)
cmpwi 0,r0,0 /* if non-zero, just restore regs and return */
bne restore_kuap
andi. r8,r8,_TIF_NEED_RESCHED
+ bne+ 1f
+ lwz r0,TI_PREEMPT_LAZY(r2)
+ cmpwi 0,r0,0 /* if non-zero, just restore regs and return */
+ bne restore_kuap
+ lwz r0,TI_FLAGS(r2)
+ andi. r0,r0,_TIF_NEED_RESCHED_LAZY
beq+ restore_kuap
+1:
lwz r3,_MSR(r1)
andi. r0,r3,MSR_EE /* interrupts off? */
beq restore_kuap /* don't schedule if so */
@@ -922,7 +931,7 @@ resume_kernel:
*/
bl trace_hardirqs_on
#endif
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
restore_kuap:
kuap_restore r1, r2, r9, r10, r0
@@ -1225,7 +1234,7 @@ global_dbcr0:
#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
do_work: /* r10 contains MSR_KERNEL here */
- andi. r0,r9,_TIF_NEED_RESCHED
+ andi. r0,r9,_TIF_NEED_RESCHED_MASK
beq do_user_signal
do_resched: /* r10 contains MSR_KERNEL here */
@@ -1246,7 +1255,7 @@ recheck:
SYNC
MTMSRD(r10) /* disable interrupts */
lwz r9,TI_FLAGS(r2)
- andi. r0,r9,_TIF_NEED_RESCHED
+ andi. r0,r9,_TIF_NEED_RESCHED_MASK
bne- do_resched
andi. r0,r9,_TIF_USER_WORK_MASK
beq restore_user
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 3fd3ef352e3fd..dfd96e87d7b6c 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -240,7 +240,9 @@ system_call_exit:
ld r9,TI_FLAGS(r12)
li r11,-MAX_ERRNO
- andi. r0,r9,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
+ lis r0,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)@h
+ ori r0,r0,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)@l
+ and. r0,r9,r0
bne- .Lsyscall_exit_work
andi. r0,r8,MSR_FP
@@ -363,25 +365,25 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
/* If TIF_RESTOREALL is set, don't scribble on either r3 or ccr.
If TIF_NOERROR is set, just save r3 as it is. */
- andi. r0,r9,_TIF_RESTOREALL
+ andis. r0,r9,_TIF_RESTOREALL@h
beq+ 0f
REST_NVGPRS(r1)
b 2f
0: cmpld r3,r11 /* r11 is -MAX_ERRNO */
blt+ 1f
- andi. r0,r9,_TIF_NOERROR
+ andis. r0,r9,_TIF_NOERROR@h
bne- 1f
ld r5,_CCR(r1)
neg r3,r3
oris r5,r5,0x1000 /* Set SO bit in CR */
std r5,_CCR(r1)
1: std r3,GPR3(r1)
-2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
+2: andis. r0,r9,(_TIF_PERSYSCALL_MASK)@h
beq 4f
/* Clear per-syscall TIF flags if any are set. */
- li r11,_TIF_PERSYSCALL_MASK
+ lis r11,(_TIF_PERSYSCALL_MASK)@h
addi r12,r12,TI_FLAGS
3: ldarx r10,0,r12
andc r10,r10,r11
@@ -786,7 +788,7 @@ _GLOBAL(ret_from_except_lite)
bl restore_math
b restore
#endif
-1: andi. r0,r4,_TIF_NEED_RESCHED
+1: andi. r0,r4,_TIF_NEED_RESCHED_MASK
beq 2f
bl restore_interrupts
SCHEDULE_USER
@@ -846,12 +848,20 @@ resume_kernel:
bne- 0b
1:
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
/* Check if we need to preempt */
+ lwz r8,TI_PREEMPT(r9)
+ cmpwi 0,r8,0 /* if non-zero, just restore regs and return */
+ bne restore
andi. r0,r4,_TIF_NEED_RESCHED
+ bne+ check_count
+
+ andi. r0,r4,_TIF_NEED_RESCHED_LAZY
beq+ restore
+ lwz r8,TI_PREEMPT_LAZY(r9)
+
/* Check that preempt_count() == 0 and interrupts are enabled */
- lwz r8,TI_PREEMPT(r9)
+check_count:
cmpwi cr0,r8,0
bne restore
ld r0,SOFTE(r1)
@@ -877,7 +887,7 @@ resume_kernel:
li r10,MSR_RI
mtmsrd r10,1 /* Update machine state */
#endif /* CONFIG_PPC_BOOK3E */
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
.globl fast_exc_return_irq
fast_exc_return_irq:
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index add67498c126b..201ddd5d3f156 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -679,10 +679,12 @@ void *mcheckirq_ctx[NR_CPUS] __read_mostly;
void *softirq_ctx[NR_CPUS] __read_mostly;
void *hardirq_ctx[NR_CPUS] __read_mostly;
+#ifndef CONFIG_PREEMPT_RT
void do_softirq_own_stack(void)
{
call_do_softirq(softirq_ctx[smp_processor_id()]);
}
+#endif
irq_hw_number_t virq_to_hw(unsigned int virq)
{
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 82df4b09e79f4..4af2ef8783619 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -37,6 +37,7 @@
* We store the saved ksp_limit in the unused part
* of the STACK_FRAME_OVERHEAD
*/
+#ifndef CONFIG_PREEMPT_RT
_GLOBAL(call_do_softirq)
mflr r0
stw r0,4(r1)
@@ -52,6 +53,7 @@ _GLOBAL(call_do_softirq)
stw r10,THREAD+KSP_LIMIT(r2)
mtlr r0
blr
+#endif
/*
* void call_do_irq(struct pt_regs *regs, void *sp);
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 9bc0aa9aeb654..9bce8e23f33eb 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -27,6 +27,7 @@
.text
+#ifndef CONFIG_PREEMPT_RT
_GLOBAL(call_do_softirq)
mflr r0
std r0,16(r1)
@@ -37,6 +38,7 @@ _GLOBAL(call_do_softirq)
ld r0,16(r1)
mtlr r0
blr
+#endif
_GLOBAL(call_do_irq)
mflr r0
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 014ff0701f245..b98d5bc68a886 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -171,7 +171,6 @@ extern void panic_flush_kmsg_start(void)
extern void panic_flush_kmsg_end(void)
{
- printk_safe_flush_on_panic();
kmsg_dump(KMSG_DUMP_PANIC);
bust_spinlocks(0);
debug_locks_off();
@@ -261,12 +260,17 @@ static char *get_mmu_str(void)
static int __die(const char *str, struct pt_regs *regs, long err)
{
+ const char *pr = "";
+
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
+ if (IS_ENABLED(CONFIG_PREEMPTION))
+ pr = IS_ENABLED(CONFIG_PREEMPT_RT) ? " PREEMPT_RT" : " PREEMPT";
+
printk("%s PAGE_SIZE=%luK%s%s%s%s%s%s %s\n",
IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN) ? "LE" : "BE",
PAGE_SIZE / 1024, get_mmu_str(),
- IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "",
+ pr,
IS_ENABLED(CONFIG_SMP) ? " SMP" : "",
IS_ENABLED(CONFIG_SMP) ? (" NR_CPUS=" __stringify(NR_CPUS)) : "",
debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "",
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c
index af3c15a1d41eb..8ae46c5945d07 100644
--- a/arch/powerpc/kernel/watchdog.c
+++ b/arch/powerpc/kernel/watchdog.c
@@ -181,11 +181,6 @@ static void watchdog_smp_panic(int cpu, u64 tb)
wd_smp_unlock(&flags);
- printk_safe_flush();
- /*
- * printk_safe_flush() seems to require another print
- * before anything actually goes out to console.
- */
if (sysctl_hardlockup_all_cpu_backtrace)
trigger_allbutself_cpu_backtrace();
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index 711fca9bc6f0c..dd3babcb3b16a 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -178,6 +178,7 @@ config KVM_E500MC
config KVM_MPIC
bool "KVM in-kernel MPIC emulation"
depends on KVM && E500
+ depends on !PREEMPT_RT
select HAVE_KVM_IRQCHIP
select HAVE_KVM_IRQFD
select HAVE_KVM_IRQ_ROUTING
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
index 2735ec90414dc..359231cea8cd7 100644
--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -738,8 +738,8 @@ static int ps3_notification_read_write(struct ps3_notification_device *dev,
}
pr_debug("%s:%u: notification %s issued\n", __func__, __LINE__, op);
- res = wait_event_interruptible(dev->done.wait,
- dev->done.done || kthread_should_stop());
+ res = swait_event_interruptible_exclusive(dev->done.wait,
+ dev->done.done || kthread_should_stop());
if (kthread_should_stop())
res = -EINTR;
if (res) {
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index b4ce9d472dfe0..4df94694ebeef 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -132,10 +133,10 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
return be64_to_cpu(*tcep);
}
-static void tce_free_pSeriesLP(unsigned long liobn, long, long);
+static void tce_free_pSeriesLP(struct iommu_table*, long, long);
static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
-static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
+static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
unsigned long attrs)
@@ -146,25 +147,25 @@ static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
int ret = 0;
long tcenum_start = tcenum, npages_start = npages;
- rpn = __pa(uaddr) >> tceshift;
+ rpn = __pa(uaddr) >> TCE_SHIFT;
proto_tce = TCE_PCI_READ;
if (direction != DMA_TO_DEVICE)
proto_tce |= TCE_PCI_WRITE;
while (npages--) {
- tce = proto_tce | (rpn & TCE_RPN_MASK) << tceshift;
- rc = plpar_tce_put((u64)liobn, (u64)tcenum << tceshift, tce);
+ tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+ rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
ret = (int)rc;
- tce_free_pSeriesLP(liobn, tcenum_start,
+ tce_free_pSeriesLP(tbl, tcenum_start,
(npages_start - (npages + 1)));
break;
}
if (rc && printk_ratelimit()) {
printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
- printk("\tindex = 0x%llx\n", (u64)liobn);
+ printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
printk("\ttcenum = 0x%llx\n", (u64)tcenum);
printk("\ttce val = 0x%llx\n", tce );
dump_stack();
@@ -177,6 +178,7 @@ static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
}
static DEFINE_PER_CPU(__be64 *, tce_page);
+static DEFINE_LOCAL_IRQ_LOCK(tcp_page_lock);
static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
@@ -193,12 +195,12 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
unsigned long flags;
if ((npages == 1) || !firmware_has_feature(FW_FEATURE_MULTITCE)) {
- return tce_build_pSeriesLP(tbl->it_index, tcenum,
- tbl->it_page_shift, npages, uaddr,
+ return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
direction, attrs);
}
- local_irq_save(flags); /* to protect tcep and the page behind it */
+ /* to protect tcep and the page behind it */
+ local_lock_irqsave(tcp_page_lock, flags);
tcep = __this_cpu_read(tce_page);
@@ -209,10 +211,9 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
/* If allocation fails, fall back to the loop implementation */
if (!tcep) {
- local_irq_restore(flags);
- return tce_build_pSeriesLP(tbl->it_index, tcenum,
- tbl->it_page_shift,
- npages, uaddr, direction, attrs);
+ local_unlock_irqrestore(tcp_page_lock, flags);
+ return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+ direction, attrs);
}
__this_cpu_write(tce_page, tcep);
}
@@ -244,7 +245,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
tcenum += limit;
} while (npages > 0 && !rc);
- local_irq_restore(flags);
+ local_unlock_irqrestore(tcp_page_lock, flags);
if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
ret = (int)rc;
@@ -263,16 +264,16 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
return ret;
}
-static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long npages)
+static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
{
u64 rc;
while (npages--) {
- rc = plpar_tce_put((u64)liobn, (u64)tcenum << 12, 0);
+ rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
if (rc && printk_ratelimit()) {
printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
- printk("\tindex = 0x%llx\n", (u64)liobn);
+ printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
printk("\ttcenum = 0x%llx\n", (u64)tcenum);
dump_stack();
}
@@ -287,7 +288,7 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
u64 rc;
if (!firmware_has_feature(FW_FEATURE_MULTITCE))
- return tce_free_pSeriesLP(tbl->it_index, tcenum, npages);
+ return tce_free_pSeriesLP(tbl, tcenum, npages);
rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
@@ -402,26 +403,14 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
u64 rc = 0;
long l, limit;
- if (!firmware_has_feature(FW_FEATURE_MULTITCE)) {
- unsigned long tceshift = be32_to_cpu(maprange->tce_shift);
- unsigned long dmastart = (start_pfn << PAGE_SHIFT) +
- be64_to_cpu(maprange->dma_base);
- unsigned long tcenum = dmastart >> tceshift;
- unsigned long npages = num_pfn << PAGE_SHIFT >> tceshift;
- void *uaddr = __va(start_pfn << PAGE_SHIFT);
-
- return tce_build_pSeriesLP(be32_to_cpu(maprange->liobn),
- tcenum, tceshift, npages, (unsigned long) uaddr,
- DMA_BIDIRECTIONAL, 0);
- }
-
- local_irq_disable(); /* to protect tcep and the page behind it */
+ /* to protect tcep and the page behind it */
+ local_lock_irq(tcp_page_lock);
tcep = __this_cpu_read(tce_page);
if (!tcep) {
tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
if (!tcep) {
- local_irq_enable();
+ local_unlock_irq(tcp_page_lock);
return -ENOMEM;
}
__this_cpu_write(tce_page, tcep);
@@ -467,7 +456,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
/* error cleanup: caller will clear whole range */
- local_irq_enable();
+ local_unlock_irq(tcp_page_lock);
return rc;
}
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 8ca4798311429..8f482313e5601 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -155,7 +155,7 @@ _save_context:
REG_L x2, PT_SP(sp)
.endm
-#if !IS_ENABLED(CONFIG_PREEMPT)
+#if !IS_ENABLED(CONFIG_PREEMPTION)
.set resume_kernel, restore_all
#endif
@@ -269,7 +269,7 @@ restore_all:
RESTORE_ALL
sret
-#if IS_ENABLED(CONFIG_PREEMPT)
+#if IS_ENABLED(CONFIG_PREEMPTION)
resume_kernel:
REG_L s0, TASK_TI_PREEMPT_COUNT(tp)
bnez s0, restore_all
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 43a81d0ad5074..33d968175038e 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -30,7 +30,7 @@ config GENERIC_BUG_RELATIVE_POINTERS
def_bool y
config GENERIC_LOCKBREAK
- def_bool y if PREEMPT
+ def_bool y if PREEMPTTION
config PGSTE
def_bool y if KVM
diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h
index b5ea9e14c017a..6ede29907fbf7 100644
--- a/arch/s390/include/asm/preempt.h
+++ b/arch/s390/include/asm/preempt.h
@@ -130,11 +130,11 @@ static inline bool should_resched(int preempt_offset)
#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
extern asmlinkage void preempt_schedule(void);
#define __preempt_schedule() preempt_schedule()
extern asmlinkage void preempt_schedule_notrace(void);
#define __preempt_schedule_notrace() preempt_schedule_notrace()
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
#endif /* __ASM_PREEMPT_H */
diff --git a/arch/s390/include/asm/spinlock_types.h b/arch/s390/include/asm/spinlock_types.h
index cfed272e4fd59..8e28e8176ec88 100644
--- a/arch/s390/include/asm/spinlock_types.h
+++ b/arch/s390/include/asm/spinlock_types.h
@@ -2,10 +2,6 @@
#ifndef __ASM_SPINLOCK_TYPES_H
#define __ASM_SPINLOCK_TYPES_H
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
typedef struct {
int lock;
} __attribute__ ((aligned (4))) arch_spinlock_t;
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index 34bdc60c0b11d..8e38447be4653 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -194,6 +194,8 @@ void die(struct pt_regs *regs, const char *str)
regs->int_code >> 17, ++die_counter);
#ifdef CONFIG_PREEMPT
pr_cont("PREEMPT ");
+#elif defined(CONFIG_PREEMPT_RT)
+ pr_cont("PREEMPT_RT ");
#endif
pr_cont("SMP ");
if (debug_pagealloc_enabled())
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 270d1d145761b..9205add8481d5 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -790,7 +790,7 @@ ENTRY(io_int_handler)
.Lio_work:
tm __PT_PSW+1(%r11),0x01 # returning to user ?
jo .Lio_work_user # yes -> do resched & signal
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
# check for preemptive scheduling
icm %r0,15,__LC_PREEMPT_COUNT
jnz .Lio_restore # preemption is disabled
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index f356ee674d89b..9ece111b02548 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -108,7 +108,7 @@ config GENERIC_CALIBRATE_DELAY
config GENERIC_LOCKBREAK
def_bool y
- depends on SMP && PREEMPT
+ depends on SMP && PREEMPTION
config ARCH_SUSPEND_POSSIBLE
def_bool n
diff --git a/arch/sh/include/asm/spinlock_types.h b/arch/sh/include/asm/spinlock_types.h
index e82369f286a20..22ca9a98bbb8b 100644
--- a/arch/sh/include/asm/spinlock_types.h
+++ b/arch/sh/include/asm/spinlock_types.h
@@ -2,10 +2,6 @@
#ifndef __ASM_SH_SPINLOCK_TYPES_H
#define __ASM_SH_SPINLOCK_TYPES_H
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
typedef struct {
volatile unsigned int lock;
} arch_spinlock_t;
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index de68ffdfffbf5..81c8b64b977ff 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -86,7 +86,7 @@
andi r6, ~0xf0, r6; \
putcon r6, SR;
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
# define preempt_stop() CLI()
#else
# define preempt_stop()
@@ -884,7 +884,7 @@ ret_from_exception:
/* Check softirqs */
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
pta ret_from_syscall, tr0
blink tr0, ZERO
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index d31f66e82ce51..956a7a03b0c83 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -41,7 +41,7 @@
*/
#include
-#if defined(CONFIG_PREEMPT)
+#if defined(CONFIG_PREEMPTION)
# define preempt_stop() cli ; TRACE_IRQS_OFF
#else
# define preempt_stop()
@@ -84,7 +84,7 @@ ENTRY(ret_from_irq)
get_current_thread_info r8, r0
bt resume_kernel ! Yes, it's from kernel, go back soon
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
bra resume_userspace
nop
ENTRY(resume_kernel)
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 5717c7cbdd97a..c4e46252377ed 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -148,6 +148,7 @@ void irq_ctx_exit(int cpu)
hardirq_ctx[cpu] = NULL;
}
+#ifndef CONFIG_PREEMPT_RT
void do_softirq_own_stack(void)
{
struct thread_info *curctx;
@@ -175,6 +176,7 @@ void do_softirq_own_stack(void)
"r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
);
}
+#endif
#else
static inline void handle_one_irq(unsigned int irq)
{
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 18e9fb6fcf1bf..7b9b3a954a761 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -276,7 +276,7 @@ config US3_MC
config GENERIC_LOCKBREAK
bool
default y
- depends on SPARC64 && SMP && PREEMPT
+ depends on SPARC64 && SMP && PREEMPTION
config NUMA
bool "NUMA support"
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index 3ec9f1402aad3..eb21682abfcb1 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -854,6 +854,7 @@ void __irq_entry handler_irq(int pil, struct pt_regs *regs)
set_irq_regs(old_regs);
}
+#ifndef CONFIG_PREEMPT_RT
void do_softirq_own_stack(void)
{
void *orig_sp, *sp = softirq_stack[smp_processor_id()];
@@ -868,6 +869,7 @@ void do_softirq_own_stack(void)
__asm__ __volatile__("mov %0, %%sp"
: : "r" (orig_sp));
}
+#endif
#ifdef CONFIG_HOTPLUG_CPU
void fixup_irqs(void)
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index 29aa34f11720c..c5fd4b450d9b6 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -310,7 +310,7 @@ kern_rtt_restore:
retry
to_kernel:
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
ldsw [%g6 + TI_PRE_COUNT], %l5
brnz %l5, kern_fpucheck
ldx [%g6 + TI_FLAGS], %l5
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b49b117bdf0c0..517944571e680 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -90,6 +90,7 @@ config X86
select ARCH_SUPPORTS_ACPI
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_NUMA_BALANCING if X86_64
+ select ARCH_SUPPORTS_RT
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
@@ -132,8 +133,8 @@ config X86
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HUGE_VMAP if X86_64 || X86_PAE
- select HAVE_ARCH_JUMP_LABEL
- select HAVE_ARCH_JUMP_LABEL_RELATIVE
+ select HAVE_ARCH_JUMP_LABEL if !PREEMPT_RT
+ select HAVE_ARCH_JUMP_LABEL_RELATIVE if !PREEMPT_RT
select HAVE_ARCH_KASAN if X86_64
select HAVE_ARCH_KGDB
select HAVE_ARCH_MMAP_RND_BITS if MMU
@@ -199,6 +200,7 @@ config X86
select HAVE_PCI
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_LAZY
select HAVE_RCU_TABLE_FREE if PARAVIRT
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE if X86_64 && (UNWINDER_FRAME_POINTER || UNWINDER_ORC) && STACK_VALIDATION
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 3e707e81afdb4..0e80da8190be1 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -387,14 +387,14 @@ static int ecb_encrypt(struct skcipher_request *req)
err = skcipher_walk_virt(&walk, req, true);
- kernel_fpu_begin();
while ((nbytes = walk.nbytes)) {
+ kernel_fpu_begin();
aesni_ecb_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
nbytes & AES_BLOCK_MASK);
+ kernel_fpu_end();
nbytes &= AES_BLOCK_SIZE - 1;
err = skcipher_walk_done(&walk, nbytes);
}
- kernel_fpu_end();
return err;
}
@@ -409,14 +409,14 @@ static int ecb_decrypt(struct skcipher_request *req)
err = skcipher_walk_virt(&walk, req, true);
- kernel_fpu_begin();
while ((nbytes = walk.nbytes)) {
+ kernel_fpu_begin();
aesni_ecb_dec(ctx, walk.dst.virt.addr, walk.src.virt.addr,
nbytes & AES_BLOCK_MASK);
+ kernel_fpu_end();
nbytes &= AES_BLOCK_SIZE - 1;
err = skcipher_walk_done(&walk, nbytes);
}
- kernel_fpu_end();
return err;
}
@@ -431,14 +431,14 @@ static int cbc_encrypt(struct skcipher_request *req)
err = skcipher_walk_virt(&walk, req, true);
- kernel_fpu_begin();
while ((nbytes = walk.nbytes)) {
+ kernel_fpu_begin();
aesni_cbc_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
nbytes & AES_BLOCK_MASK, walk.iv);
+ kernel_fpu_end();
nbytes &= AES_BLOCK_SIZE - 1;
err = skcipher_walk_done(&walk, nbytes);
}
- kernel_fpu_end();
return err;
}
@@ -453,14 +453,14 @@ static int cbc_decrypt(struct skcipher_request *req)
err = skcipher_walk_virt(&walk, req, true);
- kernel_fpu_begin();
while ((nbytes = walk.nbytes)) {
+ kernel_fpu_begin();
aesni_cbc_dec(ctx, walk.dst.virt.addr, walk.src.virt.addr,
nbytes & AES_BLOCK_MASK, walk.iv);
+ kernel_fpu_end();
nbytes &= AES_BLOCK_SIZE - 1;
err = skcipher_walk_done(&walk, nbytes);
}
- kernel_fpu_end();
return err;
}
@@ -510,18 +510,20 @@ static int ctr_crypt(struct skcipher_request *req)
err = skcipher_walk_virt(&walk, req, true);
- kernel_fpu_begin();
while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) {
+ kernel_fpu_begin();
aesni_ctr_enc_tfm(ctx, walk.dst.virt.addr, walk.src.virt.addr,
nbytes & AES_BLOCK_MASK, walk.iv);
+ kernel_fpu_end();
nbytes &= AES_BLOCK_SIZE - 1;
err = skcipher_walk_done(&walk, nbytes);
}
if (walk.nbytes) {
+ kernel_fpu_begin();
ctr_crypt_final(ctx, &walk);
+ kernel_fpu_end();
err = skcipher_walk_done(&walk, 0);
}
- kernel_fpu_end();
return err;
}
diff --git a/arch/x86/crypto/cast5_avx_glue.c b/arch/x86/crypto/cast5_avx_glue.c
index 384ccb00f9e15..2f8df8ef8644e 100644
--- a/arch/x86/crypto/cast5_avx_glue.c
+++ b/arch/x86/crypto/cast5_avx_glue.c
@@ -46,7 +46,7 @@ static inline void cast5_fpu_end(bool fpu_enabled)
static int ecb_crypt(struct skcipher_request *req, bool enc)
{
- bool fpu_enabled = false;
+ bool fpu_enabled;
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct cast5_ctx *ctx = crypto_skcipher_ctx(tfm);
struct skcipher_walk walk;
@@ -61,7 +61,7 @@ static int ecb_crypt(struct skcipher_request *req, bool enc)
u8 *wsrc = walk.src.virt.addr;
u8 *wdst = walk.dst.virt.addr;
- fpu_enabled = cast5_fpu_begin(fpu_enabled, &walk, nbytes);
+ fpu_enabled = cast5_fpu_begin(false, &walk, nbytes);
/* Process multi-block batch */
if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
@@ -90,10 +90,9 @@ static int ecb_crypt(struct skcipher_request *req, bool enc)
} while (nbytes >= bsize);
done:
+ cast5_fpu_end(fpu_enabled);
err = skcipher_walk_done(&walk, nbytes);
}
-
- cast5_fpu_end(fpu_enabled);
return err;
}
@@ -197,7 +196,7 @@ static int cbc_decrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct cast5_ctx *ctx = crypto_skcipher_ctx(tfm);
- bool fpu_enabled = false;
+ bool fpu_enabled;
struct skcipher_walk walk;
unsigned int nbytes;
int err;
@@ -205,12 +204,11 @@ static int cbc_decrypt(struct skcipher_request *req)
err = skcipher_walk_virt(&walk, req, false);
while ((nbytes = walk.nbytes)) {
- fpu_enabled = cast5_fpu_begin(fpu_enabled, &walk, nbytes);
+ fpu_enabled = cast5_fpu_begin(false, &walk, nbytes);
nbytes = __cbc_decrypt(ctx, &walk);
+ cast5_fpu_end(fpu_enabled);
err = skcipher_walk_done(&walk, nbytes);
}
-
- cast5_fpu_end(fpu_enabled);
return err;
}
@@ -277,7 +275,7 @@ static int ctr_crypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct cast5_ctx *ctx = crypto_skcipher_ctx(tfm);
- bool fpu_enabled = false;
+ bool fpu_enabled;
struct skcipher_walk walk;
unsigned int nbytes;
int err;
@@ -285,13 +283,12 @@ static int ctr_crypt(struct skcipher_request *req)
err = skcipher_walk_virt(&walk, req, false);
while ((nbytes = walk.nbytes) >= CAST5_BLOCK_SIZE) {
- fpu_enabled = cast5_fpu_begin(fpu_enabled, &walk, nbytes);
+ fpu_enabled = cast5_fpu_begin(false, &walk, nbytes);
nbytes = __ctr_crypt(&walk, ctx);
+ cast5_fpu_end(fpu_enabled);
err = skcipher_walk_done(&walk, nbytes);
}
- cast5_fpu_end(fpu_enabled);
-
if (walk.nbytes) {
ctr_crypt_final(&walk, ctx);
err = skcipher_walk_done(&walk, 0);
diff --git a/arch/x86/crypto/chacha_glue.c b/arch/x86/crypto/chacha_glue.c
index 388f95a4ec240..f8e9ee81c39dd 100644
--- a/arch/x86/crypto/chacha_glue.c
+++ b/arch/x86/crypto/chacha_glue.c
@@ -127,7 +127,6 @@ static int chacha_simd_stream_xor(struct skcipher_walk *walk,
const struct chacha_ctx *ctx, const u8 *iv)
{
u32 *state, state_buf[16 + 2] __aligned(8);
- int next_yield = 4096; /* bytes until next FPU yield */
int err = 0;
BUILD_BUG_ON(CHACHA_STATE_ALIGN != 16);
@@ -140,20 +139,14 @@ static int chacha_simd_stream_xor(struct skcipher_walk *walk,
if (nbytes < walk->total) {
nbytes = round_down(nbytes, walk->stride);
- next_yield -= nbytes;
}
chacha_dosimd(state, walk->dst.virt.addr, walk->src.virt.addr,
nbytes, ctx->nrounds);
- if (next_yield <= 0) {
- /* temporarily allow preemption */
- kernel_fpu_end();
- kernel_fpu_begin();
- next_yield = 4096;
- }
-
+ kernel_fpu_end();
err = skcipher_walk_done(walk, walk->nbytes - nbytes);
+ kernel_fpu_begin();
}
return err;
diff --git a/arch/x86/crypto/glue_helper.c b/arch/x86/crypto/glue_helper.c
index d15b99397480b..36c28b295b8e3 100644
--- a/arch/x86/crypto/glue_helper.c
+++ b/arch/x86/crypto/glue_helper.c
@@ -24,7 +24,7 @@ int glue_ecb_req_128bit(const struct common_glue_ctx *gctx,
void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
const unsigned int bsize = 128 / 8;
struct skcipher_walk walk;
- bool fpu_enabled = false;
+ bool fpu_enabled;
unsigned int nbytes;
int err;
@@ -37,7 +37,7 @@ int glue_ecb_req_128bit(const struct common_glue_ctx *gctx,
unsigned int i;
fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
- &walk, fpu_enabled, nbytes);
+ &walk, false, nbytes);
for (i = 0; i < gctx->num_funcs; i++) {
func_bytes = bsize * gctx->funcs[i].num_blocks;
@@ -55,10 +55,9 @@ int glue_ecb_req_128bit(const struct common_glue_ctx *gctx,
if (nbytes < bsize)
break;
}
+ glue_fpu_end(fpu_enabled);
err = skcipher_walk_done(&walk, nbytes);
}
-
- glue_fpu_end(fpu_enabled);
return err;
}
EXPORT_SYMBOL_GPL(glue_ecb_req_128bit);
@@ -101,7 +100,7 @@ int glue_cbc_decrypt_req_128bit(const struct common_glue_ctx *gctx,
void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
const unsigned int bsize = 128 / 8;
struct skcipher_walk walk;
- bool fpu_enabled = false;
+ bool fpu_enabled;
unsigned int nbytes;
int err;
@@ -115,7 +114,7 @@ int glue_cbc_decrypt_req_128bit(const struct common_glue_ctx *gctx,
u128 last_iv;
fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
- &walk, fpu_enabled, nbytes);
+ &walk, false, nbytes);
/* Start of the last block. */
src += nbytes / bsize - 1;
dst += nbytes / bsize - 1;
@@ -147,10 +146,10 @@ int glue_cbc_decrypt_req_128bit(const struct common_glue_ctx *gctx,
done:
u128_xor(dst, dst, (u128 *)walk.iv);
*(u128 *)walk.iv = last_iv;
+ glue_fpu_end(fpu_enabled);
err = skcipher_walk_done(&walk, nbytes);
}
- glue_fpu_end(fpu_enabled);
return err;
}
EXPORT_SYMBOL_GPL(glue_cbc_decrypt_req_128bit);
@@ -161,7 +160,7 @@ int glue_ctr_req_128bit(const struct common_glue_ctx *gctx,
void *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
const unsigned int bsize = 128 / 8;
struct skcipher_walk walk;
- bool fpu_enabled = false;
+ bool fpu_enabled;
unsigned int nbytes;
int err;
@@ -175,7 +174,7 @@ int glue_ctr_req_128bit(const struct common_glue_ctx *gctx,
le128 ctrblk;
fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
- &walk, fpu_enabled, nbytes);
+ &walk, false, nbytes);
be128_to_le128(&ctrblk, (be128 *)walk.iv);
@@ -199,11 +198,10 @@ int glue_ctr_req_128bit(const struct common_glue_ctx *gctx,
}
le128_to_be128((be128 *)walk.iv, &ctrblk);
+ glue_fpu_end(fpu_enabled);
err = skcipher_walk_done(&walk, nbytes);
}
- glue_fpu_end(fpu_enabled);
-
if (nbytes) {
le128 ctrblk;
u128 tmp;
@@ -301,8 +299,14 @@ int glue_xts_req_128bit(const struct common_glue_ctx *gctx,
tweak_fn(tweak_ctx, walk.iv, walk.iv);
while (nbytes) {
+ fpu_enabled = glue_fpu_begin(bsize, gctx->fpu_blocks_limit,
+ &walk, fpu_enabled,
+ nbytes < bsize ? bsize : nbytes);
nbytes = __glue_xts_req_128bit(gctx, crypt_ctx, &walk);
+ glue_fpu_end(fpu_enabled);
+ fpu_enabled = false;
+
err = skcipher_walk_done(&walk, nbytes);
nbytes = walk.nbytes;
}
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 3f8e22615812b..26934d55c14a0 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -130,7 +130,7 @@ static long syscall_trace_enter(struct pt_regs *regs)
#define EXIT_TO_USERMODE_LOOP_FLAGS \
(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
- _TIF_NEED_RESCHED | _TIF_USER_RETURN_NOTIFY | _TIF_PATCH_PENDING)
+ _TIF_NEED_RESCHED_MASK | _TIF_USER_RETURN_NOTIFY | _TIF_PATCH_PENDING)
static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
{
@@ -145,9 +145,16 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
/* We have work to do. */
local_irq_enable();
- if (cached_flags & _TIF_NEED_RESCHED)
+ if (cached_flags & _TIF_NEED_RESCHED_MASK)
schedule();
+#ifdef ARCH_RT_DELAYS_SIGNAL_SEND
+ if (unlikely(current->forced_info.si_signo)) {
+ struct task_struct *t = current;
+ force_sig_info(&t->forced_info);
+ t->forced_info.si_signo = 0;
+ }
+#endif
if (cached_flags & _TIF_UPROBE)
uprobe_notify_resume(regs);
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index f07baf0388bce..69049e32b4fa1 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -1106,8 +1106,26 @@ restore_all:
restore_all_kernel:
#ifdef CONFIG_PREEMPTION
DISABLE_INTERRUPTS(CLBR_ANY)
+ # preempt count == 0 + NEED_RS set?
cmpl $0, PER_CPU_VAR(__preempt_count)
+#ifndef CONFIG_PREEMPT_LAZY
jnz .Lno_preempt
+#else
+ jz test_int_off
+
+ # atleast preempt count == 0 ?
+ cmpl $_PREEMPT_ENABLED,PER_CPU_VAR(__preempt_count)
+ jne .Lno_preempt
+
+ movl PER_CPU_VAR(current_task), %ebp
+ cmpl $0,TASK_TI_preempt_lazy_count(%ebp) # non-zero preempt_lazy_count ?
+ jnz .Lno_preempt
+
+ testl $_TIF_NEED_RESCHED_LAZY, TASK_TI_flags(%ebp)
+ jz .Lno_preempt
+
+test_int_off:
+#endif
testl $X86_EFLAGS_IF, PT_EFLAGS(%esp) # interrupts off (exception path) ?
jz .Lno_preempt
call preempt_schedule_irq
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index b7c3ea4cb19d4..ce564dc48647f 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -670,7 +670,23 @@ retint_kernel:
btl $9, EFLAGS(%rsp) /* were interrupts off? */
jnc 1f
cmpl $0, PER_CPU_VAR(__preempt_count)
+#ifndef CONFIG_PREEMPT_LAZY
jnz 1f
+#else
+ jz do_preempt_schedule_irq
+
+ # atleast preempt count == 0 ?
+ cmpl $_PREEMPT_ENABLED,PER_CPU_VAR(__preempt_count)
+ jnz 1f
+
+ movq PER_CPU_VAR(current_task), %rcx
+ cmpl $0, TASK_TI_preempt_lazy_count(%rcx)
+ jnz 1f
+
+ btl $TIF_NEED_RESCHED_LAZY,TASK_TI_flags(%rcx)
+ jnc 1f
+do_preempt_schedule_irq:
+#endif
call preempt_schedule_irq
1:
#endif
@@ -1074,6 +1090,7 @@ EXPORT_SYMBOL(native_load_gs_index)
jmp 2b
.previous
+#ifndef CONFIG_PREEMPT_RT
/* Call softirq on interrupt stack. Interrupts are off. */
ENTRY(do_softirq_own_stack)
pushq %rbp
@@ -1084,6 +1101,7 @@ ENTRY(do_softirq_own_stack)
leaveq
ret
ENDPROC(do_softirq_own_stack)
+#endif
#ifdef CONFIG_XEN_PV
idtentry hypervisor_callback xen_do_hypervisor_callback has_error_code=0
diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h
index b774c52e5411f..1786e4d9f70e8 100644
--- a/arch/x86/include/asm/fpu/api.h
+++ b/arch/x86/include/asm/fpu/api.h
@@ -23,6 +23,7 @@ extern void kernel_fpu_begin(void);
extern void kernel_fpu_end(void);
extern bool irq_fpu_usable(void);
extern void fpregs_mark_activate(void);
+extern void kernel_fpu_resched(void);
/*
* Use fpregs_lock() while editing CPU's FPU registers or fpu->state.
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
index 3d4cb83a88284..1f28e9f3dc8e2 100644
--- a/arch/x86/include/asm/preempt.h
+++ b/arch/x86/include/asm/preempt.h
@@ -89,17 +89,48 @@ static __always_inline void __preempt_count_sub(int val)
* a decrement which hits zero means we have no preempt_count and should
* reschedule.
*/
-static __always_inline bool __preempt_count_dec_and_test(void)
+static __always_inline bool ____preempt_count_dec_and_test(void)
{
return GEN_UNARY_RMWcc("decl", __preempt_count, e, __percpu_arg([var]));
}
+static __always_inline bool __preempt_count_dec_and_test(void)
+{
+ if (____preempt_count_dec_and_test())
+ return true;
+#ifdef CONFIG_PREEMPT_LAZY
+ if (preempt_count())
+ return false;
+ if (current_thread_info()->preempt_lazy_count)
+ return false;
+ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
+#else
+ return false;
+#endif
+}
+
/*
* Returns true when we need to resched and can (barring IRQ state).
*/
static __always_inline bool should_resched(int preempt_offset)
{
+#ifdef CONFIG_PREEMPT_LAZY
+ u32 tmp;
+ tmp = raw_cpu_read_4(__preempt_count);
+ if (tmp == preempt_offset)
+ return true;
+
+ /* preempt count == 0 ? */
+ tmp &= ~PREEMPT_NEED_RESCHED;
+ if (tmp != preempt_offset)
+ return false;
+ /* XXX PREEMPT_LOCK_OFFSET */
+ if (current_thread_info()->preempt_lazy_count)
+ return false;
+ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
+#else
return unlikely(raw_cpu_read_4(__preempt_count) == preempt_offset);
+#endif
}
#ifdef CONFIG_PREEMPTION
diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h
index 33d3c88a7225f..65b9a5d4132b7 100644
--- a/arch/x86/include/asm/signal.h
+++ b/arch/x86/include/asm/signal.h
@@ -28,6 +28,19 @@ typedef struct {
#define SA_IA32_ABI 0x02000000u
#define SA_X32_ABI 0x01000000u
+/*
+ * Because some traps use the IST stack, we must keep preemption
+ * disabled while calling do_trap(), but do_trap() may call
+ * force_sig_info() which will grab the signal spin_locks for the
+ * task, which in PREEMPT_RT are mutexes. By defining
+ * ARCH_RT_DELAYS_SIGNAL_SEND the force_sig_info() will set
+ * TIF_NOTIFY_RESUME and set up the signal to be sent on exit of the
+ * trap.
+ */
+#if defined(CONFIG_PREEMPT_RT)
+#define ARCH_RT_DELAYS_SIGNAL_SEND
+#endif
+
#ifndef CONFIG_COMPAT
typedef sigset_t compat_sigset_t;
#endif
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
index 91e29b6a86a5e..1ef821537da8f 100644
--- a/arch/x86/include/asm/stackprotector.h
+++ b/arch/x86/include/asm/stackprotector.h
@@ -60,7 +60,7 @@
*/
static __always_inline void boot_init_stack_canary(void)
{
- u64 canary;
+ u64 uninitialized_var(canary);
u64 tsc;
#ifdef CONFIG_X86_64
@@ -71,8 +71,14 @@ static __always_inline void boot_init_stack_canary(void)
* of randomness. The TSC only matters for very early init,
* there it already has some randomness on most systems. Later
* on during the bootup the random pool has true entropy too.
+ * For preempt-rt we need to weaken the randomness a bit, as
+ * we can't call into the random generator from atomic context
+ * due to locking constraints. We just leave canary
+ * uninitialized and use the TSC based randomness on top of it.
*/
+#ifndef CONFIG_PREEMPT_RT
get_random_bytes(&canary, sizeof(canary));
+#endif
tsc = rdtsc();
canary += tsc + (tsc << 32UL);
canary &= CANARY_MASK;
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index f9453536f9bbc..f346f24140be9 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -56,17 +56,24 @@ struct task_struct;
struct thread_info {
unsigned long flags; /* low level flags */
u32 status; /* thread synchronous flags */
+ int preempt_lazy_count; /* 0 => lazy preemptable
+ <0 => BUG */
};
#define INIT_THREAD_INFO(tsk) \
{ \
.flags = 0, \
+ .preempt_lazy_count = 0, \
}
#else /* !__ASSEMBLY__ */
#include
+#define GET_THREAD_INFO(reg) \
+ _ASM_MOV PER_CPU_VAR(cpu_current_top_of_stack),reg ; \
+ _ASM_SUB $(THREAD_SIZE),reg ;
+
#endif
/*
@@ -92,6 +99,7 @@ struct thread_info {
#define TIF_NOCPUID 15 /* CPUID is not accessible in userland */
#define TIF_NOTSC 16 /* TSC is not accessible in userland */
#define TIF_IA32 17 /* IA32 compatibility process */
+#define TIF_NEED_RESCHED_LAZY 18 /* lazy rescheduling necessary */
#define TIF_NOHZ 19 /* in adaptive nohz mode */
#define TIF_MEMDIE 20 /* is terminating due to OOM killer */
#define TIF_POLLING_NRFLAG 21 /* idle is polling for TIF_NEED_RESCHED */
@@ -122,6 +130,7 @@ struct thread_info {
#define _TIF_NOCPUID (1 << TIF_NOCPUID)
#define _TIF_NOTSC (1 << TIF_NOTSC)
#define _TIF_IA32 (1 << TIF_IA32)
+#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
#define _TIF_NOHZ (1 << TIF_NOHZ)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
@@ -159,6 +168,8 @@ struct thread_info {
#define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
+#define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)
+
#define STACK_WARN (THREAD_SIZE/8)
/*
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index f0262cb5657a7..913c88617848b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1725,7 +1725,7 @@ static bool io_apic_level_ack_pending(struct mp_chip_data *data)
return false;
}
-static inline bool ioapic_irqd_mask(struct irq_data *data)
+static inline bool ioapic_prepare_move(struct irq_data *data)
{
/* If we are moving the IRQ we need to mask it */
if (unlikely(irqd_is_setaffinity_pending(data))) {
@@ -1736,9 +1736,9 @@ static inline bool ioapic_irqd_mask(struct irq_data *data)
return false;
}
-static inline void ioapic_irqd_unmask(struct irq_data *data, bool masked)
+static inline void ioapic_finish_move(struct irq_data *data, bool moveit)
{
- if (unlikely(masked)) {
+ if (unlikely(moveit)) {
/* Only migrate the irq if the ack has been received.
*
* On rare occasions the broadcast level triggered ack gets
@@ -1773,11 +1773,11 @@ static inline void ioapic_irqd_unmask(struct irq_data *data, bool masked)
}
}
#else
-static inline bool ioapic_irqd_mask(struct irq_data *data)
+static inline bool ioapic_prepare_move(struct irq_data *data)
{
return false;
}
-static inline void ioapic_irqd_unmask(struct irq_data *data, bool masked)
+static inline void ioapic_finish_move(struct irq_data *data, bool moveit)
{
}
#endif
@@ -1786,11 +1786,11 @@ static void ioapic_ack_level(struct irq_data *irq_data)
{
struct irq_cfg *cfg = irqd_cfg(irq_data);
unsigned long v;
- bool masked;
+ bool moveit;
int i;
irq_complete_move(cfg);
- masked = ioapic_irqd_mask(irq_data);
+ moveit = ioapic_prepare_move(irq_data);
/*
* It appears there is an erratum which affects at least version 0x11
@@ -1845,7 +1845,7 @@ static void ioapic_ack_level(struct irq_data *irq_data)
eoi_ioapic_pin(cfg->vector, irq_data->chip_data);
}
- ioapic_irqd_unmask(irq_data, masked);
+ ioapic_finish_move(irq_data, moveit);
}
static void ioapic_ir_ack_level(struct irq_data *irq_data)
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 5c7ee3df4d0b0..24bcc28f68d4b 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -38,6 +38,10 @@ static void __used common(void)
#endif
BLANK();
+#ifdef CONFIG_PREEMPT_LAZY
+ OFFSET(TASK_TI_flags, task_struct, thread_info.flags);
+ OFFSET(TASK_TI_preempt_lazy_count, task_struct, thread_info.preempt_lazy_count);
+#endif
OFFSET(TASK_addr_limit, task_struct, thread.addr_limit);
BLANK();
@@ -92,6 +96,7 @@ static void __used common(void)
BLANK();
DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
+ DEFINE(_PREEMPT_ENABLED, PREEMPT_ENABLED);
/* TLB state for the entry code */
OFFSET(TLB_STATE_user_pcid_flush_mask, tlb_state, user_pcid_flush_mask);
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index c656d92cd708f..de56d671bc7fd 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -77,12 +77,13 @@ EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq);
__visible void __irq_entry hv_stimer0_vector_handler(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
+ u64 ip = regs ? instruction_pointer(regs) : 0;
entering_irq();
inc_irq_stat(hyperv_stimer0_count);
if (hv_stimer0_handler)
hv_stimer0_handler();
- add_interrupt_randomness(HYPERV_STIMER0_VECTOR, 0);
+ add_interrupt_randomness(HYPERV_STIMER0_VECTOR, 0, ip);
ack_APIC_irq();
exiting_irq();
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 12c70840980e4..6909468cc7a04 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -113,6 +113,18 @@ void kernel_fpu_end(void)
}
EXPORT_SYMBOL_GPL(kernel_fpu_end);
+void kernel_fpu_resched(void)
+{
+ WARN_ON_FPU(!this_cpu_read(in_kernel_fpu));
+
+ if (should_resched(PREEMPT_OFFSET)) {
+ kernel_fpu_end();
+ cond_resched();
+ kernel_fpu_begin();
+ }
+}
+EXPORT_SYMBOL_GPL(kernel_fpu_resched);
+
/*
* Save the FPU state (mark it for reload if necessary):
*
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index a759ca97cd01c..a74a7606806c1 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -131,6 +131,7 @@ int irq_init_percpu_irqstack(unsigned int cpu)
return 0;
}
+#ifndef CONFIG_PREEMPT_RT
void do_softirq_own_stack(void)
{
struct irq_stack *irqstk;
@@ -147,6 +148,7 @@ void do_softirq_own_stack(void)
call_on_stack(__do_softirq, isp);
}
+#endif
void handle_irq(struct irq_desc *desc, struct pt_regs *regs)
{
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index b8ceec4974fe3..39510443d996e 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
#include
@@ -196,6 +197,35 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
}
EXPORT_SYMBOL_GPL(start_thread);
+#ifdef CONFIG_PREEMPT_RT
+static void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p)
+{
+ int i;
+
+ /*
+ * Clear @prev's kmap_atomic mappings
+ */
+ for (i = 0; i < prev_p->kmap_idx; i++) {
+ int idx = i + KM_TYPE_NR * smp_processor_id();
+ pte_t *ptep = kmap_pte - idx;
+
+ kpte_clear_flush(ptep, __fix_to_virt(FIX_KMAP_BEGIN + idx));
+ }
+ /*
+ * Restore @next_p's kmap_atomic mappings
+ */
+ for (i = 0; i < next_p->kmap_idx; i++) {
+ int idx = i + KM_TYPE_NR * smp_processor_id();
+
+ if (!pte_none(next_p->kmap_pte[i]))
+ set_pte(kmap_pte - idx, next_p->kmap_pte[i]);
+ }
+}
+#else
+static inline void
+switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p) { }
+#endif
+
/*
* switch_to(x,y) should switch tasks from x to y.
@@ -266,6 +296,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
switch_to_extra(prev_p, next_p);
+ switch_kmaps(prev_p, next_p);
+
/*
* Leave lazy mode, flushing any hypercalls made here.
* This must be done before restoring TLS segments so
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index edde5ee8c6f50..c15f014177fd0 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7249,6 +7249,14 @@ int kvm_arch_init(void *opaque)
goto out;
}
+#ifdef CONFIG_PREEMPT_RT
+ if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
+ pr_err("RT requires X86_FEATURE_CONSTANT_TSC\n");
+ r = -EOPNOTSUPP;
+ goto out;
+ }
+#endif
+
r = -ENOMEM;
x86_fpu_cache = kmem_cache_create("x86_fpu", sizeof(struct fpu),
__alignof__(struct fpu), SLAB_ACCOUNT,
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
index 0a1898b8552e2..8606f17582073 100644
--- a/arch/x86/mm/highmem_32.c
+++ b/arch/x86/mm/highmem_32.c
@@ -33,10 +33,11 @@ EXPORT_SYMBOL(kunmap);
*/
void *kmap_atomic_prot(struct page *page, pgprot_t prot)
{
+ pte_t pte = mk_pte(page, prot);
unsigned long vaddr;
int idx, type;
- preempt_disable();
+ preempt_disable_nort();
pagefault_disable();
if (!PageHighMem(page))
@@ -46,7 +47,10 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot)
idx = type + KM_TYPE_NR*smp_processor_id();
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
BUG_ON(!pte_none(*(kmap_pte-idx)));
- set_pte(kmap_pte-idx, mk_pte(page, prot));
+#ifdef CONFIG_PREEMPT_RT
+ current->kmap_pte[type] = pte;
+#endif
+ set_pte(kmap_pte-idx, pte);
arch_flush_lazy_mmu_mode();
return (void *)vaddr;
@@ -89,6 +93,9 @@ void __kunmap_atomic(void *kvaddr)
* is a bad idea also, in case the page changes cacheability
* attributes or becomes a protected page in a hypervisor.
*/
+#ifdef CONFIG_PREEMPT_RT
+ current->kmap_pte[type] = __pte(0);
+#endif
kpte_clear_flush(kmap_pte-idx, vaddr);
kmap_atomic_idx_pop();
arch_flush_lazy_mmu_mode();
@@ -101,7 +108,7 @@ void __kunmap_atomic(void *kvaddr)
#endif
pagefault_enable();
- preempt_enable();
+ preempt_enable_nort();
}
EXPORT_SYMBOL(__kunmap_atomic);
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c
index 6748b4c2baff3..54e2f28fe1897 100644
--- a/arch/x86/mm/iomap_32.c
+++ b/arch/x86/mm/iomap_32.c
@@ -46,6 +46,7 @@ EXPORT_SYMBOL_GPL(iomap_free);
void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
{
+ pte_t pte = pfn_pte(pfn, prot);
unsigned long vaddr;
int idx, type;
@@ -55,7 +56,12 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
type = kmap_atomic_idx_push();
idx = type + KM_TYPE_NR * smp_processor_id();
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
- set_pte(kmap_pte - idx, pfn_pte(pfn, prot));
+ WARN_ON(!pte_none(*(kmap_pte - idx)));
+
+#ifdef CONFIG_PREEMPT_RT
+ current->kmap_pte[type] = pte;
+#endif
+ set_pte(kmap_pte - idx, pte);
arch_flush_lazy_mmu_mode();
return (void *)vaddr;
@@ -106,6 +112,9 @@ iounmap_atomic(void __iomem *kvaddr)
* is a bad idea also, in case the page changes cacheability
* attributes or becomes a protected page in a hypervisor.
*/
+#ifdef CONFIG_PREEMPT_RT
+ current->kmap_pte[type] = __pte(0);
+#endif
kpte_clear_flush(kmap_pte-idx, vaddr);
kmap_atomic_idx_pop();
}
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index e6a9edc5baaf0..66f96f21a7b60 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -708,7 +708,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
(void *)info, 1);
else
on_each_cpu_cond_mask(tlb_is_not_lazy, flush_tlb_func_remote,
- (void *)info, 1, GFP_ATOMIC, cpumask);
+ (void *)info, 1, cpumask);
}
/*
diff --git a/arch/xtensa/include/asm/spinlock_types.h b/arch/xtensa/include/asm/spinlock_types.h
index 64c9389254f13..dc846323b1cd7 100644
--- a/arch/xtensa/include/asm/spinlock_types.h
+++ b/arch/xtensa/include/asm/spinlock_types.h
@@ -2,10 +2,6 @@
#ifndef __ASM_SPINLOCK_TYPES_H
#define __ASM_SPINLOCK_TYPES_H
-#if !defined(__LINUX_SPINLOCK_TYPES_H) && !defined(__ASM_SPINLOCK_H)
-# error "please don't include this file directly"
-#endif
-
#include
#include
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 9e3676879168a..a6434813df6c8 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -520,7 +520,7 @@ common_exception_return:
call4 schedule # void schedule (void)
j 1b
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
6:
_bbci.l a4, TIF_NEED_RESCHED, 4f
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 4a6c495ce9b6d..2e7cf56412a05 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -524,12 +524,15 @@ DEFINE_SPINLOCK(die_lock);
void die(const char * str, struct pt_regs * regs, long err)
{
static int die_counter;
+ const char *pr = "";
+
+ if (IS_ENABLED(CONFIG_PREEMPTION))
+ pr = IS_ENABLED(CONFIG_PREEMPT_RT) ? " PREEMPT_RT" : " PREEMPT";
console_verbose();
spin_lock_irq(&die_lock);
- pr_info("%s: sig: %ld [#%d]%s\n", str, err, ++die_counter,
- IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "");
+ pr_info("%s: sig: %ld [#%d]%s\n", str, err, ++die_counter, pr);
show_regs(regs);
if (!user_mode(regs))
show_stack(NULL, (unsigned long*)regs->areg[1]);
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 5ed59ac6ae58b..b1da5f1592eb5 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include "blk.h"
@@ -115,7 +116,7 @@ static void ioc_release_fn(struct work_struct *work)
spin_unlock(&q->queue_lock);
} else {
spin_unlock_irqrestore(&ioc->lock, flags);
- cpu_relax();
+ cpu_chill();
spin_lock_irqsave_nested(&ioc->lock, flags, 1);
}
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index ec791156e9ccd..3811881ff624e 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -611,9 +611,17 @@ static void __blk_mq_complete_request(struct request *rq)
return;
}
- cpu = get_cpu();
+ cpu = get_cpu_light();
+ /*
+ * Avoid SMP function calls for completions because they acquire
+ * sleeping spinlocks on RT.
+ */
+#ifdef CONFIG_PREEMPT_RT
+ shared = true;
+#else
if (!test_bit(QUEUE_FLAG_SAME_FORCE, &q->queue_flags))
shared = cpus_share_cache(cpu, ctx->cpu);
+#endif
if (cpu != ctx->cpu && !shared && cpu_online(ctx->cpu)) {
rq->csd.func = __blk_mq_complete_request_remote;
@@ -623,7 +631,7 @@ static void __blk_mq_complete_request(struct request *rq)
} else {
q->mq_ops->complete(rq);
}
- put_cpu();
+ put_cpu_light();
}
static void hctx_unlock(struct blk_mq_hw_ctx *hctx, int srcu_idx)
@@ -1466,14 +1474,14 @@ static void __blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async,
return;
if (!async && !(hctx->flags & BLK_MQ_F_BLOCKING)) {
- int cpu = get_cpu();
+ int cpu = get_cpu_light();
if (cpumask_test_cpu(cpu, hctx->cpumask)) {
__blk_mq_run_hw_queue(hctx);
- put_cpu();
+ put_cpu_light();
return;
}
- put_cpu();
+ put_cpu_light();
}
kblockd_mod_delayed_work_on(blk_mq_hctx_next_cpu(hctx), &hctx->run_work,
diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index 457d9ba3eb204..4debe1124b990 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -42,17 +42,13 @@ static __latent_entropy void blk_done_softirq(struct softirq_action *h)
static void trigger_softirq(void *data)
{
struct request *rq = data;
- unsigned long flags;
struct list_head *list;
- local_irq_save(flags);
list = this_cpu_ptr(&blk_cpu_done);
list_add_tail(&rq->ipi_list, list);
if (list->next == &rq->ipi_list)
raise_softirq_irqoff(BLOCK_SOFTIRQ);
-
- local_irq_restore(flags);
}
/*
@@ -91,6 +87,7 @@ static int blk_softirq_cpu_dead(unsigned int cpu)
this_cpu_ptr(&blk_cpu_done));
raise_softirq_irqoff(BLOCK_SOFTIRQ);
local_irq_enable();
+ preempt_check_resched_rt();
return 0;
}
@@ -142,6 +139,7 @@ void __blk_complete_request(struct request *req)
goto do_local;
local_irq_restore(flags);
+ preempt_check_resched_rt();
}
static __init int blk_softirq_init(void)
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 927760b316a4d..fb1e305aa3984 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -36,6 +36,7 @@ static struct workqueue_struct *cryptd_wq;
struct cryptd_cpu_queue {
struct crypto_queue queue;
struct work_struct work;
+ spinlock_t qlock;
};
struct cryptd_queue {
@@ -105,6 +106,7 @@ static int cryptd_init_queue(struct cryptd_queue *queue,
cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
crypto_init_queue(&cpu_queue->queue, max_cpu_qlen);
INIT_WORK(&cpu_queue->work, cryptd_queue_worker);
+ spin_lock_init(&cpu_queue->qlock);
}
pr_info("cryptd: max_cpu_qlen set to %d\n", max_cpu_qlen);
return 0;
@@ -129,8 +131,10 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue,
struct cryptd_cpu_queue *cpu_queue;
refcount_t *refcnt;
- cpu = get_cpu();
- cpu_queue = this_cpu_ptr(queue->cpu_queue);
+ cpu_queue = raw_cpu_ptr(queue->cpu_queue);
+ spin_lock_bh(&cpu_queue->qlock);
+ cpu = smp_processor_id();
+
err = crypto_enqueue_request(&cpu_queue->queue, request);
refcnt = crypto_tfm_ctx(request->tfm);
@@ -146,7 +150,7 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue,
refcount_inc(refcnt);
out_put_cpu:
- put_cpu();
+ spin_unlock_bh(&cpu_queue->qlock);
return err;
}
@@ -162,16 +166,11 @@ static void cryptd_queue_worker(struct work_struct *work)
cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
/*
* Only handle one request at a time to avoid hogging crypto workqueue.
- * preempt_disable/enable is used to prevent being preempted by
- * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
- * cryptd_enqueue_request() being accessed from software interrupts.
*/
- local_bh_disable();
- preempt_disable();
+ spin_lock_bh(&cpu_queue->qlock);
backlog = crypto_get_backlog(&cpu_queue->queue);
req = crypto_dequeue_request(&cpu_queue->queue);
- preempt_enable();
- local_bh_enable();
+ spin_unlock_bh(&cpu_queue->qlock);
if (!req)
return;
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 1a8564a79d8dc..9dc3cc8beb2a6 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -113,12 +113,20 @@ ssize_t zcomp_available_show(const char *comp, char *buf)
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
{
- return *get_cpu_ptr(comp->stream);
+ struct zcomp_strm *zstrm;
+
+ zstrm = *get_local_ptr(comp->stream);
+ spin_lock(&zstrm->zcomp_lock);
+ return zstrm;
}
void zcomp_stream_put(struct zcomp *comp)
{
- put_cpu_ptr(comp->stream);
+ struct zcomp_strm *zstrm;
+
+ zstrm = *this_cpu_ptr(comp->stream);
+ spin_unlock(&zstrm->zcomp_lock);
+ put_local_ptr(zstrm);
}
int zcomp_compress(struct zcomp_strm *zstrm,
@@ -168,6 +176,7 @@ int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
pr_err("Can't allocate a compression stream\n");
return -ENOMEM;
}
+ spin_lock_init(&zstrm->zcomp_lock);
*per_cpu_ptr(comp->stream, cpu) = zstrm;
return 0;
}
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index 1806475b919df..b2c1db8a75ecb 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -10,6 +10,7 @@ struct zcomp_strm {
/* compression/decompression buffer */
void *buffer;
struct crypto_comp *tfm;
+ spinlock_t zcomp_lock;
};
/* dynamic per-device compression frontend */
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 4285e75e52c34..1699e84c9fce3 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -55,6 +55,40 @@ static void zram_free_page(struct zram *zram, size_t index);
static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
u32 index, int offset, struct bio *bio);
+#ifdef CONFIG_PREEMPT_RT
+static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages)
+{
+ size_t index;
+
+ for (index = 0; index < num_pages; index++)
+ spin_lock_init(&zram->table[index].lock);
+}
+
+static int zram_slot_trylock(struct zram *zram, u32 index)
+{
+ int ret;
+
+ ret = spin_trylock(&zram->table[index].lock);
+ if (ret)
+ __set_bit(ZRAM_LOCK, &zram->table[index].flags);
+ return ret;
+}
+
+static void zram_slot_lock(struct zram *zram, u32 index)
+{
+ spin_lock(&zram->table[index].lock);
+ __set_bit(ZRAM_LOCK, &zram->table[index].flags);
+}
+
+static void zram_slot_unlock(struct zram *zram, u32 index)
+{
+ __clear_bit(ZRAM_LOCK, &zram->table[index].flags);
+ spin_unlock(&zram->table[index].lock);
+}
+
+#else
+
+static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages) { }
static int zram_slot_trylock(struct zram *zram, u32 index)
{
@@ -70,6 +104,7 @@ static void zram_slot_unlock(struct zram *zram, u32 index)
{
bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags);
}
+#endif
static inline bool init_done(struct zram *zram)
{
@@ -1155,6 +1190,7 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize)
if (!huge_class_size)
huge_class_size = zs_huge_class_size(zram->mem_pool);
+ zram_meta_init_table_locks(zram, num_pages);
return true;
}
@@ -1217,6 +1253,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
unsigned long handle;
unsigned int size;
void *src, *dst;
+ struct zcomp_strm *zstrm;
zram_slot_lock(zram, index);
if (zram_test_flag(zram, index, ZRAM_WB)) {
@@ -1247,6 +1284,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
size = zram_get_obj_size(zram, index);
+ zstrm = zcomp_stream_get(zram->comp);
src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
if (size == PAGE_SIZE) {
dst = kmap_atomic(page);
@@ -1254,14 +1292,13 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
kunmap_atomic(dst);
ret = 0;
} else {
- struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp);
dst = kmap_atomic(page);
ret = zcomp_decompress(zstrm, src, size, dst);
kunmap_atomic(dst);
- zcomp_stream_put(zram->comp);
}
zs_unmap_object(zram->mem_pool, handle);
+ zcomp_stream_put(zram->comp);
zram_slot_unlock(zram, index);
/* Should NEVER happen. Return bio error if it does. */
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index f2fd46daa7604..7e4dd447e1ddd 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -63,6 +63,7 @@ struct zram_table_entry {
unsigned long element;
};
unsigned long flags;
+ spinlock_t lock;
#ifdef CONFIG_ZRAM_MEMORY_TRACKING
ktime_t ac_time;
#endif
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index df0fc997dc3e3..5cdde00bee741 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -535,6 +535,12 @@ config ADI
and SSM (Silicon Secured Memory). Intended consumers of this
driver include crash and makedumpfile.
+config GSOC_DUMMY_CHAR_DEVICE
+ tristate "GSoC Warmup Driver"
+ help
+ This builds the GSoC Dummy Char Driver, which is required for the warmup task.
+ Say Y to build it into the kernel, M to build it as a module and N to not build it.
+
endmenu
config RANDOM_TRUST_CPU
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 7c5ea6f9df145..d979e76408c6f 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -52,3 +52,5 @@ js-rtc-y = rtc.o
obj-$(CONFIG_XILLYBUS) += xillybus/
obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
obj-$(CONFIG_ADI) += adi.o
+
+obj-$(CONFIG_GSOC_DUMMY_CHAR_DEVICE) += gsoc-dummy-char-dev.o
\ No newline at end of file
diff --git a/drivers/char/gsoc-dummy-char-dev.c b/drivers/char/gsoc-dummy-char-dev.c
new file mode 100644
index 0000000000000..b02075dd0b0e9
--- /dev/null
+++ b/drivers/char/gsoc-dummy-char-dev.c
@@ -0,0 +1,136 @@
+/*
+ * GSoC Dummy Driver for warm up exercise
+ *
+ * Author: Niklas Wantrupp
+ * based on
+ * Dummy character driver by
+ * John Madieu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static int gsoc_char_dev_open(struct inode * inode, struct file * file);
+static int gsoc_char_dev_close(struct inode * inode, struct file * file);
+static ssize_t gsoc_char_dev_read(struct file *file, char __user * buf, size_t count, loff_t * offset);
+static ssize_t gsoc_char_dev_write(struct file * file, const char __user * buf, size_t count, loff_t * offset);
+static int gsoc_char_dev_uevent(struct device *dev, struct kobj_uevent_env *env);
+
+static unsigned int major;
+static struct class *gsoc_dummy_class;
+static struct cdev gsoc_dummy_device;
+
+static const struct file_operations gsoc_dummy_dev_file_ops = {
+ .open = gsoc_char_dev_open,
+ .release = gsoc_char_dev_close,
+ .read = gsoc_char_dev_read,
+ .write = gsoc_char_dev_write,
+};
+
+static int __init gsoc_dummy_char_dev_init_module(void)
+{
+ struct device *dummy_device;
+ int err;
+ dev_t gsoc_dev;
+
+ // register a range of char dev numbers 0 to 1 in this case
+ err = alloc_chrdev_region(&gsoc_dev, 0, 1, "gsoc_dummy_char_dev");
+ if (err < 0) {
+ pr_err("Can't get major number\n");
+ return err;
+ }
+ major = MAJOR(gsoc_dev);
+ pr_info("gsoc_dummy_char_dev major number = %d\n",major);
+
+ // Create sysfs class
+ gsoc_dummy_class = class_create(THIS_MODULE, "gsoc_dummy_char_dev_class");
+
+ if (IS_ERR(gsoc_dummy_class)) {
+ pr_err("GSoC char device class could not be created.\n");
+ unregister_chrdev_region(MKDEV(major, 0), 1);
+ return PTR_ERR(gsoc_dummy_class);
+ }
+
+ gsoc_dummy_class->dev_uevent = gsoc_char_dev_uevent;
+
+ // Create device and bind file ops
+ cdev_init(&gsoc_dummy_device, &gsoc_dummy_dev_file_ops);
+ gsoc_dummy_device.owner = THIS_MODULE;
+
+ // add device to system
+ cdev_add(&gsoc_dummy_device, gsoc_dev, 1);
+
+ // create device node
+ dummy_device = device_create(gsoc_dummy_class, NULL, gsoc_dev, NULL, "gsoc_dummy_char_dev");
+
+ if (IS_ERR(dummy_device)) {
+ pr_err("GSoC char device could not be created.\n");
+ class_destroy(gsoc_dummy_class);
+ unregister_chrdev_region(gsoc_dev, 1);
+ return -1;
+ }
+
+ pr_info("loaded GSoC dummy driver\n");
+ return 0;
+}
+
+static void __exit gsoc_dummy_char_dev_exit_module(void)
+{
+ unregister_chrdev_region(MKDEV(major, 0), 1);
+ device_destroy(gsoc_dummy_class, MKDEV(major, 0));
+ cdev_del(&gsoc_dummy_device);
+ class_destroy(gsoc_dummy_class);
+
+ pr_info("unloaded GSoC dummy driver\n");
+}
+
+static int gsoc_char_dev_open(struct inode * inode, struct file * file)
+{
+ pr_info("Open function of GSoC dummy driver called.\n");
+ return 0;
+}
+
+static int gsoc_char_dev_close(struct inode * inode, struct file * file)
+{
+ pr_info("Close function of GSoC dummy driver called.\n");
+ return 0;
+}
+
+static ssize_t gsoc_char_dev_read(struct file *file, char __user * buf, size_t count, loff_t * offset)
+{
+ pr_info("Read function of GSoC dummy driver called.\n");
+ return 0;
+}
+
+static ssize_t gsoc_char_dev_write(struct file * file, const char __user * buf, size_t count, loff_t * offset)
+{
+ pr_info("Write function of GSoC dummy driver called.\n");
+ return count;
+}
+
+static int gsoc_char_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ add_uevent_var(env, "DEVMODE=%#o", 0666);
+ return 0;
+}
+
+module_init(gsoc_dummy_char_dev_init_module);
+module_exit(gsoc_dummy_char_dev_exit_module);
+
+MODULE_AUTHOR("Niklas Wantrupp ");
+MODULE_DESCRIPTION("GSoC warm up dummy char device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 01b8868b9bed2..d5ac183bf39c9 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1305,28 +1305,27 @@ static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
return *ptr;
}
-void add_interrupt_randomness(int irq, int irq_flags)
+void add_interrupt_randomness(int irq, int irq_flags, __u64 ip)
{
struct entropy_store *r;
struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
- struct pt_regs *regs = get_irq_regs();
unsigned long now = jiffies;
cycles_t cycles = random_get_entropy();
__u32 c_high, j_high;
- __u64 ip;
unsigned long seed;
int credit = 0;
if (cycles == 0)
- cycles = get_reg(fast_pool, regs);
+ cycles = get_reg(fast_pool, NULL);
c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
j_high = (sizeof(now) > 4) ? now >> 32 : 0;
fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
fast_pool->pool[1] ^= now ^ c_high;
- ip = regs ? instruction_pointer(regs) : _RET_IP_;
+ if (!ip)
+ ip = _RET_IP_;
fast_pool->pool[2] ^= ip;
fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
- get_reg(fast_pool, regs);
+ get_reg(fast_pool, NULL);
fast_mix(fast_pool);
add_interrupt_bench(cycles);
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c
index 87f4493402021..06a3a1fed42f6 100644
--- a/drivers/char/tpm/tpm-dev-common.c
+++ b/drivers/char/tpm/tpm-dev-common.c
@@ -20,7 +20,6 @@
#include "tpm-dev.h"
static struct workqueue_struct *tpm_dev_wq;
-static DEFINE_MUTEX(tpm_dev_wq_lock);
static ssize_t tpm_dev_transmit(struct tpm_chip *chip, struct tpm_space *space,
u8 *buf, size_t bufsiz)
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index e7df342a317d6..f89057fdc0536 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -49,6 +49,31 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da
return container_of(data, struct tpm_tis_tcg_phy, priv);
}
+#ifdef CONFIG_PREEMPT_RT
+/*
+ * Flushes previous write operations to chip so that a subsequent
+ * ioread*()s won't stall a cpu.
+ */
+static inline void tpm_tis_flush(void __iomem *iobase)
+{
+ ioread8(iobase + TPM_ACCESS(0));
+}
+#else
+#define tpm_tis_flush(iobase) do { } while (0)
+#endif
+
+static inline void tpm_tis_iowrite8(u8 b, void __iomem *iobase, u32 addr)
+{
+ iowrite8(b, iobase + addr);
+ tpm_tis_flush(iobase);
+}
+
+static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
+{
+ iowrite32(b, iobase + addr);
+ tpm_tis_flush(iobase);
+}
+
static bool interrupts = true;
module_param(interrupts, bool, 0444);
MODULE_PARM_DESC(interrupts, "Enable interrupts");
@@ -146,7 +171,7 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
while (len--)
- iowrite8(*value++, phy->iobase + addr);
+ tpm_tis_iowrite8(*value++, phy->iobase, addr);
return 0;
}
@@ -173,7 +198,7 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value)
{
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
- iowrite32(value, phy->iobase + addr);
+ tpm_tis_iowrite32(value, phy->iobase, addr);
return 0;
}
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index f35a53ce8988a..d02f9c8d28487 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -434,6 +434,13 @@ config ATMEL_TCB_CLKSRC
help
Support for Timer Counter Blocks on Atmel SoCs.
+config ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
+ bool "TC Block use 32 KiHz clock"
+ depends on ATMEL_TCB_CLKSRC
+ default y
+ help
+ Select this to use 32 KiHz base clock rate as TC block clock.
+
config CLKSRC_EXYNOS_MCT
bool "Exynos multi core timer driver" if COMPILE_TEST
depends on ARM || ARM64
diff --git a/drivers/clocksource/timer-atmel-tcb.c b/drivers/clocksource/timer-atmel-tcb.c
index 7427b07495a89..ce6627ee161fe 100644
--- a/drivers/clocksource/timer-atmel-tcb.c
+++ b/drivers/clocksource/timer-atmel-tcb.c
@@ -28,8 +28,7 @@
* this 32 bit free-running counter. the second channel is not used.
*
* - The third channel may be used to provide a 16-bit clockevent
- * source, used in either periodic or oneshot mode. This runs
- * at 32 KiHZ, and can handle delays of up to two seconds.
+ * source, used in either periodic or oneshot mode.
*
* REVISIT behavior during system suspend states... we should disable
* all clocks and save the power. Easily done for clockevent devices,
@@ -143,6 +142,8 @@ static unsigned long notrace tc_delay_timer_read32(void)
struct tc_clkevt_device {
struct clock_event_device clkevt;
struct clk *clk;
+ bool clk_enabled;
+ u32 freq;
void __iomem *regs;
};
@@ -151,15 +152,26 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt)
return container_of(clkevt, struct tc_clkevt_device, clkevt);
}
-/* For now, we always use the 32K clock ... this optimizes for NO_HZ,
- * because using one of the divided clocks would usually mean the
- * tick rate can never be less than several dozen Hz (vs 0.5 Hz).
- *
- * A divided clock could be good for high resolution timers, since
- * 30.5 usec resolution can seem "low".
- */
static u32 timer_clock;
+static void tc_clk_disable(struct clock_event_device *d)
+{
+ struct tc_clkevt_device *tcd = to_tc_clkevt(d);
+
+ clk_disable(tcd->clk);
+ tcd->clk_enabled = false;
+}
+
+static void tc_clk_enable(struct clock_event_device *d)
+{
+ struct tc_clkevt_device *tcd = to_tc_clkevt(d);
+
+ if (tcd->clk_enabled)
+ return;
+ clk_enable(tcd->clk);
+ tcd->clk_enabled = true;
+}
+
static int tc_shutdown(struct clock_event_device *d)
{
struct tc_clkevt_device *tcd = to_tc_clkevt(d);
@@ -167,8 +179,14 @@ static int tc_shutdown(struct clock_event_device *d)
writel(0xff, regs + ATMEL_TC_REG(2, IDR));
writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
+ return 0;
+}
+
+static int tc_shutdown_clk_off(struct clock_event_device *d)
+{
+ tc_shutdown(d);
if (!clockevent_state_detached(d))
- clk_disable(tcd->clk);
+ tc_clk_disable(d);
return 0;
}
@@ -181,9 +199,9 @@ static int tc_set_oneshot(struct clock_event_device *d)
if (clockevent_state_oneshot(d) || clockevent_state_periodic(d))
tc_shutdown(d);
- clk_enable(tcd->clk);
+ tc_clk_enable(d);
- /* slow clock, count up to RC, then irq and stop */
+ /* count up to RC, then irq and stop */
writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |
ATMEL_TC_WAVESEL_UP_AUTO, regs + ATMEL_TC_REG(2, CMR));
writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
@@ -203,12 +221,12 @@ static int tc_set_periodic(struct clock_event_device *d)
/* By not making the gentime core emulate periodic mode on top
* of oneshot, we get lower overhead and improved accuracy.
*/
- clk_enable(tcd->clk);
+ tc_clk_enable(d);
- /* slow clock, count up to RC, then irq and restart */
+ /* count up to RC, then irq and restart */
writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
regs + ATMEL_TC_REG(2, CMR));
- writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
+ writel((tcd->freq + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
/* Enable clock and interrupts on RC compare */
writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
@@ -234,9 +252,13 @@ static struct tc_clkevt_device clkevt = {
.features = CLOCK_EVT_FEAT_PERIODIC |
CLOCK_EVT_FEAT_ONESHOT,
/* Should be lower than at91rm9200's system timer */
+#ifdef CONFIG_ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
.rating = 125,
+#else
+ .rating = 200,
+#endif
.set_next_event = tc_next_event,
- .set_state_shutdown = tc_shutdown,
+ .set_state_shutdown = tc_shutdown_clk_off,
.set_state_periodic = tc_set_periodic,
.set_state_oneshot = tc_set_oneshot,
},
@@ -256,8 +278,11 @@ static irqreturn_t ch2_irq(int irq, void *handle)
return IRQ_NONE;
}
-static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
+static const u8 atmel_tcb_divisors[5] = { 2, 8, 32, 128, 0, };
+
+static int __init setup_clkevents(struct atmel_tc *tc, int divisor_idx)
{
+ unsigned divisor = atmel_tcb_divisors[divisor_idx];
int ret;
struct clk *t2_clk = tc->clk[2];
int irq = tc->irq[2];
@@ -278,7 +303,11 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
clkevt.regs = tc->regs;
clkevt.clk = t2_clk;
- timer_clock = clk32k_divisor_idx;
+ timer_clock = divisor_idx;
+ if (!divisor)
+ clkevt.freq = 32768;
+ else
+ clkevt.freq = clk_get_rate(t2_clk) / divisor;
clkevt.clkevt.cpumask = cpumask_of(0);
@@ -289,7 +318,7 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
return ret;
}
- clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff);
+ clockevents_config_and_register(&clkevt.clkevt, clkevt.freq, 1, 0xffff);
return ret;
}
@@ -346,8 +375,6 @@ static void __init tcb_setup_single_chan(struct atmel_tc *tc, int mck_divisor_id
writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
}
-static const u8 atmel_tcb_divisors[5] = { 2, 8, 32, 128, 0, };
-
static const struct of_device_id atmel_tcb_of_match[] = {
{ .compatible = "atmel,at91rm9200-tcb", .data = (void *)16, },
{ .compatible = "atmel,at91sam9x5-tcb", .data = (void *)32, },
@@ -467,7 +494,11 @@ static int __init tcb_clksrc_init(struct device_node *node)
goto err_disable_t1;
/* channel 2: periodic and oneshot timer support */
+#ifdef CONFIG_ATMEL_TCB_CLKSRC_USE_SLOW_CLOCK
ret = setup_clkevents(&tc, clk32k_divisor_idx);
+#else
+ ret = setup_clkevents(&tc, best_divisor_idx);
+#endif
if (ret)
goto err_unregister_clksrc;
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index d58ce664da843..1b2e9f19c98df 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -18,6 +18,7 @@
#include
#include
+#include
/*
* Size of a cn_msg followed by a proc_event structure. Since the
@@ -40,10 +41,11 @@ static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC };
/* proc_event_counts is used as the sequence number of the netlink message */
static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 };
+static DEFINE_LOCAL_IRQ_LOCK(send_msg_lock);
static inline void send_msg(struct cn_msg *msg)
{
- preempt_disable();
+ local_lock(send_msg_lock);
msg->seq = __this_cpu_inc_return(proc_event_counts) - 1;
((struct proc_event *)msg->data)->cpu = smp_processor_id();
@@ -56,7 +58,7 @@ static inline void send_msg(struct cn_msg *msg)
*/
cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_NOWAIT);
- preempt_enable();
+ local_unlock(send_msg_lock);
}
void proc_fork_connector(struct task_struct *task)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index a147949511436..9011c200dc00b 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -214,7 +214,7 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
return 0;
retry:
- seq = read_seqcount_begin(&resv->seq);
+ seq = read_seqbegin(&resv->seq);
rcu_read_lock();
fobj = rcu_dereference(resv->fence);
@@ -223,7 +223,7 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
else
shared_count = 0;
fence_excl = rcu_dereference(resv->fence_excl);
- if (read_seqcount_retry(&resv->seq, seq)) {
+ if (read_seqretry(&resv->seq, seq)) {
rcu_read_unlock();
goto retry;
}
@@ -1188,12 +1188,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
robj = buf_obj->resv;
while (true) {
- seq = read_seqcount_begin(&robj->seq);
+ seq = read_seqbegin(&robj->seq);
rcu_read_lock();
fobj = rcu_dereference(robj->fence);
shared_count = fobj ? fobj->shared_count : 0;
fence = rcu_dereference(robj->fence_excl);
- if (!read_seqcount_retry(&robj->seq, seq))
+ if (!read_seqretry(&robj->seq, seq))
break;
rcu_read_unlock();
}
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 709002515550c..b0c0d4fe0b331 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -49,12 +49,6 @@
DEFINE_WD_CLASS(reservation_ww_class);
EXPORT_SYMBOL(reservation_ww_class);
-struct lock_class_key reservation_seqcount_class;
-EXPORT_SYMBOL(reservation_seqcount_class);
-
-const char reservation_seqcount_string[] = "reservation_seqcount";
-EXPORT_SYMBOL(reservation_seqcount_string);
-
/**
* dma_resv_list_alloc - allocate fence list
* @shared_max: number of fences we need space for
@@ -103,8 +97,7 @@ void dma_resv_init(struct dma_resv *obj)
{
ww_mutex_init(&obj->lock, &reservation_ww_class);
- __seqcount_init(&obj->seq, reservation_seqcount_string,
- &reservation_seqcount_class);
+ seqlock_init(&obj->seq);
RCU_INIT_POINTER(obj->fence, NULL);
RCU_INIT_POINTER(obj->fence_excl, NULL);
}
@@ -234,8 +227,7 @@ void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)
fobj = dma_resv_get_list(obj);
count = fobj->shared_count;
- preempt_disable();
- write_seqcount_begin(&obj->seq);
+ write_seqlock(&obj->seq);
for (i = 0; i < count; ++i) {
@@ -255,8 +247,7 @@ void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)
/* pointer update must be visible before we extend the shared_count */
smp_store_mb(fobj->shared_count, count);
- write_seqcount_end(&obj->seq);
- preempt_enable();
+ write_sequnlock(&obj->seq);
dma_fence_put(old);
}
EXPORT_SYMBOL(dma_resv_add_shared_fence);
@@ -283,14 +274,12 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
if (fence)
dma_fence_get(fence);
- preempt_disable();
- write_seqcount_begin(&obj->seq);
- /* write_seqcount_begin provides the necessary memory barrier */
+ write_seqlock(&obj->seq);
+ /* write_seqlock provides the necessary memory barrier */
RCU_INIT_POINTER(obj->fence_excl, fence);
if (old)
old->shared_count = 0;
- write_seqcount_end(&obj->seq);
- preempt_enable();
+ write_sequnlock(&obj->seq);
/* inplace update, no shared fences */
while (i--)
@@ -368,13 +357,11 @@ int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
src_list = dma_resv_get_list(dst);
old = dma_resv_get_excl(dst);
- preempt_disable();
- write_seqcount_begin(&dst->seq);
- /* write_seqcount_begin provides the necessary memory barrier */
+ write_seqlock(&dst->seq);
+ /* write_seqlock provides the necessary memory barrier */
RCU_INIT_POINTER(dst->fence_excl, new);
RCU_INIT_POINTER(dst->fence, dst_list);
- write_seqcount_end(&dst->seq);
- preempt_enable();
+ write_sequnlock(&dst->seq);
dma_resv_list_free(src_list);
dma_fence_put(old);
@@ -414,7 +401,7 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
shared_count = i = 0;
rcu_read_lock();
- seq = read_seqcount_begin(&obj->seq);
+ seq = read_seqbegin(&obj->seq);
fence_excl = rcu_dereference(obj->fence_excl);
if (fence_excl && !dma_fence_get_rcu(fence_excl))
@@ -456,7 +443,7 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
}
}
- if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
+ if (i != shared_count || read_seqretry(&obj->seq, seq)) {
while (i--)
dma_fence_put(shared[i]);
dma_fence_put(fence_excl);
@@ -507,7 +494,7 @@ long dma_resv_wait_timeout_rcu(struct dma_resv *obj,
retry:
shared_count = 0;
- seq = read_seqcount_begin(&obj->seq);
+ seq = read_seqbegin(&obj->seq);
rcu_read_lock();
i = -1;
@@ -553,7 +540,7 @@ long dma_resv_wait_timeout_rcu(struct dma_resv *obj,
rcu_read_unlock();
if (fence) {
- if (read_seqcount_retry(&obj->seq, seq)) {
+ if (read_seqretry(&obj->seq, seq)) {
dma_fence_put(fence);
goto retry;
}
@@ -607,7 +594,7 @@ bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all)
retry:
ret = true;
shared_count = 0;
- seq = read_seqcount_begin(&obj->seq);
+ seq = read_seqbegin(&obj->seq);
if (test_all) {
unsigned i;
@@ -627,7 +614,7 @@ bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all)
break;
}
- if (read_seqcount_retry(&obj->seq, seq))
+ if (read_seqretry(&obj->seq, seq))
goto retry;
}
@@ -639,7 +626,7 @@ bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all)
if (ret < 0)
goto retry;
- if (read_seqcount_retry(&obj->seq, seq))
+ if (read_seqretry(&obj->seq, seq))
goto retry;
}
}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 34d41f67b54d1..2ee32b046f260 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -68,7 +68,7 @@ struct mm_struct efi_mm = {
struct workqueue_struct *efi_rts_wq;
-static bool disable_runtime;
+static bool disable_runtime = IS_ENABLED(CONFIG_PREEMPT_RT);
static int __init setup_noefi(char *arg)
{
disable_runtime = true;
@@ -94,6 +94,9 @@ static int __init parse_efi_cmdline(char *str)
if (parse_option_str(str, "noruntime"))
disable_runtime = true;
+ if (parse_option_str(str, "runtime"))
+ disable_runtime = false;
+
return 0;
}
early_param("efi", parse_efi_cmdline);
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 233d94be81810..399c456e0b41d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -399,7 +399,7 @@ config DRM_R128
config DRM_I810
tristate "Intel I810"
- # !PREEMPT because of missing ioctl locking
+ # !PREEMPTION because of missing ioctl locking
depends on DRM && AGP && AGP_INTEL && (!PREEMPTION || BROKEN)
help
Choose this option if you have an Intel I810 graphics card. If M is
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 6d021ecc8d598..52f77b7701c03 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -252,11 +252,9 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
new->shared_count = k;
/* Install the new fence list, seqcount provides the barriers */
- preempt_disable();
- write_seqcount_begin(&resv->seq);
+ write_seqlock(&resv->seq);
RCU_INIT_POINTER(resv->fence, new);
- write_seqcount_end(&resv->seq);
- preempt_enable();
+ write_sequnlock(&resv->seq);
/* Drop the references to the removed fences or move them to ef_list */
for (i = j, k = 0; i < old->shared_count; ++i) {
diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index 41c8e39a73ba8..00786a142ff09 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -7,6 +7,7 @@ config DRM_I915_WERROR
# We use the dependency on !COMPILE_TEST to not be enabled in
# allmodconfig or allyesconfig configurations
depends on !COMPILE_TEST
+ select HEADER_TEST
default n
help
Add -Werror to the build flags for (and only for) i915.ko.
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index cae25e493128d..da71ac8dea356 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include "i915_drv.h"
#include "i915_trace.h"
@@ -80,6 +81,8 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
#define VBLANK_EVASION_TIME_US 100
#endif
+static DEFINE_LOCAL_IRQ_LOCK(pipe_update_lock);
+
/**
* intel_pipe_update_start() - start update of a set of display registers
* @new_crtc_state: the new crtc state
@@ -129,7 +132,7 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
psr_status);
- local_irq_disable();
+ local_lock_irq(pipe_update_lock);
crtc->debug.min_vbl = min;
crtc->debug.max_vbl = max;
@@ -153,11 +156,11 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
break;
}
- local_irq_enable();
+ local_unlock_irq(pipe_update_lock);
timeout = schedule_timeout(timeout);
- local_irq_disable();
+ local_lock_irq(pipe_update_lock);
}
finish_wait(wq, &wait);
@@ -190,7 +193,7 @@ void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
return;
irq_disable:
- local_irq_disable();
+ local_lock_irq(pipe_update_lock);
}
/**
@@ -226,7 +229,7 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
new_crtc_state->base.event = NULL;
}
- local_irq_enable();
+ local_unlock_irq(pipe_update_lock);
if (intel_vgpu_active(dev_priv))
return;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
index 25235ef630c10..eaa8735aabee2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -75,7 +75,6 @@ busy_check_writer(const struct dma_fence *fence)
return __busy_set_if_active(fence, __busy_write_id);
}
-
int
i915_gem_busy_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
@@ -110,7 +109,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
*
*/
retry:
- seq = raw_read_seqcount(&obj->base.resv->seq);
+ /* XXX raw_read_seqcount() does not wait for the WRTIE to finish */
+ seq = read_seqbegin(&obj->base.resv->seq);
/* Translate the exclusive fence to the READ *and* WRITE engine */
args->busy =
@@ -129,7 +129,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
}
}
- if (args->busy && read_seqcount_retry(&obj->base.resv->seq, seq))
+ if (args->busy && read_seqretry(&obj->base.resv->seq, seq))
goto retry;
err = 0;
diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
index 09c68dda20988..55317081d48b0 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
@@ -120,7 +120,6 @@ __dma_fence_signal__notify(struct dma_fence *fence,
struct dma_fence_cb *cur, *tmp;
lockdep_assert_held(fence->lock);
- lockdep_assert_irqs_disabled();
list_for_each_entry_safe(cur, tmp, list, node) {
INIT_LIST_HEAD(&cur->node);
@@ -134,9 +133,10 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
const ktime_t timestamp = ktime_get();
struct intel_context *ce, *cn;
struct list_head *pos, *next;
+ unsigned long flags;
LIST_HEAD(signal);
- spin_lock(&b->irq_lock);
+ spin_lock_irqsave(&b->irq_lock, flags);
if (b->irq_armed && list_empty(&b->signalers))
__intel_breadcrumbs_disarm_irq(b);
@@ -182,30 +182,23 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
}
}
- spin_unlock(&b->irq_lock);
+ spin_unlock_irqrestore(&b->irq_lock, flags);
list_for_each_safe(pos, next, &signal) {
struct i915_request *rq =
list_entry(pos, typeof(*rq), signal_link);
struct list_head cb_list;
- spin_lock(&rq->lock);
+ spin_lock_irqsave(&rq->lock, flags);
list_replace(&rq->fence.cb_list, &cb_list);
__dma_fence_signal__timestamp(&rq->fence, timestamp);
__dma_fence_signal__notify(&rq->fence, &cb_list);
- spin_unlock(&rq->lock);
+ spin_unlock_irqrestore(&rq->lock, flags);
i915_request_put(rq);
}
}
-void intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine)
-{
- local_irq_disable();
- intel_engine_breadcrumbs_irq(engine);
- local_irq_enable();
-}
-
static void signal_irq_work(struct irq_work *work)
{
struct intel_engine_cs *engine =
@@ -275,7 +268,6 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
bool i915_request_enable_breadcrumb(struct i915_request *rq)
{
lockdep_assert_held(&rq->lock);
- lockdep_assert_irqs_disabled();
if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) {
struct intel_breadcrumbs *b = &rq->engine->breadcrumbs;
@@ -325,7 +317,6 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq)
struct intel_breadcrumbs *b = &rq->engine->breadcrumbs;
lockdep_assert_held(&rq->lock);
- lockdep_assert_irqs_disabled();
/*
* We must wait for b->irq_lock so that we know the interrupt handler
diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h
index 22aab8593abfa..316dccb41da80 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -349,7 +349,6 @@ void intel_engine_init_execlists(struct intel_engine_cs *engine);
void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine);
void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
-void intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine);
void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine);
static inline void
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
index 65b5ca74b3947..0e48a3d8ea22c 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
@@ -38,12 +38,15 @@ static int __engine_unpark(struct intel_wakeref *wf)
}
#if IS_ENABLED(CONFIG_LOCKDEP)
+#include
+
+static DEFINE_LOCAL_IRQ_LOCK(timeline_lock);
static inline unsigned long __timeline_mark_lock(struct intel_context *ce)
{
unsigned long flags;
- local_irq_save(flags);
+ local_lock_irqsave(timeline_lock, flags);
mutex_acquire(&ce->timeline->mutex.dep_map, 2, 0, _THIS_IP_);
return flags;
@@ -53,7 +56,7 @@ static inline void __timeline_mark_unlock(struct intel_context *ce,
unsigned long flags)
{
mutex_release(&ce->timeline->mutex.dep_map, 0, _THIS_IP_);
- local_irq_restore(flags);
+ local_unlock_irqrestore(timeline_lock, flags);
}
#else
diff --git a/drivers/gpu/drm/i915/gt/intel_hangcheck.c b/drivers/gpu/drm/i915/gt/intel_hangcheck.c
index 05d042cdefe24..7ca67aac27d4d 100644
--- a/drivers/gpu/drm/i915/gt/intel_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/intel_hangcheck.c
@@ -283,7 +283,7 @@ static void hangcheck_elapsed(struct work_struct *work)
for_each_engine(engine, gt->i915, id) {
struct hangcheck hc;
- intel_engine_signal_breadcrumbs(engine);
+ intel_engine_breadcrumbs_irq(engine);
hangcheck_load_sample(engine, &hc);
hangcheck_accumulate_sample(engine, &hc);
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
index 8cea42379dd79..05f965e2e132e 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -695,7 +695,7 @@ static void reset_finish_engine(struct intel_engine_cs *engine)
engine->reset.finish(engine);
intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL);
- intel_engine_signal_breadcrumbs(engine);
+ intel_engine_breadcrumbs_irq(engine);
}
static void reset_finish(struct intel_gt *gt, intel_engine_mask_t awake)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 37e3dd3c1a9dc..9a482fb0f4afa 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -983,6 +983,7 @@ bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
/* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
+ preempt_disable_rt();
/* Get optional system timestamp before query. */
if (stime)
@@ -1034,6 +1035,7 @@ bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
*etime = ktime_get();
/* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
+ preempt_enable_rt();
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 1c5506822dc72..cf10246fb01ad 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -205,14 +205,14 @@ static void remove_from_engine(struct i915_request *rq)
* check that the rq still belongs to the newly locked engine.
*/
locked = READ_ONCE(rq->engine);
- spin_lock(&locked->active.lock);
+ spin_lock_irq(&locked->active.lock);
while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) {
spin_unlock(&locked->active.lock);
spin_lock(&engine->active.lock);
locked = engine;
}
list_del(&rq->sched.link);
- spin_unlock(&locked->active.lock);
+ spin_unlock_irq(&locked->active.lock);
}
static bool i915_request_retire(struct i915_request *rq)
@@ -272,8 +272,6 @@ static bool i915_request_retire(struct i915_request *rq)
active->retire(active, rq);
}
- local_irq_disable();
-
/*
* We only loosely track inflight requests across preemption,
* and so we may find ourselves attempting to retire a _completed_
@@ -282,7 +280,7 @@ static bool i915_request_retire(struct i915_request *rq)
*/
remove_from_engine(rq);
- spin_lock(&rq->lock);
+ spin_lock_irq(&rq->lock);
i915_request_mark_complete(rq);
if (!i915_request_signaled(rq))
dma_fence_signal_locked(&rq->fence);
@@ -297,9 +295,7 @@ static bool i915_request_retire(struct i915_request *rq)
__notify_execute_cb(rq);
}
GEM_BUG_ON(!list_empty(&rq->execute_cb));
- spin_unlock(&rq->lock);
-
- local_irq_enable();
+ spin_unlock_irq(&rq->lock);
remove_from_client(rq);
list_del(&rq->link);
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 24f2944da09de..b8ee3cd14323d 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -2,6 +2,10 @@
#if !defined(_I915_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
#define _I915_TRACE_H_
+#ifdef CONFIG_PREEMPT_RT
+#define NOTRACE
+#endif
+
#include
#include
#include
@@ -721,7 +725,7 @@ DEFINE_EVENT(i915_request, i915_request_add,
TP_ARGS(rq)
);
-#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS)
+#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS) && !defined(NOTRACE)
DEFINE_EVENT(i915_request, i915_request_submit,
TP_PROTO(struct i915_request *rq),
TP_ARGS(rq)
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index e81b01f8db90e..b07e4684c2c40 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1819,6 +1819,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
struct radeon_device *rdev = dev->dev_private;
/* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
+ preempt_disable_rt();
/* Get optional system timestamp before query. */
if (stime)
@@ -1911,6 +1912,7 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
*etime = ktime_get();
/* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
+ preempt_enable_rt();
/* Decode into vertical and horizontal scanout position. */
*vpos = position & 0x1fff;
diff --git a/drivers/greybus/connection.c b/drivers/greybus/connection.c
index fc8f57f97ce62..e3799a53a1930 100644
--- a/drivers/greybus/connection.c
+++ b/drivers/greybus/connection.c
@@ -361,9 +361,6 @@ static int gb_connection_hd_cport_quiesce(struct gb_connection *connection)
if (connection->mode_switch)
peer_space += sizeof(struct gb_operation_msg_hdr);
- if (!hd->driver->cport_quiesce)
- return 0;
-
ret = hd->driver->cport_quiesce(hd, connection->hd_cport_id,
peer_space,
GB_CONNECTION_CPORT_QUIESCE_TIMEOUT);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index af9379a3bf899..0b1ef04302d4a 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include "hv_trace.h"
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 05ead1735c6e3..1bf1f1acc18c1 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include
#include
@@ -1199,6 +1200,8 @@ static void vmbus_isr(void)
void *page_addr = hv_cpu->synic_event_page;
struct hv_message *msg;
union hv_synic_event_flags *event;
+ struct pt_regs *regs = get_irq_regs();
+ u64 ip = regs ? instruction_pointer(regs) : 0;
bool handled = false;
if (unlikely(page_addr == NULL))
@@ -1243,7 +1246,7 @@ static void vmbus_isr(void)
tasklet_schedule(&hv_cpu->msg_dpc);
}
- add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
+ add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0, ip);
}
/*
diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig
index ce9429ca6ddea..29ccbd6acf43f 100644
--- a/drivers/leds/trigger/Kconfig
+++ b/drivers/leds/trigger/Kconfig
@@ -64,6 +64,7 @@ config LEDS_TRIGGER_BACKLIGHT
config LEDS_TRIGGER_CPU
bool "LED CPU Trigger"
+ depends on !PREEMPT_RT
help
This allows LEDs to be controlled by active CPUs. This shows
the active CPUs across an array of LEDs so you can see which
diff --git a/drivers/md/bcache/Kconfig b/drivers/md/bcache/Kconfig
index 6dfa653d30db7..29c35eb524148 100644
--- a/drivers/md/bcache/Kconfig
+++ b/drivers/md/bcache/Kconfig
@@ -2,6 +2,7 @@
config BCACHE
tristate "Block device as cache"
+ depends on !PREEMPT_RT
select CRC64
help
Allows a block device to be used as cache for other devices; uses
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 36cd7c2fbf408..aa66d14036e75 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2058,8 +2058,9 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
struct raid5_percpu *percpu;
unsigned long cpu;
- cpu = get_cpu();
+ cpu = get_cpu_light();
percpu = per_cpu_ptr(conf->percpu, cpu);
+ spin_lock(&percpu->lock);
if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) {
ops_run_biofill(sh);
overlap_clear++;
@@ -2118,7 +2119,8 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
if (test_and_clear_bit(R5_Overlap, &dev->flags))
wake_up(&sh->raid_conf->wait_for_overlap);
}
- put_cpu();
+ spin_unlock(&percpu->lock);
+ put_cpu_light();
}
static void free_stripe(struct kmem_cache *sc, struct stripe_head *sh)
@@ -6821,6 +6823,7 @@ static int raid456_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
__func__, cpu);
return -ENOMEM;
}
+ spin_lock_init(&per_cpu_ptr(conf->percpu, cpu)->lock);
return 0;
}
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index f90e0704bed99..cca69edd669da 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -634,6 +634,7 @@ struct r5conf {
int recovery_disabled;
/* per cpu variables */
struct raid5_percpu {
+ spinlock_t lock; /* Protection for -RT */
struct page *spare_page; /* Used when checking P/Q in raid6 */
void *scribble; /* space for constructing buffer
* lists and performing address
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index ee5199d5b8a7d..55f86fcb7790f 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -598,7 +598,7 @@ config VIDEO_MESON_G12A_AO_CEC
config CEC_GPIO
tristate "Generic GPIO-based CEC driver"
- depends on PREEMPT || COMPILE_TEST
+ depends on PREEMPTION || COMPILE_TEST
select CEC_CORE
select CEC_PIN
select GPIOLIB
diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
index 8c79b963bcffb..d000528b9e011 100644
--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
@@ -693,8 +693,8 @@ static void ezusb_req_ctx_wait(struct ezusb_priv *upriv,
while (!ctx->done.done && msecs--)
udelay(1000);
} else {
- wait_event_interruptible(ctx->done.wait,
- ctx->done.done);
+ swait_event_interruptible_exclusive(ctx->done.wait,
+ ctx->done.done);
}
break;
default:
diff --git a/drivers/of/base.c b/drivers/of/base.c
index db7fbc0c0893c..f7da162f126d6 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -135,115 +135,38 @@ int __weak of_node_to_nid(struct device_node *np)
}
#endif
-/*
- * Assumptions behind phandle_cache implementation:
- * - phandle property values are in a contiguous range of 1..n
- *
- * If the assumptions do not hold, then
- * - the phandle lookup overhead reduction provided by the cache
- * will likely be less
- */
+#define OF_PHANDLE_CACHE_BITS 7
+#define OF_PHANDLE_CACHE_SZ BIT(OF_PHANDLE_CACHE_BITS)
-static struct device_node **phandle_cache;
-static u32 phandle_cache_mask;
+static struct device_node *phandle_cache[OF_PHANDLE_CACHE_SZ];
-/*
- * Caller must hold devtree_lock.
- */
-static void __of_free_phandle_cache(void)
+static u32 of_phandle_cache_hash(phandle handle)
{
- u32 cache_entries = phandle_cache_mask + 1;
- u32 k;
-
- if (!phandle_cache)
- return;
-
- for (k = 0; k < cache_entries; k++)
- of_node_put(phandle_cache[k]);
-
- kfree(phandle_cache);
- phandle_cache = NULL;
+ return hash_32(handle, OF_PHANDLE_CACHE_BITS);
}
-int of_free_phandle_cache(void)
-{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&devtree_lock, flags);
-
- __of_free_phandle_cache();
-
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
-
- return 0;
-}
-#if !defined(CONFIG_MODULES)
-late_initcall_sync(of_free_phandle_cache);
-#endif
-
/*
* Caller must hold devtree_lock.
*/
-void __of_free_phandle_cache_entry(phandle handle)
+void __of_phandle_cache_inv_entry(phandle handle)
{
- phandle masked_handle;
+ u32 handle_hash;
struct device_node *np;
if (!handle)
return;
- masked_handle = handle & phandle_cache_mask;
+ handle_hash = of_phandle_cache_hash(handle);
- if (phandle_cache) {
- np = phandle_cache[masked_handle];
- if (np && handle == np->phandle) {
- of_node_put(np);
- phandle_cache[masked_handle] = NULL;
- }
- }
-}
-
-void of_populate_phandle_cache(void)
-{
- unsigned long flags;
- u32 cache_entries;
- struct device_node *np;
- u32 phandles = 0;
-
- raw_spin_lock_irqsave(&devtree_lock, flags);
-
- __of_free_phandle_cache();
-
- for_each_of_allnodes(np)
- if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
- phandles++;
-
- if (!phandles)
- goto out;
-
- cache_entries = roundup_pow_of_two(phandles);
- phandle_cache_mask = cache_entries - 1;
-
- phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache),
- GFP_ATOMIC);
- if (!phandle_cache)
- goto out;
-
- for_each_of_allnodes(np)
- if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) {
- of_node_get(np);
- phandle_cache[np->phandle & phandle_cache_mask] = np;
- }
-
-out:
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
+ np = phandle_cache[handle_hash];
+ if (np && handle == np->phandle)
+ phandle_cache[handle_hash] = NULL;
}
void __init of_core_init(void)
{
struct device_node *np;
- of_populate_phandle_cache();
/* Create the kset, and register existing nodes */
mutex_lock(&of_mutex);
@@ -253,8 +176,11 @@ void __init of_core_init(void)
pr_err("failed to register existing nodes\n");
return;
}
- for_each_of_allnodes(np)
+ for_each_of_allnodes(np) {
__of_attach_node_sysfs(np);
+ if (np->phandle && !phandle_cache[of_phandle_cache_hash(np->phandle)])
+ phandle_cache[of_phandle_cache_hash(np->phandle)] = np;
+ }
mutex_unlock(&of_mutex);
/* Symlink in /proc as required by userspace ABI */
@@ -1235,36 +1161,29 @@ struct device_node *of_find_node_by_phandle(phandle handle)
{
struct device_node *np = NULL;
unsigned long flags;
- phandle masked_handle;
+ u32 handle_hash;
if (!handle)
return NULL;
+ handle_hash = of_phandle_cache_hash(handle);
+
raw_spin_lock_irqsave(&devtree_lock, flags);
- masked_handle = handle & phandle_cache_mask;
-
- if (phandle_cache) {
- if (phandle_cache[masked_handle] &&
- handle == phandle_cache[masked_handle]->phandle)
- np = phandle_cache[masked_handle];
- if (np && of_node_check_flag(np, OF_DETACHED)) {
- WARN_ON(1); /* did not uncache np on node removal */
- of_node_put(np);
- phandle_cache[masked_handle] = NULL;
- np = NULL;
- }
+ if (phandle_cache[handle_hash] &&
+ handle == phandle_cache[handle_hash]->phandle)
+ np = phandle_cache[handle_hash];
+ if (np && of_node_check_flag(np, OF_DETACHED)) {
+ WARN_ON(1); /* did not uncache np on node removal */
+ phandle_cache[handle_hash] = NULL;
+ np = NULL;
}
if (!np) {
for_each_of_allnodes(np)
if (np->phandle == handle &&
!of_node_check_flag(np, OF_DETACHED)) {
- if (phandle_cache) {
- /* will put when removed from cache */
- of_node_get(np);
- phandle_cache[masked_handle] = np;
- }
+ phandle_cache[handle_hash] = np;
break;
}
}
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 49b16f76d78e8..08fd823edac9d 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -276,7 +276,7 @@ void __of_detach_node(struct device_node *np)
of_node_set_flag(np, OF_DETACHED);
/* race with of_find_node_by_phandle() prevented by devtree_lock */
- __of_free_phandle_cache_entry(np->phandle);
+ __of_phandle_cache_inv_entry(np->phandle);
}
/**
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 66294d29942ae..582844c158ae6 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -85,14 +85,12 @@ int of_resolve_phandles(struct device_node *tree);
#endif
#if defined(CONFIG_OF_DYNAMIC)
-void __of_free_phandle_cache_entry(phandle handle);
+void __of_phandle_cache_inv_entry(phandle handle);
#endif
#if defined(CONFIG_OF_OVERLAY)
void of_overlay_mutex_lock(void);
void of_overlay_mutex_unlock(void);
-int of_free_phandle_cache(void);
-void of_populate_phandle_cache(void);
#else
static inline void of_overlay_mutex_lock(void) {};
static inline void of_overlay_mutex_unlock(void) {};
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 9617b7df7c4da..97fe92c1f1d24 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -974,8 +974,6 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree,
goto err_free_overlay_changeset;
}
- of_populate_phandle_cache();
-
ret = __of_changeset_apply_notify(&ovcs->cset);
if (ret)
pr_err("overlay apply changeset entry notify error %d\n", ret);
@@ -1218,17 +1216,9 @@ int of_overlay_remove(int *ovcs_id)
list_del(&ovcs->ovcs_list);
- /*
- * Disable phandle cache. Avoids race condition that would arise
- * from removing cache entry when the associated node is deleted.
- */
- of_free_phandle_cache();
-
ret_apply = 0;
ret = __of_changeset_revert_entries(&ovcs->cset, &ret_apply);
- of_populate_phandle_cache();
-
if (ret) {
if (ret_apply)
devicetree_state_flags |= DTSF_REVERT_FAIL;
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
index cc43c855452f7..90d6eb310e70e 100644
--- a/drivers/pci/switch/switchtec.c
+++ b/drivers/pci/switch/switchtec.c
@@ -52,10 +52,11 @@ struct switchtec_user {
enum mrpc_state state;
- struct completion comp;
+ wait_queue_head_t cmd_comp;
struct kref kref;
struct list_head list;
+ bool cmd_done;
u32 cmd;
u32 status;
u32 return_code;
@@ -77,7 +78,7 @@ static struct switchtec_user *stuser_create(struct switchtec_dev *stdev)
stuser->stdev = stdev;
kref_init(&stuser->kref);
INIT_LIST_HEAD(&stuser->list);
- init_completion(&stuser->comp);
+ init_waitqueue_head(&stuser->cmd_comp);
stuser->event_cnt = atomic_read(&stdev->event_cnt);
dev_dbg(&stdev->dev, "%s: %p\n", __func__, stuser);
@@ -175,7 +176,7 @@ static int mrpc_queue_cmd(struct switchtec_user *stuser)
kref_get(&stuser->kref);
stuser->read_len = sizeof(stuser->data);
stuser_set_state(stuser, MRPC_QUEUED);
- init_completion(&stuser->comp);
+ stuser->cmd_done = false;
list_add_tail(&stuser->list, &stdev->mrpc_queue);
mrpc_cmd_submit(stdev);
@@ -222,7 +223,8 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data,
stuser->read_len);
out:
- complete_all(&stuser->comp);
+ stuser->cmd_done = true;
+ wake_up_interruptible(&stuser->cmd_comp);
list_del_init(&stuser->list);
stuser_put(stuser);
stdev->mrpc_busy = 0;
@@ -494,10 +496,11 @@ static ssize_t switchtec_dev_read(struct file *filp, char __user *data,
mutex_unlock(&stdev->mrpc_mutex);
if (filp->f_flags & O_NONBLOCK) {
- if (!try_wait_for_completion(&stuser->comp))
+ if (!READ_ONCE(stuser->cmd_done))
return -EAGAIN;
} else {
- rc = wait_for_completion_interruptible(&stuser->comp);
+ rc = wait_event_interruptible(stuser->cmd_comp,
+ stuser->cmd_done);
if (rc < 0)
return rc;
}
@@ -545,7 +548,7 @@ static __poll_t switchtec_dev_poll(struct file *filp, poll_table *wait)
struct switchtec_dev *stdev = stuser->stdev;
__poll_t ret = 0;
- poll_wait(filp, &stuser->comp.wait, wait);
+ poll_wait(filp, &stuser->cmd_comp, wait);
poll_wait(filp, &stdev->event_wq, wait);
if (lock_mutex_and_test_alive(stdev))
@@ -553,7 +556,7 @@ static __poll_t switchtec_dev_poll(struct file *filp, poll_table *wait)
mutex_unlock(&stdev->mrpc_mutex);
- if (try_wait_for_completion(&stuser->comp))
+ if (READ_ONCE(stuser->cmd_done))
ret |= EPOLLIN | EPOLLRDNORM;
if (stuser->event_cnt != atomic_read(&stdev->event_cnt))
@@ -1106,7 +1109,8 @@ static void stdev_kill(struct switchtec_dev *stdev)
/* Wake up and kill any users waiting on an MRPC request */
list_for_each_entry_safe(stuser, tmpuser, &stdev->mrpc_queue, list) {
- complete_all(&stuser->comp);
+ stuser->cmd_done = true;
+ wake_up_interruptible(&stuser->cmd_comp);
list_del_init(&stuser->list);
stuser_put(stuser);
}
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 25dae9f0b2055..2acc1f6da9020 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1452,11 +1452,11 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen)
{
struct fcoe_percpu_s *fps;
- int rc;
+ int rc, cpu = get_cpu_light();
- fps = &get_cpu_var(fcoe_percpu);
+ fps = &per_cpu(fcoe_percpu, cpu);
rc = fcoe_get_paged_crc_eof(skb, tlen, fps);
- put_cpu_var(fcoe_percpu);
+ put_cpu_light();
return rc;
}
@@ -1641,11 +1641,11 @@ static inline int fcoe_filter_frames(struct fc_lport *lport,
return 0;
}
- stats = per_cpu_ptr(lport->stats, get_cpu());
+ stats = per_cpu_ptr(lport->stats, get_cpu_light());
stats->InvalidCRCCount++;
if (stats->InvalidCRCCount < 5)
printk(KERN_WARNING "fcoe: dropping frame with CRC error\n");
- put_cpu();
+ put_cpu_light();
return -EINVAL;
}
@@ -1686,7 +1686,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
*/
hp = (struct fcoe_hdr *) skb_network_header(skb);
- stats = per_cpu_ptr(lport->stats, get_cpu());
+ stats = per_cpu_ptr(lport->stats, get_cpu_light());
if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
if (stats->ErrorFrames < 5)
printk(KERN_WARNING "fcoe: FCoE version "
@@ -1718,13 +1718,13 @@ static void fcoe_recv_frame(struct sk_buff *skb)
goto drop;
if (!fcoe_filter_frames(lport, fp)) {
- put_cpu();
+ put_cpu_light();
fc_exch_recv(lport, fp);
return;
}
drop:
stats->ErrorFrames++;
- put_cpu();
+ put_cpu_light();
kfree_skb(skb);
}
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 1791a393795da..8fdfae2b8782f 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -826,7 +826,7 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
INIT_LIST_HEAD(&del_list);
- stats = per_cpu_ptr(fip->lp->stats, get_cpu());
+ stats = per_cpu_ptr(fip->lp->stats, get_cpu_light());
list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2;
@@ -862,7 +862,7 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
sel_time = fcf->time;
}
}
- put_cpu();
+ put_cpu_light();
list_for_each_entry_safe(fcf, next, &del_list, list) {
/* Removes fcf from current list */
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 52e8666598531..78c75a2314228 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -821,10 +821,10 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
}
memset(ep, 0, sizeof(*ep));
- cpu = get_cpu();
+ cpu = get_cpu_light();
pool = per_cpu_ptr(mp->pool, cpu);
spin_lock_bh(&pool->lock);
- put_cpu();
+ put_cpu_light();
/* peek cache of free slot */
if (pool->left != FC_XID_UNKNOWN) {
diff --git a/drivers/staging/exfat/Kconfig b/drivers/staging/exfat/Kconfig
index ce32dfe33becd..292a19dfcaf51 100644
--- a/drivers/staging/exfat/Kconfig
+++ b/drivers/staging/exfat/Kconfig
@@ -1,50 +1,41 @@
# SPDX-License-Identifier: GPL-2.0
-config EXFAT_FS
+config STAGING_EXFAT_FS
tristate "exFAT fs support"
depends on BLOCK
select NLS
help
This adds support for the exFAT file system.
-config EXFAT_DONT_MOUNT_VFAT
- bool "Prohibit mounting of fat/vfat filesystems by exFAT"
- depends on EXFAT_FS
- default y
- help
- By default, the exFAT driver will only mount exFAT filesystems, and refuse
- to mount fat/vfat filesystems. Set this to 'n' to allow the exFAT driver
- to mount these filesystems.
-
-config EXFAT_DISCARD
+config STAGING_EXFAT_DISCARD
bool "enable discard support"
- depends on EXFAT_FS
+ depends on STAGING_EXFAT_FS
default y
-config EXFAT_DELAYED_SYNC
+config STAGING_EXFAT_DELAYED_SYNC
bool "enable delayed sync"
- depends on EXFAT_FS
+ depends on STAGING_EXFAT_FS
default n
-config EXFAT_KERNEL_DEBUG
+config STAGING_EXFAT_KERNEL_DEBUG
bool "enable kernel debug features via ioctl"
- depends on EXFAT_FS
+ depends on STAGING_EXFAT_FS
default n
-config EXFAT_DEBUG_MSG
+config STAGING_EXFAT_DEBUG_MSG
bool "print debug messages"
- depends on EXFAT_FS
+ depends on STAGING_EXFAT_FS
default n
-config EXFAT_DEFAULT_CODEPAGE
+config STAGING_EXFAT_DEFAULT_CODEPAGE
int "Default codepage for exFAT"
default 437
- depends on EXFAT_FS
+ depends on STAGING_EXFAT_FS
help
This option should be set to the codepage of your exFAT filesystems.
-config EXFAT_DEFAULT_IOCHARSET
+config STAGING_EXFAT_DEFAULT_IOCHARSET
string "Default iocharset for exFAT"
default "utf8"
- depends on EXFAT_FS
+ depends on STAGING_EXFAT_FS
help
Set this to the default input/output character set you'd like exFAT to use.
diff --git a/drivers/staging/exfat/Makefile b/drivers/staging/exfat/Makefile
index 6c90aec83febf..057556eeca0c3 100644
--- a/drivers/staging/exfat/Makefile
+++ b/drivers/staging/exfat/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
-obj-$(CONFIG_EXFAT_FS) += exfat.o
+obj-$(CONFIG_STAGING_EXFAT_FS) += exfat.o
exfat-y := exfat_core.o \
exfat_super.o \
diff --git a/drivers/staging/exfat/TODO b/drivers/staging/exfat/TODO
index a3eb282f9efc2..a283ce534cf47 100644
--- a/drivers/staging/exfat/TODO
+++ b/drivers/staging/exfat/TODO
@@ -1,8 +1,22 @@
+A laundry list of things that need looking at, most of which will
+require more work than the average checkpatch cleanup...
+
+Note that some of these entries may not be bugs - they're things
+that need to be looked at, and *possibly* fixed.
+
+Clean up the ffsCamelCase function names.
+
+Fix (thing)->flags to not use magic numbers - multiple offenders
+
+Sort out all the s32/u32/u8 nonsense - most of these should be plain int.
+
exfat_core.c - ffsReadFile - the goto err_out seem to leak a brelse().
same for ffsWriteFile.
-exfat_core.c - fs_sync(sb,0) all over the place looks fishy as hell.
-There's only one place that calls it with a non-zero argument.
+All the calls to fs_sync() need to be looked at, particularly in the
+context of EXFAT_DELAYED_SYNC. Currently, if that's defined, we only
+flush to disk when sync() gets called. We should be doing at least
+metadata flushes at appropriate times.
ffsTruncateFile - if (old_size <= new_size) {
That doesn't look right. How did it ever work? Are they relying on lazy
@@ -10,3 +24,46 @@ block allocation when actual writes happen? If nothing else, it never
does the 'fid->size = new_size' and do the inode update....
ffsSetAttr() is just dangling in the breeze, not wired up at all...
+
+Convert global mutexes to a per-superblock mutex.
+
+Right now, we load exactly one UTF-8 table. Check to see
+if that plays nice with different codepage and iocharset values
+for simultanous mounts of different devices
+
+exfat_rmdir() checks for -EBUSY but ffsRemoveDir() doesn't return it.
+In fact, there's a complete lack of -EBUSY testing anywhere.
+
+There's probably a few missing checks for -EEXIST
+
+check return codes of sync_dirty_buffer()
+
+Why is remove_file doing a num_entries++??
+
+Double check a lot of can't-happen parameter checks (for null pointers for
+things that have only one call site and can't pass a null, etc).
+
+All the DEBUG stuff can probably be tossed, including the ioctl(). Either
+that, or convert to a proper fault-injection system.
+
+exfat_remount does exactly one thing. Fix to actually deal with remount
+options, particularly handling R/O correctly. For that matter, allow
+R/O mounts in the first place.
+
+Figure out why the VFAT code used multi_sector_(read|write) but the
+exfat code doesn't use it. The difference matters on SSDs with wear leveling.
+
+exfat_fat_sync(), exfat_buf_sync(), and sync_alloc_bitmap()
+aren't called anyplace....
+
+Create helper function for exfat_set_entry_time() and exfat_set_entry_type()
+because it's sort of ugly to be calling the same functionn directly and
+other code calling through the fs_func struc ponters...
+
+clean up the remaining vol_type checks, which are of two types:
+some are ?: operators with magic numbers, and the rest are places
+where we're doing stuff with '.' and '..'.
+
+Patches to:
+ Greg Kroah-Hartman
+ Valdis Kletnieks
diff --git a/drivers/staging/exfat/exfat.h b/drivers/staging/exfat/exfat.h
index 4973c9edc26ec..4d87360fab351 100644
--- a/drivers/staging/exfat/exfat.h
+++ b/drivers/staging/exfat/exfat.h
@@ -9,7 +9,7 @@
#include
#include
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
/* For Debugging Purpose */
/* IOCTL code 'f' used by
* - file systems typically #0~0x1F
@@ -22,14 +22,16 @@
#define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01
#define EXFAT_DEBUGFLAGS_ERROR_RW 0x02
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
-#ifdef CONFIG_EXFAT_DEBUG_MSG
+#ifdef CONFIG_STAGING_EXFAT_DEBUG_MSG
#define DEBUG 1
#else
#undef DEBUG
#endif
+#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
+
#define DENTRY_SIZE 32 /* dir entry size */
#define DENTRY_SIZE_BITS 5
@@ -206,28 +208,6 @@ static inline u16 get_row_index(u16 i)
#define FM_REGULAR 0x00
#define FM_SYMLINK 0x40
-/* return values */
-#define FFS_SUCCESS 0
-#define FFS_MEDIAERR 1
-#define FFS_FORMATERR 2
-#define FFS_MOUNTED 3
-#define FFS_NOTMOUNTED 4
-#define FFS_ALIGNMENTERR 5
-#define FFS_SEMAPHOREERR 6
-#define FFS_INVALIDPATH 7
-#define FFS_INVALIDFID 8
-#define FFS_NOTFOUND 9
-#define FFS_FILEEXIST 10
-#define FFS_PERMISSIONERR 11
-#define FFS_NOTOPENED 12
-#define FFS_MAXOPENED 13
-#define FFS_FULL 14
-#define FFS_EOF 15
-#define FFS_DIRBUSY 16
-#define FFS_MEMORYERR 17
-#define FFS_NAMETOOLONG 18
-#define FFS_ERROR 19
-
#define NUM_UPCASE 2918
#define DOS_CUR_DIR_NAME ". "
@@ -536,49 +516,6 @@ struct buf_cache_t {
struct buffer_head *buf_bh;
};
-struct fs_func {
- s32 (*alloc_cluster)(struct super_block *sb, s32 num_alloc,
- struct chain_t *p_chain);
- void (*free_cluster)(struct super_block *sb, struct chain_t *p_chain,
- s32 do_relse);
- s32 (*count_used_clusters)(struct super_block *sb);
-
- s32 (*init_dir_entry)(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, u32 type, u32 start_clu, u64 size);
- s32 (*init_ext_entry)(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 num_entries,
- struct uni_name_t *p_uniname,
- struct dos_name_t *p_dosname);
- s32 (*find_dir_entry)(struct super_block *sb, struct chain_t *p_dir,
- struct uni_name_t *p_uniname, s32 num_entries,
- struct dos_name_t *p_dosname, u32 type);
- void (*delete_dir_entry)(struct super_block *sb,
- struct chain_t *p_dir, s32 entry,
- s32 offset, s32 num_entries);
- void (*get_uni_name_from_ext_entry)(struct super_block *sb,
- struct chain_t *p_dir, s32 entry,
- u16 *uniname);
- s32 (*count_ext_entries)(struct super_block *sb,
- struct chain_t *p_dir, s32 entry,
- struct dentry_t *p_entry);
- s32 (*calc_num_entries)(struct uni_name_t *p_uniname);
-
- u32 (*get_entry_type)(struct dentry_t *p_entry);
- void (*set_entry_type)(struct dentry_t *p_entry, u32 type);
- u32 (*get_entry_attr)(struct dentry_t *p_entry);
- void (*set_entry_attr)(struct dentry_t *p_entry, u32 attr);
- u8 (*get_entry_flag)(struct dentry_t *p_entry);
- void (*set_entry_flag)(struct dentry_t *p_entry, u8 flag);
- u32 (*get_entry_clu0)(struct dentry_t *p_entry);
- void (*set_entry_clu0)(struct dentry_t *p_entry, u32 clu0);
- u64 (*get_entry_size)(struct dentry_t *p_entry);
- void (*set_entry_size)(struct dentry_t *p_entry, u64 size);
- void (*get_entry_time)(struct dentry_t *p_entry,
- struct timestamp_t *tp, u8 mode);
- void (*set_entry_time)(struct dentry_t *p_entry,
- struct timestamp_t *tp, u8 mode);
-};
-
struct fs_info_t {
u32 drv; /* drive ID */
u32 vol_type; /* volume FAT type */
@@ -617,8 +554,7 @@ struct fs_info_t {
u32 dev_ejected; /* block device operation error flag */
- struct fs_func *fs_func;
- struct semaphore v_sem;
+ struct mutex v_mutex;
/* FAT cache */
struct buf_cache_t FAT_cache_array[FAT_CACHE_SIZE];
@@ -681,10 +617,10 @@ struct exfat_mount_options {
/* on error: continue, panic, remount-ro */
unsigned char errors;
-#ifdef CONFIG_EXFAT_DISCARD
+#ifdef CONFIG_STAGING_EXFAT_DISCARD
/* flag on if -o dicard specified and device support discard() */
unsigned char discard;
-#endif /* CONFIG_EXFAT_DISCARD */
+#endif /* CONFIG_STAGING_EXFAT_DISCARD */
};
#define EXFAT_HASH_BITS 8
@@ -720,9 +656,9 @@ struct exfat_sb_info {
spinlock_t inode_hash_lock;
struct hlist_head inode_hashtable[EXFAT_HASH_SIZE];
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
long debug_flags;
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
};
/*
@@ -749,14 +685,7 @@ static inline struct exfat_inode_info *EXFAT_I(struct inode *inode)
/* NLS management function */
u16 nls_upper(struct super_block *sb, u16 a);
-int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b);
int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b);
-void nls_uniname_to_dosname(struct super_block *sb,
- struct dos_name_t *p_dosname,
- struct uni_name_t *p_uniname, bool *p_lossy);
-void nls_dosname_to_uniname(struct super_block *sb,
- struct uni_name_t *p_uniname,
- struct dos_name_t *p_dosname);
void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring,
struct uni_name_t *p_uniname);
void nls_cstring_to_uniname(struct super_block *sb,
@@ -764,48 +693,33 @@ void nls_cstring_to_uniname(struct super_block *sb,
bool *p_lossy);
/* buffer cache management */
-void buf_init(struct super_block *sb);
-void buf_shutdown(struct super_block *sb);
-int FAT_read(struct super_block *sb, u32 loc, u32 *content);
-s32 FAT_write(struct super_block *sb, u32 loc, u32 content);
-u8 *FAT_getblk(struct super_block *sb, sector_t sec);
-void FAT_modify(struct super_block *sb, sector_t sec);
-void FAT_release_all(struct super_block *sb);
-void FAT_sync(struct super_block *sb);
-u8 *buf_getblk(struct super_block *sb, sector_t sec);
-void buf_modify(struct super_block *sb, sector_t sec);
-void buf_lock(struct super_block *sb, sector_t sec);
-void buf_unlock(struct super_block *sb, sector_t sec);
-void buf_release(struct super_block *sb, sector_t sec);
-void buf_release_all(struct super_block *sb);
-void buf_sync(struct super_block *sb);
+void exfat_buf_init(struct super_block *sb);
+void exfat_buf_shutdown(struct super_block *sb);
+int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content);
+s32 exfat_fat_write(struct super_block *sb, u32 loc, u32 content);
+u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec);
+void exfat_fat_modify(struct super_block *sb, sector_t sec);
+void exfat_fat_release_all(struct super_block *sb);
+void exfat_fat_sync(struct super_block *sb);
+u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec);
+void exfat_buf_modify(struct super_block *sb, sector_t sec);
+void exfat_buf_lock(struct super_block *sb, sector_t sec);
+void exfat_buf_unlock(struct super_block *sb, sector_t sec);
+void exfat_buf_release(struct super_block *sb, sector_t sec);
+void exfat_buf_release_all(struct super_block *sb);
+void exfat_buf_sync(struct super_block *sb);
/* fs management functions */
void fs_set_vol_flags(struct super_block *sb, u32 new_flag);
void fs_error(struct super_block *sb);
/* cluster management functions */
-s32 clear_cluster(struct super_block *sb, u32 clu);
-s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc,
- struct chain_t *p_chain);
-s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
- struct chain_t *p_chain);
-void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
- s32 do_relse);
-void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
- s32 do_relse);
-u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain);
s32 count_num_clusters(struct super_block *sb, struct chain_t *dir);
-s32 fat_count_used_clusters(struct super_block *sb);
-s32 exfat_count_used_clusters(struct super_block *sb);
void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len);
/* allocation bitmap management functions */
s32 load_alloc_bitmap(struct super_block *sb);
void free_alloc_bitmap(struct super_block *sb);
-s32 set_alloc_bitmap(struct super_block *sb, u32 clu);
-s32 clr_alloc_bitmap(struct super_block *sb, u32 clu);
-u32 test_alloc_bitmap(struct super_block *sb, u32 clu);
void sync_alloc_bitmap(struct super_block *sb);
/* upcase table management functions */
@@ -813,63 +727,8 @@ s32 load_upcase_table(struct super_block *sb);
void free_upcase_table(struct super_block *sb);
/* dir entry management functions */
-u32 fat_get_entry_type(struct dentry_t *p_entry);
-u32 exfat_get_entry_type(struct dentry_t *p_entry);
-void fat_set_entry_type(struct dentry_t *p_entry, u32 type);
-void exfat_set_entry_type(struct dentry_t *p_entry, u32 type);
-u32 fat_get_entry_attr(struct dentry_t *p_entry);
-u32 exfat_get_entry_attr(struct dentry_t *p_entry);
-void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
-void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
-u8 fat_get_entry_flag(struct dentry_t *p_entry);
-u8 exfat_get_entry_flag(struct dentry_t *p_entry);
-void fat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
-void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flag);
-u32 fat_get_entry_clu0(struct dentry_t *p_entry);
-u32 exfat_get_entry_clu0(struct dentry_t *p_entry);
-void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
-void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
-u64 fat_get_entry_size(struct dentry_t *p_entry);
-u64 exfat_get_entry_size(struct dentry_t *p_entry);
-void fat_set_entry_size(struct dentry_t *p_entry, u64 size);
-void exfat_set_entry_size(struct dentry_t *p_entry, u64 size);
struct timestamp_t *tm_current(struct timestamp_t *tm);
-void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
- u8 mode);
-void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
- u8 mode);
-void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
- u8 mode);
-void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
- u8 mode);
-s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
- u32 type, u32 start_clu, u64 size);
-s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, u32 type, u32 start_clu, u64 size);
-s32 fat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 num_entries,
- struct uni_name_t *p_uniname,
- struct dos_name_t *p_dosname);
-s32 exfat_init_ext_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 num_entries,
- struct uni_name_t *p_uniname,
- struct dos_name_t *p_dosname);
-void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu);
-void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum,
- u16 *uniname);
-void init_file_entry(struct file_dentry_t *ep, u32 type);
-void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu,
- u64 size);
-void init_name_entry(struct name_dentry_t *ep, u16 *uniname);
-void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 order, s32 num_entries);
-void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 order, s32 num_entries);
-s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
- sector_t *sector, s32 *offset);
-struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector,
- s32 offset);
struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
s32 entry, sector_t *sector);
struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
@@ -877,24 +736,6 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
u32 type,
struct dentry_t **file_ep);
void release_entry_set(struct entry_set_cache_t *es);
-s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es);
-s32 write_partial_entries_in_entry_set(struct super_block *sb,
- struct entry_set_cache_t *es,
- struct dentry_t *ep, u32 count);
-s32 search_deleted_or_unused_entry(struct super_block *sb,
- struct chain_t *p_dir, s32 num_entries);
-s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir,
- s32 num_entries);
-s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- struct uni_name_t *p_uniname, s32 num_entries,
- struct dos_name_t *p_dosname, u32 type);
-s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- struct uni_name_t *p_uniname, s32 num_entries,
- struct dos_name_t *p_dosname, u32 type);
-s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, struct dentry_t *p_entry);
-s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, struct dentry_t *p_entry);
s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
u32 type);
void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
@@ -907,36 +748,13 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir);
s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
struct uni_name_t *p_uniname, s32 *entries,
struct dos_name_t *p_dosname);
-void get_uni_name_from_dos_entry(struct super_block *sb,
- struct dos_dentry_t *ep,
- struct uni_name_t *p_uniname, u8 mode);
-void fat_get_uni_name_from_ext_entry(struct super_block *sb,
- struct chain_t *p_dir, s32 entry,
- u16 *uniname);
-void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
- struct chain_t *p_dir, s32 entry,
- u16 *uniname);
-s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep,
- u16 *uniname, s32 order);
-s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep,
- u16 *uniname, s32 order);
-s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
- struct dos_name_t *p_dosname);
-void fat_attach_count_to_dos_name(u8 *dosname, s32 count);
-s32 fat_calc_num_entries(struct uni_name_t *p_uniname);
-s32 exfat_calc_num_entries(struct uni_name_t *p_uniname);
-u8 calc_checksum_1byte(void *data, s32 len, u8 chksum);
u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type);
-u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type);
/* name resolution functions */
s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
struct uni_name_t *p_uniname);
-s32 resolve_name(u8 *name, u8 **arg);
/* file operation functions */
-s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
-s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr);
s32 create_dir(struct inode *inode, struct chain_t *p_dir,
struct uni_name_t *p_uniname, struct file_id_t *fid);
@@ -959,13 +777,48 @@ int multi_sector_read(struct super_block *sb, sector_t sec,
int multi_sector_write(struct super_block *sb, sector_t sec,
struct buffer_head *bh, s32 num_secs, bool sync);
-void bdev_open(struct super_block *sb);
-void bdev_close(struct super_block *sb);
-int bdev_read(struct super_block *sb, sector_t secno,
+void exfat_bdev_open(struct super_block *sb);
+void exfat_bdev_close(struct super_block *sb);
+int exfat_bdev_read(struct super_block *sb, sector_t secno,
struct buffer_head **bh, u32 num_secs, bool read);
-int bdev_write(struct super_block *sb, sector_t secno,
+int exfat_bdev_write(struct super_block *sb, sector_t secno,
struct buffer_head *bh, u32 num_secs, bool sync);
-int bdev_sync(struct super_block *sb);
+int exfat_bdev_sync(struct super_block *sb);
+
+/* cluster operation functions */
+s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
+ struct chain_t *p_chain);
+void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
+ s32 do_relse);
+s32 exfat_count_used_clusters(struct super_block *sb);
+
+/* dir operation functions */
+s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ struct uni_name_t *p_uniname, s32 num_entries,
+ struct dos_name_t *p_dosname, u32 type);
+void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ s32 entry, s32 order, s32 num_entries);
+void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
+ struct chain_t *p_dir, s32 entry,
+ u16 *uniname);
+s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
+ s32 entry, struct dentry_t *p_entry);
+s32 exfat_calc_num_entries(struct uni_name_t *p_uniname);
+
+/* dir entry getter/setter */
+u32 exfat_get_entry_type(struct dentry_t *p_entry);
+u32 exfat_get_entry_attr(struct dentry_t *p_entry);
+void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr);
+u8 exfat_get_entry_flag(struct dentry_t *p_entry);
+void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags);
+u32 exfat_get_entry_clu0(struct dentry_t *p_entry);
+void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu);
+u64 exfat_get_entry_size(struct dentry_t *p_entry);
+void exfat_set_entry_size(struct dentry_t *p_entry, u64 size);
+void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ u8 mode);
+void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
+ u8 mode);
extern const u8 uni_upcase[];
#endif /* _EXFAT_H */
diff --git a/drivers/staging/exfat/exfat_blkdev.c b/drivers/staging/exfat/exfat_blkdev.c
index 81d20e6241c65..0a3dc3568293b 100644
--- a/drivers/staging/exfat/exfat_blkdev.c
+++ b/drivers/staging/exfat/exfat_blkdev.c
@@ -8,7 +8,7 @@
#include
#include "exfat.h"
-void bdev_open(struct super_block *sb)
+void exfat_bdev_open(struct super_block *sb)
{
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
@@ -23,28 +23,28 @@ void bdev_open(struct super_block *sb)
p_bd->opened = true;
}
-void bdev_close(struct super_block *sb)
+void exfat_bdev_close(struct super_block *sb)
{
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
p_bd->opened = false;
}
-int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
- u32 num_secs, bool read)
+int exfat_bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
+ u32 num_secs, bool read)
{
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
struct exfat_sb_info *sbi = EXFAT_SB(sb);
long flags = sbi->debug_flags;
if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
- return FFS_MEDIAERR;
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+ return -EIO;
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
if (!p_bd->opened)
- return FFS_MEDIAERR;
+ return -ENODEV;
if (*bh)
__brelse(*bh);
@@ -62,26 +62,26 @@ int bdev_read(struct super_block *sb, sector_t secno, struct buffer_head **bh,
WARN(!p_fs->dev_ejected,
"[EXFAT] No bh, device seems wrong or to be ejected.\n");
- return FFS_MEDIAERR;
+ return -EIO;
}
-int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
- u32 num_secs, bool sync)
+int exfat_bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
+ u32 num_secs, bool sync)
{
s32 count;
struct buffer_head *bh2;
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
struct exfat_sb_info *sbi = EXFAT_SB(sb);
long flags = sbi->debug_flags;
if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
- return FFS_MEDIAERR;
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+ return -EIO;
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
if (!p_bd->opened)
- return FFS_MEDIAERR;
+ return -ENODEV;
if (secno == bh->b_blocknr) {
lock_buffer(bh);
@@ -89,7 +89,7 @@ int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
mark_buffer_dirty(bh);
unlock_buffer(bh);
if (sync && (sync_dirty_buffer(bh) != 0))
- return FFS_MEDIAERR;
+ return -EIO;
} else {
count = num_secs << p_bd->sector_size_bits;
@@ -115,22 +115,22 @@ int bdev_write(struct super_block *sb, sector_t secno, struct buffer_head *bh,
WARN(!p_fs->dev_ejected,
"[EXFAT] No bh, device seems wrong or to be ejected.\n");
- return FFS_MEDIAERR;
+ return -EIO;
}
-int bdev_sync(struct super_block *sb)
+int exfat_bdev_sync(struct super_block *sb)
{
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
struct exfat_sb_info *sbi = EXFAT_SB(sb);
long flags = sbi->debug_flags;
if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
- return FFS_MEDIAERR;
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+ return -EIO;
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
if (!p_bd->opened)
- return FFS_MEDIAERR;
+ return -ENODEV;
return sync_blockdev(sb->s_bdev);
}
diff --git a/drivers/staging/exfat/exfat_cache.c b/drivers/staging/exfat/exfat_cache.c
index e1b0017187090..3fd5604058a9d 100644
--- a/drivers/staging/exfat/exfat_cache.c
+++ b/drivers/staging/exfat/exfat_cache.c
@@ -12,8 +12,8 @@
#define DIRTYBIT 0x02
/* Local variables */
-static DEFINE_SEMAPHORE(f_sem);
-static DEFINE_SEMAPHORE(b_sem);
+static DEFINE_MUTEX(f_mutex);
+static DEFINE_MUTEX(b_mutex);
static struct buf_cache_t *FAT_cache_find(struct super_block *sb, sector_t sec)
{
@@ -128,7 +128,7 @@ static void buf_cache_remove_hash(struct buf_cache_t *bp)
(bp->hash_next)->hash_prev = bp->hash_prev;
}
-void buf_init(struct super_block *sb)
+void exfat_buf_init(struct super_block *sb)
{
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -189,11 +189,11 @@ void buf_init(struct super_block *sb)
buf_cache_insert_hash(sb, &p_fs->buf_cache_array[i]);
}
-void buf_shutdown(struct super_block *sb)
+void exfat_buf_shutdown(struct super_block *sb)
{
}
-static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
+static int __exfat_fat_read(struct super_block *sb, u32 loc, u32 *content)
{
s32 off;
u32 _content;
@@ -202,107 +202,22 @@ static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
- if (p_fs->vol_type == FAT12) {
- sec = p_fs->FAT1_start_sector +
- ((loc + (loc >> 1)) >> p_bd->sector_size_bits);
- off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
+ sec = p_fs->FAT1_start_sector +
+ (loc >> (p_bd->sector_size_bits - 2));
+ off = (loc << 2) & p_bd->sector_size_mask;
- if (off == (p_bd->sector_size - 1)) {
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
+ fat_sector = exfat_fat_getblk(sb, sec);
+ if (!fat_sector)
+ return -1;
- _content = (u32)fat_sector[off];
+ fat_entry = &fat_sector[off];
+ _content = GET32_A(fat_entry);
- fat_sector = FAT_getblk(sb, ++sec);
- if (!fat_sector)
- return -1;
-
- _content |= (u32)fat_sector[0] << 8;
- } else {
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
-
- fat_entry = &fat_sector[off];
- _content = GET16(fat_entry);
- }
-
- if (loc & 1)
- _content >>= 4;
-
- _content &= 0x00000FFF;
-
- if (_content >= CLUSTER_16(0x0FF8)) {
- *content = CLUSTER_32(~0);
- return 0;
- }
- *content = CLUSTER_32(_content);
- return 0;
- } else if (p_fs->vol_type == FAT16) {
- sec = p_fs->FAT1_start_sector +
- (loc >> (p_bd->sector_size_bits - 1));
- off = (loc << 1) & p_bd->sector_size_mask;
-
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
-
- fat_entry = &fat_sector[off];
-
- _content = GET16_A(fat_entry);
-
- _content &= 0x0000FFFF;
-
- if (_content >= CLUSTER_16(0xFFF8)) {
- *content = CLUSTER_32(~0);
- return 0;
- }
- *content = CLUSTER_32(_content);
- return 0;
- } else if (p_fs->vol_type == FAT32) {
- sec = p_fs->FAT1_start_sector +
- (loc >> (p_bd->sector_size_bits - 2));
- off = (loc << 2) & p_bd->sector_size_mask;
-
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
-
- fat_entry = &fat_sector[off];
-
- _content = GET32_A(fat_entry);
-
- _content &= 0x0FFFFFFF;
-
- if (_content >= CLUSTER_32(0x0FFFFFF8)) {
- *content = CLUSTER_32(~0);
- return 0;
- }
- *content = CLUSTER_32(_content);
- return 0;
- } else if (p_fs->vol_type == EXFAT) {
- sec = p_fs->FAT1_start_sector +
- (loc >> (p_bd->sector_size_bits - 2));
- off = (loc << 2) & p_bd->sector_size_mask;
-
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
-
- fat_entry = &fat_sector[off];
- _content = GET32_A(fat_entry);
-
- if (_content >= CLUSTER_32(0xFFFFFFF8)) {
- *content = CLUSTER_32(~0);
- return 0;
- }
- *content = CLUSTER_32(_content);
+ if (_content >= CLUSTER_32(0xFFFFFFF8)) {
+ *content = CLUSTER_32(~0);
return 0;
}
-
- /* Unknown volume type, throw in the towel and go home */
- *content = CLUSTER_32(~0);
+ *content = CLUSTER_32(_content);
return 0;
}
@@ -311,18 +226,18 @@ static int __FAT_read(struct super_block *sb, u32 loc, u32 *content)
* returns 0 on success
* -1 on error
*/
-int FAT_read(struct super_block *sb, u32 loc, u32 *content)
+int exfat_fat_read(struct super_block *sb, u32 loc, u32 *content)
{
s32 ret;
- down(&f_sem);
- ret = __FAT_read(sb, loc, content);
- up(&f_sem);
+ mutex_lock(&f_mutex);
+ ret = __exfat_fat_read(sb, loc, content);
+ mutex_unlock(&f_mutex);
return ret;
}
-static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
+static s32 __exfat_fat_write(struct super_block *sb, u32 loc, u32 content)
{
s32 off;
sector_t sec;
@@ -330,118 +245,34 @@ static s32 __FAT_write(struct super_block *sb, u32 loc, u32 content)
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
- if (p_fs->vol_type == FAT12) {
- content &= 0x00000FFF;
-
- sec = p_fs->FAT1_start_sector +
- ((loc + (loc >> 1)) >> p_bd->sector_size_bits);
- off = (loc + (loc >> 1)) & p_bd->sector_size_mask;
-
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
-
- if (loc & 1) { /* odd */
- content <<= 4;
-
- if (off == (p_bd->sector_size - 1)) {
- fat_sector[off] = (u8)(content |
- (fat_sector[off] &
- 0x0F));
- FAT_modify(sb, sec);
-
- fat_sector = FAT_getblk(sb, ++sec);
- if (!fat_sector)
- return -1;
-
- fat_sector[0] = (u8)(content >> 8);
- } else {
- fat_entry = &fat_sector[off];
- content |= GET16(fat_entry) & 0x000F;
-
- SET16(fat_entry, content);
- }
- } else { /* even */
- fat_sector[off] = (u8)(content);
-
- if (off == (p_bd->sector_size - 1)) {
- fat_sector[off] = (u8)(content);
- FAT_modify(sb, sec);
-
- fat_sector = FAT_getblk(sb, ++sec);
- if (!fat_sector)
- return -1;
- fat_sector[0] = (u8)((fat_sector[0] & 0xF0) |
- (content >> 8));
- } else {
- fat_entry = &fat_sector[off];
- content |= GET16(fat_entry) & 0xF000;
-
- SET16(fat_entry, content);
- }
- }
- }
-
- else if (p_fs->vol_type == FAT16) {
- content &= 0x0000FFFF;
-
- sec = p_fs->FAT1_start_sector + (loc >>
- (p_bd->sector_size_bits - 1));
- off = (loc << 1) & p_bd->sector_size_mask;
-
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
-
- fat_entry = &fat_sector[off];
-
- SET16_A(fat_entry, content);
- } else if (p_fs->vol_type == FAT32) {
- content &= 0x0FFFFFFF;
+ sec = p_fs->FAT1_start_sector + (loc >>
+ (p_bd->sector_size_bits - 2));
+ off = (loc << 2) & p_bd->sector_size_mask;
- sec = p_fs->FAT1_start_sector + (loc >>
- (p_bd->sector_size_bits - 2));
- off = (loc << 2) & p_bd->sector_size_mask;
+ fat_sector = exfat_fat_getblk(sb, sec);
+ if (!fat_sector)
+ return -1;
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
+ fat_entry = &fat_sector[off];
- fat_entry = &fat_sector[off];
-
- content |= GET32_A(fat_entry) & 0xF0000000;
-
- SET32_A(fat_entry, content);
- } else { /* p_fs->vol_type == EXFAT */
- sec = p_fs->FAT1_start_sector + (loc >>
- (p_bd->sector_size_bits - 2));
- off = (loc << 2) & p_bd->sector_size_mask;
-
- fat_sector = FAT_getblk(sb, sec);
- if (!fat_sector)
- return -1;
-
- fat_entry = &fat_sector[off];
-
- SET32_A(fat_entry, content);
- }
+ SET32_A(fat_entry, content);
- FAT_modify(sb, sec);
+ exfat_fat_modify(sb, sec);
return 0;
}
-int FAT_write(struct super_block *sb, u32 loc, u32 content)
+int exfat_fat_write(struct super_block *sb, u32 loc, u32 content)
{
s32 ret;
- down(&f_sem);
- ret = __FAT_write(sb, loc, content);
- up(&f_sem);
+ mutex_lock(&f_mutex);
+ ret = __exfat_fat_write(sb, loc, content);
+ mutex_unlock(&f_mutex);
return ret;
}
-u8 *FAT_getblk(struct super_block *sb, sector_t sec)
+u8 *exfat_fat_getblk(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -462,7 +293,7 @@ u8 *FAT_getblk(struct super_block *sb, sector_t sec)
FAT_cache_insert_hash(sb, bp);
- if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
+ if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) {
FAT_cache_remove_hash(bp);
bp->drv = -1;
bp->sec = ~0;
@@ -476,7 +307,7 @@ u8 *FAT_getblk(struct super_block *sb, sector_t sec)
return bp->buf_bh->b_data;
}
-void FAT_modify(struct super_block *sb, sector_t sec)
+void exfat_fat_modify(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
@@ -485,12 +316,12 @@ void FAT_modify(struct super_block *sb, sector_t sec)
sector_write(sb, sec, bp->buf_bh, 0);
}
-void FAT_release_all(struct super_block *sb)
+void exfat_fat_release_all(struct super_block *sb)
{
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&f_sem);
+ mutex_lock(&f_mutex);
bp = p_fs->FAT_cache_lru_list.next;
while (bp != &p_fs->FAT_cache_lru_list) {
@@ -507,15 +338,15 @@ void FAT_release_all(struct super_block *sb)
bp = bp->next;
}
- up(&f_sem);
+ mutex_unlock(&f_mutex);
}
-void FAT_sync(struct super_block *sb)
+void exfat_fat_sync(struct super_block *sb)
{
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&f_sem);
+ mutex_lock(&f_mutex);
bp = p_fs->FAT_cache_lru_list.next;
while (bp != &p_fs->FAT_cache_lru_list) {
@@ -526,7 +357,7 @@ void FAT_sync(struct super_block *sb)
bp = bp->next;
}
- up(&f_sem);
+ mutex_unlock(&f_mutex);
}
static struct buf_cache_t *buf_cache_find(struct super_block *sb, sector_t sec)
@@ -561,7 +392,7 @@ static struct buf_cache_t *buf_cache_get(struct super_block *sb, sector_t sec)
return bp;
}
-static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
+static u8 *__exfat_buf_getblk(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -582,7 +413,7 @@ static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
buf_cache_insert_hash(sb, bp);
- if (sector_read(sb, sec, &bp->buf_bh, 1) != FFS_SUCCESS) {
+ if (sector_read(sb, sec, &bp->buf_bh, 1) != 0) {
buf_cache_remove_hash(bp);
bp->drv = -1;
bp->sec = ~0;
@@ -596,22 +427,22 @@ static u8 *__buf_getblk(struct super_block *sb, sector_t sec)
return bp->buf_bh->b_data;
}
-u8 *buf_getblk(struct super_block *sb, sector_t sec)
+u8 *exfat_buf_getblk(struct super_block *sb, sector_t sec)
{
u8 *buf;
- down(&b_sem);
- buf = __buf_getblk(sb, sec);
- up(&b_sem);
+ mutex_lock(&b_mutex);
+ buf = __exfat_buf_getblk(sb, sec);
+ mutex_unlock(&b_mutex);
return buf;
}
-void buf_modify(struct super_block *sb, sector_t sec)
+void exfat_buf_modify(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = buf_cache_find(sb, sec);
if (likely(bp))
@@ -620,14 +451,14 @@ void buf_modify(struct super_block *sb, sector_t sec)
WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
(unsigned long long)sec);
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
-void buf_lock(struct super_block *sb, sector_t sec)
+void exfat_buf_lock(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = buf_cache_find(sb, sec);
if (likely(bp))
@@ -636,14 +467,14 @@ void buf_lock(struct super_block *sb, sector_t sec)
WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
(unsigned long long)sec);
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
-void buf_unlock(struct super_block *sb, sector_t sec)
+void exfat_buf_unlock(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = buf_cache_find(sb, sec);
if (likely(bp))
@@ -652,15 +483,15 @@ void buf_unlock(struct super_block *sb, sector_t sec)
WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%llu).\n",
(unsigned long long)sec);
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
-void buf_release(struct super_block *sb, sector_t sec)
+void exfat_buf_release(struct super_block *sb, sector_t sec)
{
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = buf_cache_find(sb, sec);
if (likely(bp)) {
@@ -676,15 +507,15 @@ void buf_release(struct super_block *sb, sector_t sec)
move_to_lru(bp, &p_fs->buf_cache_lru_list);
}
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
-void buf_release_all(struct super_block *sb)
+void exfat_buf_release_all(struct super_block *sb)
{
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = p_fs->buf_cache_lru_list.next;
while (bp != &p_fs->buf_cache_lru_list) {
@@ -701,15 +532,15 @@ void buf_release_all(struct super_block *sb)
bp = bp->next;
}
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
-void buf_sync(struct super_block *sb)
+void exfat_buf_sync(struct super_block *sb)
{
struct buf_cache_t *bp;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- down(&b_sem);
+ mutex_lock(&b_mutex);
bp = p_fs->buf_cache_lru_list.next;
while (bp != &p_fs->buf_cache_lru_list) {
@@ -720,5 +551,5 @@ void buf_sync(struct super_block *sb)
bp = bp->next;
}
- up(&b_sem);
+ mutex_unlock(&b_mutex);
}
diff --git a/drivers/staging/exfat/exfat_core.c b/drivers/staging/exfat/exfat_core.c
index f3774a1912d1e..07b460d01334c 100644
--- a/drivers/staging/exfat/exfat_core.c
+++ b/drivers/staging/exfat/exfat_core.c
@@ -20,15 +20,6 @@ static void __set_sb_dirty(struct super_block *sb)
static u8 name_buf[MAX_PATH_LENGTH * MAX_CHARSET_SIZE];
-static char *reserved_names[] = {
- "AUX ", "CON ", "NUL ", "PRN ",
- "COM1 ", "COM2 ", "COM3 ", "COM4 ",
- "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ",
- "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ",
- "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ",
- NULL
-};
-
static u8 free_bit[] = {
0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 0 ~ 19 */
0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /* 20 ~ 39 */
@@ -99,25 +90,23 @@ void fs_set_vol_flags(struct super_block *sb, u32 new_flag)
p_fs->vol_flag = new_flag;
- if (p_fs->vol_type == EXFAT) {
- if (!p_fs->pbr_bh) {
- if (sector_read(sb, p_fs->PBR_sector,
- &p_fs->pbr_bh, 1) != FFS_SUCCESS)
- return;
- }
+ if (!p_fs->pbr_bh) {
+ if (sector_read(sb, p_fs->PBR_sector,
+ &p_fs->pbr_bh, 1) != 0)
+ return;
+ }
- p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data;
- p_bpb = (struct bpbex_t *)p_pbr->bpb;
- SET16(p_bpb->vol_flags, (u16)new_flag);
+ p_pbr = (struct pbr_sector_t *)p_fs->pbr_bh->b_data;
+ p_bpb = (struct bpbex_t *)p_pbr->bpb;
+ SET16(p_bpb->vol_flags, (u16)new_flag);
- /* XXX duyoung
- * what can we do here? (cuz fs_set_vol_flags() is void)
- */
- if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh)))
- sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1);
- else
- sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0);
- }
+ /* XXX duyoung
+ * what can we do here? (cuz fs_set_vol_flags() is void)
+ */
+ if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh)))
+ sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1);
+ else
+ sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0);
}
void fs_error(struct super_block *sb)
@@ -136,10 +125,10 @@ void fs_error(struct super_block *sb)
* Cluster Management Functions
*/
-s32 clear_cluster(struct super_block *sb, u32 clu)
+static s32 clear_cluster(struct super_block *sb, u32 clu)
{
sector_t s, n;
- s32 ret = FFS_SUCCESS;
+ s32 ret = 0;
struct buffer_head *tmp_bh = NULL;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
@@ -154,12 +143,12 @@ s32 clear_cluster(struct super_block *sb, u32 clu)
for (; s < n; s++) {
ret = sector_read(sb, s, &tmp_bh, 0);
- if (ret != FFS_SUCCESS)
+ if (ret != 0)
return ret;
memset((char *)tmp_bh->b_data, 0x0, p_bd->sector_size);
ret = sector_write(sb, s, tmp_bh, 0);
- if (ret != FFS_SUCCESS)
+ if (ret != 0)
break;
}
@@ -167,58 +156,97 @@ s32 clear_cluster(struct super_block *sb, u32 clu)
return ret;
}
-s32 fat_alloc_cluster(struct super_block *sb, s32 num_alloc,
- struct chain_t *p_chain)
+static s32 set_alloc_bitmap(struct super_block *sb, u32 clu)
{
- int i, num_clusters = 0;
- u32 new_clu, last_clu = CLUSTER_32(~0), read_clu;
+ int i, b;
+ sector_t sector;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
- new_clu = p_chain->dir;
- if (new_clu == CLUSTER_32(~0))
- new_clu = p_fs->clu_srch_ptr;
- else if (new_clu >= p_fs->num_clusters)
- new_clu = 2;
+ i = clu >> (p_bd->sector_size_bits + 3);
+ b = clu & ((p_bd->sector_size << 3) - 1);
- __set_sb_dirty(sb);
+ sector = START_SECTOR(p_fs->map_clu) + i;
- p_chain->dir = CLUSTER_32(~0);
+ exfat_bitmap_set((u8 *)p_fs->vol_amap[i]->b_data, b);
- for (i = 2; i < p_fs->num_clusters; i++) {
- if (FAT_read(sb, new_clu, &read_clu) != 0)
- return -1;
+ return sector_write(sb, sector, p_fs->vol_amap[i], 0);
+}
- if (read_clu == CLUSTER_32(0)) {
- if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0)
- return -1;
- num_clusters++;
+static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
+{
+ int i, b;
+ sector_t sector;
+#ifdef CONFIG_STAGING_EXFAT_DISCARD
+ struct exfat_sb_info *sbi = EXFAT_SB(sb);
+ struct exfat_mount_options *opts = &sbi->options;
+ int ret;
+#endif /* CONFIG_STAGING_EXFAT_DISCARD */
+ struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
- if (p_chain->dir == CLUSTER_32(~0)) {
- p_chain->dir = new_clu;
- } else {
- if (FAT_write(sb, last_clu, new_clu) < 0)
- return -1;
- }
+ i = clu >> (p_bd->sector_size_bits + 3);
+ b = clu & ((p_bd->sector_size << 3) - 1);
- last_clu = new_clu;
+ sector = START_SECTOR(p_fs->map_clu) + i;
- if ((--num_alloc) == 0) {
- p_fs->clu_srch_ptr = new_clu;
- if (p_fs->used_clusters != UINT_MAX)
- p_fs->used_clusters += num_clusters;
+ exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b);
- return num_clusters;
- }
+#ifdef CONFIG_STAGING_EXFAT_DISCARD
+ if (opts->discard) {
+ ret = sb_issue_discard(sb, START_SECTOR(clu),
+ (1 << p_fs->sectors_per_clu_bits),
+ GFP_NOFS, 0);
+ if (ret == -EOPNOTSUPP) {
+ pr_warn("discard not supported by device, disabling");
+ opts->discard = 0;
+ } else {
+ return ret;
}
- if ((++new_clu) >= p_fs->num_clusters)
- new_clu = 2;
}
+#endif /* CONFIG_STAGING_EXFAT_DISCARD */
- p_fs->clu_srch_ptr = new_clu;
- if (p_fs->used_clusters != UINT_MAX)
- p_fs->used_clusters += num_clusters;
+ return sector_write(sb, sector, p_fs->vol_amap[i], 0);
+}
- return num_clusters;
+static u32 test_alloc_bitmap(struct super_block *sb, u32 clu)
+{
+ int i, map_i, map_b;
+ u32 clu_base, clu_free;
+ u8 k, clu_mask;
+ struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+
+ clu_base = (clu & ~(0x7)) + 2;
+ clu_mask = (1 << (clu - clu_base + 2)) - 1;
+
+ map_i = clu >> (p_bd->sector_size_bits + 3);
+ map_b = (clu >> 3) & p_bd->sector_size_mask;
+
+ for (i = 2; i < p_fs->num_clusters; i += 8) {
+ k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b);
+ if (clu_mask > 0) {
+ k |= clu_mask;
+ clu_mask = 0;
+ }
+ if (k < 0xFF) {
+ clu_free = clu_base + free_bit[k];
+ if (clu_free < p_fs->num_clusters)
+ return clu_free;
+ }
+ clu_base += 8;
+
+ if (((++map_b) >= p_bd->sector_size) ||
+ (clu_base >= p_fs->num_clusters)) {
+ if ((++map_i) >= p_fs->map_sectors) {
+ clu_base = 2;
+ map_i = 0;
+ }
+ map_b = 0;
+ }
+ }
+
+ return CLUSTER_32(~0);
}
s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
@@ -251,22 +279,22 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
}
}
- if (set_alloc_bitmap(sb, new_clu - 2) != FFS_SUCCESS)
- return -1;
+ if (set_alloc_bitmap(sb, new_clu - 2) != 0)
+ return -EIO;
num_clusters++;
if (p_chain->flags == 0x01) {
- if (FAT_write(sb, new_clu, CLUSTER_32(~0)) < 0)
- return -1;
+ if (exfat_fat_write(sb, new_clu, CLUSTER_32(~0)) < 0)
+ return -EIO;
}
if (p_chain->dir == CLUSTER_32(~0)) {
p_chain->dir = new_clu;
} else {
if (p_chain->flags == 0x01) {
- if (FAT_write(sb, last_clu, new_clu) < 0)
- return -1;
+ if (exfat_fat_write(sb, last_clu, new_clu) < 0)
+ return -EIO;
}
}
last_clu = new_clu;
@@ -300,47 +328,6 @@ s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc,
return num_clusters;
}
-void fat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
- s32 do_relse)
-{
- s32 num_clusters = 0;
- u32 clu, prev;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- int i;
- sector_t sector;
-
- if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
- return;
- __set_sb_dirty(sb);
- clu = p_chain->dir;
-
- if (p_chain->size <= 0)
- return;
-
- do {
- if (p_fs->dev_ejected)
- break;
-
- if (do_relse) {
- sector = START_SECTOR(clu);
- for (i = 0; i < p_fs->sectors_per_clu; i++)
- buf_release(sb, sector + i);
- }
-
- prev = clu;
- if (FAT_read(sb, clu, &clu) == -1)
- break;
-
- if (FAT_write(sb, prev, CLUSTER_32(0)) < 0)
- break;
- num_clusters++;
-
- } while (clu != CLUSTER_32(~0));
-
- if (p_fs->used_clusters != UINT_MAX)
- p_fs->used_clusters -= num_clusters;
-}
-
void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
s32 do_relse)
{
@@ -367,10 +354,10 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
if (do_relse) {
sector = START_SECTOR(clu);
for (i = 0; i < p_fs->sectors_per_clu; i++)
- buf_release(sb, sector + i);
+ exfat_buf_release(sb, sector + i);
}
- if (clr_alloc_bitmap(sb, clu - 2) != FFS_SUCCESS)
+ if (clr_alloc_bitmap(sb, clu - 2) != 0)
break;
clu++;
@@ -384,13 +371,13 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
if (do_relse) {
sector = START_SECTOR(clu);
for (i = 0; i < p_fs->sectors_per_clu; i++)
- buf_release(sb, sector + i);
+ exfat_buf_release(sb, sector + i);
}
- if (clr_alloc_bitmap(sb, clu - 2) != FFS_SUCCESS)
+ if (clr_alloc_bitmap(sb, clu - 2) != 0)
break;
- if (FAT_read(sb, clu, &clu) == -1)
+ if (exfat_fat_read(sb, clu, &clu) == -1)
break;
num_clusters++;
} while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0)));
@@ -400,7 +387,7 @@ void exfat_free_cluster(struct super_block *sb, struct chain_t *p_chain,
p_fs->used_clusters -= num_clusters;
}
-u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain)
+static u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain)
{
u32 clu, next;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -410,7 +397,7 @@ u32 find_last_cluster(struct super_block *sb, struct chain_t *p_chain)
if (p_chain->flags == 0x03) {
clu += p_chain->size - 1;
} else {
- while ((FAT_read(sb, clu, &next) == 0) &&
+ while ((exfat_fat_read(sb, clu, &next) == 0) &&
(next != CLUSTER_32(~0))) {
if (p_fs->dev_ejected)
break;
@@ -437,7 +424,7 @@ s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain)
} else {
for (i = 2; i < p_fs->num_clusters; i++) {
count++;
- if (FAT_read(sb, clu, &clu) != 0)
+ if (exfat_fat_read(sb, clu, &clu) != 0)
return 0;
if (clu == CLUSTER_32(~0))
break;
@@ -447,22 +434,6 @@ s32 count_num_clusters(struct super_block *sb, struct chain_t *p_chain)
return count;
}
-s32 fat_count_used_clusters(struct super_block *sb)
-{
- int i, count = 0;
- u32 clu;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
-
- for (i = 2; i < p_fs->num_clusters; i++) {
- if (FAT_read(sb, i, &clu) != 0)
- break;
- if (clu != CLUSTER_32(0))
- count++;
- }
-
- return count;
-}
-
s32 exfat_count_used_clusters(struct super_block *sb)
{
int i, map_i, map_b, count = 0;
@@ -470,7 +441,8 @@ s32 exfat_count_used_clusters(struct super_block *sb)
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
- map_i = map_b = 0;
+ map_i = 0;
+ map_b = 0;
for (i = 2; i < p_fs->num_clusters; i += 8) {
k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b);
@@ -491,12 +463,12 @@ void exfat_chain_cont_cluster(struct super_block *sb, u32 chain, s32 len)
return;
while (len > 1) {
- if (FAT_write(sb, chain, chain + 1) < 0)
+ if (exfat_fat_write(sb, chain, chain + 1) < 0)
break;
chain++;
len--;
}
- FAT_write(sb, chain, CLUSTER_32(~0));
+ exfat_fat_write(sb, chain, CLUSTER_32(~0));
}
/*
@@ -525,9 +497,9 @@ s32 load_alloc_bitmap(struct super_block *sb)
ep = (struct bmap_dentry_t *)get_entry_in_dir(sb, &clu,
i, NULL);
if (!ep)
- return FFS_MEDIAERR;
+ return -ENOENT;
- type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep);
+ type = exfat_get_entry_type((struct dentry_t *)ep);
if (type == TYPE_UNUSED)
break;
@@ -544,14 +516,14 @@ s32 load_alloc_bitmap(struct super_block *sb)
sizeof(struct buffer_head *),
GFP_KERNEL);
if (!p_fs->vol_amap)
- return FFS_MEMORYERR;
+ return -ENOMEM;
sector = START_SECTOR(p_fs->map_clu);
for (j = 0; j < p_fs->map_sectors; j++) {
p_fs->vol_amap[j] = NULL;
- ret = sector_read(sb, sector + j, &(p_fs->vol_amap[j]), 1);
- if (ret != FFS_SUCCESS) {
+ ret = sector_read(sb, sector + j, &p_fs->vol_amap[j], 1);
+ if (ret != 0) {
/* release all buffers and free vol_amap */
i = 0;
while (i < j)
@@ -564,15 +536,15 @@ s32 load_alloc_bitmap(struct super_block *sb)
}
p_fs->pbr_bh = NULL;
- return FFS_SUCCESS;
+ return 0;
}
}
- if (FAT_read(sb, clu.dir, &clu.dir) != 0)
- return FFS_MEDIAERR;
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ return -EIO;
}
- return FFS_FORMATERR;
+ return -EFSCORRUPTED;
}
void free_alloc_bitmap(struct super_block *sb)
@@ -589,97 +561,6 @@ void free_alloc_bitmap(struct super_block *sb)
p_fs->vol_amap = NULL;
}
-s32 set_alloc_bitmap(struct super_block *sb, u32 clu)
-{
- int i, b;
- sector_t sector;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
-
- i = clu >> (p_bd->sector_size_bits + 3);
- b = clu & ((p_bd->sector_size << 3) - 1);
-
- sector = START_SECTOR(p_fs->map_clu) + i;
-
- exfat_bitmap_set((u8 *)p_fs->vol_amap[i]->b_data, b);
-
- return sector_write(sb, sector, p_fs->vol_amap[i], 0);
-}
-
-s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
-{
- int i, b;
- sector_t sector;
-#ifdef CONFIG_EXFAT_DISCARD
- struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct exfat_mount_options *opts = &sbi->options;
- int ret;
-#endif /* CONFIG_EXFAT_DISCARD */
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
-
- i = clu >> (p_bd->sector_size_bits + 3);
- b = clu & ((p_bd->sector_size << 3) - 1);
-
- sector = START_SECTOR(p_fs->map_clu) + i;
-
- exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b);
-
- return sector_write(sb, sector, p_fs->vol_amap[i], 0);
-
-#ifdef CONFIG_EXFAT_DISCARD
- if (opts->discard) {
- ret = sb_issue_discard(sb, START_SECTOR(clu),
- (1 << p_fs->sectors_per_clu_bits),
- GFP_NOFS, 0);
- if (ret == -EOPNOTSUPP) {
- pr_warn("discard not supported by device, disabling");
- opts->discard = 0;
- }
- }
-#endif /* CONFIG_EXFAT_DISCARD */
-}
-
-u32 test_alloc_bitmap(struct super_block *sb, u32 clu)
-{
- int i, map_i, map_b;
- u32 clu_base, clu_free;
- u8 k, clu_mask;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
-
- clu_base = (clu & ~(0x7)) + 2;
- clu_mask = (1 << (clu - clu_base + 2)) - 1;
-
- map_i = clu >> (p_bd->sector_size_bits + 3);
- map_b = (clu >> 3) & p_bd->sector_size_mask;
-
- for (i = 2; i < p_fs->num_clusters; i += 8) {
- k = *(((u8 *)p_fs->vol_amap[map_i]->b_data) + map_b);
- if (clu_mask > 0) {
- k |= clu_mask;
- clu_mask = 0;
- }
- if (k < 0xFF) {
- clu_free = clu_base + free_bit[k];
- if (clu_free < p_fs->num_clusters)
- return clu_free;
- }
- clu_base += 8;
-
- if (((++map_b) >= p_bd->sector_size) ||
- (clu_base >= p_fs->num_clusters)) {
- if ((++map_i) >= p_fs->map_sectors) {
- clu_base = 2;
- map_i = 0;
- }
- map_b = 0;
- }
- }
-
- return CLUSTER_32(~0);
-}
-
void sync_alloc_bitmap(struct super_block *sb)
{
int i;
@@ -698,7 +579,7 @@ void sync_alloc_bitmap(struct super_block *sb)
static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
u32 num_sectors, u32 utbl_checksum)
{
- int i, ret = FFS_ERROR;
+ int i, ret = -EINVAL;
u32 j;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
@@ -712,15 +593,15 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
u32 checksum = 0;
- upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *),
- GFP_KERNEL);
+ upcase_table = kmalloc_array(UTBL_COL_COUNT, sizeof(u16 *), GFP_KERNEL);
+ p_fs->vol_utbl = upcase_table;
if (!upcase_table)
- return FFS_MEMORYERR;
+ return -ENOMEM;
memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
while (sector < end_sector) {
ret = sector_read(sb, sector, &tmp_bh, 1);
- if (ret != FFS_SUCCESS) {
+ if (ret != 0) {
pr_debug("sector read (0x%llX)fail\n",
(unsigned long long)sector);
goto error;
@@ -755,7 +636,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
upcase_table[col_index] = kmalloc_array(UTBL_ROW_COUNT,
sizeof(u16), GFP_KERNEL);
if (!upcase_table[col_index]) {
- ret = FFS_MEMORYERR;
+ ret = -ENOMEM;
goto error;
}
@@ -771,9 +652,9 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
if (index >= 0xFFFF && utbl_checksum == checksum) {
if (tmp_bh)
brelse(tmp_bh);
- return FFS_SUCCESS;
+ return 0;
}
- ret = FFS_ERROR;
+ ret = -EINVAL;
error:
if (tmp_bh)
brelse(tmp_bh);
@@ -783,7 +664,7 @@ static s32 __load_upcase_table(struct super_block *sb, sector_t sector,
static s32 __load_default_upcase_table(struct super_block *sb)
{
- int i, ret = FFS_ERROR;
+ int i, ret = -EINVAL;
u32 j;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
@@ -792,10 +673,10 @@ static s32 __load_default_upcase_table(struct super_block *sb)
u16 uni = 0;
u16 **upcase_table;
- upcase_table = p_fs->vol_utbl = kmalloc(UTBL_COL_COUNT * sizeof(u16 *),
- GFP_KERNEL);
+ upcase_table = kmalloc_array(UTBL_COL_COUNT, sizeof(u16 *), GFP_KERNEL);
+ p_fs->vol_utbl = upcase_table;
if (!upcase_table)
- return FFS_MEMORYERR;
+ return -ENOMEM;
memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
for (i = 0; index <= 0xFFFF && i < NUM_UPCASE * 2; i += 2) {
@@ -818,7 +699,7 @@ static s32 __load_default_upcase_table(struct super_block *sb)
sizeof(u16),
GFP_KERNEL);
if (!upcase_table[col_index]) {
- ret = FFS_MEMORYERR;
+ ret = -ENOMEM;
goto error;
}
@@ -832,7 +713,7 @@ static s32 __load_default_upcase_table(struct super_block *sb)
}
if (index >= 0xFFFF)
- return FFS_SUCCESS;
+ return 0;
error:
/* FATAL error: default upcase table has error */
@@ -855,16 +736,16 @@ s32 load_upcase_table(struct super_block *sb)
clu.flags = 0x01;
if (p_fs->dev_ejected)
- return FFS_MEDIAERR;
+ return -EIO;
while (clu.dir != CLUSTER_32(~0)) {
for (i = 0; i < p_fs->dentries_per_clu; i++) {
ep = (struct case_dentry_t *)get_entry_in_dir(sb, &clu,
i, NULL);
if (!ep)
- return FFS_MEDIAERR;
+ return -ENOENT;
- type = p_fs->fs_func->get_entry_type((struct dentry_t *)ep);
+ type = exfat_get_entry_type((struct dentry_t *)ep);
if (type == TYPE_UNUSED)
break;
@@ -877,12 +758,12 @@ s32 load_upcase_table(struct super_block *sb)
sector = START_SECTOR(tbl_clu);
num_sectors = ((tbl_size - 1) >> p_bd->sector_size_bits) + 1;
if (__load_upcase_table(sb, sector, num_sectors,
- GET32_A(ep->checksum)) != FFS_SUCCESS)
+ GET32_A(ep->checksum)) != 0)
break;
- return FFS_SUCCESS;
+ return 0;
}
- if (FAT_read(sb, clu.dir, &clu.dir) != 0)
- return FFS_MEDIAERR;
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ return -EIO;
}
/* load default upcase table */
return __load_default_upcase_table(sb);
@@ -906,28 +787,6 @@ void free_upcase_table(struct super_block *sb)
* Directory Entry Management Functions
*/
-u32 fat_get_entry_type(struct dentry_t *p_entry)
-{
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- if (*(ep->name) == 0x0)
- return TYPE_UNUSED;
-
- else if (*(ep->name) == 0xE5)
- return TYPE_DELETED;
-
- else if (ep->attr == ATTR_EXTEND)
- return TYPE_EXTEND;
-
- else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_VOLUME)
- return TYPE_VOLUME;
-
- else if ((ep->attr & (ATTR_SUBDIR | ATTR_VOLUME)) == ATTR_SUBDIR)
- return TYPE_DIR;
-
- return TYPE_FILE;
-}
-
u32 exfat_get_entry_type(struct dentry_t *p_entry)
{
struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
@@ -973,30 +832,7 @@ u32 exfat_get_entry_type(struct dentry_t *p_entry)
return TYPE_BENIGN_SEC;
}
-void fat_set_entry_type(struct dentry_t *p_entry, u32 type)
-{
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- if (type == TYPE_UNUSED)
- *(ep->name) = 0x0;
-
- else if (type == TYPE_DELETED)
- *(ep->name) = 0xE5;
-
- else if (type == TYPE_EXTEND)
- ep->attr = ATTR_EXTEND;
-
- else if (type == TYPE_DIR)
- ep->attr = ATTR_SUBDIR;
-
- else if (type == TYPE_FILE)
- ep->attr = ATTR_ARCHIVE;
-
- else if (type == TYPE_SYMLINK)
- ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK;
-}
-
-void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
+static void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
{
struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
@@ -1026,13 +862,6 @@ void exfat_set_entry_type(struct dentry_t *p_entry, u32 type)
}
}
-u32 fat_get_entry_attr(struct dentry_t *p_entry)
-{
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- return (u32)ep->attr;
-}
-
u32 exfat_get_entry_attr(struct dentry_t *p_entry)
{
struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
@@ -1040,13 +869,6 @@ u32 exfat_get_entry_attr(struct dentry_t *p_entry)
return (u32)GET16_A(ep->attr);
}
-void fat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
-{
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- ep->attr = (u8)attr;
-}
-
void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
{
struct file_dentry_t *ep = (struct file_dentry_t *)p_entry;
@@ -1054,11 +876,6 @@ void exfat_set_entry_attr(struct dentry_t *p_entry, u32 attr)
SET16_A(ep->attr, (u16)attr);
}
-u8 fat_get_entry_flag(struct dentry_t *p_entry)
-{
- return 0x01;
-}
-
u8 exfat_get_entry_flag(struct dentry_t *p_entry)
{
struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
@@ -1066,10 +883,6 @@ u8 exfat_get_entry_flag(struct dentry_t *p_entry)
return ep->flags;
}
-void fat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
-{
-}
-
void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
{
struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
@@ -1077,29 +890,13 @@ void exfat_set_entry_flag(struct dentry_t *p_entry, u8 flags)
ep->flags = flags;
}
-u32 fat_get_entry_clu0(struct dentry_t *p_entry)
+u32 exfat_get_entry_clu0(struct dentry_t *p_entry)
{
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- return ((u32)GET16_A(ep->start_clu_hi) << 16) |
- GET16_A(ep->start_clu_lo);
-}
-
-u32 exfat_get_entry_clu0(struct dentry_t *p_entry)
-{
- struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
+ struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
return GET32_A(ep->start_clu);
}
-void fat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
-{
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
- SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
-}
-
void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
{
struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
@@ -1107,13 +904,6 @@ void exfat_set_entry_clu0(struct dentry_t *p_entry, u32 start_clu)
SET32_A(ep->start_clu, start_clu);
}
-u64 fat_get_entry_size(struct dentry_t *p_entry)
-{
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- return (u64)GET32_A(ep->size);
-}
-
u64 exfat_get_entry_size(struct dentry_t *p_entry)
{
struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
@@ -1121,13 +911,6 @@ u64 exfat_get_entry_size(struct dentry_t *p_entry)
return GET64_A(ep->valid_size);
}
-void fat_set_entry_size(struct dentry_t *p_entry, u64 size)
-{
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- SET32_A(ep->size, (u32)size);
-}
-
void exfat_set_entry_size(struct dentry_t *p_entry, u64 size)
{
struct strm_dentry_t *ep = (struct strm_dentry_t *)p_entry;
@@ -1136,31 +919,6 @@ void exfat_set_entry_size(struct dentry_t *p_entry, u64 size)
SET64_A(ep->size, size);
}
-void fat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
- u8 mode)
-{
- u16 t = 0x00, d = 0x21;
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- switch (mode) {
- case TM_CREATE:
- t = GET16_A(ep->create_time);
- d = GET16_A(ep->create_date);
- break;
- case TM_MODIFY:
- t = GET16_A(ep->modify_time);
- d = GET16_A(ep->modify_date);
- break;
- }
-
- tp->sec = (t & 0x001F) << 1;
- tp->min = (t >> 5) & 0x003F;
- tp->hour = (t >> 11);
- tp->day = (d & 0x001F);
- tp->mon = (d >> 5) & 0x000F;
- tp->year = (d >> 9);
-}
-
void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
u8 mode)
{
@@ -1190,27 +948,6 @@ void exfat_get_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
tp->year = (d >> 9);
}
-void fat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
- u8 mode)
-{
- u16 t, d;
- struct dos_dentry_t *ep = (struct dos_dentry_t *)p_entry;
-
- t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
- d = (tp->year << 9) | (tp->mon << 5) | tp->day;
-
- switch (mode) {
- case TM_CREATE:
- SET16_A(ep->create_time, t);
- SET16_A(ep->create_date, d);
- break;
- case TM_MODIFY:
- SET16_A(ep->modify_time, t);
- SET16_A(ep->modify_date, d);
- break;
- }
-}
-
void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
u8 mode)
{
@@ -1236,25 +973,47 @@ void exfat_set_entry_time(struct dentry_t *p_entry, struct timestamp_t *tp,
}
}
-s32 fat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir, s32 entry,
- u32 type, u32 start_clu, u64 size)
+static void init_file_entry(struct file_dentry_t *ep, u32 type)
{
- sector_t sector;
- struct dos_dentry_t *dos_ep;
+ struct timestamp_t tm, *tp;
+
+ exfat_set_entry_type((struct dentry_t *)ep, type);
+
+ tp = tm_current(&tm);
+ exfat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE);
+ exfat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY);
+ exfat_set_entry_time((struct dentry_t *)ep, tp, TM_ACCESS);
+ ep->create_time_ms = 0;
+ ep->modify_time_ms = 0;
+ ep->access_time_ms = 0;
+}
+
+static void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, u64 size)
+{
+ exfat_set_entry_type((struct dentry_t *)ep, TYPE_STREAM);
+ ep->flags = flags;
+ SET32_A(ep->start_clu, start_clu);
+ SET64_A(ep->valid_size, size);
+ SET64_A(ep->size, size);
+}
- dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
- §or);
- if (!dos_ep)
- return FFS_MEDIAERR;
+static void init_name_entry(struct name_dentry_t *ep, u16 *uniname)
+{
+ int i;
- init_dos_entry(dos_ep, type, start_clu);
- buf_modify(sb, sector);
+ exfat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND);
+ ep->flags = 0x0;
- return FFS_SUCCESS;
+ for (i = 0; i < 30; i++, i++) {
+ SET16_A(ep->unicode_0_14 + i, *uniname);
+ if (*uniname == 0x0)
+ break;
+ uniname++;
+ }
}
-s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, u32 type, u32 start_clu, u64 size)
+static s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
+ s32 entry, u32 type, u32 start_clu, u64 size)
{
sector_t sector;
u8 flags;
@@ -1267,71 +1026,20 @@ s32 exfat_init_dir_entry(struct super_block *sb, struct chain_t *p_dir,
file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
§or);
if (!file_ep)
- return FFS_MEDIAERR;
+ return -ENOENT;
strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1,
§or);
if (!strm_ep)
- return FFS_MEDIAERR;
+ return -ENOENT;
init_file_entry(file_ep, type);
- buf_modify(sb, sector);
+ exfat_buf_modify(sb, sector);
init_strm_entry(strm_ep, flags, start_clu, size);
- buf_modify(sb, sector);
-
- return FFS_SUCCESS;
-}
-
-static s32 fat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 num_entries,
- struct uni_name_t *p_uniname,
- struct dos_name_t *p_dosname)
-{
- int i;
- sector_t sector;
- u8 chksum;
- u16 *uniname = p_uniname->name;
- struct dos_dentry_t *dos_ep;
- struct ext_dentry_t *ext_ep;
-
- dos_ep = (struct dos_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
- §or);
- if (!dos_ep)
- return FFS_MEDIAERR;
-
- dos_ep->lcase = p_dosname->name_case;
- memcpy(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH);
- buf_modify(sb, sector);
-
- if ((--num_entries) > 0) {
- chksum = calc_checksum_1byte((void *)dos_ep->name,
- DOS_NAME_LENGTH, 0);
-
- for (i = 1; i < num_entries; i++) {
- ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb,
- p_dir,
- entry - i,
- §or);
- if (!ext_ep)
- return FFS_MEDIAERR;
-
- init_ext_entry(ext_ep, i, chksum, uniname);
- buf_modify(sb, sector);
- uniname += 13;
- }
-
- ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir,
- entry - i,
- §or);
- if (!ext_ep)
- return FFS_MEDIAERR;
-
- init_ext_entry(ext_ep, i + 0x40, chksum, uniname);
- buf_modify(sb, sector);
- }
+ exfat_buf_modify(sb, sector);
- return FFS_SUCCESS;
+ return 0;
}
static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
@@ -1349,173 +1057,51 @@ static s32 exfat_init_ext_entry(struct super_block *sb, struct chain_t *p_dir,
file_ep = (struct file_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
§or);
if (!file_ep)
- return FFS_MEDIAERR;
+ return -ENOENT;
file_ep->num_ext = (u8)(num_entries - 1);
- buf_modify(sb, sector);
+ exfat_buf_modify(sb, sector);
strm_ep = (struct strm_dentry_t *)get_entry_in_dir(sb, p_dir, entry + 1,
§or);
if (!strm_ep)
- return FFS_MEDIAERR;
+ return -ENOENT;
strm_ep->name_len = p_uniname->name_len;
SET16_A(strm_ep->name_hash, p_uniname->name_hash);
- buf_modify(sb, sector);
+ exfat_buf_modify(sb, sector);
for (i = 2; i < num_entries; i++) {
name_ep = (struct name_dentry_t *)get_entry_in_dir(sb, p_dir,
entry + i,
§or);
if (!name_ep)
- return FFS_MEDIAERR;
+ return -ENOENT;
init_name_entry(name_ep, uniname);
- buf_modify(sb, sector);
+ exfat_buf_modify(sb, sector);
uniname += 15;
}
update_dir_checksum(sb, p_dir, entry);
- return FFS_SUCCESS;
-}
-
-void init_dos_entry(struct dos_dentry_t *ep, u32 type, u32 start_clu)
-{
- struct timestamp_t tm, *tp;
-
- fat_set_entry_type((struct dentry_t *)ep, type);
- SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
- SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
- SET32_A(ep->size, 0);
-
- tp = tm_current(&tm);
- fat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE);
- fat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY);
- SET16_A(ep->access_date, 0);
- ep->create_time_ms = 0;
-}
-
-void init_ext_entry(struct ext_dentry_t *ep, s32 order, u8 chksum, u16 *uniname)
-{
- int i;
- bool end = false;
-
- fat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND);
- ep->order = (u8)order;
- ep->sysid = 0;
- ep->checksum = chksum;
- SET16_A(ep->start_clu, 0);
-
- for (i = 0; i < 10; i += 2) {
- if (!end) {
- SET16(ep->unicode_0_4 + i, *uniname);
- if (*uniname == 0x0)
- end = true;
- else
- uniname++;
- } else {
- SET16(ep->unicode_0_4 + i, 0xFFFF);
- }
- }
-
- for (i = 0; i < 12; i += 2) {
- if (!end) {
- SET16_A(ep->unicode_5_10 + i, *uniname);
- if (*uniname == 0x0)
- end = true;
- else
- uniname++;
- } else {
- SET16_A(ep->unicode_5_10 + i, 0xFFFF);
- }
- }
-
- for (i = 0; i < 4; i += 2) {
- if (!end) {
- SET16_A(ep->unicode_11_12 + i, *uniname);
- if (*uniname == 0x0)
- end = true;
- else
- uniname++;
- } else {
- SET16_A(ep->unicode_11_12 + i, 0xFFFF);
- }
- }
-}
-
-void init_file_entry(struct file_dentry_t *ep, u32 type)
-{
- struct timestamp_t tm, *tp;
-
- exfat_set_entry_type((struct dentry_t *)ep, type);
-
- tp = tm_current(&tm);
- exfat_set_entry_time((struct dentry_t *)ep, tp, TM_CREATE);
- exfat_set_entry_time((struct dentry_t *)ep, tp, TM_MODIFY);
- exfat_set_entry_time((struct dentry_t *)ep, tp, TM_ACCESS);
- ep->create_time_ms = 0;
- ep->modify_time_ms = 0;
- ep->access_time_ms = 0;
-}
-
-void init_strm_entry(struct strm_dentry_t *ep, u8 flags, u32 start_clu, u64 size)
-{
- exfat_set_entry_type((struct dentry_t *)ep, TYPE_STREAM);
- ep->flags = flags;
- SET32_A(ep->start_clu, start_clu);
- SET64_A(ep->valid_size, size);
- SET64_A(ep->size, size);
-}
-
-void init_name_entry(struct name_dentry_t *ep, u16 *uniname)
-{
- int i;
-
- exfat_set_entry_type((struct dentry_t *)ep, TYPE_EXTEND);
- ep->flags = 0x0;
-
- for (i = 0; i < 30; i++, i++) {
- SET16_A(ep->unicode_0_14 + i, *uniname);
- if (*uniname == 0x0)
- break;
- uniname++;
- }
-}
-
-void fat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 order, s32 num_entries)
-{
- int i;
- sector_t sector;
- struct dentry_t *ep;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
-
- for (i = num_entries - 1; i >= order; i--) {
- ep = get_entry_in_dir(sb, p_dir, entry - i, §or);
- if (!ep)
- return;
-
- p_fs->fs_func->set_entry_type(ep, TYPE_DELETED);
- buf_modify(sb, sector);
- }
+ return 0;
}
void exfat_delete_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, s32 order, s32 num_entries)
+ s32 entry, s32 order, s32 num_entries)
{
int i;
sector_t sector;
struct dentry_t *ep;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
for (i = order; i < num_entries; i++) {
ep = get_entry_in_dir(sb, p_dir, entry + i, §or);
if (!ep)
return;
- p_fs->fs_func->set_entry_type(ep, TYPE_DELETED);
- buf_modify(sb, sector);
+ exfat_set_entry_type(ep, TYPE_DELETED);
+ exfat_buf_modify(sb, sector);
}
}
@@ -1533,7 +1119,7 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
if (!file_ep)
return;
- buf_lock(sb, sector);
+ exfat_buf_lock(sb, sector);
num_entries = (s32)file_ep->num_ext + 1;
chksum = calc_checksum_2byte((void *)file_ep, DENTRY_SIZE, 0,
@@ -1542,7 +1128,7 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
for (i = 1; i < num_entries; i++) {
ep = get_entry_in_dir(sb, p_dir, entry + i, NULL);
if (!ep) {
- buf_unlock(sb, sector);
+ exfat_buf_unlock(sb, sector);
return;
}
@@ -1551,8 +1137,75 @@ void update_dir_checksum(struct super_block *sb, struct chain_t *p_dir,
}
SET16_A(file_ep->checksum, chksum);
- buf_modify(sb, sector);
- buf_unlock(sb, sector);
+ exfat_buf_modify(sb, sector);
+ exfat_buf_unlock(sb, sector);
+}
+
+static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+ struct entry_set_cache_t *es,
+ sector_t sec, s32 off, u32 count)
+{
+ s32 num_entries, buf_off = (off - es->offset);
+ u32 remaining_byte_in_sector, copy_entries;
+ struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
+ u32 clu;
+ u8 *buf, *esbuf = (u8 *)&es->__buf;
+
+ pr_debug("%s entered es %p sec %llu off %d count %d\n",
+ __func__, es, (unsigned long long)sec, off, count);
+ num_entries = count;
+
+ while (num_entries) {
+ /* white per sector base */
+ remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off;
+ copy_entries = min_t(s32,
+ remaining_byte_in_sector >> DENTRY_SIZE_BITS,
+ num_entries);
+ buf = exfat_buf_getblk(sb, sec);
+ if (!buf)
+ goto err_out;
+ pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off);
+ pr_debug("copying %d entries from %p to sector %llu\n",
+ copy_entries, (esbuf + buf_off),
+ (unsigned long long)sec);
+ memcpy(buf + off, esbuf + buf_off,
+ copy_entries << DENTRY_SIZE_BITS);
+ exfat_buf_modify(sb, sec);
+ num_entries -= copy_entries;
+
+ if (num_entries) {
+ /* get next sector */
+ if (IS_LAST_SECTOR_IN_CLUSTER(sec)) {
+ clu = GET_CLUSTER_FROM_SECTOR(sec);
+ if (es->alloc_flag == 0x03) {
+ clu++;
+ } else {
+ if (exfat_fat_read(sb, clu, &clu) == -1)
+ goto err_out;
+ }
+ sec = START_SECTOR(clu);
+ } else {
+ sec++;
+ }
+ off = 0;
+ buf_off += copy_entries << DENTRY_SIZE_BITS;
+ }
+ }
+
+ pr_debug("%s exited successfully\n", __func__);
+ return 0;
+err_out:
+ pr_debug("%s failed\n", __func__);
+ return -EINVAL;
+}
+
+/* write back all entries in entry set */
+static s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es)
+{
+ return __write_partial_entries_in_entry_set(sb, es, es->sector,
+ es->offset,
+ es->num_entries);
}
void update_dir_checksum_with_entry_set(struct super_block *sb,
@@ -1562,7 +1215,7 @@ void update_dir_checksum_with_entry_set(struct super_block *sb,
u16 chksum = 0;
s32 chksum_type = CS_DIR_ENTRY, i;
- ep = (struct dentry_t *)&(es->__buf);
+ ep = (struct dentry_t *)&es->__buf;
for (i = 0; i < es->num_entries; i++) {
pr_debug("%s ep %p\n", __func__, ep);
chksum = calc_checksum_2byte((void *)ep, DENTRY_SIZE, chksum,
@@ -1571,7 +1224,7 @@ void update_dir_checksum_with_entry_set(struct super_block *sb,
chksum_type = CS_DEFAULT;
}
- ep = (struct dentry_t *)&(es->__buf);
+ ep = (struct dentry_t *)&es->__buf;
SET16_A(((struct file_dentry_t *)ep)->checksum, chksum);
write_whole_entry_set(sb, es);
}
@@ -1590,19 +1243,19 @@ static s32 _walk_fat_chain(struct super_block *sb, struct chain_t *p_dir,
cur_clu += clu_offset;
} else {
while (clu_offset > 0) {
- if (FAT_read(sb, cur_clu, &cur_clu) == -1)
- return FFS_MEDIAERR;
+ if (exfat_fat_read(sb, cur_clu, &cur_clu) == -1)
+ return -EIO;
clu_offset--;
}
}
if (clu)
*clu = cur_clu;
- return FFS_SUCCESS;
+ return 0;
}
-s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
- sector_t *sector, s32 *offset)
+static s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
+ sector_t *sector, s32 *offset)
{
s32 off, ret;
u32 clu = 0;
@@ -1617,7 +1270,7 @@ s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
*sector += p_fs->root_start_sector;
} else {
ret = _walk_fat_chain(sb, p_dir, off, &clu);
- if (ret != FFS_SUCCESS)
+ if (ret != 0)
return ret;
/* byte offset in cluster */
@@ -1630,20 +1283,7 @@ s32 find_location(struct super_block *sb, struct chain_t *p_dir, s32 entry,
*sector = off >> p_bd->sector_size_bits;
*sector += START_SECTOR(clu);
}
- return FFS_SUCCESS;
-}
-
-struct dentry_t *get_entry_with_sector(struct super_block *sb, sector_t sector,
- s32 offset)
-{
- u8 *buf;
-
- buf = buf_getblk(sb, sector);
-
- if (!buf)
- return NULL;
-
- return (struct dentry_t *)(buf + offset);
+ return 0;
}
struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
@@ -1653,10 +1293,10 @@ struct dentry_t *get_entry_in_dir(struct super_block *sb, struct chain_t *p_dir,
sector_t sec;
u8 *buf;
- if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS)
+ if (find_location(sb, p_dir, entry, &sec, &off) != 0)
return NULL;
- buf = buf_getblk(sb, sec);
+ buf = exfat_buf_getblk(sb, sec);
if (!buf)
return NULL;
@@ -1703,11 +1343,11 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
size_t bufsize;
pr_debug("%s entered p_dir dir %u flags %x size %d\n",
- __func__, p_dir->dir, p_dir->flags, p_dir->size);
+ __func__, p_dir->dir, p_dir->flags, p_dir->size);
byte_offset = entry << DENTRY_SIZE_BITS;
ret = _walk_fat_chain(sb, p_dir, byte_offset, &clu);
- if (ret != FFS_SUCCESS)
+ if (ret != 0)
return NULL;
/* byte offset in cluster */
@@ -1720,15 +1360,14 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
sec = byte_offset >> p_bd->sector_size_bits;
sec += START_SECTOR(clu);
- buf = buf_getblk(sb, sec);
+ buf = exfat_buf_getblk(sb, sec);
if (!buf)
goto err_out;
ep = (struct dentry_t *)(buf + off);
- entry_type = p_fs->fs_func->get_entry_type(ep);
+ entry_type = exfat_get_entry_type(ep);
- if ((entry_type != TYPE_FILE)
- && (entry_type != TYPE_DIR))
+ if ((entry_type != TYPE_FILE) && (entry_type != TYPE_DIR))
goto err_out;
if (type == ES_ALL_ENTRIES)
@@ -1756,7 +1395,7 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
* instead of copying whole sector, we will check every entry.
* this will provide minimum stablity and consistency.
*/
- entry_type = p_fs->fs_func->get_entry_type(ep);
+ entry_type = exfat_get_entry_type(ep);
if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED))
goto err_out;
@@ -1812,14 +1451,14 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
if (es->alloc_flag == 0x03) {
clu++;
} else {
- if (FAT_read(sb, clu, &clu) == -1)
+ if (exfat_fat_read(sb, clu, &clu) == -1)
goto err_out;
}
sec = START_SECTOR(clu);
} else {
sec++;
}
- buf = buf_getblk(sb, sec);
+ buf = exfat_buf_getblk(sb, sec);
if (!buf)
goto err_out;
off = 0;
@@ -1832,11 +1471,11 @@ struct entry_set_cache_t *get_entry_set_in_dir(struct super_block *sb,
}
if (file_ep)
- *file_ep = (struct dentry_t *)&(es->__buf);
+ *file_ep = (struct dentry_t *)&es->__buf;
pr_debug("%s exiting es %p sec %llu offset %d flags %d, num_entries %u buf ptr %p\n",
- __func__, es, (unsigned long long)es->sector, es->offset,
- es->alloc_flag, es->num_entries, &es->__buf);
+ __func__, es, (unsigned long long)es->sector, es->offset,
+ es->alloc_flag, es->num_entries, &es->__buf);
return es;
err_out:
pr_debug("%s exited NULL (es %p)\n", __func__, es);
@@ -1850,115 +1489,10 @@ void release_entry_set(struct entry_set_cache_t *es)
kfree(es);
}
-static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
- struct entry_set_cache_t *es,
- sector_t sec, s32 off, u32 count)
-{
- s32 num_entries, buf_off = (off - es->offset);
- u32 remaining_byte_in_sector, copy_entries;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
- u32 clu;
- u8 *buf, *esbuf = (u8 *)&(es->__buf);
-
- pr_debug("%s entered es %p sec %llu off %d count %d\n",
- __func__, es, (unsigned long long)sec, off, count);
- num_entries = count;
-
- while (num_entries) {
- /* white per sector base */
- remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off;
- copy_entries = min_t(s32,
- remaining_byte_in_sector >> DENTRY_SIZE_BITS,
- num_entries);
- buf = buf_getblk(sb, sec);
- if (!buf)
- goto err_out;
- pr_debug("es->buf %p buf_off %u\n", esbuf, buf_off);
- pr_debug("copying %d entries from %p to sector %llu\n",
- copy_entries, (esbuf + buf_off),
- (unsigned long long)sec);
- memcpy(buf + off, esbuf + buf_off,
- copy_entries << DENTRY_SIZE_BITS);
- buf_modify(sb, sec);
- num_entries -= copy_entries;
-
- if (num_entries) {
- /* get next sector */
- if (IS_LAST_SECTOR_IN_CLUSTER(sec)) {
- clu = GET_CLUSTER_FROM_SECTOR(sec);
- if (es->alloc_flag == 0x03) {
- clu++;
- } else {
- if (FAT_read(sb, clu, &clu) == -1)
- goto err_out;
- }
- sec = START_SECTOR(clu);
- } else {
- sec++;
- }
- off = 0;
- buf_off += copy_entries << DENTRY_SIZE_BITS;
- }
- }
-
- pr_debug("%s exited successfully\n", __func__);
- return FFS_SUCCESS;
-err_out:
- pr_debug("%s failed\n", __func__);
- return FFS_ERROR;
-}
-
-/* write back all entries in entry set */
-s32 write_whole_entry_set(struct super_block *sb, struct entry_set_cache_t *es)
-{
- return __write_partial_entries_in_entry_set(sb, es, es->sector,
- es->offset,
- es->num_entries);
-}
-
-/* write back some entries in entry set */
-s32 write_partial_entries_in_entry_set(struct super_block *sb,
- struct entry_set_cache_t *es, struct dentry_t *ep, u32 count)
-{
- s32 ret, byte_offset, off;
- u32 clu = 0;
- sector_t sec;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
- struct chain_t dir;
-
- /* vaidity check */
- if (ep + count > ((struct dentry_t *)&(es->__buf)) + es->num_entries)
- return FFS_ERROR;
-
- dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector);
- dir.flags = es->alloc_flag;
- dir.size = 0xffffffff; /* XXX */
-
- byte_offset = (es->sector - START_SECTOR(dir.dir)) <<
- p_bd->sector_size_bits;
- byte_offset += ((void **)ep - &(es->__buf)) + es->offset;
-
- ret = _walk_fat_chain(sb, &dir, byte_offset, &clu);
- if (ret != FFS_SUCCESS)
- return ret;
-
- /* byte offset in cluster */
- byte_offset &= p_fs->cluster_size - 1;
-
- /* byte offset in sector */
- off = byte_offset & p_bd->sector_size_mask;
-
- /* sector offset in cluster */
- sec = byte_offset >> p_bd->sector_size_bits;
- sec += START_SECTOR(clu);
- return __write_partial_entries_in_entry_set(sb, es, sec, off, count);
-}
-
-/* search EMPTY CONTINUOUS "num_entries" entries */
-s32 search_deleted_or_unused_entry(struct super_block *sb,
- struct chain_t *p_dir, s32 num_entries)
+/* search EMPTY CONTINUOUS "num_entries" entries */
+static s32 search_deleted_or_unused_entry(struct super_block *sb,
+ struct chain_t *p_dir,
+ s32 num_entries)
{
int i, dentry, num_empty = 0;
s32 dentries_per_clu;
@@ -2005,7 +1539,7 @@ s32 search_deleted_or_unused_entry(struct super_block *sb,
if (!ep)
return -1;
- type = p_fs->fs_func->get_entry_type(ep);
+ type = exfat_get_entry_type(ep);
if (type == TYPE_UNUSED) {
num_empty++;
@@ -2043,7 +1577,7 @@ s32 search_deleted_or_unused_entry(struct super_block *sb,
else
clu.dir = CLUSTER_32(~0);
} else {
- if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
return -1;
}
}
@@ -2051,7 +1585,7 @@ s32 search_deleted_or_unused_entry(struct super_block *sb,
return -1;
}
-s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries)
+static s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries)
{
s32 ret, dentry;
u32 last_clu;
@@ -2070,10 +1604,8 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
if (p_fs->dev_ejected)
break;
- if (p_fs->vol_type == EXFAT) {
- if (p_dir->dir != p_fs->root_dir)
- size = i_size_read(inode);
- }
+ if (p_dir->dir != p_fs->root_dir)
+ size = i_size_read(inode);
last_clu = find_last_cluster(sb, p_dir);
clu.dir = last_clu + 1;
@@ -2081,12 +1613,12 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
clu.flags = p_dir->flags;
/* (1) allocate a cluster */
- ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu);
+ ret = exfat_alloc_cluster(sb, 1, &clu);
if (ret < 1)
- return -1;
+ return -EIO;
- if (clear_cluster(sb, clu.dir) != FFS_SUCCESS)
- return -1;
+ if (clear_cluster(sb, clu.dir) != 0)
+ return -EIO;
/* (2) append to the FAT chain */
if (clu.flags != p_dir->flags) {
@@ -2095,8 +1627,8 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
p_fs->hint_uentry.clu.flags = 0x01;
}
if (clu.flags == 0x01)
- if (FAT_write(sb, last_clu, clu.dir) < 0)
- return -1;
+ if (exfat_fat_write(sb, last_clu, clu.dir) < 0)
+ return -EIO;
if (p_fs->hint_uentry.entry == -1) {
p_fs->hint_uentry.dir = p_dir->dir;
@@ -2110,21 +1642,19 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
p_dir->size++;
/* (3) update the directory entry */
- if (p_fs->vol_type == EXFAT) {
- if (p_dir->dir != p_fs->root_dir) {
- size += p_fs->cluster_size;
-
- ep = get_entry_in_dir(sb, &fid->dir,
- fid->entry + 1, §or);
- if (!ep)
- return -1;
- p_fs->fs_func->set_entry_size(ep, size);
- p_fs->fs_func->set_entry_flag(ep, p_dir->flags);
- buf_modify(sb, sector);
-
- update_dir_checksum(sb, &(fid->dir),
- fid->entry);
- }
+ if (p_dir->dir != p_fs->root_dir) {
+ size += p_fs->cluster_size;
+
+ ep = get_entry_in_dir(sb, &fid->dir,
+ fid->entry + 1, §or);
+ if (!ep)
+ return -ENOENT;
+ exfat_set_entry_size(ep, size);
+ exfat_set_entry_flag(ep, p_dir->flags);
+ exfat_buf_modify(sb, sector);
+
+ update_dir_checksum(sb, &fid->dir,
+ fid->entry);
}
i_size_write(inode, i_size_read(inode) + p_fs->cluster_size);
@@ -2137,102 +1667,21 @@ s32 find_empty_entry(struct inode *inode, struct chain_t *p_dir, s32 num_entries
return dentry;
}
-/* return values of fat_find_dir_entry()
- * >= 0 : return dir entiry position with the name in dir
- * -1 : (root dir, ".") it is the root dir itself
- * -2 : entry with the name does not exist
- */
-s32 fat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
- struct uni_name_t *p_uniname, s32 num_entries,
- struct dos_name_t *p_dosname, u32 type)
+static s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname,
+ s32 order)
{
- int i, dentry = 0, len;
- s32 order = 0;
- bool is_feasible_entry = true, has_ext_entry = false;
- s32 dentries_per_clu;
- u32 entry_type;
- u16 entry_uniname[14], *uniname = NULL, unichar;
- struct chain_t clu;
- struct dentry_t *ep;
- struct dos_dentry_t *dos_ep;
- struct ext_dentry_t *ext_ep;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
-
- if (p_dir->dir == p_fs->root_dir) {
- if ((!nls_uniname_cmp(sb, p_uniname->name,
- (u16 *)UNI_CUR_DIR_NAME)) ||
- (!nls_uniname_cmp(sb, p_uniname->name,
- (u16 *)UNI_PAR_DIR_NAME)))
- return -1; // special case, root directory itself
- }
-
- if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
- dentries_per_clu = p_fs->dentries_in_root;
- else
- dentries_per_clu = p_fs->dentries_per_clu;
-
- clu.dir = p_dir->dir;
- clu.flags = p_dir->flags;
-
- while (clu.dir != CLUSTER_32(~0)) {
- if (p_fs->dev_ejected)
- break;
-
- for (i = 0; i < dentries_per_clu; i++, dentry++) {
- ep = get_entry_in_dir(sb, &clu, i, NULL);
- if (!ep)
- return -2;
-
- entry_type = p_fs->fs_func->get_entry_type(ep);
-
- if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) {
- if ((type == TYPE_ALL) || (type == entry_type)) {
- if (is_feasible_entry && has_ext_entry)
- return dentry;
-
- dos_ep = (struct dos_dentry_t *)ep;
- if (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name))
- return dentry;
- }
- is_feasible_entry = true;
- has_ext_entry = false;
- } else if (entry_type == TYPE_EXTEND) {
- if (is_feasible_entry) {
- ext_ep = (struct ext_dentry_t *)ep;
- if (ext_ep->order > 0x40) {
- order = (s32)(ext_ep->order - 0x40);
- uniname = p_uniname->name + 13 * (order - 1);
- } else {
- order = (s32)ext_ep->order;
- uniname -= 13;
- }
-
- len = extract_uni_name_from_ext_entry(ext_ep, entry_uniname, order);
-
- unichar = *(uniname + len);
- *(uniname + len) = 0x0;
-
- if (nls_uniname_cmp(sb, uniname, entry_uniname))
- is_feasible_entry = false;
-
- *(uniname + len) = unichar;
- }
- has_ext_entry = true;
- } else if (entry_type == TYPE_UNUSED) {
- return -2;
- }
- is_feasible_entry = true;
- has_ext_entry = false;
- }
-
- if (p_dir->dir == CLUSTER_32(0))
- break; /* FAT16 root_dir */
+ int i, len = 0;
- if (FAT_read(sb, clu.dir, &clu.dir) != 0)
- return -2;
+ for (i = 0; i < 30; i += 2) {
+ *uniname = GET16_A(ep->unicode_0_14 + i);
+ if (*uniname == 0x0)
+ return len;
+ uniname++;
+ len++;
}
- return -2;
+ *uniname = 0x0;
+ return len;
}
/* return values of exfat_find_dir_entry()
@@ -2286,7 +1735,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
if (!ep)
return -2;
- entry_type = p_fs->fs_func->get_entry_type(ep);
+ entry_type = exfat_get_entry_type(ep);
step = 1;
if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) {
@@ -2375,7 +1824,7 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
else
clu.dir = CLUSTER_32(~0);
} else {
- if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
return -2;
}
}
@@ -2383,36 +1832,6 @@ s32 exfat_find_dir_entry(struct super_block *sb, struct chain_t *p_dir,
return -2;
}
-s32 fat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
- s32 entry, struct dentry_t *p_entry)
-{
- s32 count = 0;
- u8 chksum;
- struct dos_dentry_t *dos_ep = (struct dos_dentry_t *)p_entry;
- struct ext_dentry_t *ext_ep;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
-
- chksum = calc_checksum_1byte((void *)dos_ep->name, DOS_NAME_LENGTH, 0);
-
- for (entry--; entry >= 0; entry--) {
- ext_ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir,
- entry, NULL);
- if (!ext_ep)
- return -1;
-
- if ((p_fs->fs_func->get_entry_type((struct dentry_t *)ext_ep) ==
- TYPE_EXTEND) && (ext_ep->checksum == chksum)) {
- count++;
- if (ext_ep->order > 0x40)
- return count;
- } else {
- return count;
- }
- }
-
- return count;
-}
-
s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
s32 entry, struct dentry_t *p_entry)
{
@@ -2420,14 +1839,13 @@ s32 exfat_count_ext_entries(struct super_block *sb, struct chain_t *p_dir,
u32 type;
struct file_dentry_t *file_ep = (struct file_dentry_t *)p_entry;
struct dentry_t *ext_ep;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) {
ext_ep = get_entry_in_dir(sb, p_dir, entry, NULL);
if (!ext_ep)
return -1;
- type = p_fs->fs_func->get_entry_type(ext_ep);
+ type = exfat_get_entry_type(ext_ep);
if ((type == TYPE_EXTEND) || (type == TYPE_STREAM))
count++;
else
@@ -2463,9 +1881,9 @@ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
for (i = 0; i < dentries_per_clu; i++) {
ep = get_entry_in_dir(sb, &clu, i, NULL);
if (!ep)
- return -1;
+ return -ENOENT;
- entry_type = p_fs->fs_func->get_entry_type(ep);
+ entry_type = exfat_get_entry_type(ep);
if (entry_type == TYPE_UNUSED)
return count;
@@ -2486,8 +1904,8 @@ s32 count_dos_name_entries(struct super_block *sb, struct chain_t *p_dir,
else
clu.dir = CLUSTER_32(~0);
} else {
- if (FAT_read(sb, clu.dir, &clu.dir) != 0)
- return -1;
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
+ return -EIO;
}
}
@@ -2521,7 +1939,7 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir)
if (!ep)
break;
- type = p_fs->fs_func->get_entry_type(ep);
+ type = exfat_get_entry_type(ep);
if (type == TYPE_UNUSED)
return true;
@@ -2546,7 +1964,7 @@ bool is_dir_empty(struct super_block *sb, struct chain_t *p_dir)
else
clu.dir = CLUSTER_32(~0);
}
- if (FAT_read(sb, clu.dir, &clu.dir) != 0)
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) != 0)
break;
}
@@ -2564,81 +1982,15 @@ s32 get_num_entries_and_dos_name(struct super_block *sb, struct chain_t *p_dir,
struct uni_name_t *p_uniname, s32 *entries,
struct dos_name_t *p_dosname)
{
- s32 ret, num_entries;
- bool lossy = false;
- char **r;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
+ s32 num_entries;
- num_entries = p_fs->fs_func->calc_num_entries(p_uniname);
+ num_entries = exfat_calc_num_entries(p_uniname);
if (num_entries == 0)
- return FFS_INVALIDPATH;
-
- if (p_fs->vol_type != EXFAT) {
- nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy);
-
- if (lossy) {
- ret = fat_generate_dos_name(sb, p_dir, p_dosname);
- if (ret)
- return ret;
- } else {
- for (r = reserved_names; *r; r++) {
- if (!strncmp((void *)p_dosname->name, *r, 8))
- return FFS_INVALIDPATH;
- }
-
- if (p_dosname->name_case != 0xFF)
- num_entries = 1;
- }
-
- if (num_entries > 1)
- p_dosname->name_case = 0x0;
- }
+ return -EINVAL;
*entries = num_entries;
- return FFS_SUCCESS;
-}
-
-void get_uni_name_from_dos_entry(struct super_block *sb,
- struct dos_dentry_t *ep,
- struct uni_name_t *p_uniname, u8 mode)
-{
- struct dos_name_t dos_name;
-
- if (mode == 0x0)
- dos_name.name_case = 0x0;
- else
- dos_name.name_case = ep->lcase;
-
- memcpy(dos_name.name, ep->name, DOS_NAME_LENGTH);
- nls_dosname_to_uniname(sb, p_uniname, &dos_name);
-}
-
-void fat_get_uni_name_from_ext_entry(struct super_block *sb,
- struct chain_t *p_dir, s32 entry,
- u16 *uniname)
-{
- int i;
- struct ext_dentry_t *ep;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
-
- for (entry--, i = 1; entry >= 0; entry--, i++) {
- ep = (struct ext_dentry_t *)get_entry_in_dir(sb, p_dir, entry,
- NULL);
- if (!ep)
- return;
-
- if (p_fs->fs_func->get_entry_type((struct dentry_t *)ep) ==
- TYPE_EXTEND) {
- extract_uni_name_from_ext_entry(ep, uniname, i);
- if (ep->order > 0x40)
- return;
- } else {
- return;
- }
-
- uniname += 13;
- }
+ return 0;
}
void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
@@ -2648,7 +2000,6 @@ void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
int i;
struct dentry_t *ep;
struct entry_set_cache_t *es;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep);
if (!es || es->num_entries < 3) {
@@ -2666,7 +2017,7 @@ void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
* So, the index of first file-name dentry should start from 2.
*/
for (i = 2; i < es->num_entries; i++, ep++) {
- if (p_fs->fs_func->get_entry_type(ep) == TYPE_EXTEND)
+ if (exfat_get_entry_type(ep) == TYPE_EXTEND)
extract_uni_name_from_name_entry((struct name_dentry_t *)
ep, uniname, i);
else
@@ -2678,202 +2029,6 @@ void exfat_get_uni_name_from_ext_entry(struct super_block *sb,
release_entry_set(es);
}
-s32 extract_uni_name_from_ext_entry(struct ext_dentry_t *ep, u16 *uniname,
- s32 order)
-{
- int i, len = 0;
-
- for (i = 0; i < 10; i += 2) {
- *uniname = GET16(ep->unicode_0_4 + i);
- if (*uniname == 0x0)
- return len;
- uniname++;
- len++;
- }
-
- if (order < 20) {
- for (i = 0; i < 12; i += 2) {
- *uniname = GET16_A(ep->unicode_5_10 + i);
- if (*uniname == 0x0)
- return len;
- uniname++;
- len++;
- }
- } else {
- for (i = 0; i < 8; i += 2) {
- *uniname = GET16_A(ep->unicode_5_10 + i);
- if (*uniname == 0x0)
- return len;
- uniname++;
- len++;
- }
- *uniname = 0x0; /* uniname[MAX_NAME_LENGTH-1] */
- return len;
- }
-
- for (i = 0; i < 4; i += 2) {
- *uniname = GET16_A(ep->unicode_11_12 + i);
- if (*uniname == 0x0)
- return len;
- uniname++;
- len++;
- }
-
- *uniname = 0x0;
- return len;
-}
-
-s32 extract_uni_name_from_name_entry(struct name_dentry_t *ep, u16 *uniname,
- s32 order)
-{
- int i, len = 0;
-
- for (i = 0; i < 30; i += 2) {
- *uniname = GET16_A(ep->unicode_0_14 + i);
- if (*uniname == 0x0)
- return len;
- uniname++;
- len++;
- }
-
- *uniname = 0x0;
- return len;
-}
-
-s32 fat_generate_dos_name(struct super_block *sb, struct chain_t *p_dir,
- struct dos_name_t *p_dosname)
-{
- int i, j, count = 0;
- bool count_begin = false;
- s32 dentries_per_clu;
- u32 type;
- u8 bmap[128/* 1 ~ 1023 */];
- struct chain_t clu;
- struct dos_dentry_t *ep;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
-
- memset(bmap, 0, sizeof(bmap));
- exfat_bitmap_set(bmap, 0);
-
- if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */
- dentries_per_clu = p_fs->dentries_in_root;
- else
- dentries_per_clu = p_fs->dentries_per_clu;
-
- clu.dir = p_dir->dir;
- clu.flags = p_dir->flags;
-
- while (clu.dir != CLUSTER_32(~0)) {
- if (p_fs->dev_ejected)
- break;
-
- for (i = 0; i < dentries_per_clu; i++) {
- ep = (struct dos_dentry_t *)get_entry_in_dir(sb, &clu,
- i, NULL);
- if (!ep)
- return FFS_MEDIAERR;
-
- type = p_fs->fs_func->get_entry_type((struct dentry_t *)
- ep);
-
- if (type == TYPE_UNUSED)
- break;
- if ((type != TYPE_FILE) && (type != TYPE_DIR))
- continue;
-
- count = 0;
- count_begin = false;
-
- for (j = 0; j < 8; j++) {
- if (ep->name[j] == ' ')
- break;
-
- if (ep->name[j] == '~') {
- count_begin = true;
- } else if (count_begin) {
- if ((ep->name[j] >= '0') &&
- (ep->name[j] <= '9')) {
- count = count * 10 +
- (ep->name[j] - '0');
- } else {
- count = 0;
- count_begin = false;
- }
- }
- }
-
- if ((count > 0) && (count < 1024))
- exfat_bitmap_set(bmap, count);
- }
-
- if (p_dir->dir == CLUSTER_32(0))
- break; /* FAT16 root_dir */
-
- if (FAT_read(sb, clu.dir, &clu.dir) != 0)
- return FFS_MEDIAERR;
- }
-
- count = 0;
- for (i = 0; i < 128; i++) {
- if (bmap[i] != 0xFF) {
- for (j = 0; j < 8; j++) {
- if (exfat_bitmap_test(&bmap[i], j) == 0) {
- count = (i << 3) + j;
- break;
- }
- }
- if (count != 0)
- break;
- }
- }
-
- if ((count == 0) || (count >= 1024))
- return FFS_FILEEXIST;
- fat_attach_count_to_dos_name(p_dosname->name, count);
-
- /* Now dos_name has DOS~????.EXT */
- return FFS_SUCCESS;
-}
-
-void fat_attach_count_to_dos_name(u8 *dosname, s32 count)
-{
- int i, j, length;
- char str_count[6];
-
- snprintf(str_count, sizeof(str_count), "~%d", count);
- length = strlen(str_count);
-
- i = 0;
- j = 0;
- while (j <= (8 - length)) {
- i = j;
- if (dosname[j] == ' ')
- break;
- if (dosname[j] & 0x80)
- j += 2;
- else
- j++;
- }
-
- for (j = 0; j < length; i++, j++)
- dosname[i] = (u8)str_count[j];
-
- if (i == 7)
- dosname[7] = ' ';
-}
-
-s32 fat_calc_num_entries(struct uni_name_t *p_uniname)
-{
- s32 len;
-
- len = p_uniname->name_len;
- if (len == 0)
- return 0;
-
- /* 1 dos name entry + extended entries */
- return (len - 1) / 13 + 2;
-}
-
s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
{
s32 len;
@@ -2886,17 +2041,6 @@ s32 exfat_calc_num_entries(struct uni_name_t *p_uniname)
return (len - 1) / 15 + 3;
}
-u8 calc_checksum_1byte(void *data, s32 len, u8 chksum)
-{
- int i;
- u8 *c = (u8 *)data;
-
- for (i = 0; i < len; i++, c++)
- chksum = (((chksum & 1) << 7) | ((chksum & 0xFE) >> 1)) + *c;
-
- return chksum;
-}
-
u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type)
{
int i;
@@ -2921,30 +2065,6 @@ u16 calc_checksum_2byte(void *data, s32 len, u16 chksum, s32 type)
return chksum;
}
-u32 calc_checksum_4byte(void *data, s32 len, u32 chksum, s32 type)
-{
- int i;
- u8 *c = (u8 *)data;
-
- switch (type) {
- case CS_PBR_SECTOR:
- for (i = 0; i < len; i++, c++) {
- if ((i == 106) || (i == 107) || (i == 112))
- continue;
- chksum = (((chksum & 1) << 31) |
- ((chksum & 0xFFFFFFFE) >> 1)) + (u32)*c;
- }
- break;
- default
- :
- for (i = 0; i < len; i++, c++)
- chksum = (((chksum & 1) << 31) |
- ((chksum & 0xFFFFFFFE) >> 1)) + (u32)*c;
- }
-
- return chksum;
-}
-
/*
* Name Resolution Functions
*/
@@ -2962,11 +2082,11 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
struct file_id_t *fid = &(EXFAT_I(inode)->fid);
if (strscpy(name_buf, path, sizeof(name_buf)) < 0)
- return FFS_INVALIDPATH;
+ return -EINVAL;
nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy);
if (lossy)
- return FFS_INVALIDPATH;
+ return -EINVAL;
fid->size = i_size_read(inode);
@@ -2974,181 +2094,9 @@ s32 resolve_path(struct inode *inode, char *path, struct chain_t *p_dir,
p_dir->size = (s32)(fid->size >> p_fs->cluster_size_bits);
p_dir->flags = fid->flags;
- return FFS_SUCCESS;
-}
-
-/*
- * File Operation Functions
- */
-static struct fs_func fat_fs_func = {
- .alloc_cluster = fat_alloc_cluster,
- .free_cluster = fat_free_cluster,
- .count_used_clusters = fat_count_used_clusters,
-
- .init_dir_entry = fat_init_dir_entry,
- .init_ext_entry = fat_init_ext_entry,
- .find_dir_entry = fat_find_dir_entry,
- .delete_dir_entry = fat_delete_dir_entry,
- .get_uni_name_from_ext_entry = fat_get_uni_name_from_ext_entry,
- .count_ext_entries = fat_count_ext_entries,
- .calc_num_entries = fat_calc_num_entries,
-
- .get_entry_type = fat_get_entry_type,
- .set_entry_type = fat_set_entry_type,
- .get_entry_attr = fat_get_entry_attr,
- .set_entry_attr = fat_set_entry_attr,
- .get_entry_flag = fat_get_entry_flag,
- .set_entry_flag = fat_set_entry_flag,
- .get_entry_clu0 = fat_get_entry_clu0,
- .set_entry_clu0 = fat_set_entry_clu0,
- .get_entry_size = fat_get_entry_size,
- .set_entry_size = fat_set_entry_size,
- .get_entry_time = fat_get_entry_time,
- .set_entry_time = fat_set_entry_time,
-};
-
-s32 fat16_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
-{
- s32 num_reserved, num_root_sectors;
- struct bpb16_t *p_bpb = (struct bpb16_t *)p_pbr->bpb;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
-
- if (p_bpb->num_fats == 0)
- return FFS_FORMATERR;
-
- num_root_sectors = GET16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS;
- num_root_sectors = ((num_root_sectors - 1) >>
- p_bd->sector_size_bits) + 1;
-
- p_fs->sectors_per_clu = p_bpb->sectors_per_clu;
- p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu);
- p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
- p_bd->sector_size_bits;
- p_fs->cluster_size = 1 << p_fs->cluster_size_bits;
-
- p_fs->num_FAT_sectors = GET16(p_bpb->num_fat_sectors);
-
- p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved);
- if (p_bpb->num_fats == 1)
- p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
- else
- p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
- p_fs->num_FAT_sectors;
-
- p_fs->root_start_sector = p_fs->FAT2_start_sector +
- p_fs->num_FAT_sectors;
- p_fs->data_start_sector = p_fs->root_start_sector + num_root_sectors;
-
- p_fs->num_sectors = GET16(p_bpb->num_sectors);
- if (p_fs->num_sectors == 0)
- p_fs->num_sectors = GET32(p_bpb->num_huge_sectors);
-
- num_reserved = p_fs->data_start_sector - p_fs->PBR_sector;
- p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >>
- p_fs->sectors_per_clu_bits) + 2;
- /* because the cluster index starts with 2 */
-
- if (p_fs->num_clusters < FAT12_THRESHOLD)
- p_fs->vol_type = FAT12;
- else
- p_fs->vol_type = FAT16;
- p_fs->vol_id = GET32(p_bpb->vol_serial);
-
- p_fs->root_dir = 0;
- p_fs->dentries_in_root = GET16(p_bpb->num_root_entries);
- p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits -
- DENTRY_SIZE_BITS);
-
- p_fs->vol_flag = VOL_CLEAN;
- p_fs->clu_srch_ptr = 2;
- p_fs->used_clusters = UINT_MAX;
-
- p_fs->fs_func = &fat_fs_func;
-
- return FFS_SUCCESS;
+ return 0;
}
-s32 fat32_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
-{
- s32 num_reserved;
- struct bpb32_t *p_bpb = (struct bpb32_t *)p_pbr->bpb;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
-
- if (p_bpb->num_fats == 0)
- return FFS_FORMATERR;
-
- p_fs->sectors_per_clu = p_bpb->sectors_per_clu;
- p_fs->sectors_per_clu_bits = ilog2(p_bpb->sectors_per_clu);
- p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits +
- p_bd->sector_size_bits;
- p_fs->cluster_size = 1 << p_fs->cluster_size_bits;
-
- p_fs->num_FAT_sectors = GET32(p_bpb->num_fat32_sectors);
-
- p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved);
- if (p_bpb->num_fats == 1)
- p_fs->FAT2_start_sector = p_fs->FAT1_start_sector;
- else
- p_fs->FAT2_start_sector = p_fs->FAT1_start_sector +
- p_fs->num_FAT_sectors;
-
- p_fs->root_start_sector = p_fs->FAT2_start_sector +
- p_fs->num_FAT_sectors;
- p_fs->data_start_sector = p_fs->root_start_sector;
-
- p_fs->num_sectors = GET32(p_bpb->num_huge_sectors);
- num_reserved = p_fs->data_start_sector - p_fs->PBR_sector;
-
- p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >>
- p_fs->sectors_per_clu_bits) + 2;
- /* because the cluster index starts with 2 */
-
- p_fs->vol_type = FAT32;
- p_fs->vol_id = GET32(p_bpb->vol_serial);
-
- p_fs->root_dir = GET32(p_bpb->root_cluster);
- p_fs->dentries_in_root = 0;
- p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits -
- DENTRY_SIZE_BITS);
-
- p_fs->vol_flag = VOL_CLEAN;
- p_fs->clu_srch_ptr = 2;
- p_fs->used_clusters = UINT_MAX;
-
- p_fs->fs_func = &fat_fs_func;
-
- return FFS_SUCCESS;
-}
-
-static struct fs_func exfat_fs_func = {
- .alloc_cluster = exfat_alloc_cluster,
- .free_cluster = exfat_free_cluster,
- .count_used_clusters = exfat_count_used_clusters,
-
- .init_dir_entry = exfat_init_dir_entry,
- .init_ext_entry = exfat_init_ext_entry,
- .find_dir_entry = exfat_find_dir_entry,
- .delete_dir_entry = exfat_delete_dir_entry,
- .get_uni_name_from_ext_entry = exfat_get_uni_name_from_ext_entry,
- .count_ext_entries = exfat_count_ext_entries,
- .calc_num_entries = exfat_calc_num_entries,
-
- .get_entry_type = exfat_get_entry_type,
- .set_entry_type = exfat_set_entry_type,
- .get_entry_attr = exfat_get_entry_attr,
- .set_entry_attr = exfat_set_entry_attr,
- .get_entry_flag = exfat_get_entry_flag,
- .set_entry_flag = exfat_set_entry_flag,
- .get_entry_clu0 = exfat_get_entry_clu0,
- .set_entry_clu0 = exfat_set_entry_clu0,
- .get_entry_size = exfat_get_entry_size,
- .set_entry_size = exfat_set_entry_size,
- .get_entry_time = exfat_get_entry_time,
- .set_entry_time = exfat_set_entry_time,
-};
-
s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
{
struct bpbex_t *p_bpb = (struct bpbex_t *)p_pbr->bpb;
@@ -3156,7 +2104,7 @@ s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
if (p_bpb->num_fats == 0)
- return FFS_FORMATERR;
+ return -EFSCORRUPTED;
p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits;
p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits;
@@ -3192,9 +2140,7 @@ s32 exfat_mount(struct super_block *sb, struct pbr_sector_t *p_pbr)
p_fs->clu_srch_ptr = 2;
p_fs->used_clusters = UINT_MAX;
- p_fs->fs_func = &exfat_fs_func;
-
- return FFS_SUCCESS;
+ return 0;
}
s32 create_dir(struct inode *inode, struct chain_t *p_dir,
@@ -3203,10 +2149,9 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
s32 ret, dentry, num_entries;
u64 size;
struct chain_t clu;
- struct dos_name_t dos_name, dot_name;
+ struct dos_name_t dos_name;
struct super_block *sb = inode->i_sb;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct fs_func *fs_func = p_fs->fs_func;
ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries,
&dos_name);
@@ -3216,73 +2161,35 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
/* find_empty_entry must be called before alloc_cluster */
dentry = find_empty_entry(inode, p_dir, num_entries);
if (dentry < 0)
- return FFS_FULL;
+ return -ENOSPC;
clu.dir = CLUSTER_32(~0);
clu.size = 0;
clu.flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
/* (1) allocate a cluster */
- ret = fs_func->alloc_cluster(sb, 1, &clu);
+ ret = exfat_alloc_cluster(sb, 1, &clu);
if (ret < 0)
- return FFS_MEDIAERR;
+ return ret;
else if (ret == 0)
- return FFS_FULL;
+ return -ENOSPC;
ret = clear_cluster(sb, clu.dir);
- if (ret != FFS_SUCCESS)
+ if (ret != 0)
return ret;
- if (p_fs->vol_type == EXFAT) {
- size = p_fs->cluster_size;
- } else {
- size = 0;
-
- /* initialize the . and .. entry
- * Information for . points to itself
- * Information for .. points to parent dir
- */
-
- dot_name.name_case = 0x0;
- memcpy(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH);
-
- ret = fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir,
- 0);
- if (ret != FFS_SUCCESS)
- return ret;
-
- ret = fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name);
- if (ret != FFS_SUCCESS)
- return ret;
-
- memcpy(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH);
-
- if (p_dir->dir == p_fs->root_dir)
- ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR,
- CLUSTER_32(0), 0);
- else
- ret = fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR,
- p_dir->dir, 0);
-
- if (ret != FFS_SUCCESS)
- return ret;
-
- ret = p_fs->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL,
- &dot_name);
- if (ret != FFS_SUCCESS)
- return ret;
- }
+ size = p_fs->cluster_size;
/* (2) update the directory entry */
/* make sub-dir entry in parent directory */
- ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir,
- size);
- if (ret != FFS_SUCCESS)
+ ret = exfat_init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir,
+ size);
+ if (ret != 0)
return ret;
- ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname,
- &dos_name);
- if (ret != FFS_SUCCESS)
+ ret = exfat_init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname,
+ &dos_name);
+ if (ret != 0)
return ret;
fid->dir.dir = p_dir->dir;
@@ -3299,7 +2206,7 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
fid->rwoffset = 0;
fid->hint_last_off = -1;
- return FFS_SUCCESS;
+ return 0;
}
s32 create_file(struct inode *inode, struct chain_t *p_dir,
@@ -3309,7 +2216,6 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir,
struct dos_name_t dos_name;
struct super_block *sb = inode->i_sb;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct fs_func *fs_func = p_fs->fs_func;
ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries,
&dos_name);
@@ -3319,20 +2225,20 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir,
/* find_empty_entry must be called before alloc_cluster() */
dentry = find_empty_entry(inode, p_dir, num_entries);
if (dentry < 0)
- return FFS_FULL;
+ return -ENOSPC;
/* (1) update the directory entry */
/* fill the dos name directory entry information of the created file.
* the first cluster is not determined yet. (0)
*/
- ret = fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode,
- CLUSTER_32(0), 0);
- if (ret != FFS_SUCCESS)
+ ret = exfat_init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode,
+ CLUSTER_32(0), 0);
+ if (ret != 0)
return ret;
- ret = fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname,
- &dos_name);
- if (ret != FFS_SUCCESS)
+ ret = exfat_init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname,
+ &dos_name);
+ if (ret != 0)
return ret;
fid->dir.dir = p_dir->dir;
@@ -3349,7 +2255,7 @@ s32 create_file(struct inode *inode, struct chain_t *p_dir,
fid->rwoffset = 0;
fid->hint_last_off = -1;
- return FFS_SUCCESS;
+ return 0;
}
void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry)
@@ -3358,27 +2264,25 @@ void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry)
sector_t sector;
struct dentry_t *ep;
struct super_block *sb = inode->i_sb;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct fs_func *fs_func = p_fs->fs_func;
ep = get_entry_in_dir(sb, p_dir, entry, §or);
if (!ep)
return;
- buf_lock(sb, sector);
+ exfat_buf_lock(sb, sector);
- /* buf_lock() before call count_ext_entries() */
- num_entries = fs_func->count_ext_entries(sb, p_dir, entry, ep);
+ /* exfat_buf_lock() before call count_ext_entries() */
+ num_entries = exfat_count_ext_entries(sb, p_dir, entry, ep);
if (num_entries < 0) {
- buf_unlock(sb, sector);
+ exfat_buf_unlock(sb, sector);
return;
}
num_entries++;
- buf_unlock(sb, sector);
+ exfat_buf_unlock(sb, sector);
/* (1) update the directory entry */
- fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries);
+ exfat_delete_dir_entry(sb, p_dir, entry, 0, num_entries);
}
s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
@@ -3389,101 +2293,97 @@ s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
struct dos_name_t dos_name;
struct dentry_t *epold, *epnew;
struct super_block *sb = inode->i_sb;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct fs_func *fs_func = p_fs->fs_func;
epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old);
if (!epold)
- return FFS_MEDIAERR;
+ return -ENOENT;
- buf_lock(sb, sector_old);
+ exfat_buf_lock(sb, sector_old);
- /* buf_lock() before call count_ext_entries() */
- num_old_entries = fs_func->count_ext_entries(sb, p_dir, oldentry,
- epold);
+ /* exfat_buf_lock() before call count_ext_entries() */
+ num_old_entries = exfat_count_ext_entries(sb, p_dir, oldentry,
+ epold);
if (num_old_entries < 0) {
- buf_unlock(sb, sector_old);
- return FFS_MEDIAERR;
+ exfat_buf_unlock(sb, sector_old);
+ return -ENOENT;
}
num_old_entries++;
ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname,
&num_new_entries, &dos_name);
if (ret) {
- buf_unlock(sb, sector_old);
+ exfat_buf_unlock(sb, sector_old);
return ret;
}
if (num_old_entries < num_new_entries) {
newentry = find_empty_entry(inode, p_dir, num_new_entries);
if (newentry < 0) {
- buf_unlock(sb, sector_old);
- return FFS_FULL;
+ exfat_buf_unlock(sb, sector_old);
+ return -ENOSPC;
}
epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new);
if (!epnew) {
- buf_unlock(sb, sector_old);
- return FFS_MEDIAERR;
+ exfat_buf_unlock(sb, sector_old);
+ return -ENOENT;
}
memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
- if (fs_func->get_entry_type(epnew) == TYPE_FILE) {
- fs_func->set_entry_attr(epnew,
- fs_func->get_entry_attr(epnew) |
- ATTR_ARCHIVE);
+ if (exfat_get_entry_type(epnew) == TYPE_FILE) {
+ exfat_set_entry_attr(epnew,
+ exfat_get_entry_attr(epnew) |
+ ATTR_ARCHIVE);
fid->attr |= ATTR_ARCHIVE;
}
- buf_modify(sb, sector_new);
- buf_unlock(sb, sector_old);
-
- if (p_fs->vol_type == EXFAT) {
- epold = get_entry_in_dir(sb, p_dir, oldentry + 1,
- §or_old);
- buf_lock(sb, sector_old);
- epnew = get_entry_in_dir(sb, p_dir, newentry + 1,
- §or_new);
-
- if (!epold || !epnew) {
- buf_unlock(sb, sector_old);
- return FFS_MEDIAERR;
- }
+ exfat_buf_modify(sb, sector_new);
+ exfat_buf_unlock(sb, sector_old);
+
+ epold = get_entry_in_dir(sb, p_dir, oldentry + 1,
+ §or_old);
+ exfat_buf_lock(sb, sector_old);
+ epnew = get_entry_in_dir(sb, p_dir, newentry + 1,
+ §or_new);
- memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
- buf_modify(sb, sector_new);
- buf_unlock(sb, sector_old);
+ if (!epold || !epnew) {
+ exfat_buf_unlock(sb, sector_old);
+ return -ENOENT;
}
- ret = fs_func->init_ext_entry(sb, p_dir, newentry,
- num_new_entries, p_uniname,
- &dos_name);
- if (ret != FFS_SUCCESS)
+ memcpy((void *)epnew, (void *)epold, DENTRY_SIZE);
+ exfat_buf_modify(sb, sector_new);
+ exfat_buf_unlock(sb, sector_old);
+
+ ret = exfat_init_ext_entry(sb, p_dir, newentry,
+ num_new_entries, p_uniname,
+ &dos_name);
+ if (ret != 0)
return ret;
- fs_func->delete_dir_entry(sb, p_dir, oldentry, 0,
- num_old_entries);
+ exfat_delete_dir_entry(sb, p_dir, oldentry, 0,
+ num_old_entries);
fid->entry = newentry;
} else {
- if (fs_func->get_entry_type(epold) == TYPE_FILE) {
- fs_func->set_entry_attr(epold,
- fs_func->get_entry_attr(epold) |
- ATTR_ARCHIVE);
+ if (exfat_get_entry_type(epold) == TYPE_FILE) {
+ exfat_set_entry_attr(epold,
+ exfat_get_entry_attr(epold) |
+ ATTR_ARCHIVE);
fid->attr |= ATTR_ARCHIVE;
}
- buf_modify(sb, sector_old);
- buf_unlock(sb, sector_old);
+ exfat_buf_modify(sb, sector_old);
+ exfat_buf_unlock(sb, sector_old);
- ret = fs_func->init_ext_entry(sb, p_dir, oldentry,
- num_new_entries, p_uniname,
- &dos_name);
- if (ret != FFS_SUCCESS)
+ ret = exfat_init_ext_entry(sb, p_dir, oldentry,
+ num_new_entries, p_uniname,
+ &dos_name);
+ if (ret != 0)
return ret;
- fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries,
- num_old_entries);
+ exfat_delete_dir_entry(sb, p_dir, oldentry, num_new_entries,
+ num_old_entries);
}
- return FFS_SUCCESS;
+ return 0;
}
s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
@@ -3492,97 +2392,78 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
{
s32 ret, newentry, num_new_entries, num_old_entries;
sector_t sector_mov, sector_new;
- struct chain_t clu;
struct dos_name_t dos_name;
struct dentry_t *epmov, *epnew;
struct super_block *sb = inode->i_sb;
- struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct fs_func *fs_func = p_fs->fs_func;
epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov);
if (!epmov)
- return FFS_MEDIAERR;
+ return -ENOENT;
/* check if the source and target directory is the same */
- if (fs_func->get_entry_type(epmov) == TYPE_DIR &&
- fs_func->get_entry_clu0(epmov) == p_newdir->dir)
- return FFS_INVALIDPATH;
+ if (exfat_get_entry_type(epmov) == TYPE_DIR &&
+ exfat_get_entry_clu0(epmov) == p_newdir->dir)
+ return -EINVAL;
- buf_lock(sb, sector_mov);
+ exfat_buf_lock(sb, sector_mov);
- /* buf_lock() before call count_ext_entries() */
- num_old_entries = fs_func->count_ext_entries(sb, p_olddir, oldentry,
- epmov);
+ /* exfat_buf_lock() before call count_ext_entries() */
+ num_old_entries = exfat_count_ext_entries(sb, p_olddir, oldentry,
+ epmov);
if (num_old_entries < 0) {
- buf_unlock(sb, sector_mov);
- return FFS_MEDIAERR;
+ exfat_buf_unlock(sb, sector_mov);
+ return -ENOENT;
}
num_old_entries++;
ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname,
&num_new_entries, &dos_name);
if (ret) {
- buf_unlock(sb, sector_mov);
+ exfat_buf_unlock(sb, sector_mov);
return ret;
}
newentry = find_empty_entry(inode, p_newdir, num_new_entries);
if (newentry < 0) {
- buf_unlock(sb, sector_mov);
- return FFS_FULL;
+ exfat_buf_unlock(sb, sector_mov);
+ return -ENOSPC;
}
epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new);
if (!epnew) {
- buf_unlock(sb, sector_mov);
- return FFS_MEDIAERR;
+ exfat_buf_unlock(sb, sector_mov);
+ return -ENOENT;
}
memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
- if (fs_func->get_entry_type(epnew) == TYPE_FILE) {
- fs_func->set_entry_attr(epnew, fs_func->get_entry_attr(epnew) |
- ATTR_ARCHIVE);
+ if (exfat_get_entry_type(epnew) == TYPE_FILE) {
+ exfat_set_entry_attr(epnew, exfat_get_entry_attr(epnew) |
+ ATTR_ARCHIVE);
fid->attr |= ATTR_ARCHIVE;
}
- buf_modify(sb, sector_new);
- buf_unlock(sb, sector_mov);
-
- if (p_fs->vol_type == EXFAT) {
- epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1,
- §or_mov);
- buf_lock(sb, sector_mov);
- epnew = get_entry_in_dir(sb, p_newdir, newentry + 1,
- §or_new);
- if (!epmov || !epnew) {
- buf_unlock(sb, sector_mov);
- return FFS_MEDIAERR;
- }
+ exfat_buf_modify(sb, sector_new);
+ exfat_buf_unlock(sb, sector_mov);
- memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
- buf_modify(sb, sector_new);
- buf_unlock(sb, sector_mov);
- } else if (fs_func->get_entry_type(epnew) == TYPE_DIR) {
- /* change ".." pointer to new parent dir */
- clu.dir = fs_func->get_entry_clu0(epnew);
- clu.flags = 0x01;
-
- epnew = get_entry_in_dir(sb, &clu, 1, §or_new);
- if (!epnew)
- return FFS_MEDIAERR;
-
- if (p_newdir->dir == p_fs->root_dir)
- fs_func->set_entry_clu0(epnew, CLUSTER_32(0));
- else
- fs_func->set_entry_clu0(epnew, p_newdir->dir);
- buf_modify(sb, sector_new);
+ epmov = get_entry_in_dir(sb, p_olddir, oldentry + 1,
+ §or_mov);
+ exfat_buf_lock(sb, sector_mov);
+ epnew = get_entry_in_dir(sb, p_newdir, newentry + 1,
+ §or_new);
+ if (!epmov || !epnew) {
+ exfat_buf_unlock(sb, sector_mov);
+ return -ENOENT;
}
- ret = fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries,
- p_uniname, &dos_name);
- if (ret != FFS_SUCCESS)
+ memcpy((void *)epnew, (void *)epmov, DENTRY_SIZE);
+ exfat_buf_modify(sb, sector_new);
+ exfat_buf_unlock(sb, sector_mov);
+
+ ret = exfat_init_ext_entry(sb, p_newdir, newentry, num_new_entries,
+ p_uniname, &dos_name);
+ if (ret != 0)
return ret;
- fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries);
+ exfat_delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries);
fid->dir.dir = p_newdir->dir;
fid->dir.size = p_newdir->size;
@@ -3590,7 +2471,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
fid->entry = newentry;
- return FFS_SUCCESS;
+ return 0;
}
/*
@@ -3600,7 +2481,7 @@ s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
bool read)
{
- s32 ret = FFS_MEDIAERR;
+ s32 ret = -EIO;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
if ((sec >= (p_fs->PBR_sector + p_fs->num_sectors)) &&
@@ -3612,8 +2493,8 @@ int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
}
if (!p_fs->dev_ejected) {
- ret = bdev_read(sb, sec, bh, 1, read);
- if (ret != FFS_SUCCESS)
+ ret = exfat_bdev_read(sb, sec, bh, 1, read);
+ if (ret != 0)
p_fs->dev_ejected = 1;
}
@@ -3623,7 +2504,7 @@ int sector_read(struct super_block *sb, sector_t sec, struct buffer_head **bh,
int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
bool sync)
{
- s32 ret = FFS_MEDIAERR;
+ s32 ret = -EIO;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
if (sec >= (p_fs->PBR_sector + p_fs->num_sectors) &&
@@ -3641,8 +2522,8 @@ int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
}
if (!p_fs->dev_ejected) {
- ret = bdev_write(sb, sec, bh, 1, sync);
- if (ret != FFS_SUCCESS)
+ ret = exfat_bdev_write(sb, sec, bh, 1, sync);
+ if (ret != 0)
p_fs->dev_ejected = 1;
}
@@ -3652,7 +2533,7 @@ int sector_write(struct super_block *sb, sector_t sec, struct buffer_head *bh,
int multi_sector_read(struct super_block *sb, sector_t sec,
struct buffer_head **bh, s32 num_secs, bool read)
{
- s32 ret = FFS_MEDIAERR;
+ s32 ret = -EIO;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
if (((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors)) &&
@@ -3664,8 +2545,8 @@ int multi_sector_read(struct super_block *sb, sector_t sec,
}
if (!p_fs->dev_ejected) {
- ret = bdev_read(sb, sec, bh, num_secs, read);
- if (ret != FFS_SUCCESS)
+ ret = exfat_bdev_read(sb, sec, bh, num_secs, read);
+ if (ret != 0)
p_fs->dev_ejected = 1;
}
@@ -3675,7 +2556,7 @@ int multi_sector_read(struct super_block *sb, sector_t sec,
int multi_sector_write(struct super_block *sb, sector_t sec,
struct buffer_head *bh, s32 num_secs, bool sync)
{
- s32 ret = FFS_MEDIAERR;
+ s32 ret = -EIO;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
if ((sec + num_secs) > (p_fs->PBR_sector + p_fs->num_sectors) &&
@@ -3692,8 +2573,8 @@ int multi_sector_write(struct super_block *sb, sector_t sec,
}
if (!p_fs->dev_ejected) {
- ret = bdev_write(sb, sec, bh, num_secs, sync);
- if (ret != FFS_SUCCESS)
+ ret = exfat_bdev_write(sb, sec, bh, num_secs, sync);
+ if (ret != 0)
p_fs->dev_ejected = 1;
}
diff --git a/drivers/staging/exfat/exfat_nls.c b/drivers/staging/exfat/exfat_nls.c
index a5c4b68925fba..91e8b0c4dce78 100644
--- a/drivers/staging/exfat/exfat_nls.c
+++ b/drivers/staging/exfat/exfat_nls.c
@@ -7,13 +7,6 @@
#include
#include "exfat.h"
-static u16 bad_dos_chars[] = {
- /* + , ; = [ ] */
- 0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D,
- 0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D,
- 0
-};
-
static u16 bad_uni_chars[] = {
/* " * / : < > ? \ | */
0x0022, 0x002A, 0x002F, 0x003A,
@@ -96,11 +89,6 @@ static u16 *nls_wstrchr(u16 *str, u16 wchar)
return NULL;
}
-int nls_dosname_cmp(struct super_block *sb, u8 *a, u8 *b)
-{
- return strncmp(a, b, DOS_NAME_LENGTH);
-}
-
int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b)
{
int i;
@@ -114,186 +102,6 @@ int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b)
return 0;
}
-void nls_uniname_to_dosname(struct super_block *sb,
- struct dos_name_t *p_dosname,
- struct uni_name_t *p_uniname, bool *p_lossy)
-{
- int i, j, len;
- bool lossy = false;
- u8 buf[MAX_CHARSET_SIZE];
- u8 lower = 0, upper = 0;
- u8 *dosname = p_dosname->name;
- u16 *uniname = p_uniname->name;
- u16 *p, *last_period;
- struct nls_table *nls = EXFAT_SB(sb)->nls_disk;
-
- for (i = 0; i < DOS_NAME_LENGTH; i++)
- *(dosname + i) = ' ';
-
- if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_CUR_DIR_NAME)) {
- *(dosname) = '.';
- p_dosname->name_case = 0x0;
- if (p_lossy)
- *p_lossy = false;
- return;
- }
-
- if (!nls_uniname_cmp(sb, uniname, (u16 *)UNI_PAR_DIR_NAME)) {
- *(dosname) = '.';
- *(dosname + 1) = '.';
- p_dosname->name_case = 0x0;
- if (p_lossy)
- *p_lossy = false;
- return;
- }
-
- /* search for the last embedded period */
- last_period = NULL;
- for (p = uniname; *p; p++) {
- if (*p == (u16)'.')
- last_period = p;
- }
-
- i = 0;
- while (i < DOS_NAME_LENGTH) {
- if (i == 8) {
- if (!last_period)
- break;
-
- if (uniname <= last_period) {
- if (uniname < last_period)
- lossy = true;
- uniname = last_period + 1;
- }
- }
-
- if (*uniname == (u16)'\0') {
- break;
- } else if (*uniname == (u16)' ') {
- lossy = true;
- } else if (*uniname == (u16)'.') {
- if (uniname < last_period)
- lossy = true;
- else
- i = 8;
- } else if (nls_wstrchr(bad_dos_chars, *uniname)) {
- lossy = true;
- *(dosname + i) = '_';
- i++;
- } else {
- len = convert_uni_to_ch(nls, buf, *uniname, &lossy);
-
- if (len > 1) {
- if ((i >= 8) && ((i + len) > DOS_NAME_LENGTH))
- break;
-
- if ((i < 8) && ((i + len) > 8)) {
- i = 8;
- continue;
- }
-
- lower = 0xFF;
-
- for (j = 0; j < len; j++, i++)
- *(dosname + i) = *(buf + j);
- } else { /* len == 1 */
- if ((*buf >= 'a') && (*buf <= 'z')) {
- *(dosname + i) = *buf - ('a' - 'A');
-
- if (i < 8)
- lower |= 0x08;
- else
- lower |= 0x10;
- } else if ((*buf >= 'A') && (*buf <= 'Z')) {
- *(dosname + i) = *buf;
-
- if (i < 8)
- upper |= 0x08;
- else
- upper |= 0x10;
- } else {
- *(dosname + i) = *buf;
- }
- i++;
- }
- }
-
- uniname++;
- }
-
- if (*dosname == 0xE5)
- *dosname = 0x05;
-
- if (*uniname != 0x0)
- lossy = true;
-
- if (upper & lower)
- p_dosname->name_case = 0xFF;
- else
- p_dosname->name_case = lower;
-
- if (p_lossy)
- *p_lossy = lossy;
-}
-
-void nls_dosname_to_uniname(struct super_block *sb,
- struct uni_name_t *p_uniname,
- struct dos_name_t *p_dosname)
-{
- int i = 0, j, n = 0;
- u8 buf[DOS_NAME_LENGTH + 2];
- u8 *dosname = p_dosname->name;
- u16 *uniname = p_uniname->name;
- struct nls_table *nls = EXFAT_SB(sb)->nls_disk;
-
- if (*dosname == 0x05) {
- *buf = 0xE5;
- i++;
- n++;
- }
-
- for (; i < 8; i++, n++) {
- if (*(dosname + i) == ' ')
- break;
-
- if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') &&
- (p_dosname->name_case & 0x08))
- *(buf + n) = *(dosname + i) + ('a' - 'A');
- else
- *(buf + n) = *(dosname + i);
- }
- if (*(dosname + 8) != ' ') {
- *(buf + n) = '.';
- n++;
- }
-
- for (i = 8; i < DOS_NAME_LENGTH; i++, n++) {
- if (*(dosname + i) == ' ')
- break;
-
- if ((*(dosname + i) >= 'A') && (*(dosname + i) <= 'Z') &&
- (p_dosname->name_case & 0x10))
- *(buf + n) = *(dosname + i) + ('a' - 'A');
- else
- *(buf + n) = *(dosname + i);
- }
- *(buf + n) = '\0';
-
- i = 0;
- j = 0;
- while (j < (MAX_NAME_LENGTH - 1)) {
- if (*(buf + i) == '\0')
- break;
-
- i += convert_ch_to_uni(nls, uniname, (buf + i), NULL);
-
- uniname++;
- j++;
- }
-
- *uniname = (u16)'\0';
-}
-
void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring,
struct uni_name_t *p_uniname)
{
diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c
index 58c7d66060f7e..b81d2a87b82ed 100644
--- a/drivers/staging/exfat/exfat_super.c
+++ b/drivers/staging/exfat/exfat_super.c
@@ -26,7 +26,7 @@
#include
#include
#include
-
+#include
#include
#include
#include
@@ -38,8 +38,8 @@
static struct kmem_cache *exfat_inode_cachep;
-static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE;
-static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET;
+static int exfat_default_codepage = CONFIG_STAGING_EXFAT_DEFAULT_CODEPAGE;
+static char exfat_default_iocharset[] = CONFIG_STAGING_EXFAT_DEFAULT_IOCHARSET;
#define INC_IVERSION(x) (inode_inc_iversion(x))
#define GET_IVERSION(x) (inode_peek_iversion_raw(x))
@@ -284,12 +284,12 @@ static const struct dentry_operations exfat_dentry_ops = {
.d_compare = exfat_cmp,
};
-static DEFINE_SEMAPHORE(z_sem);
+static DEFINE_MUTEX(z_mutex);
static inline void fs_sync(struct super_block *sb, bool do_sync)
{
if (do_sync)
- bdev_sync(sb);
+ exfat_bdev_sync(sb);
}
/*
@@ -353,26 +353,28 @@ static int ffsMountVol(struct super_block *sb)
pr_info("[EXFAT] trying to mount...\n");
- down(&z_sem);
+ mutex_lock(&z_mutex);
- buf_init(sb);
+ exfat_buf_init(sb);
- sema_init(&p_fs->v_sem, 1);
+ mutex_init(&p_fs->v_mutex);
p_fs->dev_ejected = 0;
/* open the block device */
- bdev_open(sb);
+ exfat_bdev_open(sb);
if (p_bd->sector_size < sb->s_blocksize) {
- ret = FFS_MEDIAERR;
+ printk(KERN_INFO "EXFAT: mount failed - sector size %d less than blocksize %ld\n",
+ p_bd->sector_size, sb->s_blocksize);
+ ret = -EINVAL;
goto out;
}
if (p_bd->sector_size > sb->s_blocksize)
sb_set_blocksize(sb, p_bd->sector_size);
/* read Sector 0 */
- if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) {
- ret = FFS_MEDIAERR;
+ if (sector_read(sb, 0, &tmp_bh, 1) != 0) {
+ ret = -EIO;
goto out;
}
@@ -383,8 +385,8 @@ static int ffsMountVol(struct super_block *sb)
/* check the validity of PBR */
if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) {
brelse(tmp_bh);
- bdev_close(sb);
- ret = FFS_FORMATERR;
+ exfat_bdev_close(sb);
+ ret = -EFSCORRUPTED;
goto out;
}
@@ -394,16 +396,10 @@ static int ffsMountVol(struct super_block *sb)
break;
if (i < 53) {
-#ifdef CONFIG_EXFAT_DONT_MOUNT_VFAT
+ /* Not sure how we'd get here, but complain if it does */
ret = -EINVAL;
- printk(KERN_INFO "EXFAT: Attempted to mount VFAT filesystem\n");
+ pr_info("EXFAT: Attempted to mount VFAT filesystem\n");
goto out;
-#else
- if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */
- ret = fat16_mount(sb, p_pbr);
- else
- ret = fat32_mount(sb, p_pbr);
-#endif
} else {
ret = exfat_mount(sb, p_pbr);
}
@@ -411,38 +407,34 @@ static int ffsMountVol(struct super_block *sb)
brelse(tmp_bh);
if (ret) {
- bdev_close(sb);
+ exfat_bdev_close(sb);
goto out;
}
- if (p_fs->vol_type == EXFAT) {
- ret = load_alloc_bitmap(sb);
- if (ret) {
- bdev_close(sb);
- goto out;
- }
- ret = load_upcase_table(sb);
- if (ret) {
- free_alloc_bitmap(sb);
- bdev_close(sb);
- goto out;
- }
+ ret = load_alloc_bitmap(sb);
+ if (ret) {
+ exfat_bdev_close(sb);
+ goto out;
+ }
+ ret = load_upcase_table(sb);
+ if (ret) {
+ free_alloc_bitmap(sb);
+ exfat_bdev_close(sb);
+ goto out;
}
if (p_fs->dev_ejected) {
- if (p_fs->vol_type == EXFAT) {
- free_upcase_table(sb);
- free_alloc_bitmap(sb);
- }
- bdev_close(sb);
- ret = FFS_MEDIAERR;
+ free_upcase_table(sb);
+ free_alloc_bitmap(sb);
+ exfat_bdev_close(sb);
+ ret = -EIO;
goto out;
}
pr_info("[EXFAT] mounted successfully\n");
out:
- up(&z_sem);
+ mutex_unlock(&z_mutex);
return ret;
}
@@ -450,39 +442,37 @@ static int ffsMountVol(struct super_block *sb)
static int ffsUmountVol(struct super_block *sb)
{
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- int err = FFS_SUCCESS;
+ int err = 0;
pr_info("[EXFAT] trying to unmount...\n");
- down(&z_sem);
+ mutex_lock(&z_mutex);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
- fs_sync(sb, false);
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
- if (p_fs->vol_type == EXFAT) {
- free_upcase_table(sb);
- free_alloc_bitmap(sb);
- }
+ free_upcase_table(sb);
+ free_alloc_bitmap(sb);
- FAT_release_all(sb);
- buf_release_all(sb);
+ exfat_fat_release_all(sb);
+ exfat_buf_release_all(sb);
/* close the block device */
- bdev_close(sb);
+ exfat_bdev_close(sb);
if (p_fs->dev_ejected) {
pr_info("[EXFAT] unmounted with media errors. Device is already ejected.\n");
- err = FFS_MEDIAERR;
+ err = -EIO;
}
- buf_shutdown(sb);
+ exfat_buf_shutdown(sb);
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
- up(&z_sem);
+ mutex_unlock(&p_fs->v_mutex);
+ mutex_unlock(&z_mutex);
pr_info("[EXFAT] unmounted successfully\n");
@@ -491,18 +481,18 @@ static int ffsUmountVol(struct super_block *sb)
static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
{
- int err = FFS_SUCCESS;
+ int err = 0;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
/* check the validity of pointer parameters */
if (!info)
- return FFS_ERROR;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
if (p_fs->used_clusters == UINT_MAX)
- p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb);
+ p_fs->used_clusters = exfat_count_used_clusters(sb);
info->FatType = p_fs->vol_type;
info->ClusterSize = p_fs->cluster_size;
@@ -511,31 +501,31 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info)
info->FreeClusters = info->NumClusters - info->UsedClusters;
if (p_fs->dev_ejected)
- err = FFS_MEDIAERR;
+ err = -EIO;
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return err;
}
static int ffsSyncVol(struct super_block *sb, bool do_sync)
{
- int err = FFS_SUCCESS;
+ int err = 0;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* synchronize the file system */
fs_sync(sb, do_sync);
fs_set_vol_flags(sb, VOL_CLEAN);
if (p_fs->dev_ejected)
- err = FFS_MEDIAERR;
+ err = -EIO;
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return err;
}
@@ -559,10 +549,10 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
/* check the validity of pointer parameters */
if (!fid || !path || (*path == '\0'))
- return FFS_ERROR;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check the validity of directory name in the given pathname */
ret = resolve_path(inode, path, &dir, &uni_name);
@@ -575,10 +565,10 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
goto out;
/* search the file name for directories */
- dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries,
- &dos_name, TYPE_ALL);
+ dentry = exfat_find_dir_entry(sb, &dir, &uni_name, num_entries,
+ &dos_name, TYPE_ALL);
if (dentry < -1) {
- ret = FFS_NOTFOUND;
+ ret = -ENOENT;
goto out;
}
@@ -597,46 +587,36 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid)
fid->size = 0;
fid->start_clu = p_fs->root_dir;
} else {
- if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &dir, dentry,
- ES_2_ENTRIES, &ep);
- if (!es) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- ep2 = ep + 1;
- } else {
- ep = get_entry_in_dir(sb, &dir, dentry, NULL);
- if (!ep) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- ep2 = ep;
+ es = get_entry_set_in_dir(sb, &dir, dentry,
+ ES_2_ENTRIES, &ep);
+ if (!es) {
+ ret = -ENOENT;
+ goto out;
}
+ ep2 = ep + 1;
- fid->type = p_fs->fs_func->get_entry_type(ep);
+ fid->type = exfat_get_entry_type(ep);
fid->rwoffset = 0;
fid->hint_last_off = -1;
- fid->attr = p_fs->fs_func->get_entry_attr(ep);
+ fid->attr = exfat_get_entry_attr(ep);
- fid->size = p_fs->fs_func->get_entry_size(ep2);
+ fid->size = exfat_get_entry_size(ep2);
if ((fid->type == TYPE_FILE) && (fid->size == 0)) {
fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
fid->start_clu = CLUSTER_32(~0);
} else {
- fid->flags = p_fs->fs_func->get_entry_flag(ep2);
- fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2);
+ fid->flags = exfat_get_entry_flag(ep2);
+ fid->start_clu = exfat_get_entry_clu0(ep2);
}
- if (p_fs->vol_type == EXFAT)
- release_entry_set(es);
+ release_entry_set(es);
}
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -648,14 +628,14 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
struct uni_name_t uni_name;
struct super_block *sb = inode->i_sb;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- int ret;
+ int ret = 0;
/* check the validity of pointer parameters */
if (!fid || !path || (*path == '\0'))
- return FFS_ERROR;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check the validity of directory name in the given pathname */
ret = resolve_path(inode, path, &dir, &uni_name);
@@ -667,17 +647,17 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
/* create a new file */
ret = create_file(inode, &dir, &uni_name, mode, fid);
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -697,18 +677,18 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
/* check the validity of the given file id */
if (!fid)
- return FFS_INVALIDFID;
+ return -EINVAL;
/* check the validity of pointer parameters */
if (!buffer)
- return FFS_ERROR;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check if the given file ID is opened */
if (fid->type != TYPE_FILE) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out;
}
@@ -721,7 +701,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
if (count == 0) {
if (rcount)
*rcount = 0;
- ret = FFS_EOF;
+ ret = 0;
goto out;
}
@@ -742,9 +722,11 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
}
while (clu_offset > 0) {
- /* clu = FAT_read(sb, clu); */
- if (FAT_read(sb, clu, &clu) == -1)
- return FFS_MEDIAERR;
+ /* clu = exfat_fat_read(sb, clu); */
+ if (exfat_fat_read(sb, clu, &clu) == -1) {
+ ret = -EIO;
+ goto out;
+ }
clu_offset--;
}
@@ -772,13 +754,13 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
if ((offset == 0) && (oneblkread == p_bd->sector_size)) {
if (sector_read(sb, LogSector, &tmp_bh, 1) !=
- FFS_SUCCESS)
+ 0)
goto err_out;
memcpy((char *)buffer + read_bytes,
(char *)tmp_bh->b_data, (s32)oneblkread);
} else {
if (sector_read(sb, LogSector, &tmp_bh, 1) !=
- FFS_SUCCESS)
+ 0)
goto err_out;
memcpy((char *)buffer + read_bytes,
(char *)tmp_bh->b_data + offset,
@@ -797,11 +779,11 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
*rcount = read_bytes;
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -814,7 +796,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
s32 num_clusters, num_alloc, num_alloced = (s32)~0;
int ret = 0;
u32 clu, last_clu;
- sector_t LogSector, sector = 0;
+ sector_t LogSector;
u64 oneblkwrite, write_bytes;
struct chain_t new_clu;
struct timestamp_t tm;
@@ -827,18 +809,18 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
/* check the validity of the given file id */
if (!fid)
- return FFS_INVALIDFID;
+ return -EINVAL;
/* check the validity of pointer parameters */
if (!buffer)
- return FFS_ERROR;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check if the given file ID is opened */
if (fid->type != TYPE_FILE) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out;
}
@@ -848,7 +830,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
if (count == 0) {
if (wcount)
*wcount = 0;
- ret = FFS_SUCCESS;
+ ret = 0;
goto out;
}
@@ -864,7 +846,8 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
while (count > 0) {
clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits);
- clu = last_clu = fid->start_clu;
+ clu = fid->start_clu;
+ last_clu = fid->start_clu;
if (fid->flags == 0x03) {
if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
@@ -885,9 +868,9 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
last_clu = clu;
- /* clu = FAT_read(sb, clu); */
- if (FAT_read(sb, clu, &clu) == -1) {
- ret = FFS_MEDIAERR;
+ /* clu = exfat_fat_read(sb, clu); */
+ if (exfat_fat_read(sb, clu, &clu) == -1) {
+ ret = -EIO;
goto out;
}
clu_offset--;
@@ -903,13 +886,13 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
new_clu.flags = fid->flags;
/* (1) allocate a chain of clusters */
- num_alloced = p_fs->fs_func->alloc_cluster(sb,
- num_alloc,
- &new_clu);
+ num_alloced = exfat_alloc_cluster(sb,
+ num_alloc,
+ &new_clu);
if (num_alloced == 0)
break;
if (num_alloced < 0) {
- ret = FFS_MEDIAERR;
+ ret = num_alloced;
goto out;
}
@@ -928,7 +911,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
modified = true;
}
if (new_clu.flags == 0x01)
- FAT_write(sb, last_clu, new_clu.dir);
+ exfat_fat_write(sb, last_clu, new_clu.dir);
}
num_clusters += num_alloced;
@@ -957,12 +940,12 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) {
if (sector_read(sb, LogSector, &tmp_bh, 0) !=
- FFS_SUCCESS)
+ 0)
goto err_out;
memcpy((char *)tmp_bh->b_data,
(char *)buffer + write_bytes, (s32)oneblkwrite);
if (sector_write(sb, LogSector, tmp_bh, 0) !=
- FFS_SUCCESS) {
+ 0) {
brelse(tmp_bh);
goto err_out;
}
@@ -970,18 +953,18 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
if ((offset > 0) ||
((fid->rwoffset + oneblkwrite) < fid->size)) {
if (sector_read(sb, LogSector, &tmp_bh, 1) !=
- FFS_SUCCESS)
+ 0)
goto err_out;
} else {
if (sector_read(sb, LogSector, &tmp_bh, 0) !=
- FFS_SUCCESS)
+ 0)
goto err_out;
}
memcpy((char *)tmp_bh->b_data + offset,
(char *)buffer + write_bytes, (s32)oneblkwrite);
if (sector_write(sb, LogSector, tmp_bh, 0) !=
- FFS_SUCCESS) {
+ 0) {
brelse(tmp_bh);
goto err_out;
}
@@ -1002,46 +985,31 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
brelse(tmp_bh);
/* (3) update the direcoty entry */
- if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
- ES_ALL_ENTRIES, &ep);
- if (!es)
- goto err_out;
- ep2 = ep + 1;
- } else {
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
- if (!ep)
- goto err_out;
- ep2 = ep;
- }
-
- p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
- p_fs->fs_func->set_entry_attr(ep, fid->attr);
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ ES_ALL_ENTRIES, &ep);
+ if (!es)
+ goto err_out;
+ ep2 = ep + 1;
- if (p_fs->vol_type != EXFAT)
- buf_modify(sb, sector);
+ exfat_set_entry_time(ep, tm_current(&tm), TM_MODIFY);
+ exfat_set_entry_attr(ep, fid->attr);
if (modified) {
- if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags)
- p_fs->fs_func->set_entry_flag(ep2, fid->flags);
-
- if (p_fs->fs_func->get_entry_size(ep2) != fid->size)
- p_fs->fs_func->set_entry_size(ep2, fid->size);
+ if (exfat_get_entry_flag(ep2) != fid->flags)
+ exfat_set_entry_flag(ep2, fid->flags);
- if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu)
- p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu);
+ if (exfat_get_entry_size(ep2) != fid->size)
+ exfat_set_entry_size(ep2, fid->size);
- if (p_fs->vol_type != EXFAT)
- buf_modify(sb, sector);
+ if (exfat_get_entry_clu0(ep2) != fid->start_clu)
+ exfat_set_entry_clu0(ep2, fid->start_clu);
}
- if (p_fs->vol_type == EXFAT) {
- update_dir_checksum_with_entry_set(sb, es);
- release_entry_set(es);
- }
+ update_dir_checksum_with_entry_set(sb, es);
+ release_entry_set(es);
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
@@ -1051,14 +1019,14 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
*wcount = write_bytes;
if (num_alloced == 0)
- ret = FFS_FULL;
+ ret = -ENOSPC;
else if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1068,7 +1036,6 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
s32 num_clusters;
u32 last_clu = CLUSTER_32(0);
int ret = 0;
- sector_t sector = 0;
struct chain_t clu;
struct timestamp_t tm;
struct dentry_t *ep, *ep2;
@@ -1081,11 +1048,11 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
new_size);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check if the given file ID is opened */
if (fid->type != TYPE_FILE) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out;
}
@@ -1095,7 +1062,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
}
if (old_size <= new_size) {
- ret = FFS_SUCCESS;
+ ret = 0;
goto out;
}
@@ -1114,8 +1081,8 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
} else {
while (num_clusters > 0) {
last_clu = clu.dir;
- if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
- ret = FFS_MEDIAERR;
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) {
+ ret = -EIO;
goto out;
}
num_clusters--;
@@ -1133,65 +1100,52 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
}
/* (1) update the directory entry */
- if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
- ES_ALL_ENTRIES, &ep);
- if (!es) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- ep2 = ep + 1;
- } else {
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
- if (!ep) {
- ret = FFS_MEDIAERR;
- goto out;
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ ES_ALL_ENTRIES, &ep);
+ if (!es) {
+ ret = -ENOENT;
+ goto out;
}
- ep2 = ep;
- }
+ ep2 = ep + 1;
- p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
- p_fs->fs_func->set_entry_attr(ep, fid->attr);
+ exfat_set_entry_time(ep, tm_current(&tm), TM_MODIFY);
+ exfat_set_entry_attr(ep, fid->attr);
- p_fs->fs_func->set_entry_size(ep2, new_size);
+ exfat_set_entry_size(ep2, new_size);
if (new_size == 0) {
- p_fs->fs_func->set_entry_flag(ep2, 0x01);
- p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0));
+ exfat_set_entry_flag(ep2, 0x01);
+ exfat_set_entry_clu0(ep2, CLUSTER_32(0));
}
- if (p_fs->vol_type != EXFAT) {
- buf_modify(sb, sector);
- } else {
- update_dir_checksum_with_entry_set(sb, es);
- release_entry_set(es);
- }
+ update_dir_checksum_with_entry_set(sb, es);
+ release_entry_set(es);
/* (2) cut off from the FAT chain */
if (last_clu != CLUSTER_32(0)) {
if (fid->flags == 0x01)
- FAT_write(sb, last_clu, CLUSTER_32(~0));
+ exfat_fat_write(sb, last_clu, CLUSTER_32(~0));
}
/* (3) free the clusters */
- p_fs->fs_func->free_cluster(sb, &clu, 0);
+ exfat_free_cluster(sb, &clu, 0);
/* hint information */
fid->hint_last_off = -1;
if (fid->rwoffset > fid->size)
fid->rwoffset = fid->size;
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
pr_debug("%s exited (%d)\n", __func__, ret);
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1232,14 +1186,14 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
/* check the validity of the given file id */
if (!fid)
- return FFS_INVALIDFID;
+ return -EINVAL;
/* check the validity of pointer parameters */
if (!new_path || (*new_path == '\0'))
- return FFS_ERROR;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
update_parent_info(fid, old_parent_inode);
@@ -1252,19 +1206,19 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
/* check if the old file is "." or ".." */
if (p_fs->vol_type != EXFAT) {
if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) {
- ret = FFS_PERMISSIONERR;
+ ret = -EPERM;
goto out2;
}
}
ep = get_entry_in_dir(sb, &olddir, dentry, NULL);
if (!ep) {
- ret = FFS_MEDIAERR;
+ ret = -ENOENT;
goto out2;
}
- if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) {
- ret = FFS_PERMISSIONERR;
+ if (exfat_get_entry_attr(ep) & ATTR_READONLY) {
+ ret = -EPERM;
goto out2;
}
@@ -1272,18 +1226,18 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
if (new_inode) {
u32 entry_type;
- ret = FFS_MEDIAERR;
+ ret = -ENOENT;
new_fid = &EXFAT_I(new_inode)->fid;
update_parent_info(new_fid, new_parent_inode);
- p_dir = &(new_fid->dir);
+ p_dir = &new_fid->dir;
new_entry = new_fid->entry;
ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
if (!ep)
goto out;
- entry_type = p_fs->fs_func->get_entry_type(ep);
+ entry_type = exfat_get_entry_type(ep);
if (entry_type == TYPE_DIR) {
struct chain_t new_clu;
@@ -1294,7 +1248,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
new_clu.flags = new_fid->flags;
if (!is_dir_empty(sb, &new_clu)) {
- ret = FFS_FILEEXIST;
+ ret = -EEXIST;
goto out;
}
}
@@ -1314,30 +1268,30 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
ret = move_file(new_parent_inode, &olddir, dentry, &newdir,
&uni_name, fid);
- if ((ret == FFS_SUCCESS) && new_inode) {
+ if ((ret == 0) && new_inode) {
/* delete entries of new_dir */
ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
if (!ep)
goto out;
- num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir,
- new_entry, ep);
+ num_entries = exfat_count_ext_entries(sb, p_dir,
+ new_entry, ep);
if (num_entries < 0)
goto out;
- p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0,
- num_entries + 1);
+ exfat_delete_dir_entry(sb, p_dir, new_entry, 0,
+ num_entries + 1);
}
out:
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out2:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1345,7 +1299,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
{
s32 dentry;
- int ret = FFS_SUCCESS;
+ int ret = 0;
struct chain_t dir, clu_to_free;
struct dentry_t *ep;
struct super_block *sb = inode->i_sb;
@@ -1353,10 +1307,10 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
/* check the validity of the given file id */
if (!fid)
- return FFS_INVALIDFID;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
dir.dir = fid->dir.dir;
dir.size = fid->dir.size;
@@ -1366,12 +1320,12 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
ep = get_entry_in_dir(sb, &dir, dentry, NULL);
if (!ep) {
- ret = FFS_MEDIAERR;
+ ret = -ENOENT;
goto out;
}
- if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) {
- ret = FFS_PERMISSIONERR;
+ if (exfat_get_entry_attr(ep) & ATTR_READONLY) {
+ ret = -EPERM;
goto out;
}
fs_set_vol_flags(sb, VOL_DIRTY);
@@ -1384,22 +1338,22 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
clu_to_free.flags = fid->flags;
/* (2) free the clusters */
- p_fs->fs_func->free_cluster(sb, &clu_to_free, 0);
+ exfat_free_cluster(sb, &clu_to_free, 0);
fid->size = 0;
fid->start_clu = CLUSTER_32(~0);
fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1409,7 +1363,7 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid)
static int ffsSetAttr(struct inode *inode, u32 attr)
{
u32 type;
- int ret = FFS_SUCCESS;
+ int ret = 0;
sector_t sector = 0;
struct dentry_t *ep;
struct super_block *sb = inode->i_sb;
@@ -1420,49 +1374,40 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
if (fid->attr == attr) {
if (p_fs->dev_ejected)
- return FFS_MEDIAERR;
- return FFS_SUCCESS;
+ return -EIO;
+ return 0;
}
if (is_dir) {
if ((fid->dir.dir == p_fs->root_dir) &&
(fid->entry == -1)) {
if (p_fs->dev_ejected)
- return FFS_MEDIAERR;
- return FFS_SUCCESS;
+ return -EIO;
+ return 0;
}
}
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* get the directory entry of given file */
- if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
- ES_ALL_ENTRIES, &ep);
- if (!es) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- } else {
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
- if (!ep) {
- ret = FFS_MEDIAERR;
- goto out;
- }
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ ES_ALL_ENTRIES, &ep);
+ if (!es) {
+ ret = -ENOENT;
+ goto out;
}
- type = p_fs->fs_func->get_entry_type(ep);
+ type = exfat_get_entry_type(ep);
if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) ||
((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) {
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
else
- ret = FFS_ERROR;
+ ret = -EINVAL;
- if (p_fs->vol_type == EXFAT)
- release_entry_set(es);
+ release_entry_set(es);
goto out;
}
@@ -1470,25 +1415,21 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
/* set the file attribute */
fid->attr = attr;
- p_fs->fs_func->set_entry_attr(ep, attr);
+ exfat_set_entry_attr(ep, attr);
- if (p_fs->vol_type != EXFAT) {
- buf_modify(sb, sector);
- } else {
- update_dir_checksum_with_entry_set(sb, es);
- release_entry_set(es);
- }
+ update_dir_checksum_with_entry_set(sb, es);
+ release_entry_set(es);
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1496,9 +1437,8 @@ static int ffsSetAttr(struct inode *inode, u32 attr)
static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
{
- sector_t sector = 0;
s32 count;
- int ret = FFS_SUCCESS;
+ int ret = 0;
struct chain_t dir;
struct uni_name_t uni_name;
struct timestamp_t tm;
@@ -1512,7 +1452,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
pr_debug("%s entered\n", __func__);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
if (is_dir) {
if ((fid->dir.dir == p_fs->root_dir) &&
@@ -1541,40 +1481,30 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
count = count_dos_name_entries(sb, &dir, TYPE_DIR);
if (count < 0) {
- ret = FFS_MEDIAERR;
+ ret = count; /* propagate error upward */
goto out;
}
info->NumSubdirs = count;
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
goto out;
}
}
/* get the directory entry of given file or directory */
- if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
- ES_2_ENTRIES, &ep);
- if (!es) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- ep2 = ep + 1;
- } else {
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
- if (!ep) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- ep2 = ep;
- buf_lock(sb, sector);
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ ES_2_ENTRIES, &ep);
+ if (!es) {
+ ret = -ENOENT;
+ goto out;
}
+ ep2 = ep + 1;
/* set FILE_INFO structure using the acquired struct dentry_t */
- info->Attr = p_fs->fs_func->get_entry_attr(ep);
+ info->Attr = exfat_get_entry_attr(ep);
- p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE);
+ exfat_get_entry_time(ep, &tm, TM_CREATE);
info->CreateTimestamp.Year = tm.year;
info->CreateTimestamp.Month = tm.mon;
info->CreateTimestamp.Day = tm.day;
@@ -1583,7 +1513,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
info->CreateTimestamp.Second = tm.sec;
info->CreateTimestamp.MilliSecond = 0;
- p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
+ exfat_get_entry_time(ep, &tm, TM_MODIFY);
info->ModifyTimestamp.Year = tm.year;
info->ModifyTimestamp.Month = tm.mon;
info->ModifyTimestamp.Day = tm.day;
@@ -1594,31 +1524,19 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
memset((char *)&info->AccessTimestamp, 0, sizeof(struct date_time_t));
- *(uni_name.name) = 0x0;
+ *uni_name.name = 0x0;
/* XXX this is very bad for exfat cuz name is already included in es.
* API should be revised
*/
- p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry,
- uni_name.name);
- if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT)
- get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep,
- &uni_name, 0x1);
+ exfat_get_uni_name_from_ext_entry(sb, &fid->dir, fid->entry,
+ uni_name.name);
nls_uniname_to_cstring(sb, info->Name, &uni_name);
- if (p_fs->vol_type == EXFAT) {
- info->NumSubdirs = 2;
- } else {
- buf_unlock(sb, sector);
- get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep,
- &uni_name, 0x0);
- nls_uniname_to_cstring(sb, info->ShortName, &uni_name);
- info->NumSubdirs = 0;
- }
+ info->NumSubdirs = 2;
- info->Size = p_fs->fs_func->get_entry_size(ep2);
+ info->Size = exfat_get_entry_size(ep2);
- if (p_fs->vol_type == EXFAT)
- release_entry_set(es);
+ release_entry_set(es);
if (is_dir) {
dir.dir = fid->start_clu;
@@ -1630,18 +1548,18 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
count = count_dos_name_entries(sb, &dir, TYPE_DIR);
if (count < 0) {
- ret = FFS_MEDIAERR;
+ ret = count; /* propagate error upward */
goto out;
}
info->NumSubdirs += count;
}
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
pr_debug("%s exited successfully\n", __func__);
return ret;
@@ -1649,8 +1567,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info)
static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
{
- sector_t sector = 0;
- int ret = FFS_SUCCESS;
+ int ret = 0;
struct timestamp_t tm;
struct dentry_t *ep, *ep2;
struct entry_set_cache_t *es = NULL;
@@ -1662,14 +1579,14 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
pr_debug("%s entered (inode %p info %p\n", __func__, inode, info);
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
if (is_dir) {
if ((fid->dir.dir == p_fs->root_dir) &&
(fid->entry == -1)) {
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
- ret = FFS_SUCCESS;
+ ret = -EIO;
+ ret = 0;
goto out;
}
}
@@ -1677,25 +1594,15 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
fs_set_vol_flags(sb, VOL_DIRTY);
/* get the directory entry of given file or directory */
- if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry,
- ES_ALL_ENTRIES, &ep);
- if (!es) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- ep2 = ep + 1;
- } else {
- /* for other than exfat */
- ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
- if (!ep) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- ep2 = ep;
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ ES_ALL_ENTRIES, &ep);
+ if (!es) {
+ ret = -ENOENT;
+ goto out;
}
+ ep2 = ep + 1;
- p_fs->fs_func->set_entry_attr(ep, info->Attr);
+ exfat_set_entry_attr(ep, info->Attr);
/* set FILE_INFO structure using the acquired struct dentry_t */
tm.sec = info->CreateTimestamp.Second;
@@ -1704,7 +1611,7 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
tm.day = info->CreateTimestamp.Day;
tm.mon = info->CreateTimestamp.Month;
tm.year = info->CreateTimestamp.Year;
- p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE);
+ exfat_set_entry_time(ep, &tm, TM_CREATE);
tm.sec = info->ModifyTimestamp.Second;
tm.min = info->ModifyTimestamp.Minute;
@@ -1712,23 +1619,19 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info)
tm.day = info->ModifyTimestamp.Day;
tm.mon = info->ModifyTimestamp.Month;
tm.year = info->ModifyTimestamp.Year;
- p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY);
+ exfat_set_entry_time(ep, &tm, TM_MODIFY);
- p_fs->fs_func->set_entry_size(ep2, info->Size);
+ exfat_set_entry_size(ep2, info->Size);
- if (p_fs->vol_type != EXFAT) {
- buf_modify(sb, sector);
- } else {
- update_dir_checksum_with_entry_set(sb, es);
- release_entry_set(es);
- }
+ update_dir_checksum_with_entry_set(sb, es);
+ release_entry_set(es);
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
pr_debug("%s exited (%d)\n", __func__, ret);
@@ -1740,8 +1643,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
s32 num_clusters, num_alloced;
bool modified = false;
u32 last_clu;
- int ret = FFS_SUCCESS;
- sector_t sector = 0;
+ int ret = 0;
struct chain_t new_clu;
struct dentry_t *ep;
struct entry_set_cache_t *es = NULL;
@@ -1751,10 +1653,10 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
/* check the validity of pointer parameters */
if (!clu)
- return FFS_ERROR;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
fid->rwoffset = (s64)(clu_offset) << p_fs->cluster_size_bits;
@@ -1785,8 +1687,8 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
last_clu = *clu;
- if (FAT_read(sb, *clu, clu) == -1) {
- ret = FFS_MEDIAERR;
+ if (exfat_fat_read(sb, *clu, clu) == -1) {
+ ret = -EIO;
goto out;
}
clu_offset--;
@@ -1802,12 +1704,12 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
new_clu.flags = fid->flags;
/* (1) allocate a cluster */
- num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu);
+ num_alloced = exfat_alloc_cluster(sb, 1, &new_clu);
if (num_alloced < 0) {
- ret = FFS_MEDIAERR;
+ ret = -EIO;
goto out;
} else if (num_alloced == 0) {
- ret = FFS_FULL;
+ ret = -ENOSPC;
goto out;
}
@@ -1825,49 +1727,32 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
modified = true;
}
if (new_clu.flags == 0x01)
- FAT_write(sb, last_clu, new_clu.dir);
+ exfat_fat_write(sb, last_clu, new_clu.dir);
}
num_clusters += num_alloced;
*clu = new_clu.dir;
- if (p_fs->vol_type == EXFAT) {
- es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
- ES_ALL_ENTRIES, &ep);
- if (!es) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- /* get stream entry */
- ep++;
+ es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
+ ES_ALL_ENTRIES, &ep);
+ if (!es) {
+ ret = -ENOENT;
+ goto out;
}
+ /* get stream entry */
+ ep++;
/* (3) update directory entry */
if (modified) {
- if (p_fs->vol_type != EXFAT) {
- ep = get_entry_in_dir(sb, &(fid->dir),
- fid->entry, §or);
- if (!ep) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- }
+ if (exfat_get_entry_flag(ep) != fid->flags)
+ exfat_set_entry_flag(ep, fid->flags);
- if (p_fs->fs_func->get_entry_flag(ep) != fid->flags)
- p_fs->fs_func->set_entry_flag(ep, fid->flags);
-
- if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu)
- p_fs->fs_func->set_entry_clu0(ep,
- fid->start_clu);
-
- if (p_fs->vol_type != EXFAT)
- buf_modify(sb, sector);
+ if (exfat_get_entry_clu0(ep) != fid->start_clu)
+ exfat_set_entry_clu0(ep, fid->start_clu);
}
- if (p_fs->vol_type == EXFAT) {
- update_dir_checksum_with_entry_set(sb, es);
- release_entry_set(es);
- }
+ update_dir_checksum_with_entry_set(sb, es);
+ release_entry_set(es);
/* add number of new blocks to inode */
inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9);
@@ -1878,11 +1763,11 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
fid->hint_last_clu = *clu;
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1893,7 +1778,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu)
static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
{
- int ret = FFS_SUCCESS;
+ int ret = 0;
struct chain_t dir;
struct uni_name_t uni_name;
struct super_block *sb = inode->i_sb;
@@ -1903,10 +1788,10 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
/* check the validity of pointer parameters */
if (!fid || !path || (*path == '\0'))
- return FFS_ERROR;
+ return -EINVAL;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
/* check the validity of directory name in the given old pathname */
ret = resolve_path(inode, path, &dir, &uni_name);
@@ -1917,16 +1802,16 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
ret = create_dir(inode, &dir, &uni_name, fid);
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -1934,7 +1819,7 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid)
static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
{
int i, dentry, clu_offset;
- int ret = FFS_SUCCESS;
+ int ret = 0;
s32 dentries_per_clu, dentries_per_clu_bits = 0;
u32 type;
sector_t sector;
@@ -1944,19 +1829,18 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
struct dentry_t *ep;
struct super_block *sb = inode->i_sb;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
- struct fs_func *fs_func = p_fs->fs_func;
struct file_id_t *fid = &(EXFAT_I(inode)->fid);
/* check the validity of pointer parameters */
if (!dir_entry)
- return FFS_ERROR;
+ return -EINVAL;
/* check if the given file ID is opened */
if (fid->type != TYPE_DIR)
- return FFS_PERMISSIONERR;
+ return -ENOTDIR;
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
if (fid->entry == -1) {
dir.dir = p_fs->root_dir;
@@ -2001,9 +1885,9 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
}
while (clu_offset > 0) {
- /* clu.dir = FAT_read(sb, clu.dir); */
- if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
- ret = FFS_MEDIAERR;
+ /* clu.dir = exfat_fat_read(sb, clu.dir); */
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) {
+ ret = -EIO;
goto out;
}
clu_offset--;
@@ -2023,10 +1907,10 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
for ( ; i < dentries_per_clu; i++, dentry++) {
ep = get_entry_in_dir(sb, &clu, i, §or);
if (!ep) {
- ret = FFS_MEDIAERR;
+ ret = -ENOENT;
goto out;
}
- type = fs_func->get_entry_type(ep);
+ type = exfat_get_entry_type(ep);
if (type == TYPE_UNUSED)
break;
@@ -2034,10 +1918,10 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
if ((type != TYPE_FILE) && (type != TYPE_DIR))
continue;
- buf_lock(sb, sector);
- dir_entry->Attr = fs_func->get_entry_attr(ep);
+ exfat_buf_lock(sb, sector);
+ dir_entry->Attr = exfat_get_entry_attr(ep);
- fs_func->get_entry_time(ep, &tm, TM_CREATE);
+ exfat_get_entry_time(ep, &tm, TM_CREATE);
dir_entry->CreateTimestamp.Year = tm.year;
dir_entry->CreateTimestamp.Month = tm.mon;
dir_entry->CreateTimestamp.Day = tm.day;
@@ -2046,7 +1930,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
dir_entry->CreateTimestamp.Second = tm.sec;
dir_entry->CreateTimestamp.MilliSecond = 0;
- fs_func->get_entry_time(ep, &tm, TM_MODIFY);
+ exfat_get_entry_time(ep, &tm, TM_MODIFY);
dir_entry->ModifyTimestamp.Year = tm.year;
dir_entry->ModifyTimestamp.Month = tm.mon;
dir_entry->ModifyTimestamp.Day = tm.day;
@@ -2058,31 +1942,19 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
memset((char *)&dir_entry->AccessTimestamp, 0,
sizeof(struct date_time_t));
- *(uni_name.name) = 0x0;
- fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry,
- uni_name.name);
- if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT)
- get_uni_name_from_dos_entry(sb,
- (struct dos_dentry_t *)ep,
- &uni_name, 0x1);
+ *uni_name.name = 0x0;
+ exfat_get_uni_name_from_ext_entry(sb, &dir, dentry,
+ uni_name.name);
nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name);
- buf_unlock(sb, sector);
+ exfat_buf_unlock(sb, sector);
- if (p_fs->vol_type == EXFAT) {
- ep = get_entry_in_dir(sb, &clu, i + 1, NULL);
- if (!ep) {
- ret = FFS_MEDIAERR;
- goto out;
- }
- } else {
- get_uni_name_from_dos_entry(sb,
- (struct dos_dentry_t *)ep,
- &uni_name, 0x0);
- nls_uniname_to_cstring(sb, dir_entry->ShortName,
- &uni_name);
+ ep = get_entry_in_dir(sb, &clu, i + 1, NULL);
+ if (!ep) {
+ ret = -ENOENT;
+ goto out;
}
- dir_entry->Size = fs_func->get_entry_size(ep);
+ dir_entry->Size = exfat_get_entry_size(ep);
/* hint information */
if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */
@@ -2095,7 +1967,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
fid->rwoffset = (s64)(++dentry);
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
goto out;
}
@@ -2108,24 +1980,24 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
else
clu.dir = CLUSTER_32(~0);
} else {
- /* clu.dir = FAT_read(sb, clu.dir); */
- if (FAT_read(sb, clu.dir, &clu.dir) == -1) {
- ret = FFS_MEDIAERR;
+ /* clu.dir = exfat_fat_read(sb, clu.dir); */
+ if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) {
+ ret = -EIO;
goto out;
}
}
}
- *(dir_entry->Name) = '\0';
+ *dir_entry->Name = '\0';
fid->rwoffset = (s64)(++dentry);
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -2133,14 +2005,14 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry)
static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
{
s32 dentry;
- int ret = FFS_SUCCESS;
+ int ret = 0;
struct chain_t dir, clu_to_free;
struct super_block *sb = inode->i_sb;
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
/* check the validity of the given file id */
if (!fid)
- return FFS_INVALIDFID;
+ return -EINVAL;
dir.dir = fid->dir.dir;
dir.size = fid->dir.size;
@@ -2151,18 +2023,18 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
/* check if the file is "." or ".." */
if (p_fs->vol_type != EXFAT) {
if ((dir.dir != p_fs->root_dir) && (dentry < 2))
- return FFS_PERMISSIONERR;
+ return -EPERM;
}
/* acquire the lock for file system critical section */
- down(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
clu_to_free.dir = fid->start_clu;
clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1;
clu_to_free.flags = fid->flags;
if (!is_dir_empty(sb, &clu_to_free)) {
- ret = FFS_FILEEXIST;
+ ret = -ENOTEMPTY;
goto out;
}
@@ -2172,23 +2044,23 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid)
remove_file(inode, &dir, dentry);
/* (2) free the clusters */
- p_fs->fs_func->free_cluster(sb, &clu_to_free, 1);
+ exfat_free_cluster(sb, &clu_to_free, 1);
fid->size = 0;
fid->start_clu = CLUSTER_32(~0);
fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
-#ifdef CONFIG_EXFAT_DELAYED_SYNC
- fs_sync(sb, false);
+#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
+ fs_sync(sb, true);
fs_set_vol_flags(sb, VOL_CLEAN);
#endif
if (p_fs->dev_ejected)
- ret = FFS_MEDIAERR;
+ ret = -EIO;
out:
/* release the lock for file system critical section */
- up(&p_fs->v_sem);
+ mutex_unlock(&p_fs->v_mutex);
return ret;
}
@@ -2202,7 +2074,7 @@ static int exfat_readdir(struct file *filp, struct dir_context *ctx)
struct inode *inode = file_inode(filp);
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
struct dir_entry_t de;
unsigned long inum;
@@ -2244,12 +2116,11 @@ static int exfat_readdir(struct file *filp, struct dir_context *ctx)
/* at least we tried to read a sector
* move cpos to next sector position (should be aligned)
*/
- if (err == FFS_MEDIAERR) {
+ if (err == -EIO) {
cpos += 1 << p_bd->sector_size_bits;
cpos &= ~((1 << p_bd->sector_size_bits) - 1);
}
- err = -EIO;
goto end_of_dir;
}
@@ -2293,7 +2164,7 @@ static int exfat_ioctl_volume_id(struct inode *dir)
{
struct super_block *sb = dir->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
return p_fs->vol_id;
}
@@ -2301,15 +2172,15 @@ static int exfat_ioctl_volume_id(struct inode *dir)
static long exfat_generic_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
-struct inode *inode = filp->f_path.dentry->d_inode;
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+ struct inode *inode = filp->f_path.dentry->d_inode;
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
unsigned int flags;
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
switch (cmd) {
case EXFAT_IOCTL_GET_VOLUME_ID:
return exfat_ioctl_volume_id(inode);
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
case EXFAT_IOC_GET_DEBUGFLAGS: {
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
@@ -2333,7 +2204,7 @@ struct inode *inode = filp->f_path.dentry->d_inode;
return 0;
}
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
default:
return -ENOTTY; /* Inappropriate ioctl for device */
}
@@ -2351,6 +2222,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
bool excl)
{
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
struct inode *inode;
struct file_id_t fid;
loff_t i_pos;
@@ -2361,21 +2233,14 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
pr_debug("%s entered\n", __func__);
err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_REGULAR, &fid);
- if (err) {
- if (err == FFS_INVALIDPATH)
- err = -EINVAL;
- else if (err == FFS_FILEEXIST)
- err = -EEXIST;
- else if (err == FFS_FULL)
- err = -ENOSPC;
- else if (err == FFS_NAMETOOLONG)
- err = -ENAMETOOLONG;
- else
- err = -EIO;
+ if (err)
goto out;
- }
+
INC_IVERSION(dir);
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_ctime = curtime;
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
@@ -2389,7 +2254,10 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
goto out;
}
INC_IVERSION(inode);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
+ inode->i_ctime = curtime;
/*
* timestamp is already written, so mark_inode_dirty() is unnecessary.
*/
@@ -2522,6 +2390,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
int err;
__lock_super(sb);
@@ -2531,22 +2400,22 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
EXFAT_I(inode)->fid.size = i_size_read(inode);
err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid));
- if (err) {
- if (err == FFS_PERMISSIONERR)
- err = -EPERM;
- else
- err = -EIO;
+ if (err)
goto out;
- }
+
INC_IVERSION(dir);
- dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
mark_inode_dirty(dir);
clear_nlink(inode);
- inode->i_mtime = inode->i_atime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
exfat_detach(inode);
remove_inode_hash(inode);
@@ -2560,6 +2429,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
const char *target)
{
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
struct inode *inode;
struct file_id_t fid;
loff_t i_pos;
@@ -2572,32 +2442,22 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
pr_debug("%s entered\n", __func__);
err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_SYMLINK, &fid);
- if (err) {
- if (err == FFS_INVALIDPATH)
- err = -EINVAL;
- else if (err == FFS_FILEEXIST)
- err = -EEXIST;
- else if (err == FFS_FULL)
- err = -ENOSPC;
- else
- err = -EIO;
+ if (err)
goto out;
- }
+
err = ffsWriteFile(dir, &fid, (char *)target, len, &ret);
if (err) {
ffsRemoveFile(dir, &fid);
-
- if (err == FFS_FULL)
- err = -ENOSPC;
- else
- err = -EIO;
goto out;
}
INC_IVERSION(dir);
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_ctime = curtime;
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
@@ -2611,7 +2471,10 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
goto out;
}
INC_IVERSION(inode);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
+ inode->i_ctime = curtime;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
EXFAT_I(inode)->target = kmemdup(target, len + 1, GFP_KERNEL);
@@ -2632,6 +2495,7 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry,
static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
struct inode *inode;
struct file_id_t fid;
loff_t i_pos;
@@ -2642,21 +2506,14 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
pr_debug("%s entered\n", __func__);
err = ffsCreateDir(dir, (u8 *)dentry->d_name.name, &fid);
- if (err) {
- if (err == FFS_INVALIDPATH)
- err = -EINVAL;
- else if (err == FFS_FILEEXIST)
- err = -EEXIST;
- else if (err == FFS_FULL)
- err = -ENOSPC;
- else if (err == FFS_NAMETOOLONG)
- err = -ENAMETOOLONG;
- else
- err = -EIO;
+ if (err)
goto out;
- }
+
INC_IVERSION(dir);
- dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_ctime = curtime;
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
@@ -2671,7 +2528,10 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
goto out;
}
INC_IVERSION(inode);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
+ inode->i_ctime = curtime;
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode);
@@ -2687,6 +2547,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct super_block *sb = dir->i_sb;
+ struct timespec64 curtime;
int err;
__lock_super(sb);
@@ -2696,21 +2557,13 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
EXFAT_I(inode)->fid.size = i_size_read(inode);
err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid));
- if (err) {
- if (err == FFS_INVALIDPATH)
- err = -EINVAL;
- else if (err == FFS_FILEEXIST)
- err = -ENOTEMPTY;
- else if (err == FFS_NOTFOUND)
- err = -ENOENT;
- else if (err == FFS_DIRBUSY)
- err = -EBUSY;
- else
- err = -EIO;
+ if (err)
goto out;
- }
+
INC_IVERSION(dir);
- dir->i_mtime = dir->i_atime = current_time(dir);
+ curtime = current_time(dir);
+ dir->i_mtime = curtime;
+ dir->i_atime = curtime;
if (IS_DIRSYNC(dir))
(void)exfat_sync_inode(dir);
else
@@ -2718,7 +2571,9 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
drop_nlink(dir);
clear_nlink(inode);
- inode->i_mtime = inode->i_atime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
exfat_detach(inode);
remove_inode_hash(inode);
@@ -2734,6 +2589,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
{
struct inode *old_inode, *new_inode;
struct super_block *sb = old_dir->i_sb;
+ struct timespec64 curtime;
loff_t i_pos;
int err;
@@ -2751,24 +2607,15 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir,
new_dentry);
- if (err) {
- if (err == FFS_PERMISSIONERR)
- err = -EPERM;
- else if (err == FFS_INVALIDPATH)
- err = -EINVAL;
- else if (err == FFS_FILEEXIST)
- err = -EEXIST;
- else if (err == FFS_NOTFOUND)
- err = -ENOENT;
- else if (err == FFS_FULL)
- err = -ENOSPC;
- else
- err = -EIO;
+ if (err)
goto out;
- }
+
INC_IVERSION(new_dir);
- new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime =
- current_time(new_dir);
+ curtime = current_time(new_dir);
+ new_dir->i_ctime = curtime;
+ new_dir->i_mtime = curtime;
+ new_dir->i_atime = curtime;
+
if (IS_DIRSYNC(new_dir))
(void)exfat_sync_inode(new_dir);
else
@@ -2790,7 +2637,9 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
inc_nlink(new_dir);
}
INC_IVERSION(old_dir);
- old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir);
+ curtime = current_time(old_dir);
+ old_dir->i_ctime = curtime;
+ old_dir->i_mtime = curtime;
if (IS_DIRSYNC(old_dir))
(void)exfat_sync_inode(old_dir);
else
@@ -2814,13 +2663,16 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
{
struct address_space *mapping = inode->i_mapping;
loff_t start = i_size_read(inode), count = size - i_size_read(inode);
+ struct timespec64 curtime;
int err, err2;
err = generic_cont_expand_simple(inode, size);
if (err != 0)
return err;
- inode->i_ctime = inode->i_mtime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_ctime = curtime;
+ inode->i_mtime = curtime;
mark_inode_dirty(inode);
if (IS_SYNC(inode)) {
@@ -2895,7 +2747,8 @@ static void exfat_truncate(struct inode *inode, loff_t old_size)
{
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
+ struct timespec64 curtime;
int err;
__lock_super(sb);
@@ -2914,7 +2767,9 @@ static void exfat_truncate(struct inode *inode, loff_t old_size)
if (err)
goto out;
- inode->i_ctime = inode->i_mtime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_ctime = curtime;
+ inode->i_mtime = curtime;
if (IS_DIRSYNC(inode))
(void)exfat_sync_inode(inode);
else
@@ -2936,8 +2791,8 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr)
pr_debug("%s entered\n", __func__);
- if ((attr->ia_valid & ATTR_SIZE)
- && (attr->ia_size > i_size_read(inode))) {
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ attr->ia_size > i_size_read(inode)) {
error = exfat_cont_expand(inode, attr->ia_size);
if (error || attr->ia_valid == ATTR_SIZE)
return error;
@@ -2946,8 +2801,8 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr)
ia_valid = attr->ia_valid;
- if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET))
- && exfat_allow_set_time(sbi, inode)) {
+ if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) &&
+ exfat_allow_set_time(sbi, inode)) {
attr->ia_valid &= ~(ATTR_MTIME_SET |
ATTR_ATIME_SET |
ATTR_TIMES_SET);
@@ -3073,8 +2928,7 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
{
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
- struct bd_info_t *p_bd = &(sbi->bd_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
const unsigned long blocksize = sb->s_blocksize;
const unsigned char blocksize_bits = sb->s_blocksize_bits;
sector_t last_block;
@@ -3084,18 +2938,6 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
*phys = 0;
*mapped_blocks = 0;
- if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) {
- if (inode->i_ino == EXFAT_ROOT_INO) {
- if (sector <
- (p_fs->dentries_in_root >>
- (p_bd->sector_size_bits - DENTRY_SIZE_BITS))) {
- *phys = sector + p_fs->root_start_sector;
- *mapped_blocks = 1;
- }
- return 0;
- }
- }
-
last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
if (sector >= last_block) {
if (*create == 0)
@@ -3114,12 +2956,7 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
err = ffsMapCluster(inode, clu_offset, &cluster);
- if (err) {
- if (err == FFS_FULL)
- return -ENOSPC;
- else
- return -EIO;
- } else if (cluster != CLUSTER_32(~0)) {
+ if (!err && (cluster != CLUSTER_32(~0))) {
*phys = START_SECTOR(cluster) + sec_offset;
*mapped_blocks = p_fs->sectors_per_clu - sec_offset;
}
@@ -3215,6 +3052,7 @@ static int exfat_write_end(struct file *file, struct address_space *mapping,
{
struct inode *inode = mapping->host;
struct file_id_t *fid = &(EXFAT_I(inode)->fid);
+ struct timespec64 curtime;
int err;
err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
@@ -3223,7 +3061,9 @@ static int exfat_write_end(struct file *file, struct address_space *mapping,
exfat_write_failed(mapping, pos + len);
if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) {
- inode->i_mtime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_ctime = curtime;
fid->attr |= ATTR_ARCHIVE;
mark_inode_dirty(inode);
}
@@ -3302,7 +3142,7 @@ static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos)
static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid)
{
struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
struct dir_entry_t info;
memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(struct file_id_t));
@@ -3314,7 +3154,7 @@ static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid)
inode->i_uid = sbi->options.fs_uid;
inode->i_gid = sbi->options.fs_gid;
INC_IVERSION(inode);
- inode->i_generation = get_seconds();
+ inode->i_generation = prandom_u32();
if (info.Attr & ATTR_SUBDIR) { /* directory */
inode->i_generation &= ~1;
@@ -3501,7 +3341,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
struct vol_info_t info;
if (p_fs->used_clusters == UINT_MAX) {
- if (ffsGetVolInfo(sb, &info) == FFS_MEDIAERR)
+ if (ffsGetVolInfo(sb, &info) == -EIO)
return -EIO;
} else {
@@ -3557,7 +3397,7 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root)
seq_puts(m, ",errors=panic");
else
seq_puts(m, ",errors=remount-ro");
-#ifdef CONFIG_EXFAT_DISCARD
+#ifdef CONFIG_STAGING_EXFAT_DISCARD
if (opts->discard)
seq_puts(m, ",discard");
#endif
@@ -3638,7 +3478,7 @@ enum {
Opt_err_ro,
Opt_utf8_hack,
Opt_err,
-#ifdef CONFIG_EXFAT_DISCARD
+#ifdef CONFIG_STAGING_EXFAT_DISCARD
Opt_discard,
#endif /* EXFAT_CONFIG_DISCARD */
};
@@ -3658,9 +3498,9 @@ static const match_table_t exfat_tokens = {
{Opt_err_panic, "errors=panic"},
{Opt_err_ro, "errors=remount-ro"},
{Opt_utf8_hack, "utf8"},
-#ifdef CONFIG_EXFAT_DISCARD
+#ifdef CONFIG_STAGING_EXFAT_DISCARD
{Opt_discard, "discard"},
-#endif /* CONFIG_EXFAT_DISCARD */
+#endif /* CONFIG_STAGING_EXFAT_DISCARD */
{Opt_err, NULL}
};
@@ -3674,13 +3514,14 @@ static int parse_options(char *options, int silent, int *debug,
opts->fs_uid = current_uid();
opts->fs_gid = current_gid();
- opts->fs_fmask = opts->fs_dmask = current->fs->umask;
+ opts->fs_fmask = current->fs->umask;
+ opts->fs_dmask = current->fs->umask;
opts->allow_utime = U16_MAX;
opts->codepage = exfat_default_codepage;
opts->iocharset = exfat_default_iocharset;
opts->casesensitive = 0;
opts->errors = EXFAT_ERRORS_RO;
-#ifdef CONFIG_EXFAT_DISCARD
+#ifdef CONFIG_STAGING_EXFAT_DISCARD
opts->discard = 0;
#endif
*debug = 0;
@@ -3751,11 +3592,11 @@ static int parse_options(char *options, int silent, int *debug,
case Opt_debug:
*debug = 1;
break;
-#ifdef CONFIG_EXFAT_DISCARD
+#ifdef CONFIG_STAGING_EXFAT_DISCARD
case Opt_discard:
opts->discard = 1;
break;
-#endif /* CONFIG_EXFAT_DISCARD */
+#endif /* CONFIG_STAGING_EXFAT_DISCARD */
case Opt_utf8_hack:
break;
default:
@@ -3787,7 +3628,8 @@ static int exfat_read_root(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
- struct fs_info_t *p_fs = &(sbi->fs_info);
+ struct fs_info_t *p_fs = &sbi->fs_info;
+ struct timespec64 curtime;
struct dir_entry_t info;
EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir;
@@ -3818,7 +3660,10 @@ static int exfat_read_root(struct inode *inode)
EXFAT_I(inode)->mmu_private = i_size_read(inode);
exfat_save_attr(inode, ATTR_SUBDIR);
- inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ curtime = current_time(inode);
+ inode->i_mtime = curtime;
+ inode->i_atime = curtime;
+ inode->i_ctime = curtime;
set_nlink(inode, info.NumSubdirs + 2);
return 0;
@@ -3838,7 +3683,6 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
struct exfat_sb_info *sbi;
int debug, ret;
long error;
- char buf[50];
/*
* GFP_KERNEL is ok here, because while we do hold the
@@ -3885,17 +3729,6 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
* if (FAT_FIRST_ENT(sb, media) != first)
*/
- /* codepage is not meaningful in exfat */
- if (sbi->fs_info.vol_type != EXFAT) {
- error = -EINVAL;
- sprintf(buf, "cp%d", sbi->options.codepage);
- sbi->nls_disk = load_nls(buf);
- if (!sbi->nls_disk) {
- pr_err("[EXFAT] Codepage %s not found\n", buf);
- goto out_fail2;
- }
- }
-
sbi->nls_io = load_nls(sbi->options.iocharset);
error = -ENOMEM;
@@ -3967,7 +3800,7 @@ static void __exit exfat_destroy_inodecache(void)
kmem_cache_destroy(exfat_inode_cachep);
}
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
static void exfat_debug_kill_sb(struct super_block *sb)
{
struct exfat_sb_info *sbi = EXFAT_SB(sb);
@@ -3984,10 +3817,10 @@ static void exfat_debug_kill_sb(struct super_block *sb)
* invalidate_bdev drops all device cache include
* dirty. We use this to simulate device removal.
*/
- down(&p_fs->v_sem);
- FAT_release_all(sb);
- buf_release_all(sb);
- up(&p_fs->v_sem);
+ mutex_lock(&p_fs->v_mutex);
+ exfat_fat_release_all(sb);
+ exfat_buf_release_all(sb);
+ mutex_unlock(&p_fs->v_mutex);
invalidate_bdev(bdev);
}
@@ -3995,17 +3828,17 @@ static void exfat_debug_kill_sb(struct super_block *sb)
kill_block_super(sb);
}
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
static struct file_system_type exfat_fs_type = {
.owner = THIS_MODULE,
.name = "exfat",
.mount = exfat_fs_mount,
-#ifdef CONFIG_EXFAT_KERNEL_DEBUG
+#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
.kill_sb = exfat_debug_kill_sb,
#else
.kill_sb = kill_block_super,
-#endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
.fs_flags = FS_REQUIRES_DEV,
};
diff --git a/drivers/staging/greybus/audio_manager.c b/drivers/staging/greybus/audio_manager.c
index 9b19ea9d3fa14..9a3f7c034ab49 100644
--- a/drivers/staging/greybus/audio_manager.c
+++ b/drivers/staging/greybus/audio_manager.c
@@ -92,8 +92,8 @@ void gb_audio_manager_remove_all(void)
list_for_each_entry_safe(module, next, &modules_list, list) {
list_del(&module->list);
- kobject_put(&module->kobj);
ida_simple_remove(&module_id, module->id);
+ kobject_put(&module->kobj);
}
is_empty = list_empty(&modules_list);
diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c
index ddb4a973c6986..e18758a8e911a 100644
--- a/drivers/thermal/intel/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c
@@ -63,7 +63,7 @@ static int max_id __read_mostly;
/* Array of zone pointers */
static struct zone_device **zones;
/* Serializes interrupt notification, work and hotplug */
-static DEFINE_SPINLOCK(pkg_temp_lock);
+static DEFINE_RAW_SPINLOCK(pkg_temp_lock);
/* Protects zone operation in the work function against hotplug removal */
static DEFINE_MUTEX(thermal_zone_mutex);
@@ -266,12 +266,12 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
u64 msr_val, wr_val;
mutex_lock(&thermal_zone_mutex);
- spin_lock_irq(&pkg_temp_lock);
+ raw_spin_lock_irq(&pkg_temp_lock);
++pkg_work_cnt;
zonedev = pkg_temp_thermal_get_dev(cpu);
if (!zonedev) {
- spin_unlock_irq(&pkg_temp_lock);
+ raw_spin_unlock_irq(&pkg_temp_lock);
mutex_unlock(&thermal_zone_mutex);
return;
}
@@ -285,7 +285,7 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work)
}
enable_pkg_thres_interrupt();
- spin_unlock_irq(&pkg_temp_lock);
+ raw_spin_unlock_irq(&pkg_temp_lock);
/*
* If tzone is not NULL, then thermal_zone_mutex will prevent the
@@ -310,7 +310,7 @@ static int pkg_thermal_notify(u64 msr_val)
struct zone_device *zonedev;
unsigned long flags;
- spin_lock_irqsave(&pkg_temp_lock, flags);
+ raw_spin_lock_irqsave(&pkg_temp_lock, flags);
++pkg_interrupt_cnt;
disable_pkg_thres_interrupt();
@@ -322,7 +322,7 @@ static int pkg_thermal_notify(u64 msr_val)
pkg_thermal_schedule_work(zonedev->cpu, &zonedev->work);
}
- spin_unlock_irqrestore(&pkg_temp_lock, flags);
+ raw_spin_unlock_irqrestore(&pkg_temp_lock, flags);
return 0;
}
@@ -368,9 +368,9 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
zonedev->msr_pkg_therm_high);
cpumask_set_cpu(cpu, &zonedev->cpumask);
- spin_lock_irq(&pkg_temp_lock);
+ raw_spin_lock_irq(&pkg_temp_lock);
zones[id] = zonedev;
- spin_unlock_irq(&pkg_temp_lock);
+ raw_spin_unlock_irq(&pkg_temp_lock);
return 0;
}
@@ -407,7 +407,7 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
}
/* Protect against work and interrupts */
- spin_lock_irq(&pkg_temp_lock);
+ raw_spin_lock_irq(&pkg_temp_lock);
/*
* Check whether this cpu was the current target and store the new
@@ -439,9 +439,9 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
* To cancel the work we need to drop the lock, otherwise
* we might deadlock if the work needs to be flushed.
*/
- spin_unlock_irq(&pkg_temp_lock);
+ raw_spin_unlock_irq(&pkg_temp_lock);
cancel_delayed_work_sync(&zonedev->work);
- spin_lock_irq(&pkg_temp_lock);
+ raw_spin_lock_irq(&pkg_temp_lock);
/*
* If this is not the last cpu in the package and the work
* did not run after we dropped the lock above, then we
@@ -452,7 +452,7 @@ static int pkg_thermal_cpu_offline(unsigned int cpu)
pkg_thermal_schedule_work(target, &zonedev->work);
}
- spin_unlock_irq(&pkg_temp_lock);
+ raw_spin_unlock_irq(&pkg_temp_lock);
/* Final cleanup if this is the last cpu */
if (lastcpu)
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 33ad9d6de5323..b29aed97a54dc 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -130,12 +130,55 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
up->dl_write(up, value);
}
+static inline void serial8250_set_IER(struct uart_8250_port *up,
+ unsigned char ier)
+{
+ struct uart_port *port = &up->port;
+ unsigned int flags;
+ bool is_console;
+
+ is_console = uart_console(port);
+
+ if (is_console)
+ console_atomic_lock(&flags);
+
+ serial_out(up, UART_IER, ier);
+
+ if (is_console)
+ console_atomic_unlock(flags);
+}
+
+static inline unsigned char serial8250_clear_IER(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+ unsigned int clearval = 0;
+ unsigned int prior;
+ unsigned int flags;
+ bool is_console;
+
+ is_console = uart_console(port);
+
+ if (up->capabilities & UART_CAP_UUE)
+ clearval = UART_IER_UUE;
+
+ if (is_console)
+ console_atomic_lock(&flags);
+
+ prior = serial_port_in(port, UART_IER);
+ serial_port_out(port, UART_IER, clearval);
+
+ if (is_console)
+ console_atomic_unlock(flags);
+
+ return prior;
+}
+
static inline bool serial8250_set_THRI(struct uart_8250_port *up)
{
if (up->ier & UART_IER_THRI)
return false;
up->ier |= UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
+ serial8250_set_IER(up, up->ier);
return true;
}
@@ -144,7 +187,7 @@ static inline bool serial8250_clear_THRI(struct uart_8250_port *up)
if (!(up->ier & UART_IER_THRI))
return false;
up->ier &= ~UART_IER_THRI;
- serial_out(up, UART_IER, up->ier);
+ serial8250_set_IER(up, up->ier);
return true;
}
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index e682390ce0dea..eabb9274c0a9d 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -55,7 +55,16 @@ static struct uart_driver serial8250_reg;
static unsigned int skip_txen_test; /* force skip of txen test at init time */
-#define PASS_LIMIT 512
+/*
+ * On -rt we can have a more delays, and legitimately
+ * so - so don't drop work spuriously and spam the
+ * syslog:
+ */
+#ifdef CONFIG_PREEMPT_RT
+# define PASS_LIMIT 1000000
+#else
+# define PASS_LIMIT 512
+#endif
#include
/*
@@ -275,10 +284,8 @@ static void serial8250_backup_timeout(struct timer_list *t)
* Must disable interrupts or else we risk racing with the interrupt
* based handler.
*/
- if (up->port.irq) {
- ier = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
- }
+ if (up->port.irq)
+ ier = serial8250_clear_IER(up);
iir = serial_in(up, UART_IIR);
@@ -301,7 +308,7 @@ static void serial8250_backup_timeout(struct timer_list *t)
serial8250_tx_chars(up);
if (up->port.irq)
- serial_out(up, UART_IER, ier);
+ serial8250_set_IER(up, ier);
spin_unlock_irqrestore(&up->port.lock, flags);
@@ -579,6 +586,14 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void univ8250_console_write_atomic(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct uart_8250_port *up = &serial8250_ports[co->index];
+
+ serial8250_console_write_atomic(up, s, count);
+}
+
static void univ8250_console_write(struct console *co, const char *s,
unsigned int count)
{
@@ -664,6 +679,7 @@ static int univ8250_console_match(struct console *co, char *name, int idx,
static struct console univ8250_console = {
.name = "ttyS",
+ .write_atomic = univ8250_console_write_atomic,
.write = univ8250_console_write,
.device = uart_console_device,
.setup = univ8250_console_setup,
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
index aa0e216d5eadb..8f711afadd4b5 100644
--- a/drivers/tty/serial/8250/8250_fsl.c
+++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -57,9 +57,18 @@ int fsl8250_handle_irq(struct uart_port *port)
/* Stop processing interrupts on input overrun */
if ((orig_lsr & UART_LSR_OE) && (up->overrun_backoff_time_ms > 0)) {
+ unsigned int ca_flags;
unsigned long delay;
+ bool is_console;
+ is_console = uart_console(port);
+
+ if (is_console)
+ console_atomic_lock(&ca_flags);
up->ier = port->serial_in(port, UART_IER);
+ if (is_console)
+ console_atomic_unlock(ca_flags);
+
if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
port->ops->stop_rx(port);
} else {
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index 424c07c5f6299..47f1482bd818a 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -146,6 +146,8 @@ OF_EARLYCON_DECLARE(x1000_uart, "ingenic,x1000-uart",
static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
{
+ unsigned int flags;
+ bool is_console;
int ier;
switch (offset) {
@@ -167,7 +169,12 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
* If we have enabled modem status IRQs we should enable
* modem mode.
*/
+ is_console = uart_console(p);
+ if (is_console)
+ console_atomic_lock(&flags);
ier = p->serial_in(p, UART_IER);
+ if (is_console)
+ console_atomic_unlock(flags);
if (ier & UART_IER_MSI)
value |= UART_MCR_MDCE | UART_MCR_FCM;
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index 4d067f515f748..b509c3de0301f 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -212,12 +212,37 @@ static void mtk8250_shutdown(struct uart_port *port)
static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
{
- serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask));
+ struct uart_port *port = &up->port;
+ unsigned int flags;
+ unsigned int ier;
+ bool is_console;
+
+ is_console = uart_console(port);
+
+ if (is_console)
+ console_atomic_lock(&flags);
+
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, ier & (~mask));
+
+ if (is_console)
+ console_atomic_unlock(flags);
}
static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask)
{
- serial_out(up, UART_IER, serial_in(up, UART_IER) | mask);
+ struct uart_port *port = &up->port;
+ unsigned int flags;
+ unsigned int ier;
+
+ if (uart_console(port))
+ console_atomic_lock(&flags);
+
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, ier | mask);
+
+ if (uart_console(port))
+ console_atomic_unlock(flags);
}
static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index ea8f9085c0617..88cc461f516ae 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -721,7 +721,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
serial_out(p, UART_EFR, UART_EFR_ECB);
serial_out(p, UART_LCR, 0);
}
- serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
+ serial8250_set_IER(p, sleep ? UART_IERX_SLEEP : 0);
if (p->capabilities & UART_CAP_EFR) {
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(p, UART_EFR, efr);
@@ -1390,7 +1390,7 @@ static void serial8250_stop_rx(struct uart_port *port)
up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
up->port.read_status_mask &= ~UART_LSR_DR;
- serial_port_out(port, UART_IER, up->ier);
+ serial8250_set_IER(up, up->ier);
serial8250_rpm_put(up);
}
@@ -1408,7 +1408,7 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p)
serial8250_clear_and_reinit_fifos(p);
p->ier |= UART_IER_RLSI | UART_IER_RDI;
- serial_port_out(&p->port, UART_IER, p->ier);
+ serial8250_set_IER(p, p->ier);
}
}
static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)
@@ -1616,7 +1616,7 @@ static void serial8250_disable_ms(struct uart_port *port)
mctrl_gpio_disable_ms(up->gpios);
up->ier &= ~UART_IER_MSI;
- serial_port_out(port, UART_IER, up->ier);
+ serial8250_set_IER(up, up->ier);
}
static void serial8250_enable_ms(struct uart_port *port)
@@ -1632,7 +1632,7 @@ static void serial8250_enable_ms(struct uart_port *port)
up->ier |= UART_IER_MSI;
serial8250_rpm_get(up);
- serial_port_out(port, UART_IER, up->ier);
+ serial8250_set_IER(up, up->ier);
serial8250_rpm_put(up);
}
@@ -2040,14 +2040,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
struct uart_8250_port *up = up_to_u8250p(port);
serial8250_rpm_get(up);
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_port_in(port, UART_IER);
- if (up->capabilities & UART_CAP_UUE)
- serial_port_out(port, UART_IER, UART_IER_UUE);
- else
- serial_port_out(port, UART_IER, 0);
+ ier = serial8250_clear_IER(up);
wait_for_xmitr(up, BOTH_EMPTY);
/*
@@ -2060,7 +2053,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
- serial_port_out(port, UART_IER, ier);
+ serial8250_set_IER(up, ier);
serial8250_rpm_put(up);
}
@@ -2368,7 +2361,7 @@ void serial8250_do_shutdown(struct uart_port *port)
*/
spin_lock_irqsave(&port->lock, flags);
up->ier = 0;
- serial_port_out(port, UART_IER, 0);
+ serial8250_set_IER(up, 0);
spin_unlock_irqrestore(&port->lock, flags);
synchronize_irq(port->irq);
@@ -2653,7 +2646,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
if (up->capabilities & UART_CAP_RTOIE)
up->ier |= UART_IER_RTOIE;
- serial_port_out(port, UART_IER, up->ier);
+ serial8250_set_IER(up, up->ier);
if (up->capabilities & UART_CAP_EFR) {
unsigned char efr = 0;
@@ -3117,7 +3110,7 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults);
#ifdef CONFIG_SERIAL_8250_CONSOLE
-static void serial8250_console_putchar(struct uart_port *port, int ch)
+static void serial8250_console_putchar_locked(struct uart_port *port, int ch)
{
struct uart_8250_port *up = up_to_u8250p(port);
@@ -3125,6 +3118,18 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
serial_port_out(port, UART_TX, ch);
}
+static void serial8250_console_putchar(struct uart_port *port, int ch)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned int flags;
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+
+ console_atomic_lock(&flags);
+ serial8250_console_putchar_locked(port, ch);
+ console_atomic_unlock(flags);
+}
+
/*
* Restore serial console when h/w power-off detected
*/
@@ -3146,6 +3151,32 @@ static void serial8250_console_restore(struct uart_8250_port *up)
serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
}
+void serial8250_console_write_atomic(struct uart_8250_port *up,
+ const char *s, unsigned int count)
+{
+ struct uart_port *port = &up->port;
+ unsigned int flags;
+ unsigned int ier;
+
+ console_atomic_lock(&flags);
+
+ touch_nmi_watchdog();
+
+ ier = serial8250_clear_IER(up);
+
+ if (atomic_fetch_inc(&up->console_printing)) {
+ uart_console_write(port, "\n", 1,
+ serial8250_console_putchar_locked);
+ }
+ uart_console_write(port, s, count, serial8250_console_putchar_locked);
+ atomic_dec(&up->console_printing);
+
+ wait_for_xmitr(up, BOTH_EMPTY);
+ serial8250_set_IER(up, ier);
+
+ console_atomic_unlock(flags);
+}
+
/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
@@ -3158,26 +3189,13 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
struct uart_port *port = &up->port;
unsigned long flags;
unsigned int ier;
- int locked = 1;
touch_nmi_watchdog();
serial8250_rpm_get(up);
+ spin_lock_irqsave(&port->lock, flags);
- if (oops_in_progress)
- locked = spin_trylock_irqsave(&port->lock, flags);
- else
- spin_lock_irqsave(&port->lock, flags);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_port_in(port, UART_IER);
-
- if (up->capabilities & UART_CAP_UUE)
- serial_port_out(port, UART_IER, UART_IER_UUE);
- else
- serial_port_out(port, UART_IER, 0);
+ ier = serial8250_clear_IER(up);
/* check scratch reg to see if port powered off during system sleep */
if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
@@ -3185,14 +3203,16 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
up->canary = 0;
}
+ atomic_inc(&up->console_printing);
uart_console_write(port, s, count, serial8250_console_putchar);
+ atomic_dec(&up->console_printing);
/*
* Finally, wait for transmitter to become empty
* and restore the IER
*/
wait_for_xmitr(up, BOTH_EMPTY);
- serial_port_out(port, UART_IER, ier);
+ serial8250_set_IER(up, ier);
/*
* The receive handling will happen properly because the
@@ -3204,8 +3224,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
if (up->msr_saved_flags)
serial8250_modem_status(up);
- if (locked)
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
serial8250_rpm_put(up);
}
@@ -3226,6 +3245,7 @@ static unsigned int probe_baud(struct uart_port *port)
int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
{
+ struct uart_8250_port *up = up_to_u8250p(port);
int baud = 9600;
int bits = 8;
int parity = 'n';
@@ -3234,6 +3254,8 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
if (!port->iobase && !port->membase)
return -ENODEV;
+ atomic_set(&up->console_printing, 0);
+
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else if (probe)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index b0b6895463952..3cd2687cbb8d0 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2209,18 +2209,24 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_amba_port *uap = amba_ports[co->index];
unsigned int old_cr = 0, new_cr;
- unsigned long flags;
+ unsigned long flags = 0;
int locked = 1;
clk_enable(uap->clk);
- local_irq_save(flags);
+ /*
+ * local_irq_save(flags);
+ *
+ * This local_irq_save() is nonsense. If we come in via sysrq
+ * handling then interrupts are already disabled. Aside of
+ * that the port.sysrq check is racy on SMP regardless.
+ */
if (uap->port.sysrq)
locked = 0;
else if (oops_in_progress)
- locked = spin_trylock(&uap->port.lock);
+ locked = spin_trylock_irqsave(&uap->port.lock, flags);
else
- spin_lock(&uap->port.lock);
+ spin_lock_irqsave(&uap->port.lock, flags);
/*
* First save the CR then disable the interrupts
@@ -2246,8 +2252,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
pl011_write(old_cr, uap, REG_CR);
if (locked)
- spin_unlock(&uap->port.lock);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&uap->port.lock, flags);
clk_disable(uap->clk);
}
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6420ae581a802..0f4f41ed9ffa5 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1307,13 +1307,10 @@ serial_omap_console_write(struct console *co, const char *s,
pm_runtime_get_sync(up->dev);
- local_irq_save(flags);
- if (up->port.sysrq)
- locked = 0;
- else if (oops_in_progress)
- locked = spin_trylock(&up->port.lock);
+ if (up->port.sysrq || oops_in_progress)
+ locked = spin_trylock_irqsave(&up->port.lock, flags);
else
- spin_lock(&up->port.lock);
+ spin_lock_irqsave(&up->port.lock, flags);
/*
* First save the IER then disable the interrupts
@@ -1342,8 +1339,7 @@ serial_omap_console_write(struct console *co, const char *s,
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
if (locked)
- spin_unlock(&up->port.lock);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&up->port.lock, flags);
}
static int __init
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index ced2581cf99fe..534542865742c 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1717,7 +1717,7 @@ static void ffs_data_put(struct ffs_data *ffs)
pr_info("%s(): freeing\n", __func__);
ffs_data_clear(ffs);
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
- waitqueue_active(&ffs->ep0req_completion.wait) ||
+ swait_active(&ffs->ep0req_completion.wait) ||
waitqueue_active(&ffs->wait));
destroy_workqueue(ffs->io_completion_wq);
kfree(ffs->dev_name);
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index b47938dff1a22..e5141c1136e47 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -344,7 +344,7 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
spin_unlock_irq (&epdata->dev->lock);
if (likely (value == 0)) {
- value = wait_event_interruptible (done.wait, done.done);
+ value = swait_event_interruptible_exclusive(done.wait, done.done);
if (value != 0) {
spin_lock_irq (&epdata->dev->lock);
if (likely (epdata->ep != NULL)) {
@@ -353,7 +353,7 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
usb_ep_dequeue (epdata->ep, epdata->req);
spin_unlock_irq (&epdata->dev->lock);
- wait_event (done.wait, done.done);
+ swait_event_exclusive(done.wait, done.done);
if (epdata->status == -ECONNRESET)
epdata->status = -EINTR;
} else {
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 1b3ae40c761cf..e7a96c34a9ff8 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -99,7 +99,7 @@ config LCD_TOSA
config LCD_HP700
tristate "HP Jornada 700 series LCD Driver"
- depends on SA1100_JORNADA720_SSP && !PREEMPT
+ depends on SA1100_JORNADA720_SSP && !PREEMPTION
default y
help
If you have an HP Jornada 700 series handheld (710/720/728)
@@ -228,7 +228,7 @@ config BACKLIGHT_HP680
config BACKLIGHT_HP700
tristate "HP Jornada 700 series Backlight Driver"
- depends on SA1100_JORNADA720_SSP && !PREEMPT
+ depends on SA1100_JORNADA720_SSP && !PREEMPTION
default y
help
If you have an HP Jornada 700 series,
diff --git a/drivers/xen/preempt.c b/drivers/xen/preempt.c
index 8b9919c26095d..70650b248de5d 100644
--- a/drivers/xen/preempt.c
+++ b/drivers/xen/preempt.c
@@ -8,7 +8,7 @@
#include
#include
-#ifndef CONFIG_PREEMPT
+#ifndef CONFIG_PREEMPTION
/*
* Some hypercalls issued by the toolstack can take many 10s of
@@ -37,4 +37,4 @@ asmlinkage __visible void xen_maybe_preempt_hcall(void)
__this_cpu_write(xen_in_preemptible_hcall, true);
}
}
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
diff --git a/firmware/am335x-bone-scale-data.bin b/firmware/am335x-bone-scale-data.bin
new file mode 100644
index 0000000000000..1ce3c1c596d7a
Binary files /dev/null and b/firmware/am335x-bone-scale-data.bin differ
diff --git a/firmware/am335x-evm-scale-data.bin b/firmware/am335x-evm-scale-data.bin
new file mode 100644
index 0000000000000..a222389d233fa
Binary files /dev/null and b/firmware/am335x-evm-scale-data.bin differ
diff --git a/firmware/am335x-pm-firmware.bin b/firmware/am335x-pm-firmware.bin
new file mode 100755
index 0000000000000..1fc92e2bc40e9
Binary files /dev/null and b/firmware/am335x-pm-firmware.bin differ
diff --git a/firmware/am335x-pm-firmware.elf b/firmware/am335x-pm-firmware.elf
new file mode 100755
index 0000000000000..843fc22ce3484
Binary files /dev/null and b/firmware/am335x-pm-firmware.elf differ
diff --git a/firmware/am43x-evm-scale-data.bin b/firmware/am43x-evm-scale-data.bin
new file mode 100644
index 0000000000000..2d71341089816
Binary files /dev/null and b/firmware/am43x-evm-scale-data.bin differ
diff --git a/fs/afs/dir_silly.c b/fs/afs/dir_silly.c
index 361088a5edb98..c1b1a51eb7297 100644
--- a/fs/afs/dir_silly.c
+++ b/fs/afs/dir_silly.c
@@ -202,7 +202,7 @@ int afs_silly_iput(struct dentry *dentry, struct inode *inode)
struct dentry *alias;
int ret;
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
_enter("%p{%pd},%llx", dentry, dentry, vnode->fid.vnode);
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 5acf5c507ec2e..ad1ccf94e4b87 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -179,7 +179,7 @@ btrfs_device_set_##name(struct btrfs_device *dev, u64 size) \
write_seqcount_end(&dev->data_seqcount); \
preempt_enable(); \
}
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
#define BTRFS_DEVICE_GETSET_FUNCS(name) \
static inline u64 \
btrfs_device_get_##name(const struct btrfs_device *dev) \
diff --git a/fs/buffer.c b/fs/buffer.c
index 91ceca52d14f9..0d374ff8ff69b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -275,8 +275,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
* decide that the page is now completely done.
*/
first = page_buffers(page);
- local_irq_save(flags);
- bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
+ spin_lock_irqsave(&first->b_uptodate_lock, flags);
clear_buffer_async_read(bh);
unlock_buffer(bh);
tmp = bh;
@@ -289,8 +288,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
}
tmp = tmp->b_this_page;
} while (tmp != bh);
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
/*
* If none of the buffers had errors and they are all
@@ -302,8 +300,7 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)
return;
still_busy:
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
return;
}
@@ -331,8 +328,7 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate)
}
first = page_buffers(page);
- local_irq_save(flags);
- bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
+ spin_lock_irqsave(&first->b_uptodate_lock, flags);
clear_buffer_async_write(bh);
unlock_buffer(bh);
@@ -344,14 +340,12 @@ void end_buffer_async_write(struct buffer_head *bh, int uptodate)
}
tmp = tmp->b_this_page;
}
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
end_page_writeback(page);
return;
still_busy:
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
return;
}
EXPORT_SYMBOL(end_buffer_async_write);
@@ -1393,7 +1387,7 @@ static bool has_bh_in_lru(int cpu, void *dummy)
void invalidate_bh_lrus(void)
{
- on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1, GFP_KERNEL);
+ on_each_cpu_cond(has_bh_in_lru, invalidate_bh_lru, NULL, 1);
}
EXPORT_SYMBOL_GPL(invalidate_bh_lrus);
@@ -3345,6 +3339,7 @@ struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags);
if (ret) {
INIT_LIST_HEAD(&ret->b_assoc_buffers);
+ spin_lock_init(&ret->b_uptodate_lock);
preempt_disable();
__this_cpu_inc(bh_accounting.nr);
recalc_bh_state();
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 3925a7bfc74d6..33f7723fb83e9 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -80,7 +80,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
struct inode *inode;
struct super_block *sb = parent->d_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
diff --git a/fs/dcache.c b/fs/dcache.c
index e88cf0554e659..5699176ed169c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2482,9 +2482,10 @@ EXPORT_SYMBOL(d_rehash);
static inline unsigned start_dir_add(struct inode *dir)
{
+ preempt_disable_rt();
for (;;) {
- unsigned n = dir->i_dir_seq;
- if (!(n & 1) && cmpxchg(&dir->i_dir_seq, n, n + 1) == n)
+ unsigned n = dir->__i_dir_seq;
+ if (!(n & 1) && cmpxchg(&dir->__i_dir_seq, n, n + 1) == n)
return n;
cpu_relax();
}
@@ -2492,26 +2493,30 @@ static inline unsigned start_dir_add(struct inode *dir)
static inline void end_dir_add(struct inode *dir, unsigned n)
{
- smp_store_release(&dir->i_dir_seq, n + 2);
+ smp_store_release(&dir->__i_dir_seq, n + 2);
+ preempt_enable_rt();
}
static void d_wait_lookup(struct dentry *dentry)
{
- if (d_in_lookup(dentry)) {
- DECLARE_WAITQUEUE(wait, current);
- add_wait_queue(dentry->d_wait, &wait);
- do {
- set_current_state(TASK_UNINTERRUPTIBLE);
- spin_unlock(&dentry->d_lock);
- schedule();
- spin_lock(&dentry->d_lock);
- } while (d_in_lookup(dentry));
- }
+ struct swait_queue __wait;
+
+ if (!d_in_lookup(dentry))
+ return;
+
+ INIT_LIST_HEAD(&__wait.task_list);
+ do {
+ prepare_to_swait_exclusive(dentry->d_wait, &__wait, TASK_UNINTERRUPTIBLE);
+ spin_unlock(&dentry->d_lock);
+ schedule();
+ spin_lock(&dentry->d_lock);
+ } while (d_in_lookup(dentry));
+ finish_swait(dentry->d_wait, &__wait);
}
struct dentry *d_alloc_parallel(struct dentry *parent,
const struct qstr *name,
- wait_queue_head_t *wq)
+ struct swait_queue_head *wq)
{
unsigned int hash = name->hash;
struct hlist_bl_head *b = in_lookup_hash(parent, hash);
@@ -2525,7 +2530,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
retry:
rcu_read_lock();
- seq = smp_load_acquire(&parent->d_inode->i_dir_seq);
+ seq = smp_load_acquire(&parent->d_inode->__i_dir_seq);
r_seq = read_seqbegin(&rename_lock);
dentry = __d_lookup_rcu(parent, name, &d_seq);
if (unlikely(dentry)) {
@@ -2553,7 +2558,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
}
hlist_bl_lock(b);
- if (unlikely(READ_ONCE(parent->d_inode->i_dir_seq) != seq)) {
+ if (unlikely(READ_ONCE(parent->d_inode->__i_dir_seq) != seq)) {
hlist_bl_unlock(b);
rcu_read_unlock();
goto retry;
@@ -2626,7 +2631,7 @@ void __d_lookup_done(struct dentry *dentry)
hlist_bl_lock(b);
dentry->d_flags &= ~DCACHE_PAR_LOOKUP;
__hlist_bl_del(&dentry->d_u.d_in_lookup_hash);
- wake_up_all(dentry->d_wait);
+ swake_up_all(dentry->d_wait);
dentry->d_wait = NULL;
hlist_bl_unlock(b);
INIT_HLIST_NODE(&dentry->d_u.d_alias);
@@ -3139,6 +3144,8 @@ __setup("dhash_entries=", set_dhash_entries);
static void __init dcache_init_early(void)
{
+ unsigned int loop;
+
/* If hashes are distributed across NUMA nodes, defer
* hash allocation until vmalloc space is available.
*/
@@ -3155,11 +3162,16 @@ static void __init dcache_init_early(void)
NULL,
0,
0);
+
+ for (loop = 0; loop < (1U << d_hash_shift); loop++)
+ INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
+
d_hash_shift = 32 - d_hash_shift;
}
static void __init dcache_init(void)
{
+ unsigned int loop;
/*
* A constructor could be added for stable state like the lists,
* but it is probably not worth it because of the cache nature
@@ -3183,6 +3195,10 @@ static void __init dcache_init(void)
NULL,
0,
0);
+
+ for (loop = 0; loop < (1U << d_hash_shift); loop++)
+ INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
+
d_hash_shift = 32 - d_hash_shift;
}
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index c4159bcc05d9a..9ba07cb3cb524 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -567,12 +567,12 @@ static int ep_poll_wakeup_proc(void *priv, void *cookie, int call_nests)
static void ep_poll_safewake(wait_queue_head_t *wq)
{
- int this_cpu = get_cpu();
+ int this_cpu = get_cpu_light();
ep_call_nested(&poll_safewake_ncalls,
ep_poll_wakeup_proc, NULL, wq, (void *) (long) this_cpu);
- put_cpu();
+ put_cpu_light();
}
#else
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 2cc9f2168b9e4..33610b1bbac7a 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -87,11 +87,10 @@ static void ext4_finish_bio(struct bio *bio)
}
bh = head = page_buffers(page);
/*
- * We check all buffers in the page under BH_Uptodate_Lock
+ * We check all buffers in the page under b_uptodate_lock
* to avoid races with other end io clearing async_write flags
*/
- local_irq_save(flags);
- bit_spin_lock(BH_Uptodate_Lock, &head->b_state);
+ spin_lock_irqsave(&head->b_uptodate_lock, flags);
do {
if (bh_offset(bh) < bio_start ||
bh_offset(bh) + bh->b_size > bio_end) {
@@ -103,8 +102,7 @@ static void ext4_finish_bio(struct bio *bio)
if (bio->bi_status)
buffer_io_error(bh);
} while ((bh = bh->b_this_page) != head);
- bit_spin_unlock(BH_Uptodate_Lock, &head->b_state);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&head->b_uptodate_lock, flags);
if (!under_io) {
fscrypt_free_bounce_page(bounce_page);
end_page_writeback(page);
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index 0ce39658a6200..5508d92e3f8fc 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -958,3 +958,11 @@ int __fscache_check_consistency(struct fscache_cookie *cookie,
return -ESTALE;
}
EXPORT_SYMBOL(__fscache_check_consistency);
+
+void __init fscache_cookie_init(void)
+{
+ int i;
+
+ for (i = 0; i < (1 << fscache_cookie_hash_shift) - 1; i++)
+ INIT_HLIST_BL_HEAD(&fscache_cookie_hash[i]);
+}
diff --git a/fs/fscache/main.c b/fs/fscache/main.c
index 59c2494efda34..f9625eb898530 100644
--- a/fs/fscache/main.c
+++ b/fs/fscache/main.c
@@ -145,6 +145,7 @@ static int __init fscache_init(void)
ret = -ENOMEM;
goto error_cookie_jar;
}
+ fscache_cookie_init();
fscache_root = kobject_create_and_add("fscache", kernel_kobj);
if (!fscache_root)
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index 6a40f75a0d25e..6e813ecf8f512 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -158,7 +158,7 @@ static int fuse_direntplus_link(struct file *file,
struct inode *dir = d_inode(parent);
struct fuse_conn *fc;
struct inode *inode;
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
if (!o->nodeid) {
/*
diff --git a/fs/inode.c b/fs/inode.c
index 96d62d97694ef..e1fe4723ff80e 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -156,7 +156,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
inode->i_bdev = NULL;
inode->i_cdev = NULL;
inode->i_link = NULL;
- inode->i_dir_seq = 0;
+ inode->__i_dir_seq = 0;
inode->i_rdev = 0;
inode->dirtied_when = 0;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index c43591cd70f1c..41b7602718d0c 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -482,10 +482,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
if (jh->b_committed_data) {
struct buffer_head *bh = jh2bh(jh);
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
jbd2_free(jh->b_committed_data, bh->b_size);
jh->b_committed_data = NULL;
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
}
jbd2_journal_refile_buffer(journal, jh);
}
@@ -920,6 +920,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
transaction_t *cp_transaction;
struct buffer_head *bh;
int try_to_free = 0;
+ bool drop_ref;
jh = commit_transaction->t_forget;
spin_unlock(&journal->j_list_lock);
@@ -929,7 +930,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
* done with it.
*/
get_bh(bh);
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
J_ASSERT_JH(jh, jh->b_transaction == commit_transaction);
/*
@@ -1024,8 +1025,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
try_to_free = 1;
}
JBUFFER_TRACE(jh, "refile or unfile buffer");
- __jbd2_journal_refile_buffer(jh);
- jbd_unlock_bh_state(bh);
+ drop_ref = __jbd2_journal_refile_buffer(jh);
+ spin_unlock(&jh->b_state_lock);
+ if (drop_ref)
+ jbd2_journal_put_journal_head(jh);
if (try_to_free)
release_buffer_page(bh); /* Drops bh reference */
else
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index ef485f892d1b0..8b0612a280b39 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -363,7 +363,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
/* keep subsequent assertions sane */
atomic_set(&new_bh->b_count, 1);
- jbd_lock_bh_state(bh_in);
+ spin_lock(&jh_in->b_state_lock);
repeat:
/*
* If a new transaction has already done a buffer copy-out, then
@@ -405,13 +405,13 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
if (need_copy_out && !done_copy_out) {
char *tmp;
- jbd_unlock_bh_state(bh_in);
+ spin_unlock(&jh_in->b_state_lock);
tmp = jbd2_alloc(bh_in->b_size, GFP_NOFS);
if (!tmp) {
brelse(new_bh);
return -ENOMEM;
}
- jbd_lock_bh_state(bh_in);
+ spin_lock(&jh_in->b_state_lock);
if (jh_in->b_frozen_data) {
jbd2_free(tmp, bh_in->b_size);
goto repeat;
@@ -464,7 +464,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
__jbd2_journal_file_buffer(jh_in, transaction, BJ_Shadow);
spin_unlock(&journal->j_list_lock);
set_buffer_shadow(bh_in);
- jbd_unlock_bh_state(bh_in);
+ spin_unlock(&jh_in->b_state_lock);
return do_escape | (done_copy_out << 1);
}
@@ -2411,6 +2411,8 @@ static struct journal_head *journal_alloc_journal_head(void)
ret = kmem_cache_zalloc(jbd2_journal_head_cache,
GFP_NOFS | __GFP_NOFAIL);
}
+ if (ret)
+ spin_lock_init(&ret->b_state_lock);
return ret;
}
@@ -2530,17 +2532,23 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
J_ASSERT_BH(bh, buffer_jbd(bh));
J_ASSERT_BH(bh, jh2bh(jh) == bh);
BUFFER_TRACE(bh, "remove journal_head");
+
+ /* Unlink before dropping the lock */
+ bh->b_private = NULL;
+ jh->b_bh = NULL; /* debug, really */
+ clear_buffer_jbd(bh);
+}
+
+static void journal_release_journal_head(struct journal_head *jh, size_t b_size)
+{
if (jh->b_frozen_data) {
printk(KERN_WARNING "%s: freeing b_frozen_data\n", __func__);
- jbd2_free(jh->b_frozen_data, bh->b_size);
+ jbd2_free(jh->b_frozen_data, b_size);
}
if (jh->b_committed_data) {
printk(KERN_WARNING "%s: freeing b_committed_data\n", __func__);
- jbd2_free(jh->b_committed_data, bh->b_size);
+ jbd2_free(jh->b_committed_data, b_size);
}
- bh->b_private = NULL;
- jh->b_bh = NULL; /* debug, really */
- clear_buffer_jbd(bh);
journal_free_journal_head(jh);
}
@@ -2558,9 +2566,11 @@ void jbd2_journal_put_journal_head(struct journal_head *jh)
if (!jh->b_jcount) {
__journal_remove_journal_head(bh);
jbd_unlock_bh_journal_head(bh);
+ journal_release_journal_head(jh, bh->b_size);
__brelse(bh);
- } else
+ } else {
jbd_unlock_bh_journal_head(bh);
+ }
}
/*
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index bee8498d77929..7c11afe605320 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -879,7 +879,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
start_lock = jiffies;
lock_buffer(bh);
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
/* If it takes too long to lock the buffer, trace it */
time_lock = jbd2_time_diff(start_lock, jiffies);
@@ -929,7 +929,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
error = -EROFS;
if (is_handle_aborted(handle)) {
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
goto out;
}
error = 0;
@@ -993,7 +993,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
*/
if (buffer_shadow(bh)) {
JBUFFER_TRACE(jh, "on shadow: sleep");
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
wait_on_bit_io(&bh->b_state, BH_Shadow, TASK_UNINTERRUPTIBLE);
goto repeat;
}
@@ -1014,7 +1014,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
JBUFFER_TRACE(jh, "generate frozen data");
if (!frozen_buffer) {
JBUFFER_TRACE(jh, "allocate memory for buffer");
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
frozen_buffer = jbd2_alloc(jh2bh(jh)->b_size,
GFP_NOFS | __GFP_NOFAIL);
goto repeat;
@@ -1033,7 +1033,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
jh->b_next_transaction = transaction;
done:
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
/*
* If we are about to journal a buffer, then any revoke pending on it is
@@ -1172,7 +1172,7 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
* that case: the transaction must have deleted the buffer for it to be
* reused here.
*/
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
J_ASSERT_JH(jh, (jh->b_transaction == transaction ||
jh->b_transaction == NULL ||
(jh->b_transaction == journal->j_committing_transaction &&
@@ -1207,7 +1207,7 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
jh->b_next_transaction = transaction;
spin_unlock(&journal->j_list_lock);
}
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
/*
* akpm: I added this. ext3_alloc_branch can pick up new indirect
@@ -1275,13 +1275,13 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
committed_data = jbd2_alloc(jh2bh(jh)->b_size,
GFP_NOFS|__GFP_NOFAIL);
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
if (!jh->b_committed_data) {
/* Copy out the current buffer contents into the
* preserved, committed copy. */
JBUFFER_TRACE(jh, "generate b_committed data");
if (!committed_data) {
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
goto repeat;
}
@@ -1289,7 +1289,7 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
committed_data = NULL;
memcpy(jh->b_committed_data, bh->b_data, bh->b_size);
}
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
out:
jbd2_journal_put_journal_head(jh);
if (unlikely(committed_data))
@@ -1390,16 +1390,16 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
*/
if (jh->b_transaction != transaction &&
jh->b_next_transaction != transaction) {
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
J_ASSERT_JH(jh, jh->b_transaction == transaction ||
jh->b_next_transaction == transaction);
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
}
if (jh->b_modified == 1) {
/* If it's in our transaction it must be in BJ_Metadata list. */
if (jh->b_transaction == transaction &&
jh->b_jlist != BJ_Metadata) {
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
if (jh->b_transaction == transaction &&
jh->b_jlist != BJ_Metadata)
pr_err("JBD2: assertion failure: h_type=%u "
@@ -1409,13 +1409,13 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
jh->b_jlist);
J_ASSERT_JH(jh, jh->b_transaction != transaction ||
jh->b_jlist == BJ_Metadata);
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
}
goto out;
}
journal = transaction->t_journal;
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
if (jh->b_modified == 0) {
/*
@@ -1501,7 +1501,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
__jbd2_journal_file_buffer(jh, transaction, BJ_Metadata);
spin_unlock(&journal->j_list_lock);
out_unlock_bh:
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
out:
JBUFFER_TRACE(jh, "exit");
return ret;
@@ -1539,18 +1539,20 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
BUFFER_TRACE(bh, "entry");
- jbd_lock_bh_state(bh);
+ jh = jbd2_journal_grab_journal_head(bh);
+ if (!jh) {
+ __bforget(bh);
+ return 0;
+ }
- if (!buffer_jbd(bh))
- goto not_jbd;
- jh = bh2jh(bh);
+ spin_lock(&jh->b_state_lock);
/* Critical error: attempting to delete a bitmap buffer, maybe?
* Don't do any jbd operations, and return an error. */
if (!J_EXPECT_JH(jh, !jh->b_committed_data,
"inconsistent data on disk")) {
err = -EIO;
- goto not_jbd;
+ goto drop;
}
/* keep track of whether or not this transaction modified us */
@@ -1598,10 +1600,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
__jbd2_journal_file_buffer(jh, transaction, BJ_Forget);
} else {
__jbd2_journal_unfile_buffer(jh);
- if (!buffer_jbd(bh)) {
- spin_unlock(&journal->j_list_lock);
- goto not_jbd;
- }
+ jbd2_journal_put_journal_head(jh);
}
spin_unlock(&journal->j_list_lock);
} else if (jh->b_transaction) {
@@ -1643,7 +1642,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
if (!jh->b_cp_transaction) {
JBUFFER_TRACE(jh, "belongs to none transaction");
spin_unlock(&journal->j_list_lock);
- goto not_jbd;
+ goto drop;
}
/*
@@ -1653,7 +1652,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
if (!buffer_dirty(bh)) {
__jbd2_journal_remove_checkpoint(jh);
spin_unlock(&journal->j_list_lock);
- goto not_jbd;
+ goto drop;
}
/*
@@ -1666,20 +1665,15 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
__jbd2_journal_file_buffer(jh, transaction, BJ_Forget);
spin_unlock(&journal->j_list_lock);
}
-
- jbd_unlock_bh_state(bh);
- __brelse(bh);
drop:
+ __brelse(bh);
+ spin_unlock(&jh->b_state_lock);
+ jbd2_journal_put_journal_head(jh);
if (drop_reserve) {
/* no need to reserve log space for this block -bzzz */
handle->h_buffer_credits++;
}
return err;
-
-not_jbd:
- jbd_unlock_bh_state(bh);
- __bforget(bh);
- goto drop;
}
/**
@@ -1878,7 +1872,7 @@ int jbd2_journal_stop(handle_t *handle)
*
* j_list_lock is held.
*
- * jbd_lock_bh_state(jh2bh(jh)) is held.
+ * jh->b_state_lock is held.
*/
static inline void
@@ -1902,7 +1896,7 @@ __blist_add_buffer(struct journal_head **list, struct journal_head *jh)
*
* Called with j_list_lock held, and the journal may not be locked.
*
- * jbd_lock_bh_state(jh2bh(jh)) is held.
+ * jh->b_state_lock is held.
*/
static inline void
@@ -1934,7 +1928,7 @@ static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh)
transaction_t *transaction;
struct buffer_head *bh = jh2bh(jh);
- J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
+ lockdep_assert_held(&jh->b_state_lock);
transaction = jh->b_transaction;
if (transaction)
assert_spin_locked(&transaction->t_journal->j_list_lock);
@@ -1971,17 +1965,15 @@ static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh)
}
/*
- * Remove buffer from all transactions.
+ * Remove buffer from all transactions. The caller is responsible for dropping
+ * the jh reference that belonged to the transaction.
*
* Called with bh_state lock and j_list_lock
- *
- * jh and bh may be already freed when this function returns.
*/
static void __jbd2_journal_unfile_buffer(struct journal_head *jh)
{
__jbd2_journal_temp_unlink_buffer(jh);
jh->b_transaction = NULL;
- jbd2_journal_put_journal_head(jh);
}
void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
@@ -1990,18 +1982,19 @@ void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
/* Get reference so that buffer cannot be freed before we unlock it */
get_bh(bh);
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
spin_lock(&journal->j_list_lock);
__jbd2_journal_unfile_buffer(jh);
spin_unlock(&journal->j_list_lock);
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
+ jbd2_journal_put_journal_head(jh);
__brelse(bh);
}
/*
* Called from jbd2_journal_try_to_free_buffers().
*
- * Called under jbd_lock_bh_state(bh)
+ * Called under jh->b_state_lock
*/
static void
__journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
@@ -2088,10 +2081,10 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal,
if (!jh)
continue;
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
__journal_try_to_free_buffer(journal, bh);
+ spin_unlock(&jh->b_state_lock);
jbd2_journal_put_journal_head(jh);
- jbd_unlock_bh_state(bh);
if (buffer_jbd(bh))
goto busy;
} while ((bh = bh->b_this_page) != head);
@@ -2112,7 +2105,7 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal,
*
* Called under j_list_lock.
*
- * Called under jbd_lock_bh_state(bh).
+ * Called under jh->b_state_lock.
*/
static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
{
@@ -2133,6 +2126,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
} else {
JBUFFER_TRACE(jh, "on running transaction");
__jbd2_journal_unfile_buffer(jh);
+ jbd2_journal_put_journal_head(jh);
}
return may_free;
}
@@ -2199,18 +2193,15 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
* holding the page lock. --sct
*/
- if (!buffer_jbd(bh))
+ jh = jbd2_journal_grab_journal_head(bh);
+ if (!jh)
goto zap_buffer_unlocked;
/* OK, we have data buffer in journaled mode */
write_lock(&journal->j_state_lock);
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
spin_lock(&journal->j_list_lock);
- jh = jbd2_journal_grab_journal_head(bh);
- if (!jh)
- goto zap_buffer_no_jh;
-
/*
* We cannot remove the buffer from checkpoint lists until the
* transaction adding inode to orphan list (let's call it T)
@@ -2289,10 +2280,10 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
* for commit and try again.
*/
if (partial_page) {
- jbd2_journal_put_journal_head(jh);
spin_unlock(&journal->j_list_lock);
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
write_unlock(&journal->j_state_lock);
+ jbd2_journal_put_journal_head(jh);
return -EBUSY;
}
/*
@@ -2304,10 +2295,10 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
set_buffer_freed(bh);
if (journal->j_running_transaction && buffer_jbddirty(bh))
jh->b_next_transaction = journal->j_running_transaction;
- jbd2_journal_put_journal_head(jh);
spin_unlock(&journal->j_list_lock);
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
write_unlock(&journal->j_state_lock);
+ jbd2_journal_put_journal_head(jh);
return 0;
} else {
/* Good, the buffer belongs to the running transaction.
@@ -2331,11 +2322,10 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
* here.
*/
jh->b_modified = 0;
- jbd2_journal_put_journal_head(jh);
-zap_buffer_no_jh:
spin_unlock(&journal->j_list_lock);
- jbd_unlock_bh_state(bh);
+ spin_unlock(&jh->b_state_lock);
write_unlock(&journal->j_state_lock);
+ jbd2_journal_put_journal_head(jh);
zap_buffer_unlocked:
clear_buffer_dirty(bh);
J_ASSERT_BH(bh, !buffer_jbddirty(bh));
@@ -2422,7 +2412,7 @@ void __jbd2_journal_file_buffer(struct journal_head *jh,
int was_dirty = 0;
struct buffer_head *bh = jh2bh(jh);
- J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
+ lockdep_assert_held(&jh->b_state_lock);
assert_spin_locked(&transaction->t_journal->j_list_lock);
J_ASSERT_JH(jh, jh->b_jlist < BJ_Types);
@@ -2484,11 +2474,11 @@ void __jbd2_journal_file_buffer(struct journal_head *jh,
void jbd2_journal_file_buffer(struct journal_head *jh,
transaction_t *transaction, int jlist)
{
- jbd_lock_bh_state(jh2bh(jh));
+ spin_lock(&jh->b_state_lock);
spin_lock(&transaction->t_journal->j_list_lock);
__jbd2_journal_file_buffer(jh, transaction, jlist);
spin_unlock(&transaction->t_journal->j_list_lock);
- jbd_unlock_bh_state(jh2bh(jh));
+ spin_unlock(&jh->b_state_lock);
}
/*
@@ -2498,23 +2488,25 @@ void jbd2_journal_file_buffer(struct journal_head *jh,
* buffer on that transaction's metadata list.
*
* Called under j_list_lock
- * Called under jbd_lock_bh_state(jh2bh(jh))
+ * Called under jh->b_state_lock
*
- * jh and bh may be already free when this function returns
+ * When this function returns true, there's no next transaction to refile to
+ * and the caller has to drop jh reference through
+ * jbd2_journal_put_journal_head().
*/
-void __jbd2_journal_refile_buffer(struct journal_head *jh)
+bool __jbd2_journal_refile_buffer(struct journal_head *jh)
{
int was_dirty, jlist;
struct buffer_head *bh = jh2bh(jh);
- J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh));
+ lockdep_assert_held(&jh->b_state_lock);
if (jh->b_transaction)
assert_spin_locked(&jh->b_transaction->t_journal->j_list_lock);
/* If the buffer is now unused, just drop it. */
if (jh->b_next_transaction == NULL) {
__jbd2_journal_unfile_buffer(jh);
- return;
+ return true;
}
/*
@@ -2542,6 +2534,7 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh)
if (was_dirty)
set_buffer_jbddirty(bh);
+ return false;
}
/*
@@ -2552,16 +2545,15 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh)
*/
void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh)
{
- struct buffer_head *bh = jh2bh(jh);
+ bool drop;
- /* Get reference so that buffer cannot be freed before we unlock it */
- get_bh(bh);
- jbd_lock_bh_state(bh);
+ spin_lock(&jh->b_state_lock);
spin_lock(&journal->j_list_lock);
- __jbd2_journal_refile_buffer(jh);
- jbd_unlock_bh_state(bh);
+ drop = __jbd2_journal_refile_buffer(jh);
+ spin_unlock(&jh->b_state_lock);
spin_unlock(&journal->j_list_lock);
- __brelse(bh);
+ if (drop)
+ jbd2_journal_put_journal_head(jh);
}
/*
diff --git a/fs/namei.c b/fs/namei.c
index bd1c0ca4151c6..a6e33f240fb5c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1638,7 +1638,7 @@ static struct dentry *__lookup_slow(const struct qstr *name,
{
struct dentry *dentry, *old;
struct inode *inode = dir->d_inode;
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
/* Don't go there if it's already dead */
if (unlikely(IS_DEADDIR(inode)))
@@ -3126,7 +3126,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
struct dentry *dentry;
int error, create_error = 0;
umode_t mode = op->mode;
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
if (unlikely(IS_DEADDIR(dir_inode)))
return -ENOENT;
diff --git a/fs/namespace.c b/fs/namespace.c
index 2adfe7b166a3e..e67f6e405f366 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -321,8 +322,11 @@ int __mnt_want_write(struct vfsmount *m)
* incremented count after it has set MNT_WRITE_HOLD.
*/
smp_mb();
- while (READ_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD)
- cpu_relax();
+ while (READ_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD) {
+ preempt_enable();
+ cpu_chill();
+ preempt_disable();
+ }
/*
* After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will
* be set to match its requirements. So we must not load that until
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index af549d70ec507..86a72d0d38177 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -162,11 +162,11 @@ static int nfs_delegation_claim_opens(struct inode *inode,
sp = state->owner;
/* Block nfs4_proc_unlck */
mutex_lock(&sp->so_delegreturn_mutex);
- seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
+ seq = read_seqbegin(&sp->so_reclaim_seqlock);
err = nfs4_open_delegation_recall(ctx, state, stateid);
if (!err)
err = nfs_delegation_claim_locks(state, stateid);
- if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
+ if (!err && read_seqretry(&sp->so_reclaim_seqlock, seq))
err = -EAGAIN;
mutex_unlock(&sp->so_delegreturn_mutex);
put_nfs_open_context(ctx);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 05ed7be8a6345..5702b287e238f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -457,7 +457,7 @@ static
void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
{
struct qstr filename = QSTR_INIT(entry->name, entry->len);
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
struct dentry *dentry;
struct dentry *alias;
struct inode *dir = d_inode(parent);
@@ -1517,7 +1517,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned open_flags,
umode_t mode)
{
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
struct nfs_open_context *ctx;
struct dentry *res;
struct iattr attr = { .ia_valid = ATTR_OPEN };
@@ -1846,7 +1846,11 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
trace_nfs_rmdir_enter(dir, dentry);
if (d_really_is_positive(dentry)) {
+#ifdef CONFIG_PREEMPT_RT
+ down(&NFS_I(d_inode(dentry))->rmdir_sem);
+#else
down_write(&NFS_I(d_inode(dentry))->rmdir_sem);
+#endif
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
/* Ensure the VFS deletes this inode */
switch (error) {
@@ -1856,7 +1860,11 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
case -ENOENT:
nfs_dentry_handle_enoent(dentry);
}
+#ifdef CONFIG_PREEMPT_RT
+ up(&NFS_I(d_inode(dentry))->rmdir_sem);
+#else
up_write(&NFS_I(d_inode(dentry))->rmdir_sem);
+#endif
} else
error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
trace_nfs_rmdir_exit(dir, dentry, error);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2a03bfeec10a4..785e4c4aa8fd6 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -2105,7 +2105,11 @@ static void init_once(void *foo)
atomic_long_set(&nfsi->nrequests, 0);
atomic_long_set(&nfsi->commit_info.ncommit, 0);
atomic_set(&nfsi->commit_info.rpcs_out, 0);
+#ifdef CONFIG_PREEMPT_RT
+ sema_init(&nfsi->rmdir_sem, 1);
+#else
init_rwsem(&nfsi->rmdir_sem);
+#endif
mutex_init(&nfsi->commit_mutex);
nfs4_init_once(nfsi);
}
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index bb322d9de313b..68b8ccb53fe35 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -115,7 +115,7 @@ struct nfs4_state_owner {
unsigned long so_flags;
struct list_head so_states;
struct nfs_seqid_counter so_seqid;
- seqcount_t so_reclaim_seqcount;
+ seqlock_t so_reclaim_seqlock;
struct mutex so_delegreturn_mutex;
};
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 423960d480f10..a1d393fd27e06 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2965,7 +2965,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
unsigned int seq;
int ret;
- seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
+ seq = raw_seqcount_begin(&sp->so_reclaim_seqlock.seqcount);
ret = _nfs4_proc_open(opendata, ctx);
if (ret != 0)
@@ -3007,7 +3007,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
if (d_inode(dentry) == state->inode) {
nfs_inode_attach_open_context(ctx);
- if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
+ if (read_seqretry(&sp->so_reclaim_seqlock, seq))
nfs4_schedule_stateid_recovery(server, state);
}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index b53bcf40e2a77..bd7e6a2d2c24e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -508,7 +508,7 @@ nfs4_alloc_state_owner(struct nfs_server *server,
nfs4_init_seqid_counter(&sp->so_seqid);
atomic_set(&sp->so_count, 1);
INIT_LIST_HEAD(&sp->so_lru);
- seqcount_init(&sp->so_reclaim_seqcount);
+ seqlock_init(&sp->so_reclaim_seqlock);
mutex_init(&sp->so_delegreturn_mutex);
return sp;
}
@@ -1616,8 +1616,12 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
* recovering after a network partition or a reboot from a
* server that doesn't support a grace period.
*/
+#ifdef CONFIG_PREEMPT_RT
+ write_seqlock(&sp->so_reclaim_seqlock);
+#else
+ write_seqcount_begin(&sp->so_reclaim_seqlock.seqcount);
+#endif
spin_lock(&sp->so_lock);
- raw_write_seqcount_begin(&sp->so_reclaim_seqcount);
restart:
list_for_each_entry(state, &sp->so_states, open_states) {
if (!test_and_clear_bit(ops->state_flag_bit, &state->flags))
@@ -1678,14 +1682,20 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
spin_lock(&sp->so_lock);
goto restart;
}
- raw_write_seqcount_end(&sp->so_reclaim_seqcount);
spin_unlock(&sp->so_lock);
+#ifdef CONFIG_PREEMPT_RT
+ write_sequnlock(&sp->so_reclaim_seqlock);
+#else
+ write_seqcount_end(&sp->so_reclaim_seqlock.seqcount);
+#endif
return 0;
out_err:
nfs4_put_open_state(state);
- spin_lock(&sp->so_lock);
- raw_write_seqcount_end(&sp->so_reclaim_seqcount);
- spin_unlock(&sp->so_lock);
+#ifdef CONFIG_PREEMPT_RT
+ write_sequnlock(&sp->so_reclaim_seqlock);
+#else
+ write_seqcount_end(&sp->so_reclaim_seqlock.seqcount);
+#endif
return status;
}
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 0effeee28352f..efa5adce9b309 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -13,7 +13,7 @@
#include
#include
#include
-#include
+#include
#include
#include
@@ -53,6 +53,29 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
rpc_restart_call_prepare(task);
}
+#ifdef CONFIG_PREEMPT_RT
+static void nfs_down_anon(struct semaphore *sema)
+{
+ down(sema);
+}
+
+static void nfs_up_anon(struct semaphore *sema)
+{
+ up(sema);
+}
+
+#else
+static void nfs_down_anon(struct rw_semaphore *rwsem)
+{
+ down_read_non_owner(rwsem);
+}
+
+static void nfs_up_anon(struct rw_semaphore *rwsem)
+{
+ up_read_non_owner(rwsem);
+}
+#endif
+
/**
* nfs_async_unlink_release - Release the sillydelete data.
* @calldata: struct nfs_unlinkdata to release
@@ -66,7 +89,7 @@ static void nfs_async_unlink_release(void *calldata)
struct dentry *dentry = data->dentry;
struct super_block *sb = dentry->d_sb;
- up_read_non_owner(&NFS_I(d_inode(dentry->d_parent))->rmdir_sem);
+ nfs_up_anon(&NFS_I(d_inode(dentry->d_parent))->rmdir_sem);
d_lookup_done(dentry);
nfs_free_unlinkdata(data);
dput(dentry);
@@ -119,10 +142,10 @@ static int nfs_call_unlink(struct dentry *dentry, struct inode *inode, struct nf
struct inode *dir = d_inode(dentry->d_parent);
struct dentry *alias;
- down_read_non_owner(&NFS_I(dir)->rmdir_sem);
+ nfs_down_anon(&NFS_I(dir)->rmdir_sem);
alias = d_alloc_parallel(dentry->d_parent, &data->args.name, &data->wq);
if (IS_ERR(alias)) {
- up_read_non_owner(&NFS_I(dir)->rmdir_sem);
+ nfs_up_anon(&NFS_I(dir)->rmdir_sem);
return 0;
}
if (!d_in_lookup(alias)) {
@@ -144,7 +167,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct inode *inode, struct nf
ret = 0;
spin_unlock(&alias->d_lock);
dput(alias);
- up_read_non_owner(&NFS_I(dir)->rmdir_sem);
+ nfs_up_anon(&NFS_I(dir)->rmdir_sem);
/*
* If we'd displaced old cached devname, free it. At that
* point dentry is definitely not a root, so we won't need
@@ -180,7 +203,7 @@ nfs_async_unlink(struct dentry *dentry, const struct qstr *name)
data->cred = get_current_cred();
data->res.dir_attr = &data->dir_attr;
- init_waitqueue_head(&data->wq);
+ init_swait_queue_head(&data->wq);
status = -EBUSY;
spin_lock(&dentry->d_lock);
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 7202a1e39d70c..554b744f41bf8 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -92,8 +92,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
"0x%llx.", (unsigned long long)bh->b_blocknr);
}
first = page_buffers(page);
- local_irq_save(flags);
- bit_spin_lock(BH_Uptodate_Lock, &first->b_state);
+ spin_lock_irqsave(&first->b_uptodate_lock, flags);
clear_buffer_async_read(bh);
unlock_buffer(bh);
tmp = bh;
@@ -108,8 +107,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
}
tmp = tmp->b_this_page;
} while (tmp != bh);
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
/*
* If none of the buffers had errors then we can set the page uptodate,
* but we first have to perform the post read mst fixups, if the
@@ -142,8 +140,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
unlock_page(page);
return;
still_busy:
- bit_spin_unlock(BH_Uptodate_Lock, &first->b_state);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&first->b_uptodate_lock, flags);
return;
}
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 69c21a3843af8..4180c3ef0a68c 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -1252,6 +1252,7 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
int nr)
{
struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
+ struct journal_head *jh;
int ret;
if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap))
@@ -1260,13 +1261,14 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
if (!buffer_jbd(bg_bh))
return 1;
- jbd_lock_bh_state(bg_bh);
- bg = (struct ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data;
+ jh = bh2jh(bg_bh);
+ spin_lock(&jh->b_state_lock);
+ bg = (struct ocfs2_group_desc *) jh->b_committed_data;
if (bg)
ret = !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap);
else
ret = 1;
- jbd_unlock_bh_state(bg_bh);
+ spin_unlock(&jh->b_state_lock);
return ret;
}
@@ -2387,6 +2389,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
int status;
unsigned int tmp;
struct ocfs2_group_desc *undo_bg = NULL;
+ struct journal_head *jh;
/* The caller got this descriptor from
* ocfs2_read_group_descriptor(). Any corruption is a code bug. */
@@ -2405,10 +2408,10 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
goto bail;
}
+ jh = bh2jh(group_bh);
if (undo_fn) {
- jbd_lock_bh_state(group_bh);
- undo_bg = (struct ocfs2_group_desc *)
- bh2jh(group_bh)->b_committed_data;
+ spin_lock(&jh->b_state_lock);
+ undo_bg = (struct ocfs2_group_desc *) jh->b_committed_data;
BUG_ON(!undo_bg);
}
@@ -2423,7 +2426,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
le16_add_cpu(&bg->bg_free_bits_count, num_bits);
if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) {
if (undo_fn)
- jbd_unlock_bh_state(group_bh);
+ spin_unlock(&jh->b_state_lock);
return ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit count %u but claims %u are freed. num_bits %d\n",
(unsigned long long)le64_to_cpu(bg->bg_blkno),
le16_to_cpu(bg->bg_bits),
@@ -2432,7 +2435,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
}
if (undo_fn)
- jbd_unlock_bh_state(group_bh);
+ spin_unlock(&jh->b_state_lock);
ocfs2_journal_dirty(handle, group_bh);
bail:
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ebea9501afb84..2dcd8fb3abb58 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1891,7 +1891,7 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
child = d_hash_and_lookup(dir, &qname);
if (!child) {
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
child = d_alloc_parallel(dir, &qname, &wq);
if (IS_ERR(child))
goto end_instantiate;
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 4f4a2abb225eb..4e62963a87ca8 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -18,8 +18,6 @@
#include
#include
-extern wait_queue_head_t log_wait;
-
static int kmsg_open(struct inode * inode, struct file * file)
{
return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_PROC);
@@ -42,7 +40,7 @@ static ssize_t kmsg_read(struct file *file, char __user *buf,
static __poll_t kmsg_poll(struct file *file, poll_table *wait)
{
- poll_wait(file, &log_wait, wait);
+ poll_wait(file, printk_wait_queue(), wait);
if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC))
return EPOLLIN | EPOLLRDNORM;
return 0;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index d80989b6c3448..b5921f996e86d 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -702,7 +702,7 @@ static bool proc_sys_fill_cache(struct file *file,
child = d_lookup(dir, &qname);
if (!child) {
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
+ DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(wq);
child = d_alloc_parallel(dir, &qname, &wq);
if (IS_ERR(child))
return false;
diff --git a/fs/squashfs/decompressor_multi_percpu.c b/fs/squashfs/decompressor_multi_percpu.c
index 2a2a2d106440e..f8dd256763284 100644
--- a/fs/squashfs/decompressor_multi_percpu.c
+++ b/fs/squashfs/decompressor_multi_percpu.c
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
@@ -23,6 +24,8 @@ struct squashfs_stream {
void *stream;
};
+static DEFINE_LOCAL_IRQ_LOCK(stream_lock);
+
void *squashfs_decompressor_create(struct squashfs_sb_info *msblk,
void *comp_opts)
{
@@ -77,10 +80,15 @@ int squashfs_decompress(struct squashfs_sb_info *msblk, struct buffer_head **bh,
{
struct squashfs_stream __percpu *percpu =
(struct squashfs_stream __percpu *) msblk->stream;
- struct squashfs_stream *stream = get_cpu_ptr(percpu);
- int res = msblk->decompressor->decompress(msblk, stream->stream, bh, b,
- offset, length, output);
- put_cpu_ptr(stream);
+ struct squashfs_stream *stream;
+ int res;
+
+ stream = get_locked_ptr(stream_lock, percpu);
+
+ res = msblk->decompressor->decompress(msblk, stream->stream, bh, b,
+ offset, length, output);
+
+ put_locked_ptr(stream_lock, stream);
if (res < 0)
ERROR("%s decompression failed, data probably corrupt\n",
diff --git a/fs/stack.c b/fs/stack.c
index 4ef2c056269d5..c9830924eb125 100644
--- a/fs/stack.c
+++ b/fs/stack.c
@@ -23,7 +23,7 @@ void fsstack_copy_inode_size(struct inode *dst, struct inode *src)
/*
* But on 32-bit, we ought to make an effort to keep the two halves of
- * i_blocks in sync despite SMP or PREEMPT - though stat's
+ * i_blocks in sync despite SMP or PREEMPTION - though stat's
* generic_fillattr() doesn't bother, and we won't be applying quotas
* (where i_blocks does become important) at the upper level.
*
@@ -38,14 +38,14 @@ void fsstack_copy_inode_size(struct inode *dst, struct inode *src)
spin_unlock(&src->i_lock);
/*
- * If CONFIG_SMP or CONFIG_PREEMPT on 32-bit, it's vital for
+ * If CONFIG_SMP or CONFIG_PREEMPTION on 32-bit, it's vital for
* fsstack_copy_inode_size() to hold some lock around
* i_size_write(), otherwise i_size_read() may spin forever (see
* include/linux/fs.h). We don't necessarily hold i_mutex when this
* is called, so take i_lock for that case.
*
* And if on 32-bit, continue our effort to keep the two halves of
- * i_blocks in sync despite SMP or PREEMPT: use i_lock for that case
+ * i_blocks in sync despite SMP or PREEMPTION: use i_lock for that case
* too, and do both at once by combining the tests.
*
* There is none of this locking overhead in the 64-bit case.
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index d99d166fd8926..2deffbc812ee8 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -61,7 +61,7 @@ struct userfaultfd_ctx {
/* waitqueue head for events */
wait_queue_head_t event_wqh;
/* a refile sequence protected by fault_pending_wqh lock */
- struct seqcount refile_seq;
+ seqlock_t refile_seq;
/* pseudo fd refcounting */
refcount_t refcount;
/* userfaultfd syscall flags */
@@ -1063,7 +1063,7 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
* waitqueue could become empty if this is the
* only userfault.
*/
- write_seqcount_begin(&ctx->refile_seq);
+ write_seqlock(&ctx->refile_seq);
/*
* The fault_pending_wqh.lock prevents the uwq
@@ -1089,7 +1089,7 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
list_del(&uwq->wq.entry);
add_wait_queue(&ctx->fault_wqh, &uwq->wq);
- write_seqcount_end(&ctx->refile_seq);
+ write_sequnlock(&ctx->refile_seq);
/* careful to always initialize msg if ret == 0 */
*msg = uwq->msg;
@@ -1262,11 +1262,11 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
* sure we've userfaults to wake.
*/
do {
- seq = read_seqcount_begin(&ctx->refile_seq);
+ seq = read_seqbegin(&ctx->refile_seq);
need_wakeup = waitqueue_active(&ctx->fault_pending_wqh) ||
waitqueue_active(&ctx->fault_wqh);
cond_resched();
- } while (read_seqcount_retry(&ctx->refile_seq, seq));
+ } while (read_seqretry(&ctx->refile_seq, seq));
if (need_wakeup)
__wake_userfault(ctx, range);
}
@@ -1939,7 +1939,7 @@ static void init_once_userfaultfd_ctx(void *mem)
init_waitqueue_head(&ctx->fault_wqh);
init_waitqueue_head(&ctx->event_wqh);
init_waitqueue_head(&ctx->fd_wqh);
- seqcount_init(&ctx->refile_seq);
+ seqlock_init(&ctx->refile_seq);
}
SYSCALL_DEFINE1(userfaultfd, int, flags)
diff --git a/include/Kbuild b/include/Kbuild
new file mode 100644
index 0000000000000..95b4105a6186f
--- /dev/null
+++ b/include/Kbuild
@@ -0,0 +1,1192 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+# Add header-test-$(CONFIG_...) guard to headers that are only compiled
+# for particular architectures.
+#
+# Headers listed in header-test- are excluded from the test coverage.
+# Many headers are excluded for now because they fail to build. Please
+# consider to fix headers first before adding new ones to the blacklist.
+#
+# Sorted alphabetically.
+header-test- += acpi/acbuffer.h
+header-test- += acpi/acpi.h
+header-test- += acpi/acpi_bus.h
+header-test- += acpi/acpi_drivers.h
+header-test- += acpi/acpi_io.h
+header-test- += acpi/acpi_lpat.h
+header-test- += acpi/acpiosxf.h
+header-test- += acpi/acpixf.h
+header-test- += acpi/acrestyp.h
+header-test- += acpi/actbl.h
+header-test- += acpi/actbl1.h
+header-test- += acpi/actbl2.h
+header-test- += acpi/actbl3.h
+header-test- += acpi/actypes.h
+header-test- += acpi/battery.h
+header-test- += acpi/cppc_acpi.h
+header-test- += acpi/nfit.h
+header-test- += acpi/platform/acenv.h
+header-test- += acpi/platform/acenvex.h
+header-test- += acpi/platform/acintel.h
+header-test- += acpi/platform/aclinux.h
+header-test- += acpi/platform/aclinuxex.h
+header-test- += acpi/processor.h
+header-test-$(CONFIG_X86) += clocksource/hyperv_timer.h
+header-test- += clocksource/timer-sp804.h
+header-test- += crypto/cast_common.h
+header-test- += crypto/internal/cryptouser.h
+header-test- += crypto/pkcs7.h
+header-test- += crypto/poly1305.h
+header-test- += crypto/sha3.h
+header-test- += drm/ati_pcigart.h
+header-test- += drm/bridge/dw_hdmi.h
+header-test- += drm/bridge/dw_mipi_dsi.h
+header-test- += drm/drm_audio_component.h
+header-test- += drm/drm_auth.h
+header-test- += drm/drm_debugfs.h
+header-test- += drm/drm_debugfs_crc.h
+header-test- += drm/drm_displayid.h
+header-test- += drm/drm_encoder_slave.h
+header-test- += drm/drm_fb_cma_helper.h
+header-test- += drm/drm_fb_helper.h
+header-test- += drm/drm_fixed.h
+header-test- += drm/drm_format_helper.h
+header-test- += drm/drm_lease.h
+header-test- += drm/drm_legacy.h
+header-test- += drm/drm_panel.h
+header-test- += drm/drm_plane_helper.h
+header-test- += drm/drm_rect.h
+header-test- += drm/i915_component.h
+header-test- += drm/intel-gtt.h
+header-test- += drm/tinydrm/tinydrm-helpers.h
+header-test- += drm/ttm/ttm_debug.h
+header-test- += keys/asymmetric-parser.h
+header-test- += keys/asymmetric-subtype.h
+header-test- += keys/asymmetric-type.h
+header-test- += keys/big_key-type.h
+header-test- += keys/request_key_auth-type.h
+header-test- += keys/trusted.h
+header-test- += kvm/arm_arch_timer.h
+header-test- += kvm/arm_pmu.h
+header-test-$(CONFIG_ARM) += kvm/arm_psci.h
+header-test-$(CONFIG_ARM64) += kvm/arm_psci.h
+header-test- += kvm/arm_vgic.h
+header-test- += linux/8250_pci.h
+header-test- += linux/a.out.h
+header-test- += linux/adxl.h
+header-test- += linux/agpgart.h
+header-test- += linux/alcor_pci.h
+header-test- += linux/amba/clcd.h
+header-test- += linux/amba/pl080.h
+header-test- += linux/amd-iommu.h
+header-test-$(CONFIG_ARM) += linux/arm-cci.h
+header-test-$(CONFIG_ARM64) += linux/arm-cci.h
+header-test- += linux/arm_sdei.h
+header-test- += linux/asn1_decoder.h
+header-test- += linux/ata_platform.h
+header-test- += linux/ath9k_platform.h
+header-test- += linux/atm_tcp.h
+header-test- += linux/atomic-fallback.h
+header-test- += linux/avf/virtchnl.h
+header-test- += linux/bcm47xx_sprom.h
+header-test- += linux/bcma/bcma_driver_gmac_cmn.h
+header-test- += linux/bcma/bcma_driver_mips.h
+header-test- += linux/bcma/bcma_driver_pci.h
+header-test- += linux/bcma/bcma_driver_pcie2.h
+header-test- += linux/bit_spinlock.h
+header-test- += linux/blk-mq-rdma.h
+header-test- += linux/blk-mq.h
+header-test- += linux/blktrace_api.h
+header-test- += linux/blockgroup_lock.h
+header-test- += linux/bma150.h
+header-test- += linux/bpf_lirc.h
+header-test- += linux/bpf_types.h
+header-test- += linux/bsg-lib.h
+header-test- += linux/bsg.h
+header-test- += linux/btf.h
+header-test- += linux/btree-128.h
+header-test- += linux/btree-type.h
+header-test-$(CONFIG_CPU_BIG_ENDIAN) += linux/byteorder/big_endian.h
+header-test- += linux/byteorder/generic.h
+header-test-$(CONFIG_CPU_LITTLE_ENDIAN) += linux/byteorder/little_endian.h
+header-test- += linux/c2port.h
+header-test- += linux/can/dev/peak_canfd.h
+header-test- += linux/can/platform/cc770.h
+header-test- += linux/can/platform/sja1000.h
+header-test- += linux/ceph/ceph_features.h
+header-test- += linux/ceph/ceph_frag.h
+header-test- += linux/ceph/ceph_fs.h
+header-test- += linux/ceph/debugfs.h
+header-test- += linux/ceph/msgr.h
+header-test- += linux/ceph/rados.h
+header-test- += linux/cgroup_subsys.h
+header-test- += linux/clk/sunxi-ng.h
+header-test- += linux/clk/ti.h
+header-test- += linux/cn_proc.h
+header-test- += linux/coda_psdev.h
+header-test- += linux/compaction.h
+header-test- += linux/console_struct.h
+header-test- += linux/count_zeros.h
+header-test- += linux/cs5535.h
+header-test- += linux/cuda.h
+header-test- += linux/cyclades.h
+header-test- += linux/dcookies.h
+header-test- += linux/delayacct.h
+header-test- += linux/delayed_call.h
+header-test- += linux/device-mapper.h
+header-test- += linux/devpts_fs.h
+header-test- += linux/dio.h
+header-test- += linux/dirent.h
+header-test- += linux/dlm_plock.h
+header-test- += linux/dm-dirty-log.h
+header-test- += linux/dm-region-hash.h
+header-test- += linux/dma-debug.h
+header-test- += linux/dma/mmp-pdma.h
+header-test- += linux/dma/sprd-dma.h
+header-test- += linux/dns_resolver.h
+header-test- += linux/drbd_genl.h
+header-test- += linux/drbd_genl_api.h
+header-test- += linux/dw_apb_timer.h
+header-test- += linux/dynamic_debug.h
+header-test- += linux/dynamic_queue_limits.h
+header-test- += linux/ecryptfs.h
+header-test- += linux/edma.h
+header-test- += linux/eeprom_93cx6.h
+header-test- += linux/efs_vh.h
+header-test- += linux/elevator.h
+header-test- += linux/elfcore-compat.h
+header-test- += linux/error-injection.h
+header-test- += linux/errseq.h
+header-test- += linux/eventpoll.h
+header-test- += linux/ext2_fs.h
+header-test- += linux/f75375s.h
+header-test- += linux/falloc.h
+header-test- += linux/fault-inject.h
+header-test- += linux/fbcon.h
+header-test- += linux/firmware/intel/stratix10-svc-client.h
+header-test- += linux/firmware/meson/meson_sm.h
+header-test- += linux/firmware/trusted_foundations.h
+header-test- += linux/firmware/xlnx-zynqmp.h
+header-test- += linux/fixp-arith.h
+header-test- += linux/flat.h
+header-test- += linux/fs_types.h
+header-test- += linux/fs_uart_pd.h
+header-test- += linux/fsi-occ.h
+header-test- += linux/fsi-sbefifo.h
+header-test- += linux/fsl/bestcomm/ata.h
+header-test- += linux/fsl/bestcomm/bestcomm.h
+header-test- += linux/fsl/bestcomm/bestcomm_priv.h
+header-test- += linux/fsl/bestcomm/fec.h
+header-test- += linux/fsl/bestcomm/gen_bd.h
+header-test- += linux/fsl/bestcomm/sram.h
+header-test- += linux/fsl_hypervisor.h
+header-test- += linux/fsldma.h
+header-test- += linux/ftrace_irq.h
+header-test- += linux/gameport.h
+header-test- += linux/genl_magic_func.h
+header-test- += linux/genl_magic_struct.h
+header-test- += linux/gpio/aspeed.h
+header-test- += linux/gpio/gpio-reg.h
+header-test- += linux/hid-debug.h
+header-test- += linux/hiddev.h
+header-test- += linux/hippidevice.h
+header-test- += linux/hmm.h
+header-test- += linux/hp_sdc.h
+header-test- += linux/huge_mm.h
+header-test- += linux/hugetlb_cgroup.h
+header-test- += linux/hugetlb_inline.h
+header-test- += linux/hwmon-vid.h
+header-test- += linux/hyperv.h
+header-test- += linux/i2c-algo-pca.h
+header-test- += linux/i2c-algo-pcf.h
+header-test- += linux/i3c/ccc.h
+header-test- += linux/i3c/device.h
+header-test- += linux/i3c/master.h
+header-test- += linux/i8042.h
+header-test- += linux/ide.h
+header-test- += linux/idle_inject.h
+header-test- += linux/if_frad.h
+header-test- += linux/if_rmnet.h
+header-test- += linux/if_tap.h
+header-test- += linux/iio/accel/kxcjk_1013.h
+header-test- += linux/iio/adc/ad_sigma_delta.h
+header-test- += linux/iio/buffer-dma.h
+header-test- += linux/iio/buffer_impl.h
+header-test- += linux/iio/common/st_sensors.h
+header-test- += linux/iio/common/st_sensors_i2c.h
+header-test- += linux/iio/common/st_sensors_spi.h
+header-test- += linux/iio/dac/ad5421.h
+header-test- += linux/iio/dac/ad5504.h
+header-test- += linux/iio/dac/ad5791.h
+header-test- += linux/iio/dac/max517.h
+header-test- += linux/iio/dac/mcp4725.h
+header-test- += linux/iio/frequency/ad9523.h
+header-test- += linux/iio/frequency/adf4350.h
+header-test- += linux/iio/hw-consumer.h
+header-test- += linux/iio/imu/adis.h
+header-test- += linux/iio/sysfs.h
+header-test- += linux/iio/timer/stm32-timer-trigger.h
+header-test- += linux/iio/trigger.h
+header-test- += linux/iio/triggered_event.h
+header-test- += linux/imx-media.h
+header-test- += linux/inet_diag.h
+header-test- += linux/init_ohci1394_dma.h
+header-test- += linux/initrd.h
+header-test- += linux/input/adp5589.h
+header-test- += linux/input/bu21013.h
+header-test- += linux/input/cma3000.h
+header-test- += linux/input/kxtj9.h
+header-test- += linux/input/lm8333.h
+header-test- += linux/input/sparse-keymap.h
+header-test- += linux/input/touchscreen.h
+header-test- += linux/input/tps6507x-ts.h
+header-test-$(CONFIG_X86) += linux/intel-iommu.h
+header-test- += linux/intel-ish-client-if.h
+header-test- += linux/intel-pti.h
+header-test- += linux/intel-svm.h
+header-test- += linux/interconnect-provider.h
+header-test- += linux/ioc3.h
+header-test-$(CONFIG_BLOCK) += linux/iomap.h
+header-test- += linux/ipack.h
+header-test- += linux/irq_cpustat.h
+header-test- += linux/irq_poll.h
+header-test- += linux/irqchip/arm-gic-v3.h
+header-test- += linux/irqchip/arm-gic-v4.h
+header-test- += linux/irqchip/irq-madera.h
+header-test- += linux/irqchip/irq-sa11x0.h
+header-test- += linux/irqchip/mxs.h
+header-test- += linux/irqchip/versatile-fpga.h
+header-test- += linux/irqdesc.h
+header-test- += linux/irqflags.h
+header-test- += linux/iscsi_boot_sysfs.h
+header-test- += linux/isdn/capiutil.h
+header-test- += linux/isdn/hdlc.h
+header-test- += linux/isdn_ppp.h
+header-test- += linux/jbd2.h
+header-test- += linux/jump_label.h
+header-test- += linux/jump_label_ratelimit.h
+header-test- += linux/jz4740-adc.h
+header-test- += linux/kasan.h
+header-test- += linux/kcore.h
+header-test- += linux/kdev_t.h
+header-test- += linux/kernelcapi.h
+header-test- += linux/khugepaged.h
+header-test- += linux/kobj_map.h
+header-test- += linux/kobject_ns.h
+header-test- += linux/kvm_host.h
+header-test- += linux/kvm_irqfd.h
+header-test- += linux/kvm_para.h
+header-test- += linux/lantiq.h
+header-test- += linux/lapb.h
+header-test- += linux/latencytop.h
+header-test- += linux/led-lm3530.h
+header-test- += linux/leds-bd2802.h
+header-test- += linux/leds-lp3944.h
+header-test- += linux/leds-lp3952.h
+header-test- += linux/leds_pwm.h
+header-test- += linux/libata.h
+header-test- += linux/license.h
+header-test- += linux/lightnvm.h
+header-test- += linux/lis3lv02d.h
+header-test- += linux/list_bl.h
+header-test- += linux/list_lru.h
+header-test- += linux/list_nulls.h
+header-test- += linux/lockd/share.h
+header-test- += linux/lzo.h
+header-test- += linux/mailbox/zynqmp-ipi-message.h
+header-test- += linux/maple.h
+header-test- += linux/mbcache.h
+header-test- += linux/mbus.h
+header-test- += linux/mc146818rtc.h
+header-test- += linux/mc6821.h
+header-test- += linux/mdev.h
+header-test- += linux/mem_encrypt.h
+header-test- += linux/memfd.h
+header-test- += linux/mfd/88pm80x.h
+header-test- += linux/mfd/88pm860x.h
+header-test- += linux/mfd/abx500/ab8500-bm.h
+header-test- += linux/mfd/abx500/ab8500-gpadc.h
+header-test- += linux/mfd/adp5520.h
+header-test- += linux/mfd/arizona/pdata.h
+header-test- += linux/mfd/as3711.h
+header-test- += linux/mfd/as3722.h
+header-test- += linux/mfd/da903x.h
+header-test- += linux/mfd/da9055/pdata.h
+header-test- += linux/mfd/db8500-prcmu.h
+header-test- += linux/mfd/dbx500-prcmu.h
+header-test- += linux/mfd/dln2.h
+header-test- += linux/mfd/dm355evm_msp.h
+header-test- += linux/mfd/ds1wm.h
+header-test- += linux/mfd/ezx-pcap.h
+header-test- += linux/mfd/intel_msic.h
+header-test- += linux/mfd/janz.h
+header-test- += linux/mfd/kempld.h
+header-test- += linux/mfd/lm3533.h
+header-test- += linux/mfd/lp8788-isink.h
+header-test- += linux/mfd/lpc_ich.h
+header-test- += linux/mfd/max77693.h
+header-test- += linux/mfd/max8998-private.h
+header-test- += linux/mfd/menelaus.h
+header-test- += linux/mfd/mt6397/core.h
+header-test- += linux/mfd/palmas.h
+header-test- += linux/mfd/pcf50633/backlight.h
+header-test- += linux/mfd/rc5t583.h
+header-test- += linux/mfd/retu.h
+header-test- += linux/mfd/samsung/core.h
+header-test- += linux/mfd/si476x-platform.h
+header-test- += linux/mfd/si476x-reports.h
+header-test- += linux/mfd/sky81452.h
+header-test- += linux/mfd/smsc.h
+header-test- += linux/mfd/sta2x11-mfd.h
+header-test- += linux/mfd/stmfx.h
+header-test- += linux/mfd/tc3589x.h
+header-test- += linux/mfd/tc6387xb.h
+header-test- += linux/mfd/tc6393xb.h
+header-test- += linux/mfd/tps65090.h
+header-test- += linux/mfd/tps6586x.h
+header-test- += linux/mfd/tps65910.h
+header-test- += linux/mfd/tps80031.h
+header-test- += linux/mfd/ucb1x00.h
+header-test- += linux/mfd/viperboard.h
+header-test- += linux/mfd/wm831x/core.h
+header-test- += linux/mfd/wm831x/otp.h
+header-test- += linux/mfd/wm831x/pdata.h
+header-test- += linux/mfd/wm8994/core.h
+header-test- += linux/mfd/wm8994/pdata.h
+header-test- += linux/mlx4/doorbell.h
+header-test- += linux/mlx4/srq.h
+header-test- += linux/mlx5/doorbell.h
+header-test- += linux/mlx5/eq.h
+header-test- += linux/mlx5/fs_helpers.h
+header-test- += linux/mlx5/mlx5_ifc.h
+header-test- += linux/mlx5/mlx5_ifc_fpga.h
+header-test- += linux/mm-arch-hooks.h
+header-test- += linux/mm_inline.h
+header-test- += linux/mmu_context.h
+header-test- += linux/mpage.h
+header-test- += linux/mtd/bbm.h
+header-test- += linux/mtd/cfi.h
+header-test- += linux/mtd/doc2000.h
+header-test- += linux/mtd/flashchip.h
+header-test- += linux/mtd/ftl.h
+header-test- += linux/mtd/gen_probe.h
+header-test- += linux/mtd/jedec.h
+header-test- += linux/mtd/nand_bch.h
+header-test- += linux/mtd/nand_ecc.h
+header-test- += linux/mtd/ndfc.h
+header-test- += linux/mtd/onenand.h
+header-test- += linux/mtd/pismo.h
+header-test- += linux/mtd/plat-ram.h
+header-test- += linux/mtd/spi-nor.h
+header-test- += linux/mv643xx.h
+header-test- += linux/mv643xx_eth.h
+header-test- += linux/mvebu-pmsu.h
+header-test- += linux/mxm-wmi.h
+header-test- += linux/n_r3964.h
+header-test- += linux/ndctl.h
+header-test- += linux/nfs.h
+header-test- += linux/nfs_fs_i.h
+header-test- += linux/nfs_fs_sb.h
+header-test- += linux/nfs_page.h
+header-test- += linux/nfs_xdr.h
+header-test- += linux/nfsacl.h
+header-test- += linux/nl802154.h
+header-test- += linux/ns_common.h
+header-test- += linux/nsc_gpio.h
+header-test- += linux/ntb_transport.h
+header-test- += linux/nubus.h
+header-test- += linux/nvme-fc-driver.h
+header-test- += linux/nvme-fc.h
+header-test- += linux/nvme-rdma.h
+header-test- += linux/nvram.h
+header-test- += linux/objagg.h
+header-test- += linux/of_clk.h
+header-test- += linux/of_net.h
+header-test- += linux/of_pdt.h
+header-test- += linux/olpc-ec.h
+header-test- += linux/omap-dma.h
+header-test- += linux/omap-dmaengine.h
+header-test- += linux/omap-gpmc.h
+header-test- += linux/omap-iommu.h
+header-test- += linux/omap-mailbox.h
+header-test- += linux/once.h
+header-test- += linux/osq_lock.h
+header-test- += linux/overflow.h
+header-test- += linux/page-flags-layout.h
+header-test- += linux/page-isolation.h
+header-test- += linux/page_ext.h
+header-test- += linux/page_owner.h
+header-test- += linux/parport_pc.h
+header-test- += linux/parser.h
+header-test- += linux/pci-acpi.h
+header-test- += linux/pci-dma-compat.h
+header-test- += linux/pci_hotplug.h
+header-test- += linux/pda_power.h
+header-test- += linux/perf/arm_pmu.h
+header-test- += linux/perf_regs.h
+header-test- += linux/phy/omap_control_phy.h
+header-test- += linux/phy/tegra/xusb.h
+header-test- += linux/phy/ulpi_phy.h
+header-test- += linux/phy_fixed.h
+header-test- += linux/pipe_fs_i.h
+header-test- += linux/pktcdvd.h
+header-test- += linux/pl320-ipc.h
+header-test- += linux/pl353-smc.h
+header-test- += linux/platform_data/ad5449.h
+header-test- += linux/platform_data/ad5755.h
+header-test- += linux/platform_data/ad7266.h
+header-test- += linux/platform_data/ad7291.h
+header-test- += linux/platform_data/ad7298.h
+header-test- += linux/platform_data/ad7303.h
+header-test- += linux/platform_data/ad7791.h
+header-test- += linux/platform_data/ad7793.h
+header-test- += linux/platform_data/ad7887.h
+header-test- += linux/platform_data/adau17x1.h
+header-test- += linux/platform_data/adp8870.h
+header-test- += linux/platform_data/ads1015.h
+header-test- += linux/platform_data/ads7828.h
+header-test- += linux/platform_data/apds990x.h
+header-test- += linux/platform_data/arm-ux500-pm.h
+header-test- += linux/platform_data/asoc-s3c.h
+header-test- += linux/platform_data/at91_adc.h
+header-test- += linux/platform_data/ata-pxa.h
+header-test- += linux/platform_data/atmel.h
+header-test- += linux/platform_data/bh1770glc.h
+header-test- += linux/platform_data/brcmfmac.h
+header-test- += linux/platform_data/cros_ec_commands.h
+header-test- += linux/platform_data/clk-u300.h
+header-test- += linux/platform_data/cyttsp4.h
+header-test- += linux/platform_data/dma-coh901318.h
+header-test- += linux/platform_data/dma-imx-sdma.h
+header-test- += linux/platform_data/dma-mcf-edma.h
+header-test- += linux/platform_data/dma-s3c24xx.h
+header-test- += linux/platform_data/dmtimer-omap.h
+header-test- += linux/platform_data/dsa.h
+header-test- += linux/platform_data/edma.h
+header-test- += linux/platform_data/elm.h
+header-test- += linux/platform_data/emif_plat.h
+header-test- += linux/platform_data/fsa9480.h
+header-test- += linux/platform_data/g762.h
+header-test- += linux/platform_data/gpio-ath79.h
+header-test- += linux/platform_data/gpio-davinci.h
+header-test- += linux/platform_data/gpio-dwapb.h
+header-test- += linux/platform_data/gpio-htc-egpio.h
+header-test- += linux/platform_data/gpmc-omap.h
+header-test- += linux/platform_data/hsmmc-omap.h
+header-test- += linux/platform_data/hwmon-s3c.h
+header-test- += linux/platform_data/i2c-davinci.h
+header-test- += linux/platform_data/i2c-imx.h
+header-test- += linux/platform_data/i2c-mux-reg.h
+header-test- += linux/platform_data/i2c-ocores.h
+header-test- += linux/platform_data/i2c-xiic.h
+header-test- += linux/platform_data/intel-spi.h
+header-test- += linux/platform_data/invensense_mpu6050.h
+header-test- += linux/platform_data/irda-pxaficp.h
+header-test- += linux/platform_data/irda-sa11x0.h
+header-test- += linux/platform_data/itco_wdt.h
+header-test- += linux/platform_data/jz4740/jz4740_nand.h
+header-test- += linux/platform_data/keyboard-pxa930_rotary.h
+header-test- += linux/platform_data/keypad-omap.h
+header-test- += linux/platform_data/leds-lp55xx.h
+header-test- += linux/platform_data/leds-omap.h
+header-test- += linux/platform_data/lp855x.h
+header-test- += linux/platform_data/lp8727.h
+header-test- += linux/platform_data/max197.h
+header-test- += linux/platform_data/max3421-hcd.h
+header-test- += linux/platform_data/max732x.h
+header-test- += linux/platform_data/mcs.h
+header-test- += linux/platform_data/mdio-bcm-unimac.h
+header-test- += linux/platform_data/mdio-gpio.h
+header-test- += linux/platform_data/media/si4713.h
+header-test- += linux/platform_data/mlxreg.h
+header-test- += linux/platform_data/mmc-omap.h
+header-test- += linux/platform_data/mmc-sdhci-s3c.h
+header-test- += linux/platform_data/mmp_audio.h
+header-test- += linux/platform_data/mtd-orion_nand.h
+header-test- += linux/platform_data/mv88e6xxx.h
+header-test- += linux/platform_data/net-cw1200.h
+header-test- += linux/platform_data/omap-twl4030.h
+header-test- += linux/platform_data/omapdss.h
+header-test- += linux/platform_data/pcf857x.h
+header-test- += linux/platform_data/pixcir_i2c_ts.h
+header-test- += linux/platform_data/pwm_omap_dmtimer.h
+header-test- += linux/platform_data/pxa2xx_udc.h
+header-test- += linux/platform_data/pxa_sdhci.h
+header-test- += linux/platform_data/remoteproc-omap.h
+header-test- += linux/platform_data/sa11x0-serial.h
+header-test- += linux/platform_data/sc18is602.h
+header-test- += linux/platform_data/sdhci-pic32.h
+header-test- += linux/platform_data/serial-sccnxp.h
+header-test- += linux/platform_data/sht3x.h
+header-test- += linux/platform_data/shtc1.h
+header-test- += linux/platform_data/si5351.h
+header-test- += linux/platform_data/sky81452-backlight.h
+header-test- += linux/platform_data/spi-davinci.h
+header-test- += linux/platform_data/spi-ep93xx.h
+header-test- += linux/platform_data/spi-mt65xx.h
+header-test- += linux/platform_data/st_sensors_pdata.h
+header-test- += linux/platform_data/ti-sysc.h
+header-test- += linux/platform_data/timer-ixp4xx.h
+header-test- += linux/platform_data/touchscreen-s3c2410.h
+header-test- += linux/platform_data/tsc2007.h
+header-test- += linux/platform_data/tsl2772.h
+header-test- += linux/platform_data/uio_pruss.h
+header-test- += linux/platform_data/usb-davinci.h
+header-test- += linux/platform_data/usb-ehci-mxc.h
+header-test- += linux/platform_data/usb-ehci-orion.h
+header-test- += linux/platform_data/usb-mx2.h
+header-test- += linux/platform_data/usb-ohci-s3c2410.h
+header-test- += linux/platform_data/usb-omap.h
+header-test- += linux/platform_data/usb-s3c2410_udc.h
+header-test- += linux/platform_data/usb3503.h
+header-test- += linux/platform_data/ux500_wdt.h
+header-test- += linux/platform_data/video-clcd-versatile.h
+header-test- += linux/platform_data/video-imxfb.h
+header-test- += linux/platform_data/video-pxafb.h
+header-test- += linux/platform_data/video_s3c.h
+header-test- += linux/platform_data/voltage-omap.h
+header-test- += linux/platform_data/x86/apple.h
+header-test- += linux/platform_data/x86/clk-pmc-atom.h
+header-test- += linux/platform_data/x86/pmc_atom.h
+header-test- += linux/platform_data/xtalk-bridge.h
+header-test- += linux/pm2301_charger.h
+header-test- += linux/pm_wakeirq.h
+header-test- += linux/pm_wakeup.h
+header-test- += linux/pmbus.h
+header-test- += linux/pmu.h
+header-test- += linux/posix_acl.h
+header-test- += linux/posix_acl_xattr.h
+header-test- += linux/power/ab8500.h
+header-test- += linux/power/bq27xxx_battery.h
+header-test- += linux/power/generic-adc-battery.h
+header-test- += linux/power/jz4740-battery.h
+header-test- += linux/power/max17042_battery.h
+header-test- += linux/power/max8903_charger.h
+header-test- += linux/ppp-comp.h
+header-test- += linux/pps-gpio.h
+header-test- += linux/pr.h
+header-test- += linux/proc_ns.h
+header-test- += linux/processor.h
+header-test- += linux/psi.h
+header-test- += linux/psp-sev.h
+header-test- += linux/pstore.h
+header-test- += linux/ptr_ring.h
+header-test- += linux/ptrace.h
+header-test- += linux/qcom-geni-se.h
+header-test- += linux/qed/eth_common.h
+header-test- += linux/qed/fcoe_common.h
+header-test- += linux/qed/iscsi_common.h
+header-test- += linux/qed/iwarp_common.h
+header-test- += linux/qed/qed_eth_if.h
+header-test- += linux/qed/qed_fcoe_if.h
+header-test- += linux/qed/rdma_common.h
+header-test- += linux/qed/storage_common.h
+header-test- += linux/qed/tcp_common.h
+header-test- += linux/qnx6_fs.h
+header-test- += linux/quicklist.h
+header-test- += linux/ramfs.h
+header-test- += linux/range.h
+header-test- += linux/rcu_node_tree.h
+header-test- += linux/rculist_bl.h
+header-test- += linux/rculist_nulls.h
+header-test- += linux/rcutiny.h
+header-test- += linux/rcutree.h
+header-test- += linux/reboot-mode.h
+header-test- += linux/regulator/fixed.h
+header-test- += linux/regulator/gpio-regulator.h
+header-test- += linux/regulator/max8973-regulator.h
+header-test- += linux/regulator/of_regulator.h
+header-test- += linux/regulator/tps51632-regulator.h
+header-test- += linux/regulator/tps62360.h
+header-test- += linux/regulator/tps6507x.h
+header-test- += linux/regulator/userspace-consumer.h
+header-test- += linux/remoteproc/st_slim_rproc.h
+header-test- += linux/reset/socfpga.h
+header-test- += linux/reset/sunxi.h
+header-test- += linux/rtc/m48t59.h
+header-test- += linux/rtc/rtc-omap.h
+header-test- += linux/rtc/sirfsoc_rtciobrg.h
+header-test- += linux/rwlock.h
+header-test- += linux/rwlock_types.h
+header-test- += linux/scc.h
+header-test- += linux/sched/deadline.h
+header-test- += linux/sched/smt.h
+header-test- += linux/sched/sysctl.h
+header-test- += linux/sched_clock.h
+header-test- += linux/scpi_protocol.h
+header-test- += linux/scx200_gpio.h
+header-test- += linux/seccomp.h
+header-test- += linux/sed-opal.h
+header-test- += linux/seg6_iptunnel.h
+header-test- += linux/selection.h
+header-test- += linux/set_memory.h
+header-test- += linux/shrinker.h
+header-test- += linux/sirfsoc_dma.h
+header-test- += linux/skb_array.h
+header-test- += linux/slab_def.h
+header-test- += linux/slub_def.h
+header-test- += linux/sm501.h
+header-test- += linux/smc91x.h
+header-test- += linux/static_key.h
+header-test- += linux/soc/actions/owl-sps.h
+header-test- += linux/soc/amlogic/meson-canvas.h
+header-test- += linux/soc/brcmstb/brcmstb.h
+header-test- += linux/soc/ixp4xx/npe.h
+header-test- += linux/soc/mediatek/infracfg.h
+header-test- += linux/soc/qcom/smd-rpm.h
+header-test- += linux/soc/qcom/smem.h
+header-test- += linux/soc/qcom/smem_state.h
+header-test- += linux/soc/qcom/wcnss_ctrl.h
+header-test- += linux/soc/renesas/rcar-rst.h
+header-test- += linux/soc/samsung/exynos-pmu.h
+header-test- += linux/soc/sunxi/sunxi_sram.h
+header-test- += linux/soc/ti/ti-msgmgr.h
+header-test- += linux/soc/ti/ti_sci_inta_msi.h
+header-test- += linux/soc/ti/ti_sci_protocol.h
+header-test- += linux/soundwire/sdw.h
+header-test- += linux/soundwire/sdw_intel.h
+header-test- += linux/soundwire/sdw_type.h
+header-test- += linux/spi/ad7877.h
+header-test- += linux/spi/ads7846.h
+header-test- += linux/spi/at86rf230.h
+header-test- += linux/spi/ds1305.h
+header-test- += linux/spi/libertas_spi.h
+header-test- += linux/spi/lms283gf05.h
+header-test- += linux/spi/max7301.h
+header-test- += linux/spi/mcp23s08.h
+header-test- += linux/spi/rspi.h
+header-test- += linux/spi/s3c24xx.h
+header-test- += linux/spi/sh_msiof.h
+header-test- += linux/spi/spi-fsl-dspi.h
+header-test- += linux/spi/spi_bitbang.h
+header-test- += linux/spi/spi_gpio.h
+header-test- += linux/spi/xilinx_spi.h
+header-test- += linux/spinlock_api_smp.h
+header-test- += linux/spinlock_api_up.h
+header-test- += linux/spinlock_types.h
+header-test- += linux/splice.h
+header-test- += linux/sram.h
+header-test- += linux/srcutiny.h
+header-test- += linux/srcutree.h
+header-test- += linux/ssb/ssb_driver_chipcommon.h
+header-test- += linux/ssb/ssb_driver_extif.h
+header-test- += linux/ssb/ssb_driver_mips.h
+header-test- += linux/ssb/ssb_driver_pci.h
+header-test- += linux/ssbi.h
+header-test- += linux/stackdepot.h
+header-test- += linux/stmp3xxx_rtc_wdt.h
+header-test- += linux/string_helpers.h
+header-test- += linux/sungem_phy.h
+header-test- += linux/sunrpc/msg_prot.h
+header-test- += linux/sunrpc/rpc_pipe_fs.h
+header-test- += linux/sunrpc/xprtmultipath.h
+header-test- += linux/sunrpc/xprtsock.h
+header-test- += linux/sunxi-rsb.h
+header-test- += linux/svga.h
+header-test- += linux/sw842.h
+header-test- += linux/swapfile.h
+header-test- += linux/swapops.h
+header-test- += linux/swiotlb.h
+header-test- += linux/sysv_fs.h
+header-test- += linux/t10-pi.h
+header-test- += linux/task_io_accounting.h
+header-test- += linux/tick.h
+header-test- += linux/timb_dma.h
+header-test- += linux/timekeeping.h
+header-test- += linux/timekeeping32.h
+header-test- += linux/ts-nbus.h
+header-test- += linux/tsacct_kern.h
+header-test- += linux/tty_flip.h
+header-test- += linux/tty_ldisc.h
+header-test- += linux/ucb1400.h
+header-test- += linux/usb/association.h
+header-test- += linux/usb/cdc-wdm.h
+header-test- += linux/usb/cdc_ncm.h
+header-test- += linux/usb/ezusb.h
+header-test- += linux/usb/gadget_configfs.h
+header-test- += linux/usb/gpio_vbus.h
+header-test- += linux/usb/hcd.h
+header-test- += linux/usb/iowarrior.h
+header-test- += linux/usb/irda.h
+header-test- += linux/usb/isp116x.h
+header-test- += linux/usb/isp1362.h
+header-test- += linux/usb/musb.h
+header-test- += linux/usb/net2280.h
+header-test- += linux/usb/ohci_pdriver.h
+header-test- += linux/usb/otg-fsm.h
+header-test- += linux/usb/pd_ado.h
+header-test- += linux/usb/r8a66597.h
+header-test- += linux/usb/rndis_host.h
+header-test- += linux/usb/serial.h
+header-test- += linux/usb/sl811.h
+header-test- += linux/usb/storage.h
+header-test- += linux/usb/uas.h
+header-test- += linux/usb/usb338x.h
+header-test- += linux/usb/usbnet.h
+header-test- += linux/usb/wusb-wa.h
+header-test- += linux/usb/xhci-dbgp.h
+header-test- += linux/usb_usual.h
+header-test- += linux/user-return-notifier.h
+header-test- += linux/userfaultfd_k.h
+header-test- += linux/verification.h
+header-test- += linux/vgaarb.h
+header-test- += linux/via_core.h
+header-test- += linux/via_i2c.h
+header-test- += linux/virtio_byteorder.h
+header-test- += linux/virtio_ring.h
+header-test- += linux/visorbus.h
+header-test- += linux/vme.h
+header-test- += linux/vmstat.h
+header-test- += linux/vmw_vmci_api.h
+header-test- += linux/vmw_vmci_defs.h
+header-test- += linux/vringh.h
+header-test- += linux/vt_buffer.h
+header-test- += linux/zorro.h
+header-test- += linux/zpool.h
+header-test- += math-emu/double.h
+header-test- += math-emu/op-common.h
+header-test- += math-emu/quad.h
+header-test- += math-emu/single.h
+header-test- += math-emu/soft-fp.h
+header-test- += media/davinci/dm355_ccdc.h
+header-test- += media/davinci/dm644x_ccdc.h
+header-test- += media/davinci/isif.h
+header-test- += media/davinci/vpbe_osd.h
+header-test- += media/davinci/vpbe_types.h
+header-test- += media/davinci/vpif_types.h
+header-test- += media/demux.h
+header-test- += media/drv-intf/soc_mediabus.h
+header-test- += media/dvb_net.h
+header-test- += media/fwht-ctrls.h
+header-test- += media/i2c/ad9389b.h
+header-test- += media/i2c/adv7343.h
+header-test- += media/i2c/adv7511.h
+header-test- += media/i2c/adv7842.h
+header-test- += media/i2c/m5mols.h
+header-test- += media/i2c/mt9m032.h
+header-test- += media/i2c/mt9t112.h
+header-test- += media/i2c/mt9v032.h
+header-test- += media/i2c/ov2659.h
+header-test- += media/i2c/ov7670.h
+header-test- += media/i2c/rj54n1cb0c.h
+header-test- += media/i2c/saa6588.h
+header-test- += media/i2c/saa7115.h
+header-test- += media/i2c/sr030pc30.h
+header-test- += media/i2c/tc358743.h
+header-test- += media/i2c/tda1997x.h
+header-test- += media/i2c/ths7303.h
+header-test- += media/i2c/tvaudio.h
+header-test- += media/i2c/tvp514x.h
+header-test- += media/i2c/tvp7002.h
+header-test- += media/i2c/wm8775.h
+header-test- += media/imx.h
+header-test- += media/media-dev-allocator.h
+header-test- += media/mpeg2-ctrls.h
+header-test- += media/rcar-fcp.h
+header-test- += media/tuner-types.h
+header-test- += media/tveeprom.h
+header-test- += media/v4l2-flash-led-class.h
+header-test- += misc/altera.h
+header-test- += misc/cxl-base.h
+header-test- += misc/cxllib.h
+header-test- += net/9p/9p.h
+header-test- += net/9p/client.h
+header-test- += net/9p/transport.h
+header-test- += net/af_vsock.h
+header-test- += net/ax88796.h
+header-test- += net/bluetooth/hci.h
+header-test- += net/bluetooth/hci_core.h
+header-test- += net/bluetooth/hci_mon.h
+header-test- += net/bluetooth/hci_sock.h
+header-test- += net/bluetooth/l2cap.h
+header-test- += net/bluetooth/mgmt.h
+header-test- += net/bluetooth/rfcomm.h
+header-test- += net/bluetooth/sco.h
+header-test- += net/bond_options.h
+header-test- += net/caif/cfsrvl.h
+header-test- += net/codel_impl.h
+header-test- += net/codel_qdisc.h
+header-test- += net/compat.h
+header-test- += net/datalink.h
+header-test- += net/dcbevent.h
+header-test- += net/dcbnl.h
+header-test- += net/dn_dev.h
+header-test- += net/dn_fib.h
+header-test- += net/dn_neigh.h
+header-test- += net/dn_nsp.h
+header-test- += net/dn_route.h
+header-test- += net/erspan.h
+header-test- += net/esp.h
+header-test- += net/ethoc.h
+header-test- += net/firewire.h
+header-test- += net/flow_offload.h
+header-test- += net/fq.h
+header-test- += net/fq_impl.h
+header-test- += net/garp.h
+header-test- += net/gtp.h
+header-test- += net/gue.h
+header-test- += net/hwbm.h
+header-test- += net/ila.h
+header-test- += net/inet6_connection_sock.h
+header-test- += net/inet_common.h
+header-test- += net/inet_frag.h
+header-test- += net/ip6_route.h
+header-test- += net/ip_vs.h
+header-test- += net/ipcomp.h
+header-test- += net/ipconfig.h
+header-test- += net/iucv/af_iucv.h
+header-test- += net/iucv/iucv.h
+header-test- += net/lapb.h
+header-test- += net/llc_c_ac.h
+header-test- += net/llc_c_st.h
+header-test- += net/llc_s_ac.h
+header-test- += net/llc_s_ev.h
+header-test- += net/llc_s_st.h
+header-test- += net/mpls_iptunnel.h
+header-test- += net/mrp.h
+header-test- += net/ncsi.h
+header-test- += net/netevent.h
+header-test- += net/netns/can.h
+header-test- += net/netns/generic.h
+header-test- += net/netns/ieee802154_6lowpan.h
+header-test- += net/netns/ipv4.h
+header-test- += net/netns/ipv6.h
+header-test- += net/netns/mpls.h
+header-test- += net/netns/nftables.h
+header-test- += net/netns/sctp.h
+header-test- += net/netrom.h
+header-test- += net/p8022.h
+header-test- += net/phonet/pep.h
+header-test- += net/phonet/phonet.h
+header-test- += net/phonet/pn_dev.h
+header-test- += net/pptp.h
+header-test- += net/psample.h
+header-test- += net/psnap.h
+header-test- += net/regulatory.h
+header-test- += net/rose.h
+header-test- += net/sctp/auth.h
+header-test- += net/sctp/stream_interleave.h
+header-test- += net/sctp/stream_sched.h
+header-test- += net/sctp/tsnmap.h
+header-test- += net/sctp/ulpevent.h
+header-test- += net/sctp/ulpqueue.h
+header-test- += net/secure_seq.h
+header-test- += net/smc.h
+header-test- += net/stp.h
+header-test- += net/transp_v6.h
+header-test- += net/tun_proto.h
+header-test- += net/udplite.h
+header-test- += net/xdp.h
+header-test- += net/xdp_priv.h
+header-test- += pcmcia/cistpl.h
+header-test- += pcmcia/ds.h
+header-test- += rdma/tid_rdma_defs.h
+header-test- += scsi/fc/fc_encaps.h
+header-test- += scsi/fc/fc_fc2.h
+header-test- += scsi/fc/fc_fcoe.h
+header-test- += scsi/fc/fc_fip.h
+header-test- += scsi/fc_encode.h
+header-test- += scsi/fc_frame.h
+header-test- += scsi/iser.h
+header-test- += scsi/libfc.h
+header-test- += scsi/libfcoe.h
+header-test- += scsi/libsas.h
+header-test- += scsi/sas_ata.h
+header-test- += scsi/scsi_cmnd.h
+header-test- += scsi/scsi_dbg.h
+header-test- += scsi/scsi_device.h
+header-test- += scsi/scsi_dh.h
+header-test- += scsi/scsi_eh.h
+header-test- += scsi/scsi_host.h
+header-test- += scsi/scsi_ioctl.h
+header-test- += scsi/scsi_request.h
+header-test- += scsi/scsi_tcq.h
+header-test- += scsi/scsi_transport.h
+header-test- += scsi/scsi_transport_fc.h
+header-test- += scsi/scsi_transport_sas.h
+header-test- += scsi/scsi_transport_spi.h
+header-test- += scsi/scsi_transport_srp.h
+header-test- += scsi/scsicam.h
+header-test- += scsi/sg.h
+header-test- += soc/arc/aux.h
+header-test- += soc/arc/mcip.h
+header-test- += soc/arc/timers.h
+header-test- += soc/brcmstb/common.h
+header-test- += soc/fsl/bman.h
+header-test- += soc/fsl/qe/qe.h
+header-test- += soc/fsl/qe/qe_ic.h
+header-test- += soc/fsl/qe/qe_tdm.h
+header-test- += soc/fsl/qe/ucc.h
+header-test- += soc/fsl/qe/ucc_fast.h
+header-test- += soc/fsl/qe/ucc_slow.h
+header-test- += soc/fsl/qman.h
+header-test- += soc/nps/common.h
+header-test-$(CONFIG_ARC) += soc/nps/mtm.h
+header-test- += soc/qcom/cmd-db.h
+header-test- += soc/qcom/rpmh.h
+header-test- += soc/qcom/tcs.h
+header-test- += soc/tegra/ahb.h
+header-test- += soc/tegra/bpmp-abi.h
+header-test- += soc/tegra/common.h
+header-test- += soc/tegra/flowctrl.h
+header-test- += soc/tegra/fuse.h
+header-test- += soc/tegra/mc.h
+header-test- += sound/ac97/compat.h
+header-test- += sound/aci.h
+header-test- += sound/ad1843.h
+header-test- += sound/adau1373.h
+header-test- += sound/ak4113.h
+header-test- += sound/ak4114.h
+header-test- += sound/ak4117.h
+header-test- += sound/cs35l33.h
+header-test- += sound/cs35l34.h
+header-test- += sound/cs35l35.h
+header-test- += sound/cs35l36.h
+header-test- += sound/cs4271.h
+header-test- += sound/cs42l52.h
+header-test- += sound/cs8427.h
+header-test- += sound/da7218.h
+header-test- += sound/da7219-aad.h
+header-test- += sound/da7219.h
+header-test- += sound/da9055.h
+header-test- += sound/emu8000.h
+header-test- += sound/emux_synth.h
+header-test- += sound/hda_component.h
+header-test- += sound/hda_hwdep.h
+header-test- += sound/hda_i915.h
+header-test- += sound/hwdep.h
+header-test- += sound/i2c.h
+header-test- += sound/l3.h
+header-test- += sound/max98088.h
+header-test- += sound/max98095.h
+header-test- += sound/mixer_oss.h
+header-test- += sound/omap-hdmi-audio.h
+header-test- += sound/pcm_drm_eld.h
+header-test- += sound/pcm_iec958.h
+header-test- += sound/pcm_oss.h
+header-test- += sound/pxa2xx-lib.h
+header-test- += sound/rt286.h
+header-test- += sound/rt298.h
+header-test- += sound/rt5645.h
+header-test- += sound/rt5659.h
+header-test- += sound/rt5660.h
+header-test- += sound/rt5665.h
+header-test- += sound/rt5670.h
+header-test- += sound/s3c24xx_uda134x.h
+header-test- += sound/seq_device.h
+header-test- += sound/seq_kernel.h
+header-test- += sound/seq_midi_emul.h
+header-test- += sound/seq_oss.h
+header-test- += sound/soc-acpi-intel-match.h
+header-test- += sound/soc-dai.h
+header-test- += sound/soc-dapm.h
+header-test- += sound/soc-dpcm.h
+header-test- += sound/sof/control.h
+header-test- += sound/sof/dai-intel.h
+header-test- += sound/sof/dai.h
+header-test- += sound/sof/header.h
+header-test- += sound/sof/info.h
+header-test- += sound/sof/pm.h
+header-test- += sound/sof/stream.h
+header-test- += sound/sof/topology.h
+header-test- += sound/sof/trace.h
+header-test- += sound/sof/xtensa.h
+header-test- += sound/spear_spdif.h
+header-test- += sound/sta32x.h
+header-test- += sound/sta350.h
+header-test- += sound/tea6330t.h
+header-test- += sound/tlv320aic32x4.h
+header-test- += sound/tlv320dac33-plat.h
+header-test- += sound/uda134x.h
+header-test- += sound/wavefront.h
+header-test- += sound/wm8903.h
+header-test- += sound/wm8904.h
+header-test- += sound/wm8960.h
+header-test- += sound/wm8962.h
+header-test- += sound/wm8993.h
+header-test- += sound/wm8996.h
+header-test- += sound/wm9081.h
+header-test- += sound/wm9090.h
+header-test- += target/iscsi/iscsi_target_stat.h
+header-test- += trace/bpf_probe.h
+header-test- += trace/events/9p.h
+header-test- += trace/events/afs.h
+header-test- += trace/events/asoc.h
+header-test- += trace/events/bcache.h
+header-test- += trace/events/block.h
+header-test- += trace/events/cachefiles.h
+header-test- += trace/events/cgroup.h
+header-test- += trace/events/clk.h
+header-test- += trace/events/cma.h
+header-test- += trace/events/ext4.h
+header-test- += trace/events/f2fs.h
+header-test- += trace/events/fs_dax.h
+header-test- += trace/events/fscache.h
+header-test- += trace/events/fsi.h
+header-test- += trace/events/fsi_master_ast_cf.h
+header-test- += trace/events/fsi_master_gpio.h
+header-test- += trace/events/huge_memory.h
+header-test- += trace/events/ib_mad.h
+header-test- += trace/events/ib_umad.h
+header-test- += trace/events/iscsi.h
+header-test- += trace/events/jbd2.h
+header-test- += trace/events/kvm.h
+header-test- += trace/events/kyber.h
+header-test- += trace/events/libata.h
+header-test- += trace/events/mce.h
+header-test- += trace/events/mdio.h
+header-test- += trace/events/migrate.h
+header-test- += trace/events/mmflags.h
+header-test- += trace/events/nbd.h
+header-test- += trace/events/nilfs2.h
+header-test- += trace/events/pwc.h
+header-test- += trace/events/rdma.h
+header-test- += trace/events/rpcgss.h
+header-test- += trace/events/rpcrdma.h
+header-test- += trace/events/rxrpc.h
+header-test- += trace/events/scsi.h
+header-test- += trace/events/siox.h
+header-test- += trace/events/spi.h
+header-test- += trace/events/swiotlb.h
+header-test- += trace/events/syscalls.h
+header-test- += trace/events/target.h
+header-test- += trace/events/thermal_power_allocator.h
+header-test- += trace/events/timer.h
+header-test- += trace/events/wbt.h
+header-test- += trace/events/xen.h
+header-test- += trace/perf.h
+header-test- += trace/trace_events.h
+header-test- += uapi/drm/vmwgfx_drm.h
+header-test- += uapi/linux/a.out.h
+header-test- += uapi/linux/coda.h
+header-test- += uapi/linux/coda_psdev.h
+header-test- += uapi/linux/errqueue.h
+header-test- += uapi/linux/eventpoll.h
+header-test- += uapi/linux/hdlc/ioctl.h
+header-test- += uapi/linux/input.h
+header-test- += uapi/linux/kvm.h
+header-test- += uapi/linux/kvm_para.h
+header-test- += uapi/linux/lightnvm.h
+header-test- += uapi/linux/mic_common.h
+header-test- += uapi/linux/mman.h
+header-test- += uapi/linux/nilfs2_ondisk.h
+header-test- += uapi/linux/patchkey.h
+header-test- += uapi/linux/ptrace.h
+header-test- += uapi/linux/scc.h
+header-test- += uapi/linux/seg6_iptunnel.h
+header-test- += uapi/linux/smc_diag.h
+header-test- += uapi/linux/timex.h
+header-test- += uapi/linux/videodev2.h
+header-test- += uapi/scsi/scsi_bsg_fc.h
+header-test- += uapi/sound/asound.h
+header-test- += uapi/sound/sof/eq.h
+header-test- += uapi/sound/sof/fw.h
+header-test- += uapi/sound/sof/header.h
+header-test- += uapi/sound/sof/manifest.h
+header-test- += uapi/sound/sof/trace.h
+header-test- += uapi/xen/evtchn.h
+header-test- += uapi/xen/gntdev.h
+header-test- += uapi/xen/privcmd.h
+header-test- += vdso/vsyscall.h
+header-test- += video/broadsheetfb.h
+header-test- += video/cvisionppc.h
+header-test- += video/gbe.h
+header-test- += video/kyro.h
+header-test- += video/maxinefb.h
+header-test- += video/metronomefb.h
+header-test- += video/neomagic.h
+header-test- += video/of_display_timing.h
+header-test- += video/omapvrfb.h
+header-test- += video/s1d13xxxfb.h
+header-test- += video/sstfb.h
+header-test- += video/tgafb.h
+header-test- += video/udlfb.h
+header-test- += video/uvesafb.h
+header-test- += video/vga.h
+header-test- += video/w100fb.h
+header-test- += xen/acpi.h
+header-test- += xen/arm/hypercall.h
+header-test- += xen/arm/page-coherent.h
+header-test- += xen/arm/page.h
+header-test- += xen/balloon.h
+header-test- += xen/events.h
+header-test- += xen/features.h
+header-test- += xen/grant_table.h
+header-test- += xen/hvm.h
+header-test- += xen/interface/callback.h
+header-test- += xen/interface/event_channel.h
+header-test- += xen/interface/grant_table.h
+header-test- += xen/interface/hvm/dm_op.h
+header-test- += xen/interface/hvm/hvm_op.h
+header-test- += xen/interface/hvm/hvm_vcpu.h
+header-test- += xen/interface/hvm/params.h
+header-test- += xen/interface/hvm/start_info.h
+header-test- += xen/interface/io/9pfs.h
+header-test- += xen/interface/io/blkif.h
+header-test- += xen/interface/io/console.h
+header-test- += xen/interface/io/displif.h
+header-test- += xen/interface/io/fbif.h
+header-test- += xen/interface/io/kbdif.h
+header-test- += xen/interface/io/netif.h
+header-test- += xen/interface/io/pciif.h
+header-test- += xen/interface/io/protocols.h
+header-test- += xen/interface/io/pvcalls.h
+header-test- += xen/interface/io/ring.h
+header-test- += xen/interface/io/sndif.h
+header-test- += xen/interface/io/tpmif.h
+header-test- += xen/interface/io/vscsiif.h
+header-test- += xen/interface/io/xs_wire.h
+header-test- += xen/interface/memory.h
+header-test- += xen/interface/nmi.h
+header-test- += xen/interface/physdev.h
+header-test- += xen/interface/platform.h
+header-test- += xen/interface/sched.h
+header-test- += xen/interface/vcpu.h
+header-test- += xen/interface/version.h
+header-test- += xen/interface/xen-mca.h
+header-test- += xen/interface/xen.h
+header-test- += xen/interface/xenpmu.h
+header-test- += xen/mem-reservation.h
+header-test- += xen/page.h
+header-test- += xen/platform_pci.h
+header-test- += xen/swiotlb-xen.h
+header-test- += xen/xen-front-pgdir-shbuf.h
+header-test- += xen/xen-ops.h
+header-test- += xen/xen.h
+header-test- += xen/xenbus.h
+
+# Do not include directly
+header-test- += linux/compiler-clang.h
+header-test- += linux/compiler-gcc.h
+header-test- += linux/mutex_rt.h
+header-test- += linux/patchkey.h
+header-test- += linux/rwlock_api_smp.h
+header-test- += linux/rwlock_rt.h
+header-test- += linux/rwlock_types_rt.h
+header-test- += linux/rwsem-rt.h
+header-test- += linux/spinlock_rt.h
+header-test- += linux/spinlock_types_nort.h
+header-test- += linux/spinlock_types_rt.h
+header-test- += linux/spinlock_types_up.h
+header-test- += linux/spinlock_up.h
+header-test- += linux/wimax/debug.h
+header-test- += rdma/uverbs_named_ioctl.h
+
+# asm-generic/*.h is used by asm/*.h, and should not be included directly
+header-test- += asm-generic/% uapi/asm-generic/%
+
+# Timestamp files touched by Kconfig
+header-test- += config/%
+
+# Timestamp files touched by scripts/adjust_autoksyms.sh
+header-test- += ksym/%
+
+# You could compile-test these, but maybe not so useful...
+header-test- += dt-bindings/%
+
+# Do not test generated headers. Stale headers are often left over when you
+# traverse the git history without cleaning.
+header-test- += generated/%
+
+# The rest are compile-tested
+header-test-pattern-y += */*.h */*/*.h */*/*/*.h */*/*/*/*.h
diff --git a/include/linux/bottom_half.h b/include/linux/bottom_half.h
index a19519f4241dc..ef2366a65ba2a 100644
--- a/include/linux/bottom_half.h
+++ b/include/linux/bottom_half.h
@@ -4,6 +4,10 @@
#include
+#ifdef CONFIG_PREEMPT_RT
+extern void __local_bh_disable_ip(unsigned long ip, unsigned int cnt);
+#else
+
#ifdef CONFIG_TRACE_IRQFLAGS
extern void __local_bh_disable_ip(unsigned long ip, unsigned int cnt);
#else
@@ -13,6 +17,7 @@ static __always_inline void __local_bh_disable_ip(unsigned long ip, unsigned int
barrier();
}
#endif
+#endif
static inline void local_bh_disable(void)
{
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 3bf3835d0e866..3e6744c7122d6 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -541,7 +541,7 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array,
struct bpf_prog *_prog; \
struct bpf_prog_array *_array; \
u32 _ret = 1; \
- preempt_disable(); \
+ migrate_disable(); \
rcu_read_lock(); \
_array = rcu_dereference(array); \
if (unlikely(check_non_null && !_array))\
@@ -554,7 +554,7 @@ int bpf_prog_array_copy(struct bpf_prog_array *old_array,
} \
_out: \
rcu_read_unlock(); \
- preempt_enable(); \
+ migrate_enable(); \
_ret; \
})
@@ -588,7 +588,7 @@ _out: \
u32 ret; \
u32 _ret = 1; \
u32 _cn = 0; \
- preempt_disable(); \
+ migrate_disable(); \
rcu_read_lock(); \
_array = rcu_dereference(array); \
_item = &_array->items[0]; \
@@ -600,7 +600,7 @@ _out: \
_item++; \
} \
rcu_read_unlock(); \
- preempt_enable(); \
+ migrate_enable(); \
if (_ret) \
_ret = (_cn ? NET_XMIT_CN : NET_XMIT_SUCCESS); \
else \
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 7b73ef7f902d4..e0b020eaf32e2 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -22,9 +22,6 @@ enum bh_state_bits {
BH_Dirty, /* Is dirty */
BH_Lock, /* Is locked */
BH_Req, /* Has been submitted for I/O */
- BH_Uptodate_Lock,/* Used by the first bh in a page, to serialise
- * IO completion of other buffers in the page
- */
BH_Mapped, /* Has a disk mapping */
BH_New, /* Disk mapping was newly created by get_block */
@@ -76,6 +73,9 @@ struct buffer_head {
struct address_space *b_assoc_map; /* mapping this buffer is
associated with */
atomic_t b_count; /* users using this buffer_head */
+ spinlock_t b_uptodate_lock; /* Used by the first bh in a page, to
+ * serialise IO completion of other
+ * buffers in the page */
};
/*
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index 430e219e3abaf..5708205542bf8 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -144,9 +144,6 @@ struct cgroup_subsys_state {
struct list_head sibling;
struct list_head children;
- /* flush target list anchored at cgrp->rstat_css_list */
- struct list_head rstat_css_node;
-
/*
* PI: Subsys-unique ID. 0 is unused and root is always 1. The
* matching css can be looked up using css_from_id().
@@ -455,7 +452,6 @@ struct cgroup {
/* per-cpu recursive resource statistics */
struct cgroup_rstat_cpu __percpu *rstat_cpu;
- struct list_head rstat_css_list;
/* cgroup basic resource statistics */
struct cgroup_base_stat pending_bstat; /* pending from children */
@@ -633,7 +629,6 @@ struct cgroup_subsys {
void (*css_released)(struct cgroup_subsys_state *css);
void (*css_free)(struct cgroup_subsys_state *css);
void (*css_reset)(struct cgroup_subsys_state *css);
- void (*css_rstat_flush)(struct cgroup_subsys_state *css, int cpu);
int (*css_extra_stat_show)(struct seq_file *seq,
struct cgroup_subsys_state *css);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 3ba3e6da13a6f..affa3798c9f52 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -750,9 +750,6 @@ static inline void cgroup_path_from_kernfs_id(const union kernfs_node_id *id,
*/
void cgroup_rstat_updated(struct cgroup *cgrp, int cpu);
void cgroup_rstat_flush(struct cgroup *cgrp);
-void cgroup_rstat_flush_irqsafe(struct cgroup *cgrp);
-void cgroup_rstat_flush_hold(struct cgroup *cgrp);
-void cgroup_rstat_flush_release(void);
/*
* Basic resource stats.
diff --git a/include/linux/completion.h b/include/linux/completion.h
index 519e94915d185..bf8e77001f18f 100644
--- a/include/linux/completion.h
+++ b/include/linux/completion.h
@@ -9,7 +9,7 @@
* See kernel/sched/completion.c for details.
*/
-#include
+#include
/*
* struct completion - structure used to maintain state for a "completion"
@@ -25,7 +25,7 @@
*/
struct completion {
unsigned int done;
- wait_queue_head_t wait;
+ struct swait_queue_head wait;
};
#define init_completion_map(x, m) __init_completion(x)
@@ -34,7 +34,7 @@ static inline void complete_acquire(struct completion *x) {}
static inline void complete_release(struct completion *x) {}
#define COMPLETION_INITIALIZER(work) \
- { 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
+ { 0, __SWAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
#define COMPLETION_INITIALIZER_ONSTACK_MAP(work, map) \
(*({ init_completion_map(&(work), &(map)); &(work); }))
@@ -85,7 +85,7 @@ static inline void complete_release(struct completion *x) {}
static inline void __init_completion(struct completion *x)
{
x->done = 0;
- init_waitqueue_head(&x->wait);
+ init_swait_queue_head(&x->wait);
}
/**
diff --git a/include/linux/console.h b/include/linux/console.h
index d09951d5a94e4..39d1bb43b4f25 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -145,6 +145,7 @@ static inline int con_debug_leave(void)
struct console {
char name[16];
void (*write)(struct console *, const char *, unsigned);
+ void (*write_atomic)(struct console *, const char *, unsigned);
int (*read)(struct console *, char *, unsigned);
struct tty_driver *(*device)(struct console *, int *);
void (*unblank)(void);
@@ -153,6 +154,8 @@ struct console {
short flags;
short index;
int cflag;
+ unsigned long printk_seq;
+ int wrote_history;
void *data;
struct console *next;
};
@@ -234,4 +237,7 @@ extern void console_init(void);
void dummycon_register_output_notifier(struct notifier_block *nb);
void dummycon_unregister_output_notifier(struct notifier_block *nb);
+extern void console_atomic_lock(unsigned int *flags);
+extern void console_atomic_unlock(unsigned int flags);
+
#endif /* _LINUX_CONSOLE_H */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 10090f11ab954..ac021d808c71d 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -106,7 +106,7 @@ struct dentry {
union {
struct list_head d_lru; /* LRU list */
- wait_queue_head_t *d_wait; /* in-lookup ones only */
+ struct swait_queue_head *d_wait; /* in-lookup ones only */
};
struct list_head d_child; /* child of parent list */
struct list_head d_subdirs; /* our children */
@@ -236,7 +236,7 @@ extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op
extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
extern struct dentry * d_alloc_anon(struct super_block *);
extern struct dentry * d_alloc_parallel(struct dentry *, const struct qstr *,
- wait_queue_head_t *);
+ struct swait_queue_head *);
extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
extern struct dentry * d_exact_alias(struct dentry *, struct inode *);
diff --git a/include/linux/delay.h b/include/linux/delay.h
index 8e6828094c1ee..7f2df975a53e2 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -65,4 +65,10 @@ static inline void ssleep(unsigned int seconds)
msleep(seconds * 1000);
}
+#ifdef CONFIG_PREEMPT_RT
+extern void cpu_chill(void);
+#else
+# define cpu_chill() cpu_relax()
+#endif
+
#endif /* defined(_LINUX_DELAY_H) */
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index ee50d10f052b5..81272ca122ee5 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -65,13 +65,13 @@ struct dma_resv_list {
/**
* struct dma_resv - a reservation object manages fences for a buffer
* @lock: update side lock
- * @seq: sequence count for managing RCU read-side synchronization
+ * @seq: sequence lock for managing RCU read-side synchronization
* @fence_excl: the exclusive fence, if there is one currently
* @fence: list of current shared fences
*/
struct dma_resv {
struct ww_mutex lock;
- seqcount_t seq;
+ seqlock_t seq;
struct dma_fence __rcu *fence_excl;
struct dma_resv_list __rcu *fence;
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 0367a75f873b6..76ce2dcb52cba 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -555,7 +555,7 @@ DECLARE_STATIC_KEY_FALSE(bpf_stats_enabled_key);
#define BPF_PROG_RUN(prog, ctx) ({ \
u32 ret; \
- cant_sleep(); \
+ cant_migrate(); \
if (static_branch_unlikely(&bpf_stats_enabled_key)) { \
struct bpf_prog_stats *stats; \
u64 start = sched_clock(); \
@@ -570,6 +570,24 @@ DECLARE_STATIC_KEY_FALSE(bpf_stats_enabled_key);
} \
ret; })
+/*
+ * Use in preemptible and therefore /migratable context to make sure that
+ * the execution of the BPF program runs on one CPU.
+ *
+ * This uses migrate_disable/enable() explicitely to document that the
+ * invocation of a BPF program does not require reentrancy protection
+ * against a BPF program which is invoked from a preempting task.
+ *
+ * For non enabled RT kernels migrate_disable/enable() maps to
+ * preempt_disable/enable(), i.e. it disables also preemption.
+ */
+#define BPF_PROG_RUN_PIN_ON_CPU(prog, ctx) ({ \
+ u32 ret; \
+ migrate_disable(); \
+ ret = BPF_PROG_RUN(prog, ctx); \
+ migrate_enable(); \
+ ret; })
+
#define BPF_SKB_CB_LEN QDISC_CB_PRIV_LEN
struct bpf_skb_data_end {
@@ -647,6 +665,7 @@ static inline u8 *bpf_skb_cb(struct sk_buff *skb)
return qdisc_skb_cb(skb)->data;
}
+/* Must be invoked with migration disabled */
static inline u32 __bpf_prog_run_save_cb(const struct bpf_prog *prog,
struct sk_buff *skb)
{
@@ -672,9 +691,9 @@ static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
{
u32 res;
- preempt_disable();
+ migrate_disable();
res = __bpf_prog_run_save_cb(prog, skb);
- preempt_enable();
+ migrate_enable();
return res;
}
@@ -687,9 +706,7 @@ static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog,
if (unlikely(prog->cb_access))
memset(cb_data, 0, BPF_SKB_CB_LEN);
- preempt_disable();
- res = BPF_PROG_RUN(prog, skb);
- preempt_enable();
+ res = BPF_PROG_RUN_PIN_ON_CPU(prog, skb);
return res;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0b4d8fc79e0f3..ab03c913559c3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -716,7 +716,7 @@ struct inode {
struct block_device *i_bdev;
struct cdev *i_cdev;
char *i_link;
- unsigned i_dir_seq;
+ unsigned __i_dir_seq;
};
__u32 i_generation;
@@ -855,7 +855,7 @@ static inline loff_t i_size_read(const struct inode *inode)
i_size = inode->i_size;
} while (read_seqcount_retry(&inode->i_size_seqcount, seq));
return i_size;
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
loff_t i_size;
preempt_disable();
@@ -880,7 +880,7 @@ static inline void i_size_write(struct inode *inode, loff_t i_size)
inode->i_size = i_size;
write_seqcount_end(&inode->i_size_seqcount);
preempt_enable();
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
preempt_disable();
inode->i_size = i_size;
preempt_enable();
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index ad044c0cb1f3b..164bfe4d207d0 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -226,6 +226,7 @@ extern void __fscache_readpages_cancel(struct fscache_cookie *cookie,
extern void __fscache_disable_cookie(struct fscache_cookie *, const void *, bool);
extern void __fscache_enable_cookie(struct fscache_cookie *, const void *, loff_t,
bool (*)(void *), void *);
+extern void fscache_cookie_init(void);
/**
* fscache_register_netfs - Register a filesystem as desiring caching services
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 8b5330dd5ac09..c1583357e9cd4 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -717,7 +717,7 @@ static inline void hd_free_part(struct hd_struct *part)
* accessor function.
*
* Code written along the lines of i_size_read() and i_size_write().
- * CONFIG_PREEMPT case optimizes the case of UP kernel with preemption
+ * CONFIG_PREEMPTION case optimizes the case of UP kernel with preemption
* on.
*/
static inline sector_t part_nr_sects_read(struct hd_struct *part)
@@ -730,7 +730,7 @@ static inline sector_t part_nr_sects_read(struct hd_struct *part)
nr_sects = part->nr_sects;
} while (read_seqcount_retry(&part->nr_sects_seq, seq));
return nr_sects;
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
sector_t nr_sects;
preempt_disable();
@@ -753,7 +753,7 @@ static inline void part_nr_sects_write(struct hd_struct *part, sector_t size)
write_seqcount_begin(&part->nr_sects_seq);
part->nr_sects = size;
write_seqcount_end(&part->nr_sects_seq);
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
preempt_disable();
part->nr_sects = size;
preempt_enable();
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 61f2f6ff94673..6ce61770ef343 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -580,6 +580,7 @@ extern void page_frag_free(void *addr);
void page_alloc_init(void);
void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp);
void drain_all_pages(struct zone *zone);
+void drain_cpu_pages(unsigned int cpu, struct zone *zone);
void drain_local_pages(struct zone *zone);
void page_alloc_init_late(void);
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index da0af631ded5b..8d7bb3c0ff061 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -68,7 +68,6 @@ extern void irq_exit(void);
#define nmi_enter() \
do { \
arch_nmi_enter(); \
- printk_nmi_enter(); \
lockdep_off(); \
ftrace_nmi_enter(); \
BUG_ON(in_nmi()); \
@@ -85,7 +84,6 @@ extern void irq_exit(void);
preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \
ftrace_nmi_exit(); \
lockdep_on(); \
- printk_nmi_exit(); \
arch_nmi_exit(); \
} while (0)
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index ea5cdbd8c2c32..4191b158c66a0 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
@@ -90,7 +91,7 @@ static inline void kunmap(struct page *page)
static inline void *kmap_atomic(struct page *page)
{
- preempt_disable();
+ preempt_disable_nort();
pagefault_disable();
return page_address(page);
}
@@ -99,7 +100,7 @@ static inline void *kmap_atomic(struct page *page)
static inline void __kunmap_atomic(void *addr)
{
pagefault_enable();
- preempt_enable();
+ preempt_enable_nort();
}
#define kmap_atomic_pfn(pfn) kmap_atomic(pfn_to_page(pfn))
@@ -111,32 +112,51 @@ static inline void __kunmap_atomic(void *addr)
#if defined(CONFIG_HIGHMEM) || defined(CONFIG_X86_32)
+#ifndef CONFIG_PREEMPT_RT
DECLARE_PER_CPU(int, __kmap_atomic_idx);
+#endif
static inline int kmap_atomic_idx_push(void)
{
+#ifndef CONFIG_PREEMPT_RT
int idx = __this_cpu_inc_return(__kmap_atomic_idx) - 1;
-#ifdef CONFIG_DEBUG_HIGHMEM
+# ifdef CONFIG_DEBUG_HIGHMEM
WARN_ON_ONCE(in_irq() && !irqs_disabled());
BUG_ON(idx >= KM_TYPE_NR);
-#endif
+# endif
return idx;
+#else
+ current->kmap_idx++;
+ BUG_ON(current->kmap_idx > KM_TYPE_NR);
+ return current->kmap_idx - 1;
+#endif
}
static inline int kmap_atomic_idx(void)
{
+#ifndef CONFIG_PREEMPT_RT
return __this_cpu_read(__kmap_atomic_idx) - 1;
+#else
+ return current->kmap_idx - 1;
+#endif
}
static inline void kmap_atomic_idx_pop(void)
{
-#ifdef CONFIG_DEBUG_HIGHMEM
+#ifndef CONFIG_PREEMPT_RT
+# ifdef CONFIG_DEBUG_HIGHMEM
int idx = __this_cpu_dec_return(__kmap_atomic_idx);
BUG_ON(idx < 0);
-#else
+# else
__this_cpu_dec(__kmap_atomic_idx);
+# endif
+#else
+ current->kmap_idx--;
+# ifdef CONFIG_DEBUG_HIGHMEM
+ BUG_ON(current->kmap_idx < 0);
+# endif
#endif
}
diff --git a/include/linux/idr.h b/include/linux/idr.h
index ac6e946b6767b..839da8f2f6f13 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -169,10 +169,7 @@ static inline bool idr_is_empty(const struct idr *idr)
* Each idr_preload() should be matched with an invocation of this
* function. See idr_preload() for details.
*/
-static inline void idr_preload_end(void)
-{
- preempt_enable();
-}
+void idr_preload_end(void);
/**
* idr_for_each_entry() - Iterate over an IDR's elements of a given type.
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 89fc59dab57d2..029042f474c69 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -546,7 +546,7 @@ struct softirq_action
asmlinkage void do_softirq(void);
asmlinkage void __do_softirq(void);
-#ifdef __ARCH_HAS_DO_SOFTIRQ
+#if defined(__ARCH_HAS_DO_SOFTIRQ) && !defined(CONFIG_PREEMPT_RT)
void do_softirq_own_stack(void);
#else
static inline void do_softirq_own_stack(void)
@@ -561,6 +561,7 @@ extern void __raise_softirq_irqoff(unsigned int nr);
extern void raise_softirq_irqoff(unsigned int nr);
extern void raise_softirq(unsigned int nr);
+extern void softirq_check_pending_idle(void);
DECLARE_PER_CPU(struct task_struct *, ksoftirqd);
@@ -625,7 +626,10 @@ static inline void tasklet_unlock(struct tasklet_struct *t)
static inline void tasklet_unlock_wait(struct tasklet_struct *t)
{
- while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); }
+ while (test_bit(TASKLET_STATE_RUN, &(t)->state)) {
+ local_bh_disable();
+ local_bh_enable();
+ }
}
#else
#define tasklet_trylock(t) 1
diff --git a/include/linux/irq_work.h b/include/linux/irq_work.h
index b11fcdfd07707..2964f4526f79e 100644
--- a/include/linux/irq_work.h
+++ b/include/linux/irq_work.h
@@ -18,6 +18,8 @@
/* Doesn't want IPI, wait for tick: */
#define IRQ_WORK_LAZY BIT(2)
+/* Run hard IRQ context, even on RT */
+#define IRQ_WORK_HARD_IRQ BIT(3)
#define IRQ_WORK_CLAIMED (IRQ_WORK_PENDING | IRQ_WORK_BUSY)
@@ -52,4 +54,10 @@ static inline bool irq_work_needs_cpu(void) { return false; }
static inline void irq_work_run(void) { }
#endif
+#if defined(CONFIG_IRQ_WORK) && defined(CONFIG_PREEMPT_RT)
+void irq_work_tick_soft(void);
+#else
+static inline void irq_work_tick_soft(void) { }
+#endif
+
#endif /* _LINUX_IRQ_WORK_H */
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index d6e2ab538ef27..1e7fc375c36da 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -72,6 +72,7 @@ struct irq_desc {
unsigned int irqs_unhandled;
atomic_t threads_handled;
int threads_handled_last;
+ u64 random_ip;
raw_spinlock_t lock;
struct cpumask *percpu_enabled;
const struct cpumask *percpu_affinity;
diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
index 21619c92c3770..5304de2f78386 100644
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -43,14 +43,6 @@ do { \
do { \
current->hardirq_context--; \
} while (0)
-# define lockdep_softirq_enter() \
-do { \
- current->softirq_context++; \
-} while (0)
-# define lockdep_softirq_exit() \
-do { \
- current->softirq_context--; \
-} while (0)
#else
# define trace_hardirqs_on() do { } while (0)
# define trace_hardirqs_off() do { } while (0)
@@ -64,6 +56,21 @@ do { \
# define lockdep_softirq_exit() do { } while (0)
#endif
+#if defined(CONFIG_TRACE_IRQFLAGS) && !defined(CONFIG_PREEMPT_RT)
+# define lockdep_softirq_enter() \
+do { \
+ current->softirq_context++; \
+} while (0)
+# define lockdep_softirq_exit() \
+do { \
+ current->softirq_context--; \
+} while (0)
+
+#else
+# define lockdep_softirq_enter() do { } while (0)
+# define lockdep_softirq_exit() do { } while (0)
+#endif
+
#if defined(CONFIG_IRQSOFF_TRACER) || \
defined(CONFIG_PREEMPT_TRACER)
extern void stop_critical_timings(void);
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 10e6049c0ba91..b56dbe515ad73 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -313,7 +313,6 @@ enum jbd_state_bits {
BH_Revoked, /* Has been revoked from the log */
BH_RevokeValid, /* Revoked flag is valid */
BH_JBDDirty, /* Is dirty but journaled */
- BH_State, /* Pins most journal_head state */
BH_JournalHead, /* Pins bh->b_private and jh->b_bh */
BH_Shadow, /* IO on shadow buffer is running */
BH_Verified, /* Metadata block has been verified ok */
@@ -342,26 +341,6 @@ static inline struct journal_head *bh2jh(struct buffer_head *bh)
return bh->b_private;
}
-static inline void jbd_lock_bh_state(struct buffer_head *bh)
-{
- bit_spin_lock(BH_State, &bh->b_state);
-}
-
-static inline int jbd_trylock_bh_state(struct buffer_head *bh)
-{
- return bit_spin_trylock(BH_State, &bh->b_state);
-}
-
-static inline int jbd_is_locked_bh_state(struct buffer_head *bh)
-{
- return bit_spin_is_locked(BH_State, &bh->b_state);
-}
-
-static inline void jbd_unlock_bh_state(struct buffer_head *bh)
-{
- bit_spin_unlock(BH_State, &bh->b_state);
-}
-
static inline void jbd_lock_bh_journal_head(struct buffer_head *bh)
{
bit_spin_lock(BH_JournalHead, &bh->b_state);
@@ -556,9 +535,9 @@ struct transaction_chp_stats_s {
* ->jbd_lock_bh_journal_head() (This is "innermost")
*
* j_state_lock
- * ->jbd_lock_bh_state()
+ * ->b_state_lock
*
- * jbd_lock_bh_state()
+ * b_state_lock
* ->j_list_lock
*
* j_state_lock
@@ -1257,7 +1236,7 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3)
/* Filing buffers */
extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *);
-extern void __jbd2_journal_refile_buffer(struct journal_head *);
+extern bool __jbd2_journal_refile_buffer(struct journal_head *);
extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *);
extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int);
extern void __journal_free_buffer(struct journal_head *bh);
diff --git a/include/linux/journal-head.h b/include/linux/journal-head.h
index 9fb8705243145..75bc56109031f 100644
--- a/include/linux/journal-head.h
+++ b/include/linux/journal-head.h
@@ -11,6 +11,8 @@
#ifndef JOURNAL_HEAD_H_INCLUDED
#define JOURNAL_HEAD_H_INCLUDED
+#include
+
typedef unsigned int tid_t; /* Unique transaction ID */
typedef struct transaction_s transaction_t; /* Compound transaction type */
@@ -23,6 +25,11 @@ struct journal_head {
*/
struct buffer_head *b_bh;
+ /*
+ * Protect the buffer head state
+ */
+ spinlock_t b_state_lock;
+
/*
* Reference count - see description in journal.c
* [jbd_lock_bh_journal_head()]
@@ -30,7 +37,7 @@ struct journal_head {
int b_jcount;
/*
- * Journalling list for this buffer [jbd_lock_bh_state()]
+ * Journalling list for this buffer [b_state_lock]
* NOTE: We *cannot* combine this with b_modified into a bitfield
* as gcc would then (which the C standard allows but which is
* very unuseful) make 64-bit accesses to the bitfield and clobber
@@ -41,20 +48,20 @@ struct journal_head {
/*
* This flag signals the buffer has been modified by
* the currently running transaction
- * [jbd_lock_bh_state()]
+ * [b_state_lock]
*/
unsigned b_modified;
/*
* Copy of the buffer data frozen for writing to the log.
- * [jbd_lock_bh_state()]
+ * [b_state_lock]
*/
char *b_frozen_data;
/*
* Pointer to a saved copy of the buffer containing no uncommitted
* deallocation references, so that allocations can avoid overwriting
- * uncommitted deletes. [jbd_lock_bh_state()]
+ * uncommitted deletes. [b_state_lock]
*/
char *b_committed_data;
@@ -63,7 +70,7 @@ struct journal_head {
* metadata: either the running transaction or the committing
* transaction (if there is one). Only applies to buffers on a
* transaction's data or metadata journaling list.
- * [j_list_lock] [jbd_lock_bh_state()]
+ * [j_list_lock] [b_state_lock]
* Either of these locks is enough for reading, both are needed for
* changes.
*/
@@ -73,13 +80,13 @@ struct journal_head {
* Pointer to the running compound transaction which is currently
* modifying the buffer's metadata, if there was already a transaction
* committing it when the new transaction touched it.
- * [t_list_lock] [jbd_lock_bh_state()]
+ * [t_list_lock] [b_state_lock]
*/
transaction_t *b_next_transaction;
/*
* Doubly-linked list of buffers on a transaction's data, metadata or
- * forget queue. [t_list_lock] [jbd_lock_bh_state()]
+ * forget queue. [t_list_lock] [b_state_lock]
*/
struct journal_head *b_tnext, *b_tprev;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 52a10f9bb4836..3b5cb7cc29b08 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -228,6 +228,10 @@ extern void __cant_sleep(const char *file, int line, int preempt_offset);
*/
# define might_sleep() \
do { __might_sleep(__FILE__, __LINE__, 0); might_resched(); } while (0)
+
+# define might_sleep_no_state_check() \
+ do { ___might_sleep(__FILE__, __LINE__, 0); might_resched(); } while (0)
+
/**
* cant_sleep - annotation for functions that cannot sleep
*
@@ -259,6 +263,7 @@ extern void __cant_sleep(const char *file, int line, int preempt_offset);
static inline void __might_sleep(const char *file, int line,
int preempt_offset) { }
# define might_sleep() do { might_resched(); } while (0)
+# define might_sleep_no_state_check() do { might_resched(); } while (0)
# define cant_sleep() do { } while (0)
# define sched_annotate_sleep() do { } while (0)
# define non_block_start() do { } while (0)
@@ -267,6 +272,13 @@ extern void __cant_sleep(const char *file, int line, int preempt_offset);
#define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0)
+#ifndef CONFIG_PREEMPT_RT
+# define cant_migrate() cant_sleep()
+#else
+ /* Placeholder for now */
+# define cant_migrate() do { } while (0)
+#endif
+
/**
* abs - return absolute value of an argument
* @x: the value. If it is unsigned type, it is converted to signed type first.
diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h
index 2e7a1e032c71a..ede5066663b92 100644
--- a/include/linux/kmsg_dump.h
+++ b/include/linux/kmsg_dump.h
@@ -46,10 +46,8 @@ struct kmsg_dumper {
bool registered;
/* private state of the kmsg iterator */
- u32 cur_idx;
- u32 next_idx;
- u64 cur_seq;
- u64 next_seq;
+ u64 line_seq;
+ u64 buffer_end_seq;
};
#ifdef CONFIG_PRINTK
diff --git a/include/linux/list_bl.h b/include/linux/list_bl.h
index ae1b541446c90..83e0ec90ed0d5 100644
--- a/include/linux/list_bl.h
+++ b/include/linux/list_bl.h
@@ -3,6 +3,7 @@
#define _LINUX_LIST_BL_H
#include
+#include
#include
/*
@@ -33,13 +34,24 @@
struct hlist_bl_head {
struct hlist_bl_node *first;
+#ifdef CONFIG_PREEMPT_RT
+ raw_spinlock_t lock;
+#endif
};
struct hlist_bl_node {
struct hlist_bl_node *next, **pprev;
};
-#define INIT_HLIST_BL_HEAD(ptr) \
- ((ptr)->first = NULL)
+
+#ifdef CONFIG_PREEMPT_RT
+#define INIT_HLIST_BL_HEAD(h) \
+do { \
+ (h)->first = NULL; \
+ raw_spin_lock_init(&(h)->lock); \
+} while (0)
+#else
+#define INIT_HLIST_BL_HEAD(h) (h)->first = NULL
+#endif
static inline void INIT_HLIST_BL_NODE(struct hlist_bl_node *h)
{
@@ -145,12 +157,26 @@ static inline void hlist_bl_del_init(struct hlist_bl_node *n)
static inline void hlist_bl_lock(struct hlist_bl_head *b)
{
+#ifndef CONFIG_PREEMPT_RT
bit_spin_lock(0, (unsigned long *)b);
+#else
+ raw_spin_lock(&b->lock);
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+ __set_bit(0, (unsigned long *)b);
+#endif
+#endif
}
static inline void hlist_bl_unlock(struct hlist_bl_head *b)
{
+#ifndef CONFIG_PREEMPT_RT
__bit_spin_unlock(0, (unsigned long *)b);
+#else
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+ __clear_bit(0, (unsigned long *)b);
+#endif
+ raw_spin_unlock(&b->lock);
+#endif
}
static inline bool hlist_bl_is_locked(struct hlist_bl_head *b)
diff --git a/include/linux/locallock.h b/include/linux/locallock.h
new file mode 100644
index 0000000000000..9b6b4def52d49
--- /dev/null
+++ b/include/linux/locallock.h
@@ -0,0 +1,282 @@
+#ifndef _LINUX_LOCALLOCK_H
+#define _LINUX_LOCALLOCK_H
+
+#include
+#include
+#include
+
+#ifdef CONFIG_PREEMPT_RT
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+# define LL_WARN(cond) WARN_ON(cond)
+#else
+# define LL_WARN(cond) do { } while (0)
+#endif
+
+/*
+ * per cpu lock based substitute for local_irq_*()
+ */
+struct local_irq_lock {
+ spinlock_t lock;
+ struct task_struct *owner;
+ int nestcnt;
+ unsigned long flags;
+};
+
+#define DEFINE_LOCAL_IRQ_LOCK(lvar) \
+ DEFINE_PER_CPU(struct local_irq_lock, lvar) = { \
+ .lock = __SPIN_LOCK_UNLOCKED((lvar).lock) }
+
+#define DECLARE_LOCAL_IRQ_LOCK(lvar) \
+ DECLARE_PER_CPU(struct local_irq_lock, lvar)
+
+#define local_irq_lock_init(lvar) \
+ do { \
+ int __cpu; \
+ for_each_possible_cpu(__cpu) \
+ spin_lock_init(&per_cpu(lvar, __cpu).lock); \
+ } while (0)
+
+static inline void __local_lock(struct local_irq_lock *lv)
+{
+ if (lv->owner != current) {
+ spin_lock(&lv->lock);
+ LL_WARN(lv->owner);
+ LL_WARN(lv->nestcnt);
+ lv->owner = current;
+ }
+ lv->nestcnt++;
+}
+
+#define local_lock(lvar) \
+ do { __local_lock(&get_local_var(lvar)); } while (0)
+
+#define local_lock_on(lvar, cpu) \
+ do { __local_lock(&per_cpu(lvar, cpu)); } while (0)
+
+static inline int __local_trylock(struct local_irq_lock *lv)
+{
+ if (lv->owner != current && spin_trylock(&lv->lock)) {
+ LL_WARN(lv->owner);
+ LL_WARN(lv->nestcnt);
+ lv->owner = current;
+ lv->nestcnt = 1;
+ return 1;
+ } else if (lv->owner == current) {
+ lv->nestcnt++;
+ return 1;
+ }
+ return 0;
+}
+
+#define local_trylock(lvar) \
+ ({ \
+ int __locked; \
+ __locked = __local_trylock(&get_local_var(lvar)); \
+ if (!__locked) \
+ put_local_var(lvar); \
+ __locked; \
+ })
+
+static inline void __local_unlock(struct local_irq_lock *lv)
+{
+ LL_WARN(lv->nestcnt == 0);
+ LL_WARN(lv->owner != current);
+ if (--lv->nestcnt)
+ return;
+
+ lv->owner = NULL;
+ spin_unlock(&lv->lock);
+}
+
+#define local_unlock(lvar) \
+ do { \
+ __local_unlock(this_cpu_ptr(&lvar)); \
+ put_local_var(lvar); \
+ } while (0)
+
+#define local_unlock_on(lvar, cpu) \
+ do { __local_unlock(&per_cpu(lvar, cpu)); } while (0)
+
+static inline void __local_lock_irq(struct local_irq_lock *lv)
+{
+ spin_lock_irqsave(&lv->lock, lv->flags);
+ LL_WARN(lv->owner);
+ LL_WARN(lv->nestcnt);
+ lv->owner = current;
+ lv->nestcnt = 1;
+}
+
+#define local_lock_irq(lvar) \
+ do { __local_lock_irq(&get_local_var(lvar)); } while (0)
+
+#define local_lock_irq_on(lvar, cpu) \
+ do { __local_lock_irq(&per_cpu(lvar, cpu)); } while (0)
+
+static inline void __local_unlock_irq(struct local_irq_lock *lv)
+{
+ LL_WARN(!lv->nestcnt);
+ LL_WARN(lv->owner != current);
+ lv->owner = NULL;
+ lv->nestcnt = 0;
+ spin_unlock_irq(&lv->lock);
+}
+
+#define local_unlock_irq(lvar) \
+ do { \
+ __local_unlock_irq(this_cpu_ptr(&lvar)); \
+ put_local_var(lvar); \
+ } while (0)
+
+#define local_unlock_irq_on(lvar, cpu) \
+ do { \
+ __local_unlock_irq(&per_cpu(lvar, cpu)); \
+ } while (0)
+
+static inline int __local_lock_irqsave(struct local_irq_lock *lv)
+{
+ if (lv->owner != current) {
+ __local_lock_irq(lv);
+ return 0;
+ } else {
+ lv->nestcnt++;
+ return 1;
+ }
+}
+
+#define local_lock_irqsave(lvar, _flags) \
+ do { \
+ if (__local_lock_irqsave(&get_local_var(lvar))) \
+ put_local_var(lvar); \
+ _flags = __this_cpu_read(lvar.flags); \
+ } while (0)
+
+#define local_lock_irqsave_on(lvar, _flags, cpu) \
+ do { \
+ __local_lock_irqsave(&per_cpu(lvar, cpu)); \
+ _flags = per_cpu(lvar, cpu).flags; \
+ } while (0)
+
+static inline int __local_unlock_irqrestore(struct local_irq_lock *lv,
+ unsigned long flags)
+{
+ LL_WARN(!lv->nestcnt);
+ LL_WARN(lv->owner != current);
+ if (--lv->nestcnt)
+ return 0;
+
+ lv->owner = NULL;
+ spin_unlock_irqrestore(&lv->lock, lv->flags);
+ return 1;
+}
+
+#define local_unlock_irqrestore(lvar, flags) \
+ do { \
+ if (__local_unlock_irqrestore(this_cpu_ptr(&lvar), flags)) \
+ put_local_var(lvar); \
+ } while (0)
+
+#define local_unlock_irqrestore_on(lvar, flags, cpu) \
+ do { \
+ __local_unlock_irqrestore(&per_cpu(lvar, cpu), flags); \
+ } while (0)
+
+#define local_spin_trylock_irq(lvar, lock) \
+ ({ \
+ int __locked; \
+ local_lock_irq(lvar); \
+ __locked = spin_trylock(lock); \
+ if (!__locked) \
+ local_unlock_irq(lvar); \
+ __locked; \
+ })
+
+#define local_spin_lock_irq(lvar, lock) \
+ do { \
+ local_lock_irq(lvar); \
+ spin_lock(lock); \
+ } while (0)
+
+#define local_spin_unlock_irq(lvar, lock) \
+ do { \
+ spin_unlock(lock); \
+ local_unlock_irq(lvar); \
+ } while (0)
+
+#define local_spin_lock_irqsave(lvar, lock, flags) \
+ do { \
+ local_lock_irqsave(lvar, flags); \
+ spin_lock(lock); \
+ } while (0)
+
+#define local_spin_unlock_irqrestore(lvar, lock, flags) \
+ do { \
+ spin_unlock(lock); \
+ local_unlock_irqrestore(lvar, flags); \
+ } while (0)
+
+#define get_locked_var(lvar, var) \
+ (*({ \
+ local_lock(lvar); \
+ this_cpu_ptr(&var); \
+ }))
+
+#define put_locked_var(lvar, var) local_unlock(lvar);
+
+#define get_locked_ptr(lvar, var) \
+ ({ \
+ local_lock(lvar); \
+ this_cpu_ptr(var); \
+ })
+
+#define put_locked_ptr(lvar, var) local_unlock(lvar);
+
+#define local_lock_cpu(lvar) \
+ ({ \
+ local_lock(lvar); \
+ smp_processor_id(); \
+ })
+
+#define local_unlock_cpu(lvar) local_unlock(lvar)
+
+#else /* PREEMPT_RT */
+
+#define DEFINE_LOCAL_IRQ_LOCK(lvar) __typeof__(const int) lvar
+#define DECLARE_LOCAL_IRQ_LOCK(lvar) extern __typeof__(const int) lvar
+
+static inline void local_irq_lock_init(int lvar) { }
+
+#define local_trylock(lvar) \
+ ({ \
+ preempt_disable(); \
+ 1; \
+ })
+
+#define local_lock(lvar) preempt_disable()
+#define local_unlock(lvar) preempt_enable()
+#define local_lock_irq(lvar) local_irq_disable()
+#define local_lock_irq_on(lvar, cpu) local_irq_disable()
+#define local_unlock_irq(lvar) local_irq_enable()
+#define local_unlock_irq_on(lvar, cpu) local_irq_enable()
+#define local_lock_irqsave(lvar, flags) local_irq_save(flags)
+#define local_unlock_irqrestore(lvar, flags) local_irq_restore(flags)
+
+#define local_spin_trylock_irq(lvar, lock) spin_trylock_irq(lock)
+#define local_spin_lock_irq(lvar, lock) spin_lock_irq(lock)
+#define local_spin_unlock_irq(lvar, lock) spin_unlock_irq(lock)
+#define local_spin_lock_irqsave(lvar, lock, flags) \
+ spin_lock_irqsave(lock, flags)
+#define local_spin_unlock_irqrestore(lvar, lock, flags) \
+ spin_unlock_irqrestore(lock, flags)
+
+#define get_locked_var(lvar, var) get_cpu_var(var)
+#define put_locked_var(lvar, var) put_cpu_var(var)
+#define get_locked_ptr(lvar, var) get_cpu_ptr(var)
+#define put_locked_ptr(lvar, var) put_cpu_ptr(var)
+
+#define local_lock_cpu(lvar) get_cpu()
+#define local_unlock_cpu(lvar) put_cpu()
+
+#endif
+
+#endif
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 270aa8fd2800b..497440fe047c0 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -12,6 +12,7 @@
#include
#include
#include
+#include
#include
#include
@@ -520,6 +521,9 @@ struct mm_struct {
bool tlb_flush_batched;
#endif
struct uprobes_state uprobes_state;
+#ifdef CONFIG_PREEMPT_RT
+ struct rcu_head delayed_drop;
+#endif
#ifdef CONFIG_HUGETLB_PAGE
atomic_long_t hugetlb_usage;
#endif
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index aca8f36dfac9a..2b72473ded555 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -22,6 +22,17 @@
struct ww_acquire_ctx;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __DEP_MAP_MUTEX_INITIALIZER(lockname) \
+ , .dep_map = { .name = #lockname }
+#else
+# define __DEP_MAP_MUTEX_INITIALIZER(lockname)
+#endif
+
+#ifdef CONFIG_PREEMPT_RT
+# include
+#else
+
/*
* Simple, straightforward mutexes with strict semantics:
*
@@ -108,13 +119,6 @@ do { \
__mutex_init((mutex), #mutex, &__key); \
} while (0)
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __DEP_MAP_MUTEX_INITIALIZER(lockname) \
- , .dep_map = { .name = #lockname }
-#else
-# define __DEP_MAP_MUTEX_INITIALIZER(lockname)
-#endif
-
#define __MUTEX_INITIALIZER(lockname) \
{ .owner = ATOMIC_LONG_INIT(0) \
, .wait_lock = __SPIN_LOCK_UNLOCKED(lockname.wait_lock) \
@@ -210,4 +214,6 @@ enum mutex_trylock_recursive_enum {
extern /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
mutex_trylock_recursive(struct mutex *lock);
+#endif /* !PREEMPT_RT */
+
#endif /* __LINUX_MUTEX_H */
diff --git a/include/linux/mutex_rt.h b/include/linux/mutex_rt.h
new file mode 100644
index 0000000000000..3fcb5edb1d2b4
--- /dev/null
+++ b/include/linux/mutex_rt.h
@@ -0,0 +1,130 @@
+#ifndef __LINUX_MUTEX_RT_H
+#define __LINUX_MUTEX_RT_H
+
+#ifndef __LINUX_MUTEX_H
+#error "Please include mutex.h"
+#endif
+
+#include
+
+/* FIXME: Just for __lockfunc */
+#include
+
+struct mutex {
+ struct rt_mutex lock;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
+};
+
+#define __MUTEX_INITIALIZER(mutexname) \
+ { \
+ .lock = __RT_MUTEX_INITIALIZER(mutexname.lock) \
+ __DEP_MAP_MUTEX_INITIALIZER(mutexname) \
+ }
+
+#define DEFINE_MUTEX(mutexname) \
+ struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+extern void __mutex_do_init(struct mutex *lock, const char *name, struct lock_class_key *key);
+extern void __lockfunc _mutex_lock(struct mutex *lock);
+extern void __lockfunc _mutex_lock_io(struct mutex *lock);
+extern void __lockfunc _mutex_lock_io_nested(struct mutex *lock, int subclass);
+extern int __lockfunc _mutex_lock_interruptible(struct mutex *lock);
+extern int __lockfunc _mutex_lock_killable(struct mutex *lock);
+extern void __lockfunc _mutex_lock_nested(struct mutex *lock, int subclass);
+extern void __lockfunc _mutex_lock_nest_lock(struct mutex *lock, struct lockdep_map *nest_lock);
+extern int __lockfunc _mutex_lock_interruptible_nested(struct mutex *lock, int subclass);
+extern int __lockfunc _mutex_lock_killable_nested(struct mutex *lock, int subclass);
+extern int __lockfunc _mutex_trylock(struct mutex *lock);
+extern void __lockfunc _mutex_unlock(struct mutex *lock);
+
+#define mutex_is_locked(l) rt_mutex_is_locked(&(l)->lock)
+#define mutex_lock(l) _mutex_lock(l)
+#define mutex_lock_interruptible(l) _mutex_lock_interruptible(l)
+#define mutex_lock_killable(l) _mutex_lock_killable(l)
+#define mutex_trylock(l) _mutex_trylock(l)
+#define mutex_unlock(l) _mutex_unlock(l)
+#define mutex_lock_io(l) _mutex_lock_io(l);
+
+#define __mutex_owner(l) ((l)->lock.owner)
+
+#ifdef CONFIG_DEBUG_MUTEXES
+#define mutex_destroy(l) rt_mutex_destroy(&(l)->lock)
+#else
+static inline void mutex_destroy(struct mutex *lock) {}
+#endif
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define mutex_lock_nested(l, s) _mutex_lock_nested(l, s)
+# define mutex_lock_interruptible_nested(l, s) \
+ _mutex_lock_interruptible_nested(l, s)
+# define mutex_lock_killable_nested(l, s) \
+ _mutex_lock_killable_nested(l, s)
+# define mutex_lock_io_nested(l, s) _mutex_lock_io_nested(l, s)
+
+# define mutex_lock_nest_lock(lock, nest_lock) \
+do { \
+ typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \
+ _mutex_lock_nest_lock(lock, &(nest_lock)->dep_map); \
+} while (0)
+
+#else
+# define mutex_lock_nested(l, s) _mutex_lock(l)
+# define mutex_lock_interruptible_nested(l, s) \
+ _mutex_lock_interruptible(l)
+# define mutex_lock_killable_nested(l, s) \
+ _mutex_lock_killable(l)
+# define mutex_lock_nest_lock(lock, nest_lock) mutex_lock(lock)
+# define mutex_lock_io_nested(l, s) _mutex_lock_io(l)
+#endif
+
+# define mutex_init(mutex) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ rt_mutex_init(&(mutex)->lock); \
+ __mutex_do_init((mutex), #mutex, &__key); \
+} while (0)
+
+# define __mutex_init(mutex, name, key) \
+do { \
+ rt_mutex_init(&(mutex)->lock); \
+ __mutex_do_init((mutex), name, key); \
+} while (0)
+
+/**
+ * These values are chosen such that FAIL and SUCCESS match the
+ * values of the regular mutex_trylock().
+ */
+enum mutex_trylock_recursive_enum {
+ MUTEX_TRYLOCK_FAILED = 0,
+ MUTEX_TRYLOCK_SUCCESS = 1,
+ MUTEX_TRYLOCK_RECURSIVE,
+};
+/**
+ * mutex_trylock_recursive - trylock variant that allows recursive locking
+ * @lock: mutex to be locked
+ *
+ * This function should not be used, _ever_. It is purely for hysterical GEM
+ * raisins, and once those are gone this will be removed.
+ *
+ * Returns:
+ * MUTEX_TRYLOCK_FAILED - trylock failed,
+ * MUTEX_TRYLOCK_SUCCESS - lock acquired,
+ * MUTEX_TRYLOCK_RECURSIVE - we already owned the lock.
+ */
+int __rt_mutex_owner_current(struct rt_mutex *lock);
+
+static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
+mutex_trylock_recursive(struct mutex *lock)
+{
+ if (unlikely(__rt_mutex_owner_current(&lock->lock)))
+ return MUTEX_TRYLOCK_RECURSIVE;
+
+ return mutex_trylock(lock);
+}
+
+extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
+
+#endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f8fde9fa479c8..b4aeead9104c2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3016,6 +3016,7 @@ struct softnet_data {
unsigned int dropped;
struct sk_buff_head input_pkt_queue;
struct napi_struct backlog;
+ struct sk_buff_head tofree_queue;
};
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 570a60c2f4f48..8e7f60827ecd9 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -165,7 +165,11 @@ struct nfs_inode {
/* Readers: in-flight sillydelete RPC calls */
/* Writers: rmdir */
+#ifdef CONFIG_PREEMPT_RT
+ struct semaphore rmdir_sem;
+#else
struct rw_semaphore rmdir_sem;
+#endif
struct mutex commit_mutex;
#if IS_ENABLED(CONFIG_NFS_V4)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9b8324ec08f31..c805cd551337a 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1594,7 +1594,7 @@ struct nfs_unlinkdata {
struct nfs_removeargs args;
struct nfs_removeres res;
struct dentry *dentry;
- wait_queue_head_t wq;
+ struct swait_queue_head wq;
const struct cred *cred;
struct nfs_fattr dir_attr;
long timeout;
diff --git a/include/linux/percpu-refcount.h b/include/linux/percpu-refcount.h
index 7aef0abc194a2..390031e816dcd 100644
--- a/include/linux/percpu-refcount.h
+++ b/include/linux/percpu-refcount.h
@@ -186,14 +186,14 @@ static inline void percpu_ref_get_many(struct percpu_ref *ref, unsigned long nr)
{
unsigned long __percpu *percpu_count;
- rcu_read_lock_sched();
+ rcu_read_lock();
if (__ref_is_percpu(ref, &percpu_count))
this_cpu_add(*percpu_count, nr);
else
atomic_long_add(nr, &ref->count);
- rcu_read_unlock_sched();
+ rcu_read_unlock();
}
/**
@@ -223,7 +223,7 @@ static inline bool percpu_ref_tryget(struct percpu_ref *ref)
unsigned long __percpu *percpu_count;
bool ret;
- rcu_read_lock_sched();
+ rcu_read_lock();
if (__ref_is_percpu(ref, &percpu_count)) {
this_cpu_inc(*percpu_count);
@@ -232,7 +232,7 @@ static inline bool percpu_ref_tryget(struct percpu_ref *ref)
ret = atomic_long_inc_not_zero(&ref->count);
}
- rcu_read_unlock_sched();
+ rcu_read_unlock();
return ret;
}
@@ -257,7 +257,7 @@ static inline bool percpu_ref_tryget_live(struct percpu_ref *ref)
unsigned long __percpu *percpu_count;
bool ret = false;
- rcu_read_lock_sched();
+ rcu_read_lock();
if (__ref_is_percpu(ref, &percpu_count)) {
this_cpu_inc(*percpu_count);
@@ -266,7 +266,7 @@ static inline bool percpu_ref_tryget_live(struct percpu_ref *ref)
ret = atomic_long_inc_not_zero(&ref->count);
}
- rcu_read_unlock_sched();
+ rcu_read_unlock();
return ret;
}
@@ -285,14 +285,14 @@ static inline void percpu_ref_put_many(struct percpu_ref *ref, unsigned long nr)
{
unsigned long __percpu *percpu_count;
- rcu_read_lock_sched();
+ rcu_read_lock();
if (__ref_is_percpu(ref, &percpu_count))
this_cpu_sub(*percpu_count, nr);
else if (unlikely(atomic_long_sub_and_test(nr, &ref->count)))
ref->release(ref);
- rcu_read_unlock_sched();
+ rcu_read_unlock();
}
/**
diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h
index 3998cdf9cd148..6e8d3871450a4 100644
--- a/include/linux/percpu-rwsem.h
+++ b/include/linux/percpu-rwsem.h
@@ -3,41 +3,52 @@
#define _LINUX_PERCPU_RWSEM_H
#include
-#include
#include
#include
+#include
#include
#include
struct percpu_rw_semaphore {
struct rcu_sync rss;
unsigned int __percpu *read_count;
- struct rw_semaphore rw_sem; /* slowpath */
- struct rcuwait writer; /* blocked writer */
- int readers_block;
+ struct rcuwait writer;
+ wait_queue_head_t waiters;
+ atomic_t block;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
};
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#define __PERCPU_RWSEM_DEP_MAP_INIT(lockname) .dep_map = { .name = #lockname },
+#else
+#define __PERCPU_RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
#define __DEFINE_PERCPU_RWSEM(name, is_static) \
static DEFINE_PER_CPU(unsigned int, __percpu_rwsem_rc_##name); \
is_static struct percpu_rw_semaphore name = { \
.rss = __RCU_SYNC_INITIALIZER(name.rss), \
.read_count = &__percpu_rwsem_rc_##name, \
- .rw_sem = __RWSEM_INITIALIZER(name.rw_sem), \
.writer = __RCUWAIT_INITIALIZER(name.writer), \
+ .waiters = __WAIT_QUEUE_HEAD_INITIALIZER(name.waiters), \
+ .block = ATOMIC_INIT(0), \
+ __PERCPU_RWSEM_DEP_MAP_INIT(name) \
}
+
#define DEFINE_PERCPU_RWSEM(name) \
__DEFINE_PERCPU_RWSEM(name, /* not static */)
#define DEFINE_STATIC_PERCPU_RWSEM(name) \
__DEFINE_PERCPU_RWSEM(name, static)
-extern int __percpu_down_read(struct percpu_rw_semaphore *, int);
-extern void __percpu_up_read(struct percpu_rw_semaphore *);
+extern bool __percpu_down_read(struct percpu_rw_semaphore *, bool);
static inline void percpu_down_read(struct percpu_rw_semaphore *sem)
{
might_sleep();
- rwsem_acquire_read(&sem->rw_sem.dep_map, 0, 0, _RET_IP_);
+ rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_);
preempt_disable();
/*
@@ -48,8 +59,9 @@ static inline void percpu_down_read(struct percpu_rw_semaphore *sem)
* and that once the synchronize_rcu() is done, the writer will see
* anything we did within this RCU-sched read-size critical section.
*/
- __this_cpu_inc(*sem->read_count);
- if (unlikely(!rcu_sync_is_idle(&sem->rss)))
+ if (likely(rcu_sync_is_idle(&sem->rss)))
+ __this_cpu_inc(*sem->read_count);
+ else
__percpu_down_read(sem, false); /* Unconditional memory barrier */
/*
* The preempt_enable() prevents the compiler from
@@ -58,16 +70,17 @@ static inline void percpu_down_read(struct percpu_rw_semaphore *sem)
preempt_enable();
}
-static inline int percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
+static inline bool percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
{
- int ret = 1;
+ bool ret = true;
preempt_disable();
/*
* Same as in percpu_down_read().
*/
- __this_cpu_inc(*sem->read_count);
- if (unlikely(!rcu_sync_is_idle(&sem->rss)))
+ if (likely(rcu_sync_is_idle(&sem->rss)))
+ __this_cpu_inc(*sem->read_count);
+ else
ret = __percpu_down_read(sem, true); /* Unconditional memory barrier */
preempt_enable();
/*
@@ -76,24 +89,36 @@ static inline int percpu_down_read_trylock(struct percpu_rw_semaphore *sem)
*/
if (ret)
- rwsem_acquire_read(&sem->rw_sem.dep_map, 0, 1, _RET_IP_);
+ rwsem_acquire_read(&sem->dep_map, 0, 1, _RET_IP_);
return ret;
}
static inline void percpu_up_read(struct percpu_rw_semaphore *sem)
{
+ rwsem_release(&sem->dep_map, 1, _RET_IP_);
+
preempt_disable();
/*
* Same as in percpu_down_read().
*/
- if (likely(rcu_sync_is_idle(&sem->rss)))
+ if (likely(rcu_sync_is_idle(&sem->rss))) {
__this_cpu_dec(*sem->read_count);
- else
- __percpu_up_read(sem); /* Unconditional memory barrier */
+ } else {
+ /*
+ * slowpath; reader will only ever wake a single blocked
+ * writer.
+ */
+ smp_mb(); /* B matches C */
+ /*
+ * In other words, if they see our decrement (presumably to
+ * aggregate zero, as that is the only time it matters) they
+ * will also see our critical section.
+ */
+ __this_cpu_dec(*sem->read_count);
+ rcuwait_wake_up(&sem->writer);
+ }
preempt_enable();
-
- rwsem_release(&sem->rw_sem.dep_map, 1, _RET_IP_);
}
extern void percpu_down_write(struct percpu_rw_semaphore *);
@@ -110,29 +135,19 @@ extern void percpu_free_rwsem(struct percpu_rw_semaphore *);
__percpu_init_rwsem(sem, #sem, &rwsem_key); \
})
-#define percpu_rwsem_is_held(sem) lockdep_is_held(&(sem)->rw_sem)
-
-#define percpu_rwsem_assert_held(sem) \
- lockdep_assert_held(&(sem)->rw_sem)
+#define percpu_rwsem_is_held(sem) lockdep_is_held(sem)
+#define percpu_rwsem_assert_held(sem) lockdep_assert_held(sem)
static inline void percpu_rwsem_release(struct percpu_rw_semaphore *sem,
bool read, unsigned long ip)
{
- lock_release(&sem->rw_sem.dep_map, 1, ip);
-#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
- if (!read)
- atomic_long_set(&sem->rw_sem.owner, RWSEM_OWNER_UNKNOWN);
-#endif
+ lock_release(&sem->dep_map, 1, ip);
}
static inline void percpu_rwsem_acquire(struct percpu_rw_semaphore *sem,
bool read, unsigned long ip)
{
- lock_acquire(&sem->rw_sem.dep_map, 0, 1, read, 1, NULL, ip);
-#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
- if (!read)
- atomic_long_set(&sem->rw_sem.owner, (long)current);
-#endif
+ lock_acquire(&sem->dep_map, 0, 1, read, 1, NULL, ip);
}
#endif
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 5e76af742c807..3d0d9873de61e 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -19,6 +19,35 @@
#define PERCPU_MODULE_RESERVE 0
#endif
+#ifdef CONFIG_PREEMPT_RT
+
+#define get_local_var(var) (*({ \
+ migrate_disable(); \
+ this_cpu_ptr(&var); }))
+
+#define put_local_var(var) do { \
+ (void)&(var); \
+ migrate_enable(); \
+} while (0)
+
+# define get_local_ptr(var) ({ \
+ migrate_disable(); \
+ this_cpu_ptr(var); })
+
+# define put_local_ptr(var) do { \
+ (void)(var); \
+ migrate_enable(); \
+} while (0)
+
+#else
+
+#define get_local_var(var) get_cpu_var(var)
+#define put_local_var(var) put_cpu_var(var)
+#define get_local_ptr(var) get_cpu_ptr(var)
+#define put_local_ptr(var) put_cpu_ptr(var)
+
+#endif
+
/* minimum unit size, also is the maximum supported allocation size */
#define PCPU_MIN_UNIT_SIZE PFN_ALIGN(32 << 10)
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 9645b1194c981..916c1d0e42c22 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -3,6 +3,7 @@
#define _LINUX_PID_H
#include
+#include
#include
#include
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 3d10c84a97a94..bad09364b20a1 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -72,6 +72,7 @@ struct cpu_timer {
struct task_struct *task;
struct list_head elist;
int firing;
+ int firing_cpu;
};
static inline bool cpu_timer_enqueue(struct timerqueue_head *head,
@@ -123,6 +124,9 @@ struct posix_cputimers {
struct posix_cputimer_base bases[CPUCLOCK_MAX];
unsigned int timers_active;
unsigned int expiry_active;
+#ifdef CONFIG_PREEMPT_RT
+ struct task_struct *posix_timer_list;
+#endif
};
static inline void posix_cputimers_init(struct posix_cputimers *pct)
@@ -152,9 +156,16 @@ static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
INIT_CPU_TIMERBASE(b[2]), \
}
+#ifdef CONFIG_PREEMPT_RT
+# define INIT_TIMER_LIST .posix_timer_list = NULL,
+#else
+# define INIT_TIMER_LIST
+#endif
+
#define INIT_CPU_TIMERS(s) \
.posix_cputimers = { \
.bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \
+ INIT_TIMER_LIST \
},
#else
struct posix_cputimers { };
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index bbb68dba37cc8..e1aab77564eeb 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -78,10 +78,8 @@
#include
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
-#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \
| NMI_MASK))
-
/*
* Are we doing bottom half or hardware interrupt processing?
*
@@ -96,12 +94,23 @@
* should not be used in new code.
*/
#define in_irq() (hardirq_count())
-#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())
-#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
#define in_nmi() (preempt_count() & NMI_MASK)
#define in_task() (!(preempt_count() & \
(NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))
+#ifdef CONFIG_PREEMPT_RT
+
+#define softirq_count() ((long)current->softirq_count)
+#define in_softirq() (softirq_count())
+#define in_serving_softirq() (current->softirq_count & SOFTIRQ_OFFSET)
+
+#else
+
+#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
+#define in_softirq() (softirq_count())
+#define in_serving_softirq() (softirq_count() & SOFTIRQ_OFFSET)
+
+#endif
/*
* The preempt_count offset after preempt_disable();
@@ -115,7 +124,11 @@
/*
* The preempt_count offset after spin_lock()
*/
+#if !defined(CONFIG_PREEMPT_RT)
#define PREEMPT_LOCK_OFFSET PREEMPT_DISABLE_OFFSET
+#else
+#define PREEMPT_LOCK_OFFSET 0
+#endif
/*
* The preempt_count offset needed for things like:
@@ -164,6 +177,20 @@ extern void preempt_count_sub(int val);
#define preempt_count_inc() preempt_count_add(1)
#define preempt_count_dec() preempt_count_sub(1)
+#ifdef CONFIG_PREEMPT_LAZY
+#define add_preempt_lazy_count(val) do { preempt_lazy_count() += (val); } while (0)
+#define sub_preempt_lazy_count(val) do { preempt_lazy_count() -= (val); } while (0)
+#define inc_preempt_lazy_count() add_preempt_lazy_count(1)
+#define dec_preempt_lazy_count() sub_preempt_lazy_count(1)
+#define preempt_lazy_count() (current_thread_info()->preempt_lazy_count)
+#else
+#define add_preempt_lazy_count(val) do { } while (0)
+#define sub_preempt_lazy_count(val) do { } while (0)
+#define inc_preempt_lazy_count() do { } while (0)
+#define dec_preempt_lazy_count() do { } while (0)
+#define preempt_lazy_count() (0)
+#endif
+
#ifdef CONFIG_PREEMPT_COUNT
#define preempt_disable() \
@@ -172,16 +199,75 @@ do { \
barrier(); \
} while (0)
+#define preempt_lazy_disable() \
+do { \
+ inc_preempt_lazy_count(); \
+ barrier(); \
+} while (0)
+
#define sched_preempt_enable_no_resched() \
do { \
barrier(); \
preempt_count_dec(); \
} while (0)
-#define preempt_enable_no_resched() sched_preempt_enable_no_resched()
+#ifdef CONFIG_PREEMPT_RT
+# define preempt_enable_no_resched() sched_preempt_enable_no_resched()
+# define preempt_check_resched_rt() preempt_check_resched()
+#else
+# define preempt_enable_no_resched() preempt_enable()
+# define preempt_check_resched_rt() barrier();
+#endif
#define preemptible() (preempt_count() == 0 && !irqs_disabled())
+#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+
+extern void migrate_disable(void);
+extern void migrate_enable(void);
+
+int __migrate_disabled(struct task_struct *p);
+
+#elif !defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+
+extern void migrate_disable(void);
+extern void migrate_enable(void);
+static inline int __migrate_disabled(struct task_struct *p)
+{
+ return 0;
+}
+
+#else
+/**
+ * migrate_disable - Prevent migration of the current task
+ *
+ * Maps to preempt_disable() which also disables preemption. Use
+ * migrate_disable() to annotate that the intent is to prevent migration
+ * but not necessarily preemption.
+ *
+ * Can be invoked nested like preempt_disable() and needs the corresponding
+ * number of migrate_enable() invocations.
+ */
+#define migrate_disable() preempt_disable()
+
+/**
+ * migrate_enable - Allow migration of the current task
+ *
+ * Counterpart to migrate_disable().
+ *
+ * As migrate_disable() can be invoked nested only the uttermost invocation
+ * reenables migration.
+ *
+ * Currently mapped to preempt_enable().
+ */
+#define migrate_enable() preempt_enable()
+
+static inline int __migrate_disabled(struct task_struct *p)
+{
+ return 0;
+}
+#endif
+
#ifdef CONFIG_PREEMPTION
#define preempt_enable() \
do { \
@@ -203,6 +289,13 @@ do { \
__preempt_schedule(); \
} while (0)
+#define preempt_lazy_enable() \
+do { \
+ dec_preempt_lazy_count(); \
+ barrier(); \
+ preempt_check_resched(); \
+} while (0)
+
#else /* !CONFIG_PREEMPTION */
#define preempt_enable() \
do { \
@@ -210,6 +303,12 @@ do { \
preempt_count_dec(); \
} while (0)
+#define preempt_lazy_enable() \
+do { \
+ dec_preempt_lazy_count(); \
+ barrier(); \
+} while (0)
+
#define preempt_enable_notrace() \
do { \
barrier(); \
@@ -248,8 +347,16 @@ do { \
#define preempt_disable_notrace() barrier()
#define preempt_enable_no_resched_notrace() barrier()
#define preempt_enable_notrace() barrier()
+#define preempt_check_resched_rt() barrier()
#define preemptible() 0
+#define migrate_disable() barrier()
+#define migrate_enable() barrier()
+
+static inline int __migrate_disabled(struct task_struct *p)
+{
+ return 0;
+}
#endif /* CONFIG_PREEMPT_COUNT */
#ifdef MODULE
@@ -268,10 +375,22 @@ do { \
} while (0)
#define preempt_fold_need_resched() \
do { \
- if (tif_need_resched()) \
+ if (tif_need_resched_now()) \
set_preempt_need_resched(); \
} while (0)
+#ifdef CONFIG_PREEMPT_RT
+# define preempt_disable_rt() preempt_disable()
+# define preempt_enable_rt() preempt_enable()
+# define preempt_disable_nort() barrier()
+# define preempt_enable_nort() barrier()
+#else
+# define preempt_disable_rt() barrier()
+# define preempt_enable_rt() barrier()
+# define preempt_disable_nort() preempt_disable()
+# define preempt_enable_nort() preempt_enable()
+#endif
+
#ifdef CONFIG_PREEMPT_NOTIFIERS
struct preempt_notifier;
diff --git a/include/linux/printk.h b/include/linux/printk.h
index c09d67edda3a1..1fe8068100c25 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -58,6 +58,7 @@ static inline const char *printk_skip_headers(const char *buffer)
*/
#define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT
#define CONSOLE_LOGLEVEL_QUIET CONFIG_CONSOLE_LOGLEVEL_QUIET
+#define CONSOLE_LOGLEVEL_EMERGENCY CONFIG_CONSOLE_LOGLEVEL_EMERGENCY
extern int console_printk[];
@@ -65,6 +66,7 @@ extern int console_printk[];
#define default_message_loglevel (console_printk[1])
#define minimum_console_loglevel (console_printk[2])
#define default_console_loglevel (console_printk[3])
+#define emergency_console_loglevel (console_printk[4])
static inline void console_silent(void)
{
@@ -146,18 +148,6 @@ static inline __printf(1, 2) __cold
void early_printk(const char *s, ...) { }
#endif
-#ifdef CONFIG_PRINTK_NMI
-extern void printk_nmi_enter(void);
-extern void printk_nmi_exit(void);
-extern void printk_nmi_direct_enter(void);
-extern void printk_nmi_direct_exit(void);
-#else
-static inline void printk_nmi_enter(void) { }
-static inline void printk_nmi_exit(void) { }
-static inline void printk_nmi_direct_enter(void) { }
-static inline void printk_nmi_direct_exit(void) { }
-#endif /* PRINTK_NMI */
-
#ifdef CONFIG_PRINTK
asmlinkage __printf(5, 0)
int vprintk_emit(int facility, int level,
@@ -202,9 +192,7 @@ __printf(1, 2) void dump_stack_set_arch_desc(const char *fmt, ...);
void dump_stack_print_info(const char *log_lvl);
void show_regs_print_info(const char *log_lvl);
extern asmlinkage void dump_stack(void) __cold;
-extern void printk_safe_init(void);
-extern void printk_safe_flush(void);
-extern void printk_safe_flush_on_panic(void);
+struct wait_queue_head *printk_wait_queue(void);
#else
static inline __printf(1, 0)
int vprintk(const char *s, va_list args)
@@ -268,18 +256,6 @@ static inline void show_regs_print_info(const char *log_lvl)
static inline void dump_stack(void)
{
}
-
-static inline void printk_safe_init(void)
-{
-}
-
-static inline void printk_safe_flush(void)
-{
-}
-
-static inline void printk_safe_flush_on_panic(void)
-{
-}
#endif
extern int kptr_restrict;
diff --git a/include/linux/printk_ringbuffer.h b/include/linux/printk_ringbuffer.h
new file mode 100644
index 0000000000000..ec3d7ceec378e
--- /dev/null
+++ b/include/linux/printk_ringbuffer.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_PRINTK_RINGBUFFER_H
+#define _LINUX_PRINTK_RINGBUFFER_H
+
+#include
+#include
+#include
+#include
+
+struct prb_cpulock {
+ atomic_t owner;
+ unsigned long __percpu *irqflags;
+};
+
+struct printk_ringbuffer {
+ void *buffer;
+ unsigned int size_bits;
+
+ u64 seq;
+ atomic_long_t lost;
+
+ atomic_long_t tail;
+ atomic_long_t head;
+ atomic_long_t reserve;
+
+ struct prb_cpulock *cpulock;
+ atomic_t ctx;
+
+ struct wait_queue_head *wq;
+ atomic_long_t wq_counter;
+ struct irq_work *wq_work;
+};
+
+struct prb_entry {
+ unsigned int size;
+ u64 seq;
+ char data[0];
+};
+
+struct prb_handle {
+ struct printk_ringbuffer *rb;
+ unsigned int cpu;
+ struct prb_entry *entry;
+};
+
+#define DECLARE_STATIC_PRINTKRB_CPULOCK(name) \
+static DEFINE_PER_CPU(unsigned long, _##name##_percpu_irqflags); \
+static struct prb_cpulock name = { \
+ .owner = ATOMIC_INIT(-1), \
+ .irqflags = &_##name##_percpu_irqflags, \
+}
+
+#define PRB_INIT ((unsigned long)-1)
+
+#define DECLARE_STATIC_PRINTKRB_ITER(name, rbaddr) \
+static struct prb_iterator name = { \
+ .rb = rbaddr, \
+ .lpos = PRB_INIT, \
+}
+
+struct prb_iterator {
+ struct printk_ringbuffer *rb;
+ unsigned long lpos;
+};
+
+#define DECLARE_STATIC_PRINTKRB(name, szbits, cpulockptr) \
+static char _##name##_buffer[1 << (szbits)] \
+ __aligned(__alignof__(long)); \
+static DECLARE_WAIT_QUEUE_HEAD(_##name##_wait); \
+static void _##name##_wake_work_func(struct irq_work *irq_work) \
+{ \
+ wake_up_interruptible_all(&_##name##_wait); \
+} \
+static struct irq_work _##name##_wake_work = { \
+ .func = _##name##_wake_work_func, \
+ .flags = IRQ_WORK_LAZY, \
+}; \
+static struct printk_ringbuffer name = { \
+ .buffer = &_##name##_buffer[0], \
+ .size_bits = szbits, \
+ .seq = 0, \
+ .lost = ATOMIC_LONG_INIT(0), \
+ .tail = ATOMIC_LONG_INIT(-111 * sizeof(long)), \
+ .head = ATOMIC_LONG_INIT(-111 * sizeof(long)), \
+ .reserve = ATOMIC_LONG_INIT(-111 * sizeof(long)), \
+ .cpulock = cpulockptr, \
+ .ctx = ATOMIC_INIT(0), \
+ .wq = &_##name##_wait, \
+ .wq_counter = ATOMIC_LONG_INIT(0), \
+ .wq_work = &_##name##_wake_work, \
+}
+
+/* writer interface */
+char *prb_reserve(struct prb_handle *h, struct printk_ringbuffer *rb,
+ unsigned int size);
+void prb_commit(struct prb_handle *h);
+
+/* reader interface */
+void prb_iter_init(struct prb_iterator *iter, struct printk_ringbuffer *rb,
+ u64 *seq);
+void prb_iter_copy(struct prb_iterator *dest, struct prb_iterator *src);
+int prb_iter_next(struct prb_iterator *iter, char *buf, int size, u64 *seq);
+int prb_iter_wait_next(struct prb_iterator *iter, char *buf, int size,
+ u64 *seq);
+int prb_iter_seek(struct prb_iterator *iter, u64 seq);
+int prb_iter_data(struct prb_iterator *iter, char *buf, int size, u64 *seq);
+
+/* utility functions */
+int prb_buffer_size(struct printk_ringbuffer *rb);
+void prb_inc_lost(struct printk_ringbuffer *rb);
+void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store);
+void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store);
+
+#endif /*_LINUX_PRINTK_RINGBUFFER_H */
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 63e62372443a5..040b1fd0ab940 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -226,6 +226,7 @@ unsigned int radix_tree_gang_lookup(const struct radix_tree_root *,
unsigned int max_items);
int radix_tree_preload(gfp_t gfp_mask);
int radix_tree_maybe_preload(gfp_t gfp_mask);
+void radix_tree_preload_end(void);
void radix_tree_init(void);
void *radix_tree_tag_set(struct radix_tree_root *,
unsigned long index, unsigned int tag);
@@ -243,11 +244,6 @@ unsigned int radix_tree_gang_lookup_tag_slot(const struct radix_tree_root *,
unsigned int max_items, unsigned int tag);
int radix_tree_tagged(const struct radix_tree_root *, unsigned int tag);
-static inline void radix_tree_preload_end(void)
-{
- preempt_enable();
-}
-
void __rcu **idr_get_free(struct radix_tree_root *root,
struct radix_tree_iter *iter, gfp_t gfp,
unsigned long max);
diff --git a/include/linux/random.h b/include/linux/random.h
index f189c927fdea5..62d8caa3b0b12 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -33,7 +33,7 @@ static inline void add_latent_entropy(void) {}
extern void add_input_randomness(unsigned int type, unsigned int code,
unsigned int value) __latent_entropy;
-extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy;
+extern void add_interrupt_randomness(int irq, int irq_flags, __u64 ip) __latent_entropy;
extern void get_random_bytes(void *buf, int nbytes);
extern int wait_for_random_bytes(void);
diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h
index 8ddf79e9207a9..51e90cea9c455 100644
--- a/include/linux/ratelimit.h
+++ b/include/linux/ratelimit.h
@@ -59,7 +59,7 @@ static inline void ratelimit_state_exit(struct ratelimit_state *rs)
return;
if (rs->missed) {
- pr_warn("%s: %d output lines suppressed due to ratelimiting\n",
+ pr_info("%s: %d output lines suppressed due to ratelimiting\n",
current->comm, rs->missed);
rs->missed = 0;
}
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index 1fd61a9af45cd..c667ec871abb5 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -19,7 +19,7 @@
#include
#include
-#include
+#include
struct rb_node {
unsigned long __rb_parent_color;
diff --git a/include/linux/rcu_assign_pointer.h b/include/linux/rcu_assign_pointer.h
new file mode 100644
index 0000000000000..78c05f606a73d
--- /dev/null
+++ b/include/linux/rcu_assign_pointer.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef __LINUX_RCU_ASSIGN_POINTER_H__
+#define __LINUX_RCU_ASSIGN_POINTER_H__
+#include
+#include
+
+#ifdef __CHECKER__
+#define rcu_check_sparse(p, space) \
+ ((void)(((typeof(*p) space *)p) == p))
+#else /* #ifdef __CHECKER__ */
+#define rcu_check_sparse(p, space)
+#endif /* #else #ifdef __CHECKER__ */
+
+/**
+ * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
+ * @v: The value to statically initialize with.
+ */
+#define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
+
+/**
+ * rcu_assign_pointer() - assign to RCU-protected pointer
+ * @p: pointer to assign to
+ * @v: value to assign (publish)
+ *
+ * Assigns the specified value to the specified RCU-protected
+ * pointer, ensuring that any concurrent RCU readers will see
+ * any prior initialization.
+ *
+ * Inserts memory barriers on architectures that require them
+ * (which is most of them), and also prevents the compiler from
+ * reordering the code that initializes the structure after the pointer
+ * assignment. More importantly, this call documents which pointers
+ * will be dereferenced by RCU read-side code.
+ *
+ * In some special cases, you may use RCU_INIT_POINTER() instead
+ * of rcu_assign_pointer(). RCU_INIT_POINTER() is a bit faster due
+ * to the fact that it does not constrain either the CPU or the compiler.
+ * That said, using RCU_INIT_POINTER() when you should have used
+ * rcu_assign_pointer() is a very bad thing that results in
+ * impossible-to-diagnose memory corruption. So please be careful.
+ * See the RCU_INIT_POINTER() comment header for details.
+ *
+ * Note that rcu_assign_pointer() evaluates each of its arguments only
+ * once, appearances notwithstanding. One of the "extra" evaluations
+ * is in typeof() and the other visible only to sparse (__CHECKER__),
+ * neither of which actually execute the argument. As with most cpp
+ * macros, this execute-arguments-only-once property is important, so
+ * please be careful when making changes to rcu_assign_pointer() and the
+ * other macros that it invokes.
+ */
+#define rcu_assign_pointer(p, v) \
+do { \
+ uintptr_t _r_a_p__v = (uintptr_t)(v); \
+ rcu_check_sparse(p, __rcu); \
+ \
+ if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \
+ WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \
+ else \
+ smp_store_release(&p, RCU_INITIALIZER((typeof(p))_r_a_p__v)); \
+} while (0)
+
+#endif
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 75a2eded7aa2c..4b7c52128409d 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b))
#define ULONG_CMP_LT(a, b) (ULONG_MAX / 2 < (a) - (b))
@@ -51,6 +52,11 @@ void __rcu_read_unlock(void);
* types of kernel builds, the rcu_read_lock() nesting depth is unknowable.
*/
#define rcu_preempt_depth() (current->rcu_read_lock_nesting)
+#ifndef CONFIG_PREEMPT_RT
+#define sched_rcu_preempt_depth() rcu_preempt_depth()
+#else
+static inline int sched_rcu_preempt_depth(void) { return 0; }
+#endif
#else /* #ifdef CONFIG_PREEMPT_RCU */
@@ -69,6 +75,8 @@ static inline int rcu_preempt_depth(void)
return 0;
}
+#define sched_rcu_preempt_depth() rcu_preempt_depth()
+
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
/* Internal to kernel */
@@ -154,7 +162,7 @@ static inline void exit_tasks_rcu_finish(void) { }
*
* This macro resembles cond_resched(), except that it is defined to
* report potential quiescent states to RCU-tasks even if the cond_resched()
- * machinery were to be shut off, as some advocate for PREEMPT kernels.
+ * machinery were to be shut off, as some advocate for PREEMPTION kernels.
*/
#define cond_resched_tasks_rcu_qs() \
do { \
@@ -279,7 +287,8 @@ static inline void rcu_preempt_sleep_check(void) { }
#define rcu_sleep_check() \
do { \
rcu_preempt_sleep_check(); \
- RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map), \
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) \
+ RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map), \
"Illegal context switch in RCU-bh read-side critical section"); \
RCU_LOCKDEP_WARN(lock_is_held(&rcu_sched_lock_map), \
"Illegal context switch in RCU-sched read-side critical section"); \
@@ -300,13 +309,6 @@ static inline void rcu_preempt_sleep_check(void) { }
* (e.g., __srcu), should this make sense in the future.
*/
-#ifdef __CHECKER__
-#define rcu_check_sparse(p, space) \
- ((void)(((typeof(*p) space *)p) == p))
-#else /* #ifdef __CHECKER__ */
-#define rcu_check_sparse(p, space)
-#endif /* #else #ifdef __CHECKER__ */
-
#define __rcu_access_pointer(p, space) \
({ \
typeof(*p) *_________p1 = (typeof(*p) *__force)READ_ONCE(p); \
@@ -334,54 +336,6 @@ static inline void rcu_preempt_sleep_check(void) { }
((typeof(*p) __force __kernel *)(________p1)); \
})
-/**
- * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
- * @v: The value to statically initialize with.
- */
-#define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
-
-/**
- * rcu_assign_pointer() - assign to RCU-protected pointer
- * @p: pointer to assign to
- * @v: value to assign (publish)
- *
- * Assigns the specified value to the specified RCU-protected
- * pointer, ensuring that any concurrent RCU readers will see
- * any prior initialization.
- *
- * Inserts memory barriers on architectures that require them
- * (which is most of them), and also prevents the compiler from
- * reordering the code that initializes the structure after the pointer
- * assignment. More importantly, this call documents which pointers
- * will be dereferenced by RCU read-side code.
- *
- * In some special cases, you may use RCU_INIT_POINTER() instead
- * of rcu_assign_pointer(). RCU_INIT_POINTER() is a bit faster due
- * to the fact that it does not constrain either the CPU or the compiler.
- * That said, using RCU_INIT_POINTER() when you should have used
- * rcu_assign_pointer() is a very bad thing that results in
- * impossible-to-diagnose memory corruption. So please be careful.
- * See the RCU_INIT_POINTER() comment header for details.
- *
- * Note that rcu_assign_pointer() evaluates each of its arguments only
- * once, appearances notwithstanding. One of the "extra" evaluations
- * is in typeof() and the other visible only to sparse (__CHECKER__),
- * neither of which actually execute the argument. As with most cpp
- * macros, this execute-arguments-only-once property is important, so
- * please be careful when making changes to rcu_assign_pointer() and the
- * other macros that it invokes.
- */
-#define rcu_assign_pointer(p, v) \
-do { \
- uintptr_t _r_a_p__v = (uintptr_t)(v); \
- rcu_check_sparse(p, __rcu); \
- \
- if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \
- WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \
- else \
- smp_store_release(&p, RCU_INITIALIZER((typeof(p))_r_a_p__v)); \
-} while (0)
-
/**
* rcu_swap_protected() - swap an RCU and a regular pointer
* @rcu_ptr: RCU pointer
@@ -580,7 +534,7 @@ do { \
*
* You can avoid reading and understanding the next paragraph by
* following this rule: don't put anything in an rcu_read_lock() RCU
- * read-side critical section that would block in a !PREEMPT kernel.
+ * read-side critical section that would block in a !PREEMPTION kernel.
* But if you want the full story, read on!
*
* In non-preemptible RCU implementations (TREE_RCU and TINY_RCU),
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
index 6fd615a0eea94..138bd1e183e09 100644
--- a/include/linux/rtmutex.h
+++ b/include/linux/rtmutex.h
@@ -14,11 +14,15 @@
#define __LINUX_RT_MUTEX_H
#include
+#include
#include
-#include
extern int max_lock_depth; /* for sysctl */
+#ifdef CONFIG_DEBUG_MUTEXES
+#include
+#endif
+
/**
* The rt_mutex structure
*
@@ -31,8 +35,8 @@ struct rt_mutex {
raw_spinlock_t wait_lock;
struct rb_root_cached waiters;
struct task_struct *owner;
-#ifdef CONFIG_DEBUG_RT_MUTEXES
int save_state;
+#ifdef CONFIG_DEBUG_RT_MUTEXES
const char *name, *file;
int line;
void *magic;
@@ -82,16 +86,23 @@ do { \
#define __DEP_MAP_RT_MUTEX_INITIALIZER(mutexname)
#endif
-#define __RT_MUTEX_INITIALIZER(mutexname) \
- { .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \
+#define __RT_MUTEX_INITIALIZER_PLAIN(mutexname) \
+ .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \
, .waiters = RB_ROOT_CACHED \
, .owner = NULL \
__DEBUG_RT_MUTEX_INITIALIZER(mutexname) \
- __DEP_MAP_RT_MUTEX_INITIALIZER(mutexname)}
+ __DEP_MAP_RT_MUTEX_INITIALIZER(mutexname)
+
+#define __RT_MUTEX_INITIALIZER(mutexname) \
+ { __RT_MUTEX_INITIALIZER_PLAIN(mutexname) }
#define DEFINE_RT_MUTEX(mutexname) \
struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname)
+#define __RT_MUTEX_INITIALIZER_SAVE_STATE(mutexname) \
+ { __RT_MUTEX_INITIALIZER_PLAIN(mutexname) \
+ , .save_state = 1 }
+
/**
* rt_mutex_is_locked - is the mutex locked
* @lock: the mutex to be queried
@@ -115,6 +126,7 @@ extern void rt_mutex_lock(struct rt_mutex *lock);
#endif
extern int rt_mutex_lock_interruptible(struct rt_mutex *lock);
+extern int rt_mutex_lock_killable(struct rt_mutex *lock);
extern int rt_mutex_timed_lock(struct rt_mutex *lock,
struct hrtimer_sleeper *timeout);
diff --git a/include/linux/rwlock_rt.h b/include/linux/rwlock_rt.h
new file mode 100644
index 0000000000000..a9c4c2ac4d1fa
--- /dev/null
+++ b/include/linux/rwlock_rt.h
@@ -0,0 +1,119 @@
+#ifndef __LINUX_RWLOCK_RT_H
+#define __LINUX_RWLOCK_RT_H
+
+#ifndef __LINUX_SPINLOCK_H
+#error Do not include directly. Use spinlock.h
+#endif
+
+extern void __lockfunc rt_write_lock(rwlock_t *rwlock);
+extern void __lockfunc rt_read_lock(rwlock_t *rwlock);
+extern int __lockfunc rt_write_trylock(rwlock_t *rwlock);
+extern int __lockfunc rt_read_trylock(rwlock_t *rwlock);
+extern void __lockfunc rt_write_unlock(rwlock_t *rwlock);
+extern void __lockfunc rt_read_unlock(rwlock_t *rwlock);
+extern int __lockfunc rt_read_can_lock(rwlock_t *rwlock);
+extern int __lockfunc rt_write_can_lock(rwlock_t *rwlock);
+extern void __rt_rwlock_init(rwlock_t *rwlock, char *name, struct lock_class_key *key);
+
+#define read_can_lock(rwlock) rt_read_can_lock(rwlock)
+#define write_can_lock(rwlock) rt_write_can_lock(rwlock)
+
+#define read_trylock(lock) __cond_lock(lock, rt_read_trylock(lock))
+#define write_trylock(lock) __cond_lock(lock, rt_write_trylock(lock))
+
+static inline int __write_trylock_rt_irqsave(rwlock_t *lock, unsigned long *flags)
+{
+ /* XXX ARCH_IRQ_ENABLED */
+ *flags = 0;
+ return rt_write_trylock(lock);
+}
+
+#define write_trylock_irqsave(lock, flags) \
+ __cond_lock(lock, __write_trylock_rt_irqsave(lock, &(flags)))
+
+#define read_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ rt_read_lock(lock); \
+ flags = 0; \
+ } while (0)
+
+#define write_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ rt_write_lock(lock); \
+ flags = 0; \
+ } while (0)
+
+#define read_lock(lock) rt_read_lock(lock)
+
+#define read_lock_bh(lock) \
+ do { \
+ local_bh_disable(); \
+ rt_read_lock(lock); \
+ } while (0)
+
+#define read_lock_irq(lock) read_lock(lock)
+
+#define write_lock(lock) rt_write_lock(lock)
+
+#define write_lock_bh(lock) \
+ do { \
+ local_bh_disable(); \
+ rt_write_lock(lock); \
+ } while (0)
+
+#define write_lock_irq(lock) write_lock(lock)
+
+#define read_unlock(lock) rt_read_unlock(lock)
+
+#define read_unlock_bh(lock) \
+ do { \
+ rt_read_unlock(lock); \
+ local_bh_enable(); \
+ } while (0)
+
+#define read_unlock_irq(lock) read_unlock(lock)
+
+#define write_unlock(lock) rt_write_unlock(lock)
+
+#define write_unlock_bh(lock) \
+ do { \
+ rt_write_unlock(lock); \
+ local_bh_enable(); \
+ } while (0)
+
+#define write_unlock_irq(lock) write_unlock(lock)
+
+#define read_unlock_irqrestore(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ (void) flags; \
+ rt_read_unlock(lock); \
+ } while (0)
+
+#define write_unlock_irqrestore(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ (void) flags; \
+ rt_write_unlock(lock); \
+ } while (0)
+
+#define rwlock_init(rwl) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ __rt_rwlock_init(rwl, #rwl, &__key); \
+} while (0)
+
+/*
+ * Internal functions made global for CPU pinning
+ */
+void __read_rt_lock(struct rt_rw_lock *lock);
+int __read_rt_trylock(struct rt_rw_lock *lock);
+void __write_rt_lock(struct rt_rw_lock *lock);
+int __write_rt_trylock(struct rt_rw_lock *lock);
+void __read_rt_unlock(struct rt_rw_lock *lock);
+void __write_rt_unlock(struct rt_rw_lock *lock);
+
+#endif
diff --git a/include/linux/rwlock_types.h b/include/linux/rwlock_types.h
index 857a72ceb7942..c21683f3e14af 100644
--- a/include/linux/rwlock_types.h
+++ b/include/linux/rwlock_types.h
@@ -1,6 +1,10 @@
#ifndef __LINUX_RWLOCK_TYPES_H
#define __LINUX_RWLOCK_TYPES_H
+#if !defined(__LINUX_SPINLOCK_TYPES_H)
+# error "Do not include directly, include spinlock_types.h"
+#endif
+
/*
* include/linux/rwlock_types.h - generic rwlock type definitions
* and initializers
diff --git a/include/linux/rwlock_types_rt.h b/include/linux/rwlock_types_rt.h
new file mode 100644
index 0000000000000..546a1f8f12748
--- /dev/null
+++ b/include/linux/rwlock_types_rt.h
@@ -0,0 +1,55 @@
+#ifndef __LINUX_RWLOCK_TYPES_RT_H
+#define __LINUX_RWLOCK_TYPES_RT_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+#error "Do not include directly. Include spinlock_types.h instead"
+#endif
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define RW_DEP_MAP_INIT(lockname) .dep_map = { .name = #lockname }
+#else
+# define RW_DEP_MAP_INIT(lockname)
+#endif
+
+typedef struct rt_rw_lock rwlock_t;
+
+#define __RW_LOCK_UNLOCKED(name) __RWLOCK_RT_INITIALIZER(name)
+
+#define DEFINE_RWLOCK(name) \
+ rwlock_t name = __RW_LOCK_UNLOCKED(name)
+
+/*
+ * A reader biased implementation primarily for CPU pinning.
+ *
+ * Can be selected as general replacement for the single reader RT rwlock
+ * variant
+ */
+struct rt_rw_lock {
+ struct rt_mutex rtmutex;
+ atomic_t readers;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
+};
+
+#define READER_BIAS (1U << 31)
+#define WRITER_BIAS (1U << 30)
+
+#define __RWLOCK_RT_INITIALIZER(name) \
+{ \
+ .readers = ATOMIC_INIT(READER_BIAS), \
+ .rtmutex = __RT_MUTEX_INITIALIZER_SAVE_STATE(name.rtmutex), \
+ RW_DEP_MAP_INIT(name) \
+}
+
+void __rwlock_biased_rt_init(struct rt_rw_lock *lock, const char *name,
+ struct lock_class_key *key);
+
+#define rwlock_biased_rt_init(rwlock) \
+ do { \
+ static struct lock_class_key __key; \
+ \
+ __rwlock_biased_rt_init((rwlock), #rwlock, &__key); \
+ } while (0)
+
+#endif
diff --git a/include/linux/rwsem-rt.h b/include/linux/rwsem-rt.h
new file mode 100644
index 0000000000000..2018ff77904ad
--- /dev/null
+++ b/include/linux/rwsem-rt.h
@@ -0,0 +1,68 @@
+#ifndef _LINUX_RWSEM_RT_H
+#define _LINUX_RWSEM_RT_H
+
+#ifndef _LINUX_RWSEM_H
+#error "Include rwsem.h"
+#endif
+
+#include
+#include
+
+#define READER_BIAS (1U << 31)
+#define WRITER_BIAS (1U << 30)
+
+struct rw_semaphore {
+ atomic_t readers;
+ struct rt_mutex rtmutex;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
+};
+
+#define __RWSEM_INITIALIZER(name) \
+{ \
+ .readers = ATOMIC_INIT(READER_BIAS), \
+ .rtmutex = __RT_MUTEX_INITIALIZER(name.rtmutex), \
+ RW_DEP_MAP_INIT(name) \
+}
+
+#define DECLARE_RWSEM(lockname) \
+ struct rw_semaphore lockname = __RWSEM_INITIALIZER(lockname)
+
+extern void __rwsem_init(struct rw_semaphore *rwsem, const char *name,
+ struct lock_class_key *key);
+
+#define __init_rwsem(sem, name, key) \
+do { \
+ rt_mutex_init(&(sem)->rtmutex); \
+ __rwsem_init((sem), (name), (key)); \
+} while (0)
+
+#define init_rwsem(sem) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ __init_rwsem((sem), #sem, &__key); \
+} while (0)
+
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+ return atomic_read(&sem->readers) != READER_BIAS;
+}
+
+static inline int rwsem_is_contended(struct rw_semaphore *sem)
+{
+ return atomic_read(&sem->readers) > 0;
+}
+
+extern void __down_read(struct rw_semaphore *sem);
+extern int __down_read_killable(struct rw_semaphore *sem);
+extern int __down_read_trylock(struct rw_semaphore *sem);
+extern void __down_write(struct rw_semaphore *sem);
+extern int __must_check __down_write_killable(struct rw_semaphore *sem);
+extern int __down_write_trylock(struct rw_semaphore *sem);
+extern void __up_read(struct rw_semaphore *sem);
+extern void __up_write(struct rw_semaphore *sem);
+extern void __downgrade_write(struct rw_semaphore *sem);
+
+#endif
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index 00d6054687dd2..393f4520befc9 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -16,6 +16,11 @@
#include
#include
#include
+
+#ifdef CONFIG_PREEMPT_RT
+#include
+#else /* PREEMPT_RT */
+
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
#include
#endif
@@ -53,12 +58,6 @@ struct rw_semaphore {
#endif
};
-/*
- * Setting all bits of the owner field except bit 0 will indicate
- * that the rwsem is writer-owned with an unknown owner.
- */
-#define RWSEM_OWNER_UNKNOWN (-2L)
-
/* In all implementations count != 0 means locked */
static inline int rwsem_is_locked(struct rw_semaphore *sem)
{
@@ -121,6 +120,13 @@ static inline int rwsem_is_contended(struct rw_semaphore *sem)
return !list_empty(&sem->wait_list);
}
+#endif /* !PREEMPT_RT */
+
+/*
+ * The functions below are the same for all rwsem implementations including
+ * the RT specific variant.
+ */
+
/*
* lock for reading
*/
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b968d736833bb..31f5cb1b15200 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
/* task_struct member predeclarations (sorted alphabetically): */
struct audit_context;
@@ -107,12 +108,8 @@ struct task_group;
__TASK_TRACED | EXIT_DEAD | EXIT_ZOMBIE | \
TASK_PARKED)
-#define task_is_traced(task) ((task->state & __TASK_TRACED) != 0)
-
#define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0)
-#define task_is_stopped_or_traced(task) ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
-
#define task_contributes_to_load(task) ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \
(task->flags & PF_FROZEN) == 0 && \
(task->state & TASK_NOLOAD) == 0)
@@ -140,6 +137,9 @@ struct task_group;
smp_store_mb(current->state, (state_value)); \
} while (0)
+#define __set_current_state_no_track(state_value) \
+ current->state = (state_value);
+
#define set_special_state(state_value) \
do { \
unsigned long flags; /* may shadow */ \
@@ -149,6 +149,7 @@ struct task_group;
current->state = (state_value); \
raw_spin_unlock_irqrestore(¤t->pi_lock, flags); \
} while (0)
+
#else
/*
* set_current_state() includes a barrier so that the write of current->state
@@ -193,6 +194,9 @@ struct task_group;
#define set_current_state(state_value) \
smp_store_mb(current->state, (state_value))
+#define __set_current_state_no_track(state_value) \
+ __set_current_state(state_value)
+
/*
* set_special_state() should be used for those states when the blocking task
* can not use the regular condition based wait-loop. In that case we must
@@ -230,6 +234,8 @@ extern void io_schedule_finish(int token);
extern long io_schedule_timeout(long timeout);
extern void io_schedule(void);
+int cpu_nr_pinned(int cpu);
+
/**
* struct prev_cputime - snapshot of system and user cputime
* @utime: time spent in user mode
@@ -631,6 +637,8 @@ struct task_struct {
#endif
/* -1 unrunnable, 0 runnable, >0 stopped: */
volatile long state;
+ /* saved state for "spinlock sleepers" */
+ volatile long saved_state;
/*
* This begins the randomizable portion of task_struct. Only
@@ -700,6 +708,20 @@ struct task_struct {
int nr_cpus_allowed;
const cpumask_t *cpus_ptr;
cpumask_t cpus_mask;
+#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+ int migrate_disable;
+ bool migrate_disable_scheduled;
+# ifdef CONFIG_SCHED_DEBUG
+ int pinned_on_cpu;
+# endif
+#elif !defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+# ifdef CONFIG_SCHED_DEBUG
+ int migrate_disable;
+# endif
+#endif
+#ifdef CONFIG_PREEMPT_RT
+ int sleeping_lock;
+#endif
#ifdef CONFIG_PREEMPT_RCU
int rcu_read_lock_nesting;
@@ -913,11 +935,17 @@ struct task_struct {
/* Signal handlers: */
struct signal_struct *signal;
struct sighand_struct *sighand;
+ struct sigqueue *sigqueue_cache;
+
sigset_t blocked;
sigset_t real_blocked;
/* Restored if set_restore_sigmask() was used: */
sigset_t saved_sigmask;
struct sigpending pending;
+#ifdef CONFIG_PREEMPT_RT
+ /* TODO: move me into ->restart_block ? */
+ struct kernel_siginfo forced_info;
+#endif
unsigned long sas_ss_sp;
size_t sas_ss_size;
unsigned int sas_ss_flags;
@@ -944,6 +972,7 @@ struct task_struct {
raw_spinlock_t pi_lock;
struct wake_q_node wake_q;
+ struct wake_q_node wake_q_sleeper;
#ifdef CONFIG_RT_MUTEXES
/* PI waiters blocked on a rt_mutex held by this task: */
@@ -978,6 +1007,9 @@ struct task_struct {
int softirqs_enabled;
int softirq_context;
#endif
+#ifdef CONFIG_PREEMPT_RT
+ int softirq_count;
+#endif
#ifdef CONFIG_LOCKDEP
# define MAX_LOCK_DEPTH 48UL
@@ -1241,6 +1273,12 @@ struct task_struct {
unsigned int sequential_io;
unsigned int sequential_io_avg;
#endif
+#ifdef CONFIG_PREEMPT_RT
+# if defined CONFIG_HIGHMEM || defined CONFIG_X86_32
+ int kmap_idx;
+ pte_t kmap_pte[KM_TYPE_NR];
+# endif
+#endif
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
unsigned long task_state_change;
#endif
@@ -1672,6 +1710,7 @@ extern struct task_struct *find_get_task_by_vpid(pid_t nr);
extern int wake_up_state(struct task_struct *tsk, unsigned int state);
extern int wake_up_process(struct task_struct *tsk);
+extern int wake_up_lock_sleeper(struct task_struct *tsk);
extern void wake_up_new_task(struct task_struct *tsk);
#ifdef CONFIG_SMP
@@ -1754,6 +1793,89 @@ static inline int test_tsk_need_resched(struct task_struct *tsk)
return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED));
}
+#ifdef CONFIG_PREEMPT_LAZY
+static inline void set_tsk_need_resched_lazy(struct task_struct *tsk)
+{
+ set_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY);
+}
+
+static inline void clear_tsk_need_resched_lazy(struct task_struct *tsk)
+{
+ clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY);
+}
+
+static inline int test_tsk_need_resched_lazy(struct task_struct *tsk)
+{
+ return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY));
+}
+
+static inline int need_resched_lazy(void)
+{
+ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
+}
+
+static inline int need_resched_now(void)
+{
+ return test_thread_flag(TIF_NEED_RESCHED);
+}
+
+#else
+static inline void clear_tsk_need_resched_lazy(struct task_struct *tsk) { }
+static inline int need_resched_lazy(void) { return 0; }
+
+static inline int need_resched_now(void)
+{
+ return test_thread_flag(TIF_NEED_RESCHED);
+}
+
+#endif
+
+
+static inline bool __task_is_stopped_or_traced(struct task_struct *task)
+{
+ if (task->state & (__TASK_STOPPED | __TASK_TRACED))
+ return true;
+#ifdef CONFIG_PREEMPT_RT
+ if (task->saved_state & (__TASK_STOPPED | __TASK_TRACED))
+ return true;
+#endif
+ return false;
+}
+
+static inline bool task_is_stopped_or_traced(struct task_struct *task)
+{
+ bool traced_stopped;
+
+#ifdef CONFIG_PREEMPT_RT
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&task->pi_lock, flags);
+ traced_stopped = __task_is_stopped_or_traced(task);
+ raw_spin_unlock_irqrestore(&task->pi_lock, flags);
+#else
+ traced_stopped = __task_is_stopped_or_traced(task);
+#endif
+ return traced_stopped;
+}
+
+static inline bool task_is_traced(struct task_struct *task)
+{
+ bool traced = false;
+
+ if (task->state & __TASK_TRACED)
+ return true;
+#ifdef CONFIG_PREEMPT_RT
+ /* in case the task is sleeping on tasklist_lock */
+ raw_spin_lock_irq(&task->pi_lock);
+ if (task->state & __TASK_TRACED)
+ traced = true;
+ else if (task->saved_state & __TASK_TRACED)
+ traced = true;
+ raw_spin_unlock_irq(&task->pi_lock);
+#endif
+ return traced;
+}
+
/*
* cond_resched() and cond_resched_lock(): latency reduction via
* explicit rescheduling in places that are safe. The return
@@ -1806,6 +1928,23 @@ static __always_inline bool need_resched(void)
return unlikely(tif_need_resched());
}
+#ifdef CONFIG_PREEMPT_RT
+static inline void sleeping_lock_inc(void)
+{
+ current->sleeping_lock++;
+}
+
+static inline void sleeping_lock_dec(void)
+{
+ current->sleeping_lock--;
+}
+
+#else
+
+static inline void sleeping_lock_inc(void) { }
+static inline void sleeping_lock_dec(void) { }
+#endif
+
/*
* Wrappers for p->thread_info->cpu access. No-op on UP.
*/
@@ -1997,4 +2136,6 @@ int sched_trace_rq_cpu(struct rq *rq);
const struct cpumask *sched_trace_rd_span(struct root_domain *rd);
+extern struct task_struct *takedown_cpu_task;
+
#endif
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
index c49257a3b5108..2a498fc3d949f 100644
--- a/include/linux/sched/mm.h
+++ b/include/linux/sched/mm.h
@@ -49,6 +49,17 @@ static inline void mmdrop(struct mm_struct *mm)
__mmdrop(mm);
}
+#ifdef CONFIG_PREEMPT_RT
+extern void __mmdrop_delayed(struct rcu_head *rhp);
+static inline void mmdrop_delayed(struct mm_struct *mm)
+{
+ if (atomic_dec_and_test(&mm->mm_count))
+ call_rcu(&mm->delayed_drop, __mmdrop_delayed);
+}
+#else
+# define mmdrop_delayed(mm) mmdrop(mm)
+#endif
+
/*
* This has to be called after a get_task_mm()/mmget_not_zero()
* followed by taking the mmap_sem for writing before modifying the
diff --git a/include/linux/sched/wake_q.h b/include/linux/sched/wake_q.h
index 26a2013ac39c4..6e2dff721547c 100644
--- a/include/linux/sched/wake_q.h
+++ b/include/linux/sched/wake_q.h
@@ -58,6 +58,17 @@ static inline bool wake_q_empty(struct wake_q_head *head)
extern void wake_q_add(struct wake_q_head *head, struct task_struct *task);
extern void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task);
-extern void wake_up_q(struct wake_q_head *head);
+extern void wake_q_add_sleeper(struct wake_q_head *head, struct task_struct *task);
+extern void __wake_up_q(struct wake_q_head *head, bool sleeper);
+
+static inline void wake_up_q(struct wake_q_head *head)
+{
+ __wake_up_q(head, false);
+}
+
+static inline void wake_up_q_sleeper(struct wake_q_head *head)
+{
+ __wake_up_q(head, true);
+}
#endif /* _LINUX_SCHED_WAKE_Q_H */
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index bcf4cf26b8c89..bc458c2658e4d 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -221,20 +221,30 @@ static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
return __read_seqcount_retry(s, start);
}
-
-
-static inline void raw_write_seqcount_begin(seqcount_t *s)
+static inline void __raw_write_seqcount_begin(seqcount_t *s)
{
s->sequence++;
smp_wmb();
}
-static inline void raw_write_seqcount_end(seqcount_t *s)
+static inline void raw_write_seqcount_begin(seqcount_t *s)
+{
+ preempt_disable_rt();
+ __raw_write_seqcount_begin(s);
+}
+
+static inline void __raw_write_seqcount_end(seqcount_t *s)
{
smp_wmb();
s->sequence++;
}
+static inline void raw_write_seqcount_end(seqcount_t *s)
+{
+ __raw_write_seqcount_end(s);
+ preempt_enable_rt();
+}
+
/**
* raw_write_seqcount_barrier - do a seq write barrier
* @s: pointer to seqcount_t
@@ -428,10 +438,33 @@ typedef struct {
/*
* Read side functions for starting and finalizing a read side section.
*/
+#ifndef CONFIG_PREEMPT_RT
static inline unsigned read_seqbegin(const seqlock_t *sl)
{
return read_seqcount_begin(&sl->seqcount);
}
+#else
+/*
+ * Starvation safe read side for RT
+ */
+static inline unsigned read_seqbegin(seqlock_t *sl)
+{
+ unsigned ret;
+
+repeat:
+ ret = READ_ONCE(sl->seqcount.sequence);
+ if (unlikely(ret & 1)) {
+ /*
+ * Take the lock and let the writer proceed (i.e. evtl
+ * boost it), otherwise we could loop here forever.
+ */
+ spin_unlock_wait(&sl->lock);
+ goto repeat;
+ }
+ smp_rmb();
+ return ret;
+}
+#endif
static inline unsigned read_seqretry(const seqlock_t *sl, unsigned start)
{
@@ -446,36 +479,45 @@ static inline unsigned read_seqretry(const seqlock_t *sl, unsigned start)
static inline void write_seqlock(seqlock_t *sl)
{
spin_lock(&sl->lock);
- write_seqcount_begin(&sl->seqcount);
+ __raw_write_seqcount_begin(&sl->seqcount);
+}
+
+static inline int try_write_seqlock(seqlock_t *sl)
+{
+ if (spin_trylock(&sl->lock)) {
+ __raw_write_seqcount_begin(&sl->seqcount);
+ return 1;
+ }
+ return 0;
}
static inline void write_sequnlock(seqlock_t *sl)
{
- write_seqcount_end(&sl->seqcount);
+ __raw_write_seqcount_end(&sl->seqcount);
spin_unlock(&sl->lock);
}
static inline void write_seqlock_bh(seqlock_t *sl)
{
spin_lock_bh(&sl->lock);
- write_seqcount_begin(&sl->seqcount);
+ __raw_write_seqcount_begin(&sl->seqcount);
}
static inline void write_sequnlock_bh(seqlock_t *sl)
{
- write_seqcount_end(&sl->seqcount);
+ __raw_write_seqcount_end(&sl->seqcount);
spin_unlock_bh(&sl->lock);
}
static inline void write_seqlock_irq(seqlock_t *sl)
{
spin_lock_irq(&sl->lock);
- write_seqcount_begin(&sl->seqcount);
+ __raw_write_seqcount_begin(&sl->seqcount);
}
static inline void write_sequnlock_irq(seqlock_t *sl)
{
- write_seqcount_end(&sl->seqcount);
+ __raw_write_seqcount_end(&sl->seqcount);
spin_unlock_irq(&sl->lock);
}
@@ -484,7 +526,7 @@ static inline unsigned long __write_seqlock_irqsave(seqlock_t *sl)
unsigned long flags;
spin_lock_irqsave(&sl->lock, flags);
- write_seqcount_begin(&sl->seqcount);
+ __raw_write_seqcount_begin(&sl->seqcount);
return flags;
}
@@ -494,7 +536,7 @@ static inline unsigned long __write_seqlock_irqsave(seqlock_t *sl)
static inline void
write_sequnlock_irqrestore(seqlock_t *sl, unsigned long flags)
{
- write_seqcount_end(&sl->seqcount);
+ __raw_write_seqcount_end(&sl->seqcount);
spin_unlock_irqrestore(&sl->lock, flags);
}
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index bb2bc99388cae..be74bb7cae64f 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -7,6 +7,7 @@
#ifndef _LINUX_SERIAL_8250_H
#define _LINUX_SERIAL_8250_H
+#include
#include
#include
#include
@@ -123,6 +124,8 @@ struct uart_8250_port {
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
unsigned char msr_saved_flags;
+ atomic_t console_printing;
+
struct uart_8250_dma *dma;
const struct uart_8250_ops *ops;
@@ -174,6 +177,8 @@ void serial8250_init_port(struct uart_8250_port *up);
void serial8250_set_defaults(struct uart_8250_port *up);
void serial8250_console_write(struct uart_8250_port *up, const char *s,
unsigned int count);
+void serial8250_console_write_atomic(struct uart_8250_port *up, const char *s,
+ unsigned int count);
int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
extern void serial8250_set_isa_configurator(void (*v)
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 1a5f88316b081..1870c233799ee 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -255,6 +255,7 @@ static inline void init_sigpending(struct sigpending *sig)
}
extern void flush_sigqueue(struct sigpending *queue);
+extern void flush_task_sigqueue(struct task_struct *tsk);
/* Test if 'sig' is valid signal. Use this instead of testing _NSIG directly */
static inline int valid_signal(unsigned long sig)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6ae88b0c1c31d..e0178d7b775e7 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -293,6 +293,7 @@ struct sk_buff_head {
__u32 qlen;
spinlock_t lock;
+ raw_spinlock_t raw_lock;
};
struct sk_buff;
@@ -1844,6 +1845,12 @@ static inline void skb_queue_head_init(struct sk_buff_head *list)
__skb_queue_head_init(list);
}
+static inline void skb_queue_head_init_raw(struct sk_buff_head *list)
+{
+ raw_spin_lock_init(&list->raw_lock);
+ __skb_queue_head_init(list);
+}
+
static inline void skb_queue_head_init_class(struct sk_buff_head *list,
struct lock_class_key *class)
{
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 6fc856c9eda58..01ff6ed61591f 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -15,6 +15,7 @@
#include
typedef void (*smp_call_func_t)(void *info);
+typedef bool (*smp_cond_func_t)(int cpu, void *info);
struct __call_single_data {
struct llist_node llist;
smp_call_func_t func;
@@ -49,13 +50,11 @@ void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
* cond_func returns a positive value. This may include the local
* processor.
*/
-void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
- smp_call_func_t func, void *info, bool wait,
- gfp_t gfp_flags);
+void on_each_cpu_cond(smp_cond_func_t cond_func, smp_call_func_t func,
+ void *info, bool wait);
-void on_each_cpu_cond_mask(bool (*cond_func)(int cpu, void *info),
- smp_call_func_t func, void *info, bool wait,
- gfp_t gfp_flags, const struct cpumask *mask);
+void on_each_cpu_cond_mask(smp_cond_func_t cond_func, smp_call_func_t func,
+ void *info, bool wait, const struct cpumask *mask);
int smp_call_function_single_async(int cpu, call_single_data_t *csd);
@@ -222,6 +221,9 @@ static inline int get_boot_cpu_id(void)
#define get_cpu() ({ preempt_disable(); __smp_processor_id(); })
#define put_cpu() preempt_enable()
+#define get_cpu_light() ({ migrate_disable(); __smp_processor_id(); })
+#define put_cpu_light() migrate_enable()
+
/*
* Callback to arch code if there's nosmp or maxcpus=0 on the
* boot command line:
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 031ce8617df8f..826ddd48e6059 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -307,7 +307,11 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
})
/* Include rwlock functions */
-#include
+#ifdef CONFIG_PREEMPT_RT
+# include
+#else
+# include
+#endif
/*
* Pull the _spin_*()/_read_*()/_write_*() functions/declarations:
@@ -318,6 +322,10 @@ static inline void do_raw_spin_unlock(raw_spinlock_t *lock) __releases(lock)
# include
#endif
+#ifdef CONFIG_PREEMPT_RT
+# include
+#else /* PREEMPT_RT */
+
/*
* Map the spin_lock functions to the raw variants for PREEMPT_RT=n
*/
@@ -438,6 +446,8 @@ static __always_inline int spin_is_contended(spinlock_t *lock)
#define assert_spin_locked(lock) assert_raw_spin_locked(&(lock)->rlock)
+#endif /* !PREEMPT_RT */
+
/*
* Pull the atomic_t declaration:
* (asm-mips/atomic.h needs above definitions)
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
index b762eaba4cdf4..60f593969fe13 100644
--- a/include/linux/spinlock_api_smp.h
+++ b/include/linux/spinlock_api_smp.h
@@ -187,6 +187,8 @@ static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock)
return 0;
}
-#include
+#ifndef CONFIG_PREEMPT_RT
+# include
+#endif
#endif /* __LINUX_SPINLOCK_API_SMP_H */
diff --git a/include/linux/spinlock_rt.h b/include/linux/spinlock_rt.h
new file mode 100644
index 0000000000000..3696a77fa77d6
--- /dev/null
+++ b/include/linux/spinlock_rt.h
@@ -0,0 +1,156 @@
+#ifndef __LINUX_SPINLOCK_RT_H
+#define __LINUX_SPINLOCK_RT_H
+
+#ifndef __LINUX_SPINLOCK_H
+#error Do not include directly. Use spinlock.h
+#endif
+
+#include
+
+extern void
+__rt_spin_lock_init(spinlock_t *lock, const char *name, struct lock_class_key *key);
+
+#define spin_lock_init(slock) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ rt_mutex_init(&(slock)->lock); \
+ __rt_spin_lock_init(slock, #slock, &__key); \
+} while (0)
+
+extern void __lockfunc rt_spin_lock(spinlock_t *lock);
+extern unsigned long __lockfunc rt_spin_lock_trace_flags(spinlock_t *lock);
+extern void __lockfunc rt_spin_lock_nested(spinlock_t *lock, int subclass);
+extern void __lockfunc rt_spin_unlock(spinlock_t *lock);
+extern void __lockfunc rt_spin_unlock_wait(spinlock_t *lock);
+extern int __lockfunc rt_spin_trylock_irqsave(spinlock_t *lock, unsigned long *flags);
+extern int __lockfunc rt_spin_trylock_bh(spinlock_t *lock);
+extern int __lockfunc rt_spin_trylock(spinlock_t *lock);
+extern int atomic_dec_and_spin_lock(atomic_t *atomic, spinlock_t *lock);
+
+/*
+ * lockdep-less calls, for derived types like rwlock:
+ * (for trylock they can use rt_mutex_trylock() directly.
+ * Migrate disable handling must be done at the call site.
+ */
+extern void __lockfunc __rt_spin_lock(struct rt_mutex *lock);
+extern void __lockfunc __rt_spin_trylock(struct rt_mutex *lock);
+extern void __lockfunc __rt_spin_unlock(struct rt_mutex *lock);
+
+#define spin_lock(lock) rt_spin_lock(lock)
+
+#define spin_lock_bh(lock) \
+ do { \
+ local_bh_disable(); \
+ rt_spin_lock(lock); \
+ } while (0)
+
+#define spin_lock_irq(lock) spin_lock(lock)
+
+#define spin_do_trylock(lock) __cond_lock(lock, rt_spin_trylock(lock))
+
+#define spin_trylock(lock) \
+({ \
+ int __locked; \
+ __locked = spin_do_trylock(lock); \
+ __locked; \
+})
+
+#ifdef CONFIG_LOCKDEP
+# define spin_lock_nested(lock, subclass) \
+ do { \
+ rt_spin_lock_nested(lock, subclass); \
+ } while (0)
+
+#define spin_lock_bh_nested(lock, subclass) \
+ do { \
+ local_bh_disable(); \
+ rt_spin_lock_nested(lock, subclass); \
+ } while (0)
+
+# define spin_lock_irqsave_nested(lock, flags, subclass) \
+ do { \
+ typecheck(unsigned long, flags); \
+ flags = 0; \
+ rt_spin_lock_nested(lock, subclass); \
+ } while (0)
+#else
+# define spin_lock_nested(lock, subclass) spin_lock(lock)
+# define spin_lock_bh_nested(lock, subclass) spin_lock_bh(lock)
+
+# define spin_lock_irqsave_nested(lock, flags, subclass) \
+ do { \
+ typecheck(unsigned long, flags); \
+ flags = 0; \
+ spin_lock(lock); \
+ } while (0)
+#endif
+
+#define spin_lock_irqsave(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ flags = 0; \
+ spin_lock(lock); \
+ } while (0)
+
+static inline unsigned long spin_lock_trace_flags(spinlock_t *lock)
+{
+ unsigned long flags = 0;
+#ifdef CONFIG_TRACE_IRQFLAGS
+ flags = rt_spin_lock_trace_flags(lock);
+#else
+ spin_lock(lock); /* lock_local */
+#endif
+ return flags;
+}
+
+/* FIXME: we need rt_spin_lock_nest_lock */
+#define spin_lock_nest_lock(lock, nest_lock) spin_lock_nested(lock, 0)
+
+#define spin_unlock(lock) rt_spin_unlock(lock)
+
+#define spin_unlock_bh(lock) \
+ do { \
+ rt_spin_unlock(lock); \
+ local_bh_enable(); \
+ } while (0)
+
+#define spin_unlock_irq(lock) spin_unlock(lock)
+
+#define spin_unlock_irqrestore(lock, flags) \
+ do { \
+ typecheck(unsigned long, flags); \
+ (void) flags; \
+ spin_unlock(lock); \
+ } while (0)
+
+#define spin_trylock_bh(lock) __cond_lock(lock, rt_spin_trylock_bh(lock))
+#define spin_trylock_irq(lock) spin_trylock(lock)
+
+#define spin_trylock_irqsave(lock, flags) \
+ rt_spin_trylock_irqsave(lock, &(flags))
+
+#define spin_unlock_wait(lock) rt_spin_unlock_wait(lock)
+
+#ifdef CONFIG_GENERIC_LOCKBREAK
+# define spin_is_contended(lock) ((lock)->break_lock)
+#else
+# define spin_is_contended(lock) (((void)(lock), 0))
+#endif
+
+static inline int spin_can_lock(spinlock_t *lock)
+{
+ return !rt_mutex_is_locked(&lock->lock);
+}
+
+static inline int spin_is_locked(spinlock_t *lock)
+{
+ return rt_mutex_is_locked(&lock->lock);
+}
+
+static inline void assert_spin_locked(spinlock_t *lock)
+{
+ BUG_ON(!spin_is_locked(lock));
+}
+
+#endif
diff --git a/include/linux/spinlock_types.h b/include/linux/spinlock_types.h
index 24b4e6f2c1a22..8d896d3e1a017 100644
--- a/include/linux/spinlock_types.h
+++ b/include/linux/spinlock_types.h
@@ -9,77 +9,15 @@
* Released under the General Public License (GPL).
*/
-#if defined(CONFIG_SMP)
-# include
-#else
-# include
-#endif
-
-#include
-
-typedef struct raw_spinlock {
- arch_spinlock_t raw_lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
- unsigned int magic, owner_cpu;
- void *owner;
-#endif
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- struct lockdep_map dep_map;
-#endif
-} raw_spinlock_t;
-
-#define SPINLOCK_MAGIC 0xdead4ead
-
-#define SPINLOCK_OWNER_INIT ((void *)-1L)
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define SPIN_DEP_MAP_INIT(lockname) .dep_map = { .name = #lockname }
-#else
-# define SPIN_DEP_MAP_INIT(lockname)
-#endif
+#include
-#ifdef CONFIG_DEBUG_SPINLOCK
-# define SPIN_DEBUG_INIT(lockname) \
- .magic = SPINLOCK_MAGIC, \
- .owner_cpu = -1, \
- .owner = SPINLOCK_OWNER_INIT,
+#ifndef CONFIG_PREEMPT_RT
+# include
+# include
#else
-# define SPIN_DEBUG_INIT(lockname)
+# include
+# include
+# include
#endif
-#define __RAW_SPIN_LOCK_INITIALIZER(lockname) \
- { \
- .raw_lock = __ARCH_SPIN_LOCK_UNLOCKED, \
- SPIN_DEBUG_INIT(lockname) \
- SPIN_DEP_MAP_INIT(lockname) }
-
-#define __RAW_SPIN_LOCK_UNLOCKED(lockname) \
- (raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER(lockname)
-
-#define DEFINE_RAW_SPINLOCK(x) raw_spinlock_t x = __RAW_SPIN_LOCK_UNLOCKED(x)
-
-typedef struct spinlock {
- union {
- struct raw_spinlock rlock;
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
- struct {
- u8 __padding[LOCK_PADSIZE];
- struct lockdep_map dep_map;
- };
-#endif
- };
-} spinlock_t;
-
-#define __SPIN_LOCK_INITIALIZER(lockname) \
- { { .rlock = __RAW_SPIN_LOCK_INITIALIZER(lockname) } }
-
-#define __SPIN_LOCK_UNLOCKED(lockname) \
- (spinlock_t ) __SPIN_LOCK_INITIALIZER(lockname)
-
-#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
-
-#include
-
#endif /* __LINUX_SPINLOCK_TYPES_H */
diff --git a/include/linux/spinlock_types_nort.h b/include/linux/spinlock_types_nort.h
new file mode 100644
index 0000000000000..f1dac1fb1d6ac
--- /dev/null
+++ b/include/linux/spinlock_types_nort.h
@@ -0,0 +1,33 @@
+#ifndef __LINUX_SPINLOCK_TYPES_NORT_H
+#define __LINUX_SPINLOCK_TYPES_NORT_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+#error "Do not include directly. Include spinlock_types.h instead"
+#endif
+
+/*
+ * The non RT version maps spinlocks to raw_spinlocks
+ */
+typedef struct spinlock {
+ union {
+ struct raw_spinlock rlock;
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
+ struct {
+ u8 __padding[LOCK_PADSIZE];
+ struct lockdep_map dep_map;
+ };
+#endif
+ };
+} spinlock_t;
+
+#define __SPIN_LOCK_INITIALIZER(lockname) \
+ { { .rlock = __RAW_SPIN_LOCK_INITIALIZER(lockname) } }
+
+#define __SPIN_LOCK_UNLOCKED(lockname) \
+ (spinlock_t ) __SPIN_LOCK_INITIALIZER(lockname)
+
+#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
+
+#endif
diff --git a/include/linux/spinlock_types_raw.h b/include/linux/spinlock_types_raw.h
new file mode 100644
index 0000000000000..822bf64a61d3b
--- /dev/null
+++ b/include/linux/spinlock_types_raw.h
@@ -0,0 +1,55 @@
+#ifndef __LINUX_SPINLOCK_TYPES_RAW_H
+#define __LINUX_SPINLOCK_TYPES_RAW_H
+
+#include
+
+#if defined(CONFIG_SMP)
+# include
+#else
+# include
+#endif
+
+#include
+
+typedef struct raw_spinlock {
+ arch_spinlock_t raw_lock;
+#ifdef CONFIG_DEBUG_SPINLOCK
+ unsigned int magic, owner_cpu;
+ void *owner;
+#endif
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
+} raw_spinlock_t;
+
+#define SPINLOCK_MAGIC 0xdead4ead
+
+#define SPINLOCK_OWNER_INIT ((void *)-1L)
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define SPIN_DEP_MAP_INIT(lockname) .dep_map = { .name = #lockname }
+#else
+# define SPIN_DEP_MAP_INIT(lockname)
+#endif
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+# define SPIN_DEBUG_INIT(lockname) \
+ .magic = SPINLOCK_MAGIC, \
+ .owner_cpu = -1, \
+ .owner = SPINLOCK_OWNER_INIT,
+#else
+# define SPIN_DEBUG_INIT(lockname)
+#endif
+
+#define __RAW_SPIN_LOCK_INITIALIZER(lockname) \
+ { \
+ .raw_lock = __ARCH_SPIN_LOCK_UNLOCKED, \
+ SPIN_DEBUG_INIT(lockname) \
+ SPIN_DEP_MAP_INIT(lockname) }
+
+#define __RAW_SPIN_LOCK_UNLOCKED(lockname) \
+ (raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER(lockname)
+
+#define DEFINE_RAW_SPINLOCK(x) raw_spinlock_t x = __RAW_SPIN_LOCK_UNLOCKED(x)
+
+#endif
diff --git a/include/linux/spinlock_types_rt.h b/include/linux/spinlock_types_rt.h
new file mode 100644
index 0000000000000..3e3d8c5f7a9ad
--- /dev/null
+++ b/include/linux/spinlock_types_rt.h
@@ -0,0 +1,48 @@
+#ifndef __LINUX_SPINLOCK_TYPES_RT_H
+#define __LINUX_SPINLOCK_TYPES_RT_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+#error "Do not include directly. Include spinlock_types.h instead"
+#endif
+
+#include
+
+/*
+ * PREEMPT_RT: spinlocks - an RT mutex plus lock-break field:
+ */
+typedef struct spinlock {
+ struct rt_mutex lock;
+ unsigned int break_lock;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lockdep_map dep_map;
+#endif
+} spinlock_t;
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# define __RT_SPIN_INITIALIZER(name) \
+ { \
+ .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock), \
+ .save_state = 1, \
+ .file = __FILE__, \
+ .line = __LINE__ , \
+ }
+#else
+# define __RT_SPIN_INITIALIZER(name) \
+ { \
+ .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock), \
+ .save_state = 1, \
+ }
+#endif
+
+/*
+.wait_list = PLIST_HEAD_INIT_RAW((name).lock.wait_list, (name).lock.wait_lock)
+*/
+
+#define __SPIN_LOCK_UNLOCKED(name) \
+ { .lock = __RT_SPIN_INITIALIZER(name.lock), \
+ SPIN_DEP_MAP_INIT(name) }
+
+#define DEFINE_SPINLOCK(name) \
+ spinlock_t name = __SPIN_LOCK_UNLOCKED(name)
+
+#endif
diff --git a/include/linux/spinlock_types_up.h b/include/linux/spinlock_types_up.h
index c09b6407ae1b3..b0243ba07fb78 100644
--- a/include/linux/spinlock_types_up.h
+++ b/include/linux/spinlock_types_up.h
@@ -1,10 +1,6 @@
#ifndef __LINUX_SPINLOCK_TYPES_UP_H
#define __LINUX_SPINLOCK_TYPES_UP_H
-#ifndef __LINUX_SPINLOCK_TYPES_H
-# error "please don't include this file directly"
-#endif
-
/*
* include/linux/spinlock_types_up.h - spinlock type definitions for UP
*
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index f9a0c6189852e..27d32887103dd 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -26,6 +26,8 @@ struct cpu_stop_work {
cpu_stop_fn_t fn;
void *arg;
struct cpu_stop_done *done;
+ /* Did not run due to disabled stopper; for nowait debug checks */
+ bool disabled;
};
int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 6fc8843f1c9e9..dd0c894fb1090 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -197,6 +197,12 @@ struct platform_s2idle_ops {
void (*end)(void);
};
+#if defined(CONFIG_SUSPEND) || defined(CONFIG_HIBERNATION)
+extern bool pm_in_action;
+#else
+# define pm_in_action false
+#endif
+
#ifdef CONFIG_SUSPEND
extern suspend_state_t mem_sleep_current;
extern suspend_state_t mem_sleep_default;
diff --git a/include/linux/swait.h b/include/linux/swait.h
index 73e06e9986d4b..21ae66cd41d30 100644
--- a/include/linux/swait.h
+++ b/include/linux/swait.h
@@ -160,7 +160,9 @@ static inline bool swq_has_sleeper(struct swait_queue_head *wq)
extern void swake_up_one(struct swait_queue_head *q);
extern void swake_up_all(struct swait_queue_head *q);
extern void swake_up_locked(struct swait_queue_head *q);
+extern void swake_up_all_locked(struct swait_queue_head *q);
+extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
extern void prepare_to_swait_exclusive(struct swait_queue_head *q, struct swait_queue *wait, int state);
extern long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state);
@@ -297,4 +299,18 @@ do { \
__ret; \
})
+#define __swait_event_lock_irq(wq, condition, lock, cmd) \
+ ___swait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, \
+ raw_spin_unlock_irq(&lock); \
+ cmd; \
+ schedule(); \
+ raw_spin_lock_irq(&lock))
+
+#define swait_event_lock_irq(wq_head, condition, lock) \
+ do { \
+ if (condition) \
+ break; \
+ __swait_event_lock_irq(wq_head, condition, lock, ); \
+ } while (0)
+
#endif /* _LINUX_SWAIT_H */
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index e93e249a4e9bf..c88b9cecc78aa 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -97,7 +97,17 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
#define test_thread_flag(flag) \
test_ti_thread_flag(current_thread_info(), flag)
-#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
+#ifdef CONFIG_PREEMPT_LAZY
+#define tif_need_resched() (test_thread_flag(TIF_NEED_RESCHED) || \
+ test_thread_flag(TIF_NEED_RESCHED_LAZY))
+#define tif_need_resched_now() (test_thread_flag(TIF_NEED_RESCHED))
+#define tif_need_resched_lazy() test_thread_flag(TIF_NEED_RESCHED_LAZY))
+
+#else
+#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
+#define tif_need_resched_now() test_thread_flag(TIF_NEED_RESCHED)
+#define tif_need_resched_lazy() 0
+#endif
#ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES
static inline int arch_within_stack_frames(const void * const stack,
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 30a8cdcfd4a4f..f3b1ef07e4a5f 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -62,6 +62,9 @@ struct trace_entry {
unsigned char flags;
unsigned char preempt_count;
int pid;
+ unsigned short migrate_disable;
+ unsigned short padding;
+ unsigned char preempt_lazy_count;
};
#define TRACE_EVENT_TYPE_MAX \
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 38555435a64a3..e2777169c5399 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -182,6 +182,7 @@ static __always_inline void pagefault_disabled_dec(void)
*/
static inline void pagefault_disable(void)
{
+ migrate_disable();
pagefault_disabled_inc();
/*
* make sure to have issued the store before a pagefault
@@ -198,6 +199,7 @@ static inline void pagefault_enable(void)
*/
barrier();
pagefault_disabled_dec();
+ migrate_enable();
}
/*
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index bdeda4b079fe8..dec95902b138c 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -54,7 +54,9 @@ DECLARE_PER_CPU(struct vm_event_state, vm_event_states);
*/
static inline void __count_vm_event(enum vm_event_item item)
{
+ preempt_disable_rt();
raw_cpu_inc(vm_event_states.event[item]);
+ preempt_enable_rt();
}
static inline void count_vm_event(enum vm_event_item item)
@@ -64,7 +66,9 @@ static inline void count_vm_event(enum vm_event_item item)
static inline void __count_vm_events(enum vm_event_item item, long delta)
{
+ preempt_disable_rt();
raw_cpu_add(vm_event_states.event[item], delta);
+ preempt_enable_rt();
}
static inline void count_vm_events(enum vm_event_item item, long delta)
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 3eb7cae8206c3..1781c47d81f0b 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -10,6 +10,7 @@
#include
#include
+#include
typedef struct wait_queue_entry wait_queue_entry_t;
@@ -20,6 +21,7 @@ int default_wake_function(struct wait_queue_entry *wq_entry, unsigned mode, int
#define WQ_FLAG_EXCLUSIVE 0x01
#define WQ_FLAG_WOKEN 0x02
#define WQ_FLAG_BOOKMARK 0x04
+#define WQ_FLAG_CUSTOM 0x08
/*
* A single wait-queue entry structure:
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h
index ca23860adbb95..599572f9dcd1d 100644
--- a/include/net/gen_stats.h
+++ b/include/net/gen_stats.h
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
struct gnet_stats_basic_cpu {
struct gnet_stats_basic_packed bstats;
@@ -36,15 +37,15 @@ int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
spinlock_t *lock, struct gnet_dump *d,
int padattr);
-int gnet_stats_copy_basic(const seqcount_t *running,
+int gnet_stats_copy_basic(net_seqlock_t *running,
struct gnet_dump *d,
struct gnet_stats_basic_cpu __percpu *cpu,
struct gnet_stats_basic_packed *b);
-void __gnet_stats_copy_basic(const seqcount_t *running,
+void __gnet_stats_copy_basic(net_seqlock_t *running,
struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu,
struct gnet_stats_basic_packed *b);
-int gnet_stats_copy_basic_hw(const seqcount_t *running,
+int gnet_stats_copy_basic_hw(net_seqlock_t *running,
struct gnet_dump *d,
struct gnet_stats_basic_cpu __percpu *cpu,
struct gnet_stats_basic_packed *b);
@@ -64,13 +65,13 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
struct net_rate_estimator __rcu **rate_est,
spinlock_t *lock,
- seqcount_t *running, struct nlattr *opt);
+ net_seqlock_t *running, struct nlattr *opt);
void gen_kill_estimator(struct net_rate_estimator __rcu **ptr);
int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
struct gnet_stats_basic_cpu __percpu *cpu_bstats,
struct net_rate_estimator __rcu **ptr,
spinlock_t *lock,
- seqcount_t *running, struct nlattr *opt);
+ net_seqlock_t *running, struct nlattr *opt);
bool gen_estimator_active(struct net_rate_estimator __rcu **ptr);
bool gen_estimator_read(struct net_rate_estimator __rcu **ptr,
struct gnet_stats_rate_est64 *sample);
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 8ec77bfdc1a41..6cdf3a0741974 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -459,7 +459,7 @@ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
}
#endif
-static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb)
+static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
{
unsigned int hh_alen = 0;
unsigned int seq;
@@ -502,7 +502,7 @@ static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb
static inline int neigh_output(struct neighbour *n, struct sk_buff *skb,
bool skip_cache)
{
- const struct hh_cache *hh = &n->hh;
+ struct hh_cache *hh = &n->hh;
if ((n->nud_state & NUD_CONNECTED) && hh->hh_len && !skip_cache)
return neigh_hh_output(hh, skb);
@@ -543,7 +543,7 @@ struct neighbour_cb {
#define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb)
-static inline void neigh_ha_snapshot(char *dst, const struct neighbour *n,
+static inline void neigh_ha_snapshot(char *dst, struct neighbour *n,
const struct net_device *dev)
{
unsigned int seq;
diff --git a/include/net/net_seq_lock.h b/include/net/net_seq_lock.h
new file mode 100644
index 0000000000000..67710bace7418
--- /dev/null
+++ b/include/net/net_seq_lock.h
@@ -0,0 +1,15 @@
+#ifndef __NET_NET_SEQ_LOCK_H__
+#define __NET_NET_SEQ_LOCK_H__
+
+#ifdef CONFIG_PREEMPT_RT
+# define net_seqlock_t seqlock_t
+# define net_seq_begin(__r) read_seqbegin(__r)
+# define net_seq_retry(__r, __s) read_seqretry(__r, __s)
+
+#else
+# define net_seqlock_t seqcount_t
+# define net_seq_begin(__r) read_seqcount_begin(__r)
+# define net_seq_retry(__r, __s) read_seqcount_retry(__r, __s)
+#endif
+
+#endif
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index d334e4609dd41..d50ddd90a77bc 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -100,7 +101,7 @@ struct Qdisc {
struct sk_buff_head gso_skb ____cacheline_aligned_in_smp;
struct qdisc_skb_head q;
struct gnet_stats_basic_packed bstats;
- seqcount_t running;
+ net_seqlock_t running;
struct gnet_stats_queue qstats;
unsigned long state;
struct Qdisc *next_sched;
@@ -138,7 +139,11 @@ static inline bool qdisc_is_running(struct Qdisc *qdisc)
{
if (qdisc->flags & TCQ_F_NOLOCK)
return spin_is_locked(&qdisc->seqlock);
+#ifdef CONFIG_PREEMPT_RT
+ return spin_is_locked(&qdisc->running.lock) ? true : false;
+#else
return (raw_read_seqcount(&qdisc->running) & 1) ? true : false;
+#endif
}
static inline bool qdisc_is_percpu_stats(const struct Qdisc *q)
@@ -162,17 +167,27 @@ static inline bool qdisc_run_begin(struct Qdisc *qdisc)
} else if (qdisc_is_running(qdisc)) {
return false;
}
+#ifdef CONFIG_PREEMPT_RT
+ if (try_write_seqlock(&qdisc->running))
+ return true;
+ return false;
+#else
/* Variant of write_seqcount_begin() telling lockdep a trylock
* was attempted.
*/
raw_write_seqcount_begin(&qdisc->running);
seqcount_acquire(&qdisc->running.dep_map, 0, 1, _RET_IP_);
return true;
+#endif
}
static inline void qdisc_run_end(struct Qdisc *qdisc)
{
+#ifdef CONFIG_PREEMPT_RT
+ write_sequnlock(&qdisc->running);
+#else
write_seqcount_end(&qdisc->running);
+#endif
if (qdisc->flags & TCQ_F_NOLOCK)
spin_unlock(&qdisc->seqlock);
}
@@ -541,7 +556,7 @@ static inline spinlock_t *qdisc_root_sleeping_lock(const struct Qdisc *qdisc)
return qdisc_lock(root);
}
-static inline seqcount_t *qdisc_root_sleeping_running(const struct Qdisc *qdisc)
+static inline net_seqlock_t *qdisc_root_sleeping_running(const struct Qdisc *qdisc)
{
struct Qdisc *root = qdisc_root_sleeping(qdisc);
diff --git a/include/uapi/linux/can/isotp.h b/include/uapi/linux/can/isotp.h
new file mode 100644
index 0000000000000..548e732f33a8e
--- /dev/null
+++ b/include/uapi/linux/can/isotp.h
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/*
+ * socketcan/can/isotp.h
+ *
+ * Definitions for isotp CAN sockets
+ *
+ * Author: Oliver Hartkopp
+ * Copyright (c) 2008 Volkswagen Group Electronic Research
+ * All rights reserved.
+ *
+ * Send feedback to
+ *
+ */
+
+#ifndef CAN_ISOTP_H
+#define CAN_ISOTP_H
+
+#include
+
+#define SOL_CAN_ISOTP (SOL_CAN_BASE + CAN_ISOTP)
+
+/* for socket options affecting the socket (not the global system) */
+
+#define CAN_ISOTP_OPTS 1 /* pass struct can_isotp_options */
+
+#define CAN_ISOTP_RECV_FC 2 /* pass struct can_isotp_fc_options */
+
+/* sockopts to force stmin timer values for protocol regression tests */
+
+#define CAN_ISOTP_TX_STMIN 3 /* pass __u32 value in nano secs */
+ /* use this time instead of value */
+ /* provided in FC from the receiver */
+
+#define CAN_ISOTP_RX_STMIN 4 /* pass __u32 value in nano secs */
+ /* ignore received CF frames which */
+ /* timestamps differ less than val */
+
+#define CAN_ISOTP_LL_OPTS 5 /* pass struct can_isotp_ll_options */
+
+struct can_isotp_options {
+
+ __u32 flags; /* set flags for isotp behaviour. */
+ /* __u32 value : flags see below */
+
+ __u32 frame_txtime; /* frame transmission time (N_As/N_Ar) */
+ /* __u32 value : time in nano secs */
+
+ __u8 ext_address; /* set address for extended addressing */
+ /* __u8 value : extended address */
+
+ __u8 txpad_content; /* set content of padding byte (tx) */
+ /* __u8 value : content on tx path */
+
+ __u8 rxpad_content; /* set content of padding byte (rx) */
+ /* __u8 value : content on rx path */
+
+ __u8 rx_ext_address; /* set address for extended addressing */
+ /* __u8 value : extended address (rx) */
+};
+
+struct can_isotp_fc_options {
+
+ __u8 bs; /* blocksize provided in FC frame */
+ /* __u8 value : blocksize. 0 = off */
+
+ __u8 stmin; /* separation time provided in FC frame */
+ /* __u8 value : */
+ /* 0x00 - 0x7F : 0 - 127 ms */
+ /* 0x80 - 0xF0 : reserved */
+ /* 0xF1 - 0xF9 : 100 us - 900 us */
+ /* 0xFA - 0xFF : reserved */
+
+ __u8 wftmax; /* max. number of wait frame transmiss. */
+ /* __u8 value : 0 = omit FC N_PDU WT */
+};
+
+struct can_isotp_ll_options {
+
+ __u8 mtu; /* generated & accepted CAN frame type */
+ /* __u8 value : */
+ /* CAN_MTU (16) -> standard CAN 2.0 */
+ /* CANFD_MTU (72) -> CAN FD frame */
+
+ __u8 tx_dl; /* tx link layer data length in bytes */
+ /* (configured maximum payload length) */
+ /* __u8 value : 8,12,16,20,24,32,48,64 */
+ /* => rx path supports all LL_DL values */
+
+ __u8 tx_flags; /* set into struct canfd_frame.flags */
+ /* at frame creation: e.g. CANFD_BRS */
+ /* Obsolete when the BRS flag is fixed */
+ /* by the CAN netdriver configuration */
+};
+
+/* flags for isotp behaviour */
+
+#define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */
+#define CAN_ISOTP_EXTEND_ADDR 0x002 /* enable extended addressing */
+#define CAN_ISOTP_TX_PADDING 0x004 /* enable CAN frame padding tx path */
+#define CAN_ISOTP_RX_PADDING 0x008 /* enable CAN frame padding rx path */
+#define CAN_ISOTP_CHK_PAD_LEN 0x010 /* check received CAN frame padding */
+#define CAN_ISOTP_CHK_PAD_DATA 0x020 /* check received CAN frame padding */
+#define CAN_ISOTP_HALF_DUPLEX 0x040 /* half duplex error state handling */
+#define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */
+#define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */
+#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */
+
+
+/* default values */
+
+#define CAN_ISOTP_DEFAULT_FLAGS 0
+#define CAN_ISOTP_DEFAULT_EXT_ADDRESS 0x00
+#define CAN_ISOTP_DEFAULT_PAD_CONTENT 0xCC /* prevent bit-stuffing */
+#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 0
+#define CAN_ISOTP_DEFAULT_RECV_BS 0
+#define CAN_ISOTP_DEFAULT_RECV_STMIN 0x00
+#define CAN_ISOTP_DEFAULT_RECV_WFTMAX 0
+
+#define CAN_ISOTP_DEFAULT_LL_MTU CAN_MTU
+#define CAN_ISOTP_DEFAULT_LL_TX_DL CAN_MAX_DLEN
+#define CAN_ISOTP_DEFAULT_LL_TX_FLAGS 0
+
+/*
+ * Remark on CAN_ISOTP_DEFAULT_RECV_* values:
+ *
+ * We can strongly assume, that the Linux Kernel implementation of
+ * CAN_ISOTP is capable to run with BS=0, STmin=0 and WFTmax=0.
+ * But as we like to be able to behave as a commonly available ECU,
+ * these default settings can be changed via sockopts.
+ * For that reason the STmin value is intentionally _not_ checked for
+ * consistency and copied directly into the flow control (FC) frame.
+ *
+ */
+
+#endif
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index d89969aa9942c..095be1d66f31c 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -215,7 +215,7 @@ bool xen_running_on_version_or_later(unsigned int major, unsigned int minor);
void xen_efi_runtime_setup(void);
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPTION
static inline void xen_preemptible_hcall_begin(void)
{
@@ -239,6 +239,6 @@ static inline void xen_preemptible_hcall_end(void)
__this_cpu_write(xen_in_preemptible_hcall, false);
}
-#endif /* CONFIG_PREEMPT */
+#endif /* CONFIG_PREEMPTION */
#endif /* INCLUDE_XEN_OPS_H */
diff --git a/init/Kconfig b/init/Kconfig
index 0bffc8fdbf3da..c9e5274d3704a 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -105,9 +105,29 @@ config COMPILE_TEST
here. If you are a user/distributor, say N here to exclude useless
drivers to be distributed.
+config HEADER_TEST
+ bool "Compile test headers that should be standalone compilable"
+ help
+ Compile test headers listed in header-test-y target to ensure they are
+ self-contained, i.e. compilable as standalone units.
+
+ If you are a developer or tester and want to ensure the requested
+ headers are self-contained, say Y here. Otherwise, choose N.
+
+config KERNEL_HEADER_TEST
+ bool "Compile test kernel headers"
+ depends on HEADER_TEST
+ help
+ Headers in include/ are used to build external moduls.
+ Compile test them to ensure they are self-contained, i.e.
+ compilable as standalone units.
+
+ If you are a developer or tester and want to ensure the headers
+ in include/ are self-contained, say Y here. Otherwise, choose N.
+
config UAPI_HEADER_TEST
bool "Compile test UAPI headers"
- depends on HEADERS_INSTALL && CC_CAN_LINK
+ depends on HEADER_TEST && HEADERS_INSTALL && CC_CAN_LINK
help
Compile test headers exported to user-space to ensure they are
self-contained, i.e. compilable as standalone units.
@@ -904,6 +924,7 @@ config CFS_BANDWIDTH
config RT_GROUP_SCHED
bool "Group scheduling for SCHED_RR/FIFO"
depends on CGROUP_SCHED
+ depends on !PREEMPT_RT
default n
help
This feature lets you explicitly allocate real CPU bandwidth
@@ -1610,6 +1631,7 @@ config KALLSYMS_BASE_RELATIVE
# syscall, maps, verifier
config BPF_SYSCALL
bool "Enable bpf() system call"
+ depends on !PREEMPT_RT
select BPF
select IRQ_WORK
default n
@@ -1785,6 +1807,7 @@ choice
config SLAB
bool "SLAB"
+ depends on !PREEMPT_RT
select HAVE_HARDENED_USERCOPY_ALLOCATOR
help
The regular slab allocator that is established and known to work
@@ -1805,6 +1828,7 @@ config SLUB
config SLOB
depends on EXPERT
bool "SLOB (Simple Allocator)"
+ depends on !PREEMPT_RT
help
SLOB replaces the stock allocator with a drastically simpler
allocator. SLOB is generally more space efficient but
@@ -1870,7 +1894,7 @@ config SHUFFLE_PAGE_ALLOCATOR
config SLUB_CPU_PARTIAL
default y
- depends on SLUB && SMP
+ depends on SLUB && SMP && !PREEMPT_RT
bool "SLUB per cpu partial cache"
help
Per cpu partial caches accelerate objects allocation and freeing
diff --git a/init/init_task.c b/init/init_task.c
index 9e5cbe5eab7b1..1539bfba1bef8 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -73,6 +73,10 @@ struct task_struct init_task
.cpus_ptr = &init_task.cpus_mask,
.cpus_mask = CPU_MASK_ALL,
.nr_cpus_allowed= NR_CPUS,
+#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT) && \
+ defined(CONFIG_SCHED_DEBUG)
+ .pinned_on_cpu = -1,
+#endif
.mm = NULL,
.active_mm = &init_mm,
.restart_block = {
diff --git a/init/main.c b/init/main.c
index c0206c507eba9..5cbb9fe937e0b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -694,7 +694,6 @@ asmlinkage __visible void __init start_kernel(void)
boot_init_stack_canary();
time_init();
- printk_safe_init();
perf_event_init();
profile_init();
call_function_init();
diff --git a/jenkins_build.sh b/jenkins_build.sh
new file mode 100755
index 0000000000000..8fba37bce2880
--- /dev/null
+++ b/jenkins_build.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+#gcc:
+
+#
+#https://releases.linaro.org/components/toolchain/binaries/7.1-2017.05/arm-linux-gnueabihf/gcc-linaro-7.1.1-2017.05-x86_64_arm-linux-gnueabihf.tar.xz
+#https://releases.linaro.org/components/toolchain/binaries/7.1-2017.08/arm-linux-gnueabihf/gcc-linaro-7.1.1-2017.08-x86_64_arm-linux-gnueabihf.tar.xz
+#https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/arm-linux-gnueabihf/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabihf.tar.xz
+#https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/arm-linux-gnueabihf/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz
+#https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/arm-linux-gnueabihf/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf.tar.xz
+#https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
+#
+
+gcc_html_path="https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/"
+gcc_filename_prefix="gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf"
+gcc_banner="arm-linux-gnueabihf-gcc (Linaro GCC 7.5-2019.12) 7.5.0"
+gcc_copyright="2017"
+datestamp="2019.12-gcc-arm-linux-gnueabihf"
+
+#
+
+if [ ! -d ${gcc_filename_prefix}/ ] ; then
+ rm -rf ./gcc-* || true
+ #wget -c ${site}/${version}/${filename}
+ wget -c http://gfnd.rcn-ee.org/farm/jenkins-dl/${gcc_filename_prefix}.tar.xz
+ tar xf ${gcc_filename_prefix}.tar.xz
+fi
+
+export CC=`pwd`/${gcc_filename_prefix}/bin/arm-linux-gnueabihf-
+
+make ARCH=arm clean
+make ARCH=arm bb.org_defconfig
+
+echo "[make ARCH=arm -j4 CROSS_COMPILE=\"${binary}\" zImage]"
+make ARCH=arm -j4 CROSS_COMPILE="ccache ${CC}" zImage
+if [ ! -f arch/arm/boot/zImage ] ; then
+ echo "failed: [arch/arm/boot/zImage]"
+ exit 1
+fi
+
+echo "[make ARCH=arm -j4 CROSS_COMPILE=\"${binary}\" modules]"
+make ARCH=arm -j4 CROSS_COMPILE="ccache ${CC}" modules
+if [ ! -f drivers/spi/spidev.ko ] ; then
+ echo "failed: [drivers/spi/spidev.ko]"
+ exit 1
+fi
+
+echo "[make ARCH=arm CROSS_COMPILE=\"${binary}\" dtbs]"
+make ARCH=arm CROSS_COMPILE="ccache ${CC}" dtbs
+if [ ! -f arch/arm/boot/dts/am335x-boneblack.dtb ] ; then
+ echo "failed: [arch/arm/boot/dts/am335x-boneblack.dtb]"
+ exit 1
+else
+ if [ -f arch/arm/boot/dts/am335x-pocketbeagle.dts ] ; then
+ if [ ! -f arch/arm/boot/dts/am335x-pocketbeagle.dtb ] ; then
+ echo "failed: [arch/arm/boot/dts/am335x-pocketbeagle.dtb]"
+ exit 1
+ fi
+ fi
+fi
+
+make ARCH=arm clean
diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks
index e0852dc333acd..3de8fd11873b4 100644
--- a/kernel/Kconfig.locks
+++ b/kernel/Kconfig.locks
@@ -101,7 +101,7 @@ config UNINLINE_SPIN_UNLOCK
# unlock and unlock_irq functions are inlined when:
# - DEBUG_SPINLOCK=n and ARCH_INLINE_*LOCK=y
# or
-# - DEBUG_SPINLOCK=n and PREEMPT=n
+# - DEBUG_SPINLOCK=n and PREEMPTION=n
#
# unlock_bh and unlock_irqrestore functions are inlined when:
# - DEBUG_SPINLOCK=n and ARCH_INLINE_*LOCK=y
@@ -139,7 +139,7 @@ config INLINE_SPIN_UNLOCK_BH
config INLINE_SPIN_UNLOCK_IRQ
def_bool y
- depends on !PREEMPT || ARCH_INLINE_SPIN_UNLOCK_IRQ
+ depends on !PREEMPTION || ARCH_INLINE_SPIN_UNLOCK_IRQ
config INLINE_SPIN_UNLOCK_IRQRESTORE
def_bool y
@@ -168,7 +168,7 @@ config INLINE_READ_LOCK_IRQSAVE
config INLINE_READ_UNLOCK
def_bool y
- depends on !PREEMPT || ARCH_INLINE_READ_UNLOCK
+ depends on !PREEMPTION || ARCH_INLINE_READ_UNLOCK
config INLINE_READ_UNLOCK_BH
def_bool y
@@ -176,7 +176,7 @@ config INLINE_READ_UNLOCK_BH
config INLINE_READ_UNLOCK_IRQ
def_bool y
- depends on !PREEMPT || ARCH_INLINE_READ_UNLOCK_IRQ
+ depends on !PREEMPTION || ARCH_INLINE_READ_UNLOCK_IRQ
config INLINE_READ_UNLOCK_IRQRESTORE
def_bool y
@@ -205,7 +205,7 @@ config INLINE_WRITE_LOCK_IRQSAVE
config INLINE_WRITE_UNLOCK
def_bool y
- depends on !PREEMPT || ARCH_INLINE_WRITE_UNLOCK
+ depends on !PREEMPTION || ARCH_INLINE_WRITE_UNLOCK
config INLINE_WRITE_UNLOCK_BH
def_bool y
@@ -213,7 +213,7 @@ config INLINE_WRITE_UNLOCK_BH
config INLINE_WRITE_UNLOCK_IRQ
def_bool y
- depends on !PREEMPT || ARCH_INLINE_WRITE_UNLOCK_IRQ
+ depends on !PREEMPTION || ARCH_INLINE_WRITE_UNLOCK_IRQ
config INLINE_WRITE_UNLOCK_IRQRESTORE
def_bool y
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
index deff972174967..7871ec3c9a02a 100644
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
@@ -1,5 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
+config HAVE_PREEMPT_LAZY
+ bool
+
+config PREEMPT_LAZY
+ def_bool y if HAVE_PREEMPT_LAZY && PREEMPT_RT
+
choice
prompt "Preemption Model"
default PREEMPT_NONE
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 22066a62c8c97..c91ec298decad 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -17,9 +17,62 @@
(BPF_F_NO_PREALLOC | BPF_F_NO_COMMON_LRU | BPF_F_NUMA_NODE | \
BPF_F_ACCESS_MASK | BPF_F_ZERO_SEED)
+/*
+ * The bucket lock has two protection scopes:
+ *
+ * 1) Serializing concurrent operations from BPF programs on differrent
+ * CPUs
+ *
+ * 2) Serializing concurrent operations from BPF programs and sys_bpf()
+ *
+ * BPF programs can execute in any context including perf, kprobes and
+ * tracing. As there are almost no limits where perf, kprobes and tracing
+ * can be invoked from the lock operations need to be protected against
+ * deadlocks. Deadlocks can be caused by recursion and by an invocation in
+ * the lock held section when functions which acquire this lock are invoked
+ * from sys_bpf(). BPF recursion is prevented by incrementing the per CPU
+ * variable bpf_prog_active, which prevents BPF programs attached to perf
+ * events, kprobes and tracing to be invoked before the prior invocation
+ * from one of these contexts completed. sys_bpf() uses the same mechanism
+ * by pinning the task to the current CPU and incrementing the recursion
+ * protection accross the map operation.
+ *
+ * This has subtle implications on PREEMPT_RT. PREEMPT_RT forbids certain
+ * operations like memory allocations (even with GFP_ATOMIC) from atomic
+ * contexts. This is required because even with GFP_ATOMIC the memory
+ * allocator calls into code pathes which acquire locks with long held lock
+ * sections. To ensure the deterministic behaviour these locks are regular
+ * spinlocks, which are converted to 'sleepable' spinlocks on RT. The only
+ * true atomic contexts on an RT kernel are the low level hardware
+ * handling, scheduling, low level interrupt handling, NMIs etc. None of
+ * these contexts should ever do memory allocations.
+ *
+ * As regular device interrupt handlers and soft interrupts are forced into
+ * thread context, the existing code which does
+ * spin_lock*(); alloc(GPF_ATOMIC); spin_unlock*();
+ * just works.
+ *
+ * In theory the BPF locks could be converted to regular spinlocks as well,
+ * but the bucket locks and percpu_freelist locks can be taken from
+ * arbitrary contexts (perf, kprobes, tracepoints) which are required to be
+ * atomic contexts even on RT. These mechanisms require preallocated maps,
+ * so there is no need to invoke memory allocations within the lock held
+ * sections.
+ *
+ * BPF maps which need dynamic allocation are only used from (forced)
+ * thread context on RT and can therefore use regular spinlocks which in
+ * turn allows to invoke memory allocations from the lock held section.
+ *
+ * On a non RT kernel this distinction is neither possible nor required.
+ * spinlock maps to raw_spinlock and the extra code is optimized out by the
+ * compiler.
+ */
struct bucket {
struct hlist_nulls_head head;
- raw_spinlock_t lock;
+ union {
+ raw_spinlock_t raw_lock;
+ spinlock_t lock;
+ };
};
struct bpf_htab {
@@ -57,6 +110,51 @@ struct htab_elem {
char key[0] __aligned(8);
};
+static inline bool htab_is_prealloc(const struct bpf_htab *htab)
+{
+ return !(htab->map.map_flags & BPF_F_NO_PREALLOC);
+}
+
+static inline bool htab_use_raw_lock(const struct bpf_htab *htab)
+{
+ return (!IS_ENABLED(CONFIG_PREEMPT_RT) || htab_is_prealloc(htab));
+}
+
+static void htab_init_buckets(struct bpf_htab *htab)
+{
+ unsigned i;
+
+ for (i = 0; i < htab->n_buckets; i++) {
+ INIT_HLIST_NULLS_HEAD(&htab->buckets[i].head, i);
+ if (htab_use_raw_lock(htab))
+ raw_spin_lock_init(&htab->buckets[i].raw_lock);
+ else
+ spin_lock_init(&htab->buckets[i].lock);
+ }
+}
+
+static inline unsigned long htab_lock_bucket(const struct bpf_htab *htab,
+ struct bucket *b)
+{
+ unsigned long flags;
+
+ if (htab_use_raw_lock(htab))
+ raw_spin_lock_irqsave(&b->raw_lock, flags);
+ else
+ spin_lock_irqsave(&b->lock, flags);
+ return flags;
+}
+
+static inline void htab_unlock_bucket(const struct bpf_htab *htab,
+ struct bucket *b,
+ unsigned long flags)
+{
+ if (htab_use_raw_lock(htab))
+ raw_spin_unlock_irqrestore(&b->raw_lock, flags);
+ else
+ spin_unlock_irqrestore(&b->lock, flags);
+}
+
static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node);
static bool htab_is_lru(const struct bpf_htab *htab)
@@ -71,11 +169,6 @@ static bool htab_is_percpu(const struct bpf_htab *htab)
htab->map.map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
}
-static bool htab_is_prealloc(const struct bpf_htab *htab)
-{
- return !(htab->map.map_flags & BPF_F_NO_PREALLOC);
-}
-
static inline void htab_elem_set_ptr(struct htab_elem *l, u32 key_size,
void __percpu *pptr)
{
@@ -306,8 +399,8 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
bool percpu_lru = (attr->map_flags & BPF_F_NO_COMMON_LRU);
bool prealloc = !(attr->map_flags & BPF_F_NO_PREALLOC);
struct bpf_htab *htab;
- int err, i;
u64 cost;
+ int err;
htab = kzalloc(sizeof(*htab), GFP_USER);
if (!htab)
@@ -369,10 +462,7 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
else
htab->hashrnd = get_random_int();
- for (i = 0; i < htab->n_buckets; i++) {
- INIT_HLIST_NULLS_HEAD(&htab->buckets[i].head, i);
- raw_spin_lock_init(&htab->buckets[i].lock);
- }
+ htab_init_buckets(htab);
if (prealloc) {
err = prealloc_init(htab);
@@ -580,7 +670,7 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
b = __select_bucket(htab, tgt_l->hash);
head = &b->head;
- raw_spin_lock_irqsave(&b->lock, flags);
+ flags = htab_lock_bucket(htab, b);
hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
if (l == tgt_l) {
@@ -588,7 +678,7 @@ static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node)
break;
}
- raw_spin_unlock_irqrestore(&b->lock, flags);
+ htab_unlock_bucket(htab, b, flags);
return l == tgt_l;
}
@@ -668,11 +758,11 @@ static void htab_elem_free_rcu(struct rcu_head *head)
* we're calling kfree, otherwise deadlock is possible if kprobes
* are placed somewhere inside of slub
*/
- preempt_disable();
+ migrate_disable();
__this_cpu_inc(bpf_prog_active);
htab_elem_free(htab, l);
__this_cpu_dec(bpf_prog_active);
- preempt_enable();
+ migrate_enable();
}
static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
@@ -862,8 +952,7 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value,
*/
}
- /* bpf_map_update_elem() can be called in_irq() */
- raw_spin_lock_irqsave(&b->lock, flags);
+ flags = htab_lock_bucket(htab, b);
l_old = lookup_elem_raw(head, hash, key, key_size);
@@ -904,7 +993,7 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value,
}
ret = 0;
err:
- raw_spin_unlock_irqrestore(&b->lock, flags);
+ htab_unlock_bucket(htab, b, flags);
return ret;
}
@@ -942,8 +1031,7 @@ static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value,
return -ENOMEM;
memcpy(l_new->key + round_up(map->key_size, 8), value, map->value_size);
- /* bpf_map_update_elem() can be called in_irq() */
- raw_spin_lock_irqsave(&b->lock, flags);
+ flags = htab_lock_bucket(htab, b);
l_old = lookup_elem_raw(head, hash, key, key_size);
@@ -962,7 +1050,7 @@ static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value,
ret = 0;
err:
- raw_spin_unlock_irqrestore(&b->lock, flags);
+ htab_unlock_bucket(htab, b, flags);
if (ret)
bpf_lru_push_free(&htab->lru, &l_new->lru_node);
@@ -997,8 +1085,7 @@ static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
b = __select_bucket(htab, hash);
head = &b->head;
- /* bpf_map_update_elem() can be called in_irq() */
- raw_spin_lock_irqsave(&b->lock, flags);
+ flags = htab_lock_bucket(htab, b);
l_old = lookup_elem_raw(head, hash, key, key_size);
@@ -1021,7 +1108,7 @@ static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key,
}
ret = 0;
err:
- raw_spin_unlock_irqrestore(&b->lock, flags);
+ htab_unlock_bucket(htab, b, flags);
return ret;
}
@@ -1061,8 +1148,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
return -ENOMEM;
}
- /* bpf_map_update_elem() can be called in_irq() */
- raw_spin_lock_irqsave(&b->lock, flags);
+ flags = htab_lock_bucket(htab, b);
l_old = lookup_elem_raw(head, hash, key, key_size);
@@ -1084,7 +1170,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
}
ret = 0;
err:
- raw_spin_unlock_irqrestore(&b->lock, flags);
+ htab_unlock_bucket(htab, b, flags);
if (l_new)
bpf_lru_push_free(&htab->lru, &l_new->lru_node);
return ret;
@@ -1122,7 +1208,7 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key)
b = __select_bucket(htab, hash);
head = &b->head;
- raw_spin_lock_irqsave(&b->lock, flags);
+ flags = htab_lock_bucket(htab, b);
l = lookup_elem_raw(head, hash, key, key_size);
@@ -1132,7 +1218,7 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key)
ret = 0;
}
- raw_spin_unlock_irqrestore(&b->lock, flags);
+ htab_unlock_bucket(htab, b, flags);
return ret;
}
@@ -1154,7 +1240,7 @@ static int htab_lru_map_delete_elem(struct bpf_map *map, void *key)
b = __select_bucket(htab, hash);
head = &b->head;
- raw_spin_lock_irqsave(&b->lock, flags);
+ flags = htab_lock_bucket(htab, b);
l = lookup_elem_raw(head, hash, key, key_size);
@@ -1163,7 +1249,7 @@ static int htab_lru_map_delete_elem(struct bpf_map *map, void *key)
ret = 0;
}
- raw_spin_unlock_irqrestore(&b->lock, flags);
+ htab_unlock_bucket(htab, b, flags);
if (l)
bpf_lru_push_free(&htab->lru, &l->lru_node);
return ret;
diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index 56e6c75d354d9..3b3c420bc8ed8 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -34,7 +34,7 @@ struct lpm_trie {
size_t n_entries;
size_t max_prefixlen;
size_t data_size;
- raw_spinlock_t lock;
+ spinlock_t lock;
};
/* This trie implements a longest prefix match algorithm that can be used to
@@ -315,7 +315,7 @@ static int trie_update_elem(struct bpf_map *map,
if (key->prefixlen > trie->max_prefixlen)
return -EINVAL;
- raw_spin_lock_irqsave(&trie->lock, irq_flags);
+ spin_lock_irqsave(&trie->lock, irq_flags);
/* Allocate and fill a new node */
@@ -422,7 +422,7 @@ static int trie_update_elem(struct bpf_map *map,
kfree(im_node);
}
- raw_spin_unlock_irqrestore(&trie->lock, irq_flags);
+ spin_unlock_irqrestore(&trie->lock, irq_flags);
return ret;
}
@@ -442,7 +442,7 @@ static int trie_delete_elem(struct bpf_map *map, void *_key)
if (key->prefixlen > trie->max_prefixlen)
return -EINVAL;
- raw_spin_lock_irqsave(&trie->lock, irq_flags);
+ spin_lock_irqsave(&trie->lock, irq_flags);
/* Walk the tree looking for an exact key/length match and keeping
* track of the path we traverse. We will need to know the node
@@ -518,7 +518,7 @@ static int trie_delete_elem(struct bpf_map *map, void *_key)
kfree_rcu(node, rcu);
out:
- raw_spin_unlock_irqrestore(&trie->lock, irq_flags);
+ spin_unlock_irqrestore(&trie->lock, irq_flags);
return ret;
}
@@ -575,7 +575,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)
if (ret)
goto out_err;
- raw_spin_lock_init(&trie->lock);
+ spin_lock_init(&trie->lock);
return &trie->map;
out_err:
diff --git a/kernel/bpf/percpu_freelist.c b/kernel/bpf/percpu_freelist.c
index 6e090140b9240..b367430e611c7 100644
--- a/kernel/bpf/percpu_freelist.c
+++ b/kernel/bpf/percpu_freelist.c
@@ -25,12 +25,18 @@ void pcpu_freelist_destroy(struct pcpu_freelist *s)
free_percpu(s->freelist);
}
+static inline void pcpu_freelist_push_node(struct pcpu_freelist_head *head,
+ struct pcpu_freelist_node *node)
+{
+ node->next = head->first;
+ head->first = node;
+}
+
static inline void ___pcpu_freelist_push(struct pcpu_freelist_head *head,
struct pcpu_freelist_node *node)
{
raw_spin_lock(&head->lock);
- node->next = head->first;
- head->first = node;
+ pcpu_freelist_push_node(head, node);
raw_spin_unlock(&head->lock);
}
@@ -56,21 +62,16 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
u32 nr_elems)
{
struct pcpu_freelist_head *head;
- unsigned long flags;
int i, cpu, pcpu_entries;
pcpu_entries = nr_elems / num_possible_cpus() + 1;
i = 0;
- /* disable irq to workaround lockdep false positive
- * in bpf usage pcpu_freelist_populate() will never race
- * with pcpu_freelist_push()
- */
- local_irq_save(flags);
for_each_possible_cpu(cpu) {
again:
head = per_cpu_ptr(s->freelist, cpu);
- ___pcpu_freelist_push(head, buf);
+ /* No locking required as this is not visible yet. */
+ pcpu_freelist_push_node(head, buf);
i++;
buf += elem_size;
if (i == nr_elems)
@@ -78,7 +79,6 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
if (i % pcpu_entries)
goto again;
}
- local_irq_restore(flags);
}
struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *s)
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
index 173e983619d77..e753900ff137a 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
@@ -40,6 +40,9 @@ static void do_up_read(struct irq_work *entry)
{
struct stack_map_irq_work *work;
+ if (WARN_ON_ONCE(IS_ENABLED(CONFIG_PREEMPT_RT)))
+ return;
+
work = container_of(entry, struct stack_map_irq_work, irq_work);
up_read_non_owner(work->sem);
work->sem = NULL;
@@ -288,10 +291,18 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
struct stack_map_irq_work *work = NULL;
if (irqs_disabled()) {
- work = this_cpu_ptr(&up_read_work);
- if (work->irq_work.flags & IRQ_WORK_BUSY)
- /* cannot queue more up_read, fallback */
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) {
+ work = this_cpu_ptr(&up_read_work);
+ if (work->irq_work.flags & IRQ_WORK_BUSY)
+ /* cannot queue more up_read, fallback */
+ irq_work_busy = true;
+ } else {
+ /*
+ * PREEMPT_RT does not allow to trylock mmap sem in
+ * interrupt disabled context. Force the fallback code.
+ */
irq_work_busy = true;
+ }
}
/*
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index ace1cfaa24b6b..e773c23b10a4b 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -794,7 +794,7 @@ static int map_lookup_elem(union bpf_attr *attr)
goto done;
}
- preempt_disable();
+ migrate_disable();
this_cpu_inc(bpf_prog_active);
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
@@ -837,7 +837,7 @@ static int map_lookup_elem(union bpf_attr *attr)
rcu_read_unlock();
}
this_cpu_dec(bpf_prog_active);
- preempt_enable();
+ migrate_enable();
done:
if (err)
@@ -937,7 +937,7 @@ static int map_update_elem(union bpf_attr *attr)
/* must increment bpf_prog_active to avoid kprobe+bpf triggering from
* inside bpf map update or delete otherwise deadlocks are possible
*/
- preempt_disable();
+ migrate_disable();
__this_cpu_inc(bpf_prog_active);
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
@@ -970,7 +970,7 @@ static int map_update_elem(union bpf_attr *attr)
rcu_read_unlock();
}
__this_cpu_dec(bpf_prog_active);
- preempt_enable();
+ migrate_enable();
maybe_wait_bpf_programs(map);
out:
free_value:
@@ -1016,13 +1016,13 @@ static int map_delete_elem(union bpf_attr *attr)
goto out;
}
- preempt_disable();
+ migrate_disable();
__this_cpu_inc(bpf_prog_active);
rcu_read_lock();
err = map->ops->map_delete_elem(map, key);
rcu_read_unlock();
__this_cpu_dec(bpf_prog_active);
- preempt_enable();
+ migrate_enable();
maybe_wait_bpf_programs(map);
out:
kfree(key);
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 595c52d59f310..ac9ec8fc92675 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1957,7 +1957,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
cgrp->dom_cgrp = cgrp;
cgrp->max_descendants = INT_MAX;
cgrp->max_depth = INT_MAX;
- INIT_LIST_HEAD(&cgrp->rstat_css_list);
prev_cputime_init(&cgrp->prev_cputime);
for_each_subsys(ss, ssid)
@@ -5014,12 +5013,6 @@ static void css_release_work_fn(struct work_struct *work)
list_del_rcu(&css->sibling);
if (ss) {
- /* css release path */
- if (!list_empty(&css->rstat_css_node)) {
- cgroup_rstat_flush(cgrp);
- list_del_rcu(&css->rstat_css_node);
- }
-
cgroup_idr_replace(&ss->css_idr, NULL, css->id);
if (ss->css_released)
ss->css_released(css);
@@ -5081,7 +5074,6 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
css->id = -1;
INIT_LIST_HEAD(&css->sibling);
INIT_LIST_HEAD(&css->children);
- INIT_LIST_HEAD(&css->rstat_css_node);
css->serial_nr = css_serial_nr_next++;
atomic_set(&css->online_cnt, 0);
@@ -5090,9 +5082,6 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
css_get(css->parent);
}
- if (cgroup_on_dfl(cgrp) && ss->css_rstat_flush)
- list_add_rcu(&css->rstat_css_node, &cgrp->rstat_css_list);
-
BUG_ON(cgroup_css(cgrp, ss));
}
@@ -5194,7 +5183,6 @@ static struct cgroup_subsys_state *css_create(struct cgroup *cgrp,
err_list_del:
list_del_rcu(&css->sibling);
err_free_css:
- list_del_rcu(&css->rstat_css_node);
INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn);
queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork);
return ERR_PTR(err);
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index c87ee6412b36a..680034721002b 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -345,7 +345,7 @@ void cpuset_read_unlock(void)
percpu_up_read(&cpuset_rwsem);
}
-static DEFINE_SPINLOCK(callback_lock);
+static DEFINE_RAW_SPINLOCK(callback_lock);
static struct workqueue_struct *cpuset_migrate_mm_wq;
@@ -1255,7 +1255,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
* Newly added CPUs will be removed from effective_cpus and
* newly deleted ones will be added back to effective_cpus.
*/
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
if (adding) {
cpumask_or(parent->subparts_cpus,
parent->subparts_cpus, tmp->addmask);
@@ -1274,7 +1274,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
}
parent->nr_subparts_cpus = cpumask_weight(parent->subparts_cpus);
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
return cmd == partcmd_update;
}
@@ -1379,7 +1379,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp)
continue;
rcu_read_unlock();
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
cpumask_copy(cp->effective_cpus, tmp->new_cpus);
if (cp->nr_subparts_cpus &&
@@ -1410,7 +1410,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp)
= cpumask_weight(cp->subparts_cpus);
}
}
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
WARN_ON(!is_in_v2_mode() &&
!cpumask_equal(cp->cpus_allowed, cp->effective_cpus));
@@ -1528,7 +1528,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
return -EINVAL;
}
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
cpumask_copy(cs->cpus_allowed, trialcs->cpus_allowed);
/*
@@ -1539,7 +1539,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
cs->cpus_allowed);
cs->nr_subparts_cpus = cpumask_weight(cs->subparts_cpus);
}
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
update_cpumasks_hier(cs, &tmp);
@@ -1733,9 +1733,9 @@ static void update_nodemasks_hier(struct cpuset *cs, nodemask_t *new_mems)
continue;
rcu_read_unlock();
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
cp->effective_mems = *new_mems;
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
WARN_ON(!is_in_v2_mode() &&
!nodes_equal(cp->mems_allowed, cp->effective_mems));
@@ -1803,9 +1803,9 @@ static int update_nodemask(struct cpuset *cs, struct cpuset *trialcs,
if (retval < 0)
goto done;
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
cs->mems_allowed = trialcs->mems_allowed;
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
/* use trialcs->mems_allowed as a temp variable */
update_nodemasks_hier(cs, &trialcs->mems_allowed);
@@ -1896,9 +1896,9 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
spread_flag_changed = ((is_spread_slab(cs) != is_spread_slab(trialcs))
|| (is_spread_page(cs) != is_spread_page(trialcs)));
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
cs->flags = trialcs->flags;
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
if (!cpumask_empty(trialcs->cpus_allowed) && balance_flag_changed)
rebuild_sched_domains_locked();
@@ -2407,7 +2407,7 @@ static int cpuset_common_seq_show(struct seq_file *sf, void *v)
cpuset_filetype_t type = seq_cft(sf)->private;
int ret = 0;
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
switch (type) {
case FILE_CPULIST:
@@ -2429,7 +2429,7 @@ static int cpuset_common_seq_show(struct seq_file *sf, void *v)
ret = -EINVAL;
}
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
return ret;
}
@@ -2742,14 +2742,14 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
cpuset_inc();
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
if (is_in_v2_mode()) {
cpumask_copy(cs->effective_cpus, parent->effective_cpus);
cs->effective_mems = parent->effective_mems;
cs->use_parent_ecpus = true;
parent->child_ecpus_count++;
}
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
if (!test_bit(CGRP_CPUSET_CLONE_CHILDREN, &css->cgroup->flags))
goto out_unlock;
@@ -2776,12 +2776,12 @@ static int cpuset_css_online(struct cgroup_subsys_state *css)
}
rcu_read_unlock();
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
cs->mems_allowed = parent->mems_allowed;
cs->effective_mems = parent->mems_allowed;
cpumask_copy(cs->cpus_allowed, parent->cpus_allowed);
cpumask_copy(cs->effective_cpus, parent->cpus_allowed);
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
out_unlock:
percpu_up_write(&cpuset_rwsem);
put_online_cpus();
@@ -2837,7 +2837,7 @@ static void cpuset_css_free(struct cgroup_subsys_state *css)
static void cpuset_bind(struct cgroup_subsys_state *root_css)
{
percpu_down_write(&cpuset_rwsem);
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
if (is_in_v2_mode()) {
cpumask_copy(top_cpuset.cpus_allowed, cpu_possible_mask);
@@ -2848,7 +2848,7 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
top_cpuset.mems_allowed = top_cpuset.effective_mems;
}
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
percpu_up_write(&cpuset_rwsem);
}
@@ -2945,12 +2945,12 @@ hotplug_update_tasks_legacy(struct cpuset *cs,
{
bool is_empty;
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
cpumask_copy(cs->cpus_allowed, new_cpus);
cpumask_copy(cs->effective_cpus, new_cpus);
cs->mems_allowed = *new_mems;
cs->effective_mems = *new_mems;
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
/*
* Don't call update_tasks_cpumask() if the cpuset becomes empty,
@@ -2987,10 +2987,10 @@ hotplug_update_tasks(struct cpuset *cs,
if (nodes_empty(*new_mems))
*new_mems = parent_cs(cs)->effective_mems;
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
cpumask_copy(cs->effective_cpus, new_cpus);
cs->effective_mems = *new_mems;
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
if (cpus_updated)
update_tasks_cpumask(cs);
@@ -3145,7 +3145,7 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
/* synchronize cpus_allowed to cpu_active_mask */
if (cpus_updated) {
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
if (!on_dfl)
cpumask_copy(top_cpuset.cpus_allowed, &new_cpus);
/*
@@ -3165,17 +3165,17 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
}
}
cpumask_copy(top_cpuset.effective_cpus, &new_cpus);
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
/* we don't mess with cpumasks of tasks in top_cpuset */
}
/* synchronize mems_allowed to N_MEMORY */
if (mems_updated) {
- spin_lock_irq(&callback_lock);
+ raw_spin_lock_irq(&callback_lock);
if (!on_dfl)
top_cpuset.mems_allowed = new_mems;
top_cpuset.effective_mems = new_mems;
- spin_unlock_irq(&callback_lock);
+ raw_spin_unlock_irq(&callback_lock);
update_tasks_nodemask(&top_cpuset);
}
@@ -3276,11 +3276,11 @@ void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask)
{
unsigned long flags;
- spin_lock_irqsave(&callback_lock, flags);
+ raw_spin_lock_irqsave(&callback_lock, flags);
rcu_read_lock();
guarantee_online_cpus(task_cs(tsk), pmask);
rcu_read_unlock();
- spin_unlock_irqrestore(&callback_lock, flags);
+ raw_spin_unlock_irqrestore(&callback_lock, flags);
}
/**
@@ -3341,11 +3341,11 @@ nodemask_t cpuset_mems_allowed(struct task_struct *tsk)
nodemask_t mask;
unsigned long flags;
- spin_lock_irqsave(&callback_lock, flags);
+ raw_spin_lock_irqsave(&callback_lock, flags);
rcu_read_lock();
guarantee_online_mems(task_cs(tsk), &mask);
rcu_read_unlock();
- spin_unlock_irqrestore(&callback_lock, flags);
+ raw_spin_unlock_irqrestore(&callback_lock, flags);
return mask;
}
@@ -3437,14 +3437,14 @@ bool __cpuset_node_allowed(int node, gfp_t gfp_mask)
return true;
/* Not hardwall and node outside mems_allowed: scan up cpusets */
- spin_lock_irqsave(&callback_lock, flags);
+ raw_spin_lock_irqsave(&callback_lock, flags);
rcu_read_lock();
cs = nearest_hardwall_ancestor(task_cs(current));
allowed = node_isset(node, cs->mems_allowed);
rcu_read_unlock();
- spin_unlock_irqrestore(&callback_lock, flags);
+ raw_spin_unlock_irqrestore(&callback_lock, flags);
return allowed;
}
diff --git a/kernel/cgroup/rstat.c b/kernel/cgroup/rstat.c
index ca19b4c8acf53..a59962e66aea1 100644
--- a/kernel/cgroup/rstat.c
+++ b/kernel/cgroup/rstat.c
@@ -149,7 +149,7 @@ static struct cgroup *cgroup_rstat_cpu_pop_updated(struct cgroup *pos,
}
/* see cgroup_rstat_flush() */
-static void cgroup_rstat_flush_locked(struct cgroup *cgrp, bool may_sleep)
+static void cgroup_rstat_flush_locked(struct cgroup *cgrp)
__releases(&cgroup_rstat_lock) __acquires(&cgroup_rstat_lock)
{
int cpu;
@@ -161,27 +161,17 @@ static void cgroup_rstat_flush_locked(struct cgroup *cgrp, bool may_sleep)
cpu);
struct cgroup *pos = NULL;
- raw_spin_lock(cpu_lock);
- while ((pos = cgroup_rstat_cpu_pop_updated(pos, cgrp, cpu))) {
- struct cgroup_subsys_state *css;
-
+ raw_spin_lock_irq(cpu_lock);
+ while ((pos = cgroup_rstat_cpu_pop_updated(pos, cgrp, cpu)))
cgroup_base_stat_flush(pos, cpu);
- rcu_read_lock();
- list_for_each_entry_rcu(css, &pos->rstat_css_list,
- rstat_css_node)
- css->ss->css_rstat_flush(css, cpu);
- rcu_read_unlock();
- }
- raw_spin_unlock(cpu_lock);
+ raw_spin_unlock_irq(cpu_lock);
- /* if @may_sleep, play nice and yield if necessary */
- if (may_sleep && (need_resched() ||
- spin_needbreak(&cgroup_rstat_lock))) {
- spin_unlock_irq(&cgroup_rstat_lock);
+ if (need_resched() || spin_needbreak(&cgroup_rstat_lock)) {
+ spin_unlock(&cgroup_rstat_lock);
if (!cond_resched())
cpu_relax();
- spin_lock_irq(&cgroup_rstat_lock);
+ spin_lock(&cgroup_rstat_lock);
}
}
}
@@ -203,24 +193,9 @@ void cgroup_rstat_flush(struct cgroup *cgrp)
{
might_sleep();
- spin_lock_irq(&cgroup_rstat_lock);
- cgroup_rstat_flush_locked(cgrp, true);
- spin_unlock_irq(&cgroup_rstat_lock);
-}
-
-/**
- * cgroup_rstat_flush_irqsafe - irqsafe version of cgroup_rstat_flush()
- * @cgrp: target cgroup
- *
- * This function can be called from any context.
- */
-void cgroup_rstat_flush_irqsafe(struct cgroup *cgrp)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cgroup_rstat_lock, flags);
- cgroup_rstat_flush_locked(cgrp, false);
- spin_unlock_irqrestore(&cgroup_rstat_lock, flags);
+ spin_lock(&cgroup_rstat_lock);
+ cgroup_rstat_flush_locked(cgrp);
+ spin_unlock(&cgroup_rstat_lock);
}
/**
@@ -232,21 +207,21 @@ void cgroup_rstat_flush_irqsafe(struct cgroup *cgrp)
*
* This function may block.
*/
-void cgroup_rstat_flush_hold(struct cgroup *cgrp)
+static void cgroup_rstat_flush_hold(struct cgroup *cgrp)
__acquires(&cgroup_rstat_lock)
{
might_sleep();
- spin_lock_irq(&cgroup_rstat_lock);
- cgroup_rstat_flush_locked(cgrp, true);
+ spin_lock(&cgroup_rstat_lock);
+ cgroup_rstat_flush_locked(cgrp);
}
/**
* cgroup_rstat_flush_release - release cgroup_rstat_flush_hold()
*/
-void cgroup_rstat_flush_release(void)
+static void cgroup_rstat_flush_release(void)
__releases(&cgroup_rstat_lock)
{
- spin_unlock_irq(&cgroup_rstat_lock);
+ spin_unlock(&cgroup_rstat_lock);
}
int cgroup_rstat_init(struct cgroup *cgrp)
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 116825437cd61..368309e9a1f52 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -331,12 +331,12 @@ void lockdep_assert_cpus_held(void)
static void lockdep_acquire_cpus_lock(void)
{
- rwsem_acquire(&cpu_hotplug_lock.rw_sem.dep_map, 0, 0, _THIS_IP_);
+ rwsem_acquire(&cpu_hotplug_lock.dep_map, 0, 0, _THIS_IP_);
}
static void lockdep_release_cpus_lock(void)
{
- rwsem_release(&cpu_hotplug_lock.rw_sem.dep_map, 1, _THIS_IP_);
+ rwsem_release(&cpu_hotplug_lock.dep_map, 1, _THIS_IP_);
}
/*
@@ -849,6 +849,15 @@ static int take_cpu_down(void *_param)
int err, cpu = smp_processor_id();
int ret;
+#ifdef CONFIG_PREEMPT_RT
+ /*
+ * If any tasks disabled migration before we got here,
+ * go back and sleep again.
+ */
+ if (cpu_nr_pinned(cpu))
+ return -EAGAIN;
+#endif
+
/* Ensure this CPU doesn't handle any more interrupts. */
err = __cpu_disable();
if (err < 0)
@@ -878,6 +887,10 @@ static int take_cpu_down(void *_param)
return 0;
}
+#ifdef CONFIG_PREEMPT_RT
+struct task_struct *takedown_cpu_task;
+#endif
+
static int takedown_cpu(unsigned int cpu)
{
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
@@ -892,11 +905,39 @@ static int takedown_cpu(unsigned int cpu)
*/
irq_lock_sparse();
+#ifdef CONFIG_PREEMPT_RT
+ WARN_ON_ONCE(takedown_cpu_task);
+ takedown_cpu_task = current;
+
+again:
+ /*
+ * If a task pins this CPU after we pass this check, take_cpu_down
+ * will return -EAGAIN.
+ */
+ for (;;) {
+ int nr_pinned;
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ nr_pinned = cpu_nr_pinned(cpu);
+ if (nr_pinned == 0)
+ break;
+ schedule();
+ }
+ set_current_state(TASK_RUNNING);
+#endif
+
/*
* So now all preempt/rcu users must observe !cpu_active().
*/
err = stop_machine_cpuslocked(take_cpu_down, NULL, cpumask_of(cpu));
+#ifdef CONFIG_PREEMPT_RT
+ if (err == -EAGAIN)
+ goto again;
+#endif
if (err) {
+#ifdef CONFIG_PREEMPT_RT
+ takedown_cpu_task = NULL;
+#endif
/* CPU refused to die */
irq_unlock_sparse();
/* Unpark the hotplug thread so we can rollback there */
@@ -915,6 +956,9 @@ static int takedown_cpu(unsigned int cpu)
wait_for_ap_thread(st, false);
BUG_ON(st->state != CPUHP_AP_IDLE_DEAD);
+#ifdef CONFIG_PREEMPT_RT
+ takedown_cpu_task = NULL;
+#endif
/* Interrupts are moved away from the dying cpu, reenable alloc/free */
irq_unlock_sparse();
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 15b123bdcaf53..253bdc106cb8c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -8966,7 +8966,6 @@ static void bpf_overflow_handler(struct perf_event *event,
int ret = 0;
ctx.regs = perf_arch_bpf_user_pt_regs(regs);
- preempt_disable();
if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1))
goto out;
rcu_read_lock();
@@ -8974,7 +8973,6 @@ static void bpf_overflow_handler(struct perf_event *event,
rcu_read_unlock();
out:
__this_cpu_dec(bpf_prog_active);
- preempt_enable();
if (!ret)
return;
@@ -10264,7 +10262,7 @@ static struct pmu *perf_init_event(struct perf_event *event)
goto unlock;
}
- list_for_each_entry_rcu(pmu, &pmus, entry) {
+ list_for_each_entry_rcu(pmu, &pmus, entry, lockdep_is_held(&pmus_srcu)) {
ret = perf_try_init_event(pmu, event);
if (!ret)
goto unlock;
diff --git a/kernel/exit.c b/kernel/exit.c
index 22dfaac9e48c5..dcb1f1182101e 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -161,7 +161,7 @@ static void __exit_signal(struct task_struct *tsk)
* Do this under ->siglock, we can race with another thread
* doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals.
*/
- flush_sigqueue(&tsk->pending);
+ flush_task_sigqueue(tsk);
tsk->sighand = NULL;
spin_unlock(&sighand->siglock);
@@ -258,6 +258,7 @@ void rcuwait_wake_up(struct rcuwait *w)
wake_up_process(task);
rcu_read_unlock();
}
+EXPORT_SYMBOL_GPL(rcuwait_wake_up);
/*
* Determine if a process group is "orphaned", according to the POSIX
diff --git a/kernel/fork.c b/kernel/fork.c
index 755d8160e0012..44e95c5207a46 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -289,7 +290,7 @@ static inline void free_thread_stack(struct task_struct *tsk)
return;
}
- vfree_atomic(tsk->stack);
+ vfree(tsk->stack);
return;
}
#endif
@@ -696,6 +697,19 @@ void __mmdrop(struct mm_struct *mm)
}
EXPORT_SYMBOL_GPL(__mmdrop);
+#ifdef CONFIG_PREEMPT_RT
+/*
+ * RCU callback for delayed mm drop. Not strictly rcu, but we don't
+ * want another facility to make this work.
+ */
+void __mmdrop_delayed(struct rcu_head *rhp)
+{
+ struct mm_struct *mm = container_of(rhp, struct mm_struct, delayed_drop);
+
+ __mmdrop(mm);
+}
+#endif
+
static void mmdrop_async_fn(struct work_struct *work)
{
struct mm_struct *mm;
@@ -737,6 +751,15 @@ void __put_task_struct(struct task_struct *tsk)
WARN_ON(refcount_read(&tsk->usage));
WARN_ON(tsk == current);
+ /*
+ * Remove function-return probe instances associated with this
+ * task and put them back on the free list.
+ */
+ kprobe_flush_task(tsk);
+
+ /* Task is done with its stack. */
+ put_task_stack(tsk);
+
cgroup_free(tsk);
task_numa_free(tsk, true);
security_task_free(tsk);
@@ -927,6 +950,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
tsk->splice_pipe = NULL;
tsk->task_frag.page = NULL;
tsk->wake_q.next = NULL;
+ tsk->wake_q_sleeper.next = NULL;
account_kernel_stack(tsk, 1);
@@ -1900,6 +1924,7 @@ static __latent_entropy struct task_struct *copy_process(
spin_lock_init(&p->alloc_lock);
init_sigpending(&p->pending);
+ p->sigqueue_cache = NULL;
p->utime = p->stime = p->gtime = 0;
#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
diff --git a/kernel/futex.c b/kernel/futex.c
index afbf928d6a6b0..58c0c77fda797 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -945,7 +945,9 @@ static void exit_pi_state_list(struct task_struct *curr)
if (head->next != next) {
/* retain curr->pi_lock for the loop invariant */
raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
+ raw_spin_unlock_irq(&curr->pi_lock);
spin_unlock(&hb->lock);
+ raw_spin_lock_irq(&curr->pi_lock);
put_pi_state(pi_state);
continue;
}
@@ -1554,6 +1556,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_
struct task_struct *new_owner;
bool postunlock = false;
DEFINE_WAKE_Q(wake_q);
+ DEFINE_WAKE_Q(wake_sleeper_q);
int ret = 0;
new_owner = rt_mutex_next_owner(&pi_state->pi_mutex);
@@ -1613,13 +1616,13 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_
pi_state->owner = new_owner;
raw_spin_unlock(&new_owner->pi_lock);
- postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q);
-
+ postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q,
+ &wake_sleeper_q);
out_unlock:
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
if (postunlock)
- rt_mutex_postunlock(&wake_q);
+ rt_mutex_postunlock(&wake_q, &wake_sleeper_q);
return ret;
}
@@ -2243,6 +2246,16 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
requeue_pi_wake_futex(this, &key2, hb2);
drop_count++;
continue;
+ } else if (ret == -EAGAIN) {
+ /*
+ * Waiter was woken by timeout or
+ * signal and has set pi_blocked_on to
+ * PI_WAKEUP_INPROGRESS before we
+ * tried to enqueue it on the rtmutex.
+ */
+ this->pi_state = NULL;
+ put_pi_state(pi_state);
+ continue;
} else if (ret) {
/*
* rt_mutex_start_proxy_lock() detected a
@@ -2951,7 +2964,7 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
goto no_block;
}
- rt_mutex_init_waiter(&rt_waiter);
+ rt_mutex_init_waiter(&rt_waiter, false);
/*
* On PREEMPT_RT_FULL, when hb->lock becomes an rt_mutex, we must not
@@ -2967,6 +2980,14 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
* before __rt_mutex_start_proxy_lock() is done.
*/
raw_spin_lock_irq(&q.pi_state->pi_mutex.wait_lock);
+ /*
+ * the migrate_disable() here disables migration in the in_atomic() fast
+ * path which is enabled again in the following spin_unlock(). We have
+ * one migrate_disable() pending in the slow-path which is reversed
+ * after the raw_spin_unlock_irq() where we leave the atomic context.
+ */
+ migrate_disable();
+
spin_unlock(q.lock_ptr);
/*
* __rt_mutex_start_proxy_lock() unconditionally enqueues the @rt_waiter
@@ -2975,6 +2996,7 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
*/
ret = __rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current);
raw_spin_unlock_irq(&q.pi_state->pi_mutex.wait_lock);
+ migrate_enable();
if (ret) {
if (ret == 1)
@@ -3123,10 +3145,19 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
* rt_waiter. Also see the WARN in wake_futex_pi().
*/
raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
+ /*
+ * Magic trickery for now to make the RT migrate disable
+ * logic happy. The following spin_unlock() happens with
+ * interrupts disabled so the internal migrate_enable()
+ * won't undo the migrate_disable() which was issued when
+ * locking hb->lock.
+ */
+ migrate_disable();
spin_unlock(&hb->lock);
/* drops pi_state->pi_mutex.wait_lock */
ret = wake_futex_pi(uaddr, uval, pi_state);
+ migrate_enable();
put_pi_state(pi_state);
@@ -3298,7 +3329,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
struct hrtimer_sleeper timeout, *to;
struct futex_pi_state *pi_state = NULL;
struct rt_mutex_waiter rt_waiter;
- struct futex_hash_bucket *hb;
+ struct futex_hash_bucket *hb, *hb2;
union futex_key key2 = FUTEX_KEY_INIT;
struct futex_q q = futex_q_init;
int res, ret;
@@ -3319,7 +3350,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* The waiter is allocated on our stack, manipulated by the requeue
* code while we sleep on uaddr.
*/
- rt_mutex_init_waiter(&rt_waiter);
+ rt_mutex_init_waiter(&rt_waiter, false);
ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, FUTEX_WRITE);
if (unlikely(ret != 0))
@@ -3350,20 +3381,55 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
/* Queue the futex_q, drop the hb lock, wait for wakeup. */
futex_wait_queue_me(hb, &q, to);
- spin_lock(&hb->lock);
- ret = handle_early_requeue_pi_wakeup(hb, &q, &key2, to);
- spin_unlock(&hb->lock);
- if (ret)
- goto out_put_keys;
+ /*
+ * On RT we must avoid races with requeue and trying to block
+ * on two mutexes (hb->lock and uaddr2's rtmutex) by
+ * serializing access to pi_blocked_on with pi_lock.
+ */
+ raw_spin_lock_irq(¤t->pi_lock);
+ if (current->pi_blocked_on) {
+ /*
+ * We have been requeued or are in the process of
+ * being requeued.
+ */
+ raw_spin_unlock_irq(¤t->pi_lock);
+ } else {
+ /*
+ * Setting pi_blocked_on to PI_WAKEUP_INPROGRESS
+ * prevents a concurrent requeue from moving us to the
+ * uaddr2 rtmutex. After that we can safely acquire
+ * (and possibly block on) hb->lock.
+ */
+ current->pi_blocked_on = PI_WAKEUP_INPROGRESS;
+ raw_spin_unlock_irq(¤t->pi_lock);
+
+ spin_lock(&hb->lock);
+
+ /*
+ * Clean up pi_blocked_on. We might leak it otherwise
+ * when we succeeded with the hb->lock in the fast
+ * path.
+ */
+ raw_spin_lock_irq(¤t->pi_lock);
+ current->pi_blocked_on = NULL;
+ raw_spin_unlock_irq(¤t->pi_lock);
+
+ ret = handle_early_requeue_pi_wakeup(hb, &q, &key2, to);
+ spin_unlock(&hb->lock);
+ if (ret)
+ goto out_put_keys;
+ }
/*
- * In order for us to be here, we know our q.key == key2, and since
- * we took the hb->lock above, we also know that futex_requeue() has
- * completed and we no longer have to concern ourselves with a wakeup
- * race with the atomic proxy lock acquisition by the requeue code. The
- * futex_requeue dropped our key1 reference and incremented our key2
- * reference count.
+ * In order to be here, we have either been requeued, are in
+ * the process of being requeued, or requeue successfully
+ * acquired uaddr2 on our behalf. If pi_blocked_on was
+ * non-null above, we may be racing with a requeue. Do not
+ * rely on q->lock_ptr to be hb2->lock until after blocking on
+ * hb->lock or hb2->lock. The futex_requeue dropped our key1
+ * reference and incremented our key2 reference count.
*/
+ hb2 = hash_futex(&key2);
/* Check if the requeue code acquired the second futex for us. */
if (!q.rt_waiter) {
@@ -3372,7 +3438,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* did a lock-steal - fix up the PI-state in that case.
*/
if (q.pi_state && (q.pi_state->owner != current)) {
- spin_lock(q.lock_ptr);
+ spin_lock(&hb2->lock);
+ BUG_ON(&hb2->lock != q.lock_ptr);
ret = fixup_pi_state_owner(uaddr2, &q, current);
if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) {
pi_state = q.pi_state;
@@ -3383,7 +3450,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
* the requeue_pi() code acquired for us.
*/
put_pi_state(q.pi_state);
- spin_unlock(q.lock_ptr);
+ spin_unlock(&hb2->lock);
}
} else {
struct rt_mutex *pi_mutex;
@@ -3397,7 +3464,8 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
pi_mutex = &q.pi_state->pi_mutex;
ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter);
- spin_lock(q.lock_ptr);
+ spin_lock(&hb2->lock);
+ BUG_ON(&hb2->lock != q.lock_ptr);
if (ret && !rt_mutex_cleanup_proxy_lock(pi_mutex, &rt_waiter))
ret = 0;
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index a4ace611f47fe..3306fabed2217 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -185,10 +185,16 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
{
irqreturn_t retval;
unsigned int flags = 0;
+ struct pt_regs *regs = get_irq_regs();
+ u64 ip = regs ? instruction_pointer(regs) : 0;
retval = __handle_irq_event_percpu(desc, &flags);
- add_interrupt_randomness(desc->irq_data.irq, flags);
+#ifdef CONFIG_PREEMPT_RT
+ desc->random_ip = ip;
+#else
+ add_interrupt_randomness(desc->irq_data.irq, flags, ip);
+#endif
if (!noirqdebug)
note_interrupt(desc, retval);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 1753486b440cb..665a1dd59e5fc 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1099,6 +1099,12 @@ static int irq_thread(void *data)
if (action_ret == IRQ_WAKE_THREAD)
irq_wake_secondary(desc, action);
+#ifdef CONFIG_PREEMPT_RT
+ migrate_disable();
+ add_interrupt_randomness(action->irq, 0,
+ desc->random_ip ^ (unsigned long) action);
+ migrate_enable();
+#endif
wake_threads_waitq(desc);
}
@@ -2681,7 +2687,7 @@ EXPORT_SYMBOL_GPL(irq_get_irqchip_state);
* This call sets the internal irqchip state of an interrupt,
* depending on the value of @which.
*
- * This function should be called with preemption disabled if the
+ * This function should be called with migration disabled if the
* interrupt controller has per-cpu registers.
*/
int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 2ed97a7c9b2a6..9e97124946a6a 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -442,6 +442,10 @@ MODULE_PARM_DESC(noirqdebug, "Disable irq lockup detection when true");
static int __init irqfixup_setup(char *str)
{
+#ifdef CONFIG_PREEMPT_RT
+ pr_warn("irqfixup boot option not supported w/ CONFIG_PREEMPT_RT\n");
+ return 1;
+#endif
irqfixup = 1;
printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
printk(KERN_WARNING "This may impact system performance.\n");
@@ -454,6 +458,10 @@ module_param(irqfixup, int, 0644);
static int __init irqpoll_setup(char *str)
{
+#ifdef CONFIG_PREEMPT_RT
+ pr_warn("irqpoll boot option not supported w/ CONFIG_PREEMPT_RT\n");
+ return 1;
+#endif
irqfixup = 2;
printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
"enabled\n");
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index d42acaf818861..aab68fdbcb8d2 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include
@@ -60,13 +61,19 @@ void __weak arch_irq_work_raise(void)
/* Enqueue on current CPU, work must already be claimed and preempt disabled */
static void __irq_work_queue_local(struct irq_work *work)
{
+ struct llist_head *list;
+ bool lazy_work, realtime = IS_ENABLED(CONFIG_PREEMPT_RT);
+
+ lazy_work = work->flags & IRQ_WORK_LAZY;
+
/* If the work is "lazy", handle it from next tick if any */
- if (work->flags & IRQ_WORK_LAZY) {
- if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) &&
- tick_nohz_tick_stopped())
- arch_irq_work_raise();
- } else {
- if (llist_add(&work->llnode, this_cpu_ptr(&raised_list)))
+ if (lazy_work || (realtime && !(work->flags & IRQ_WORK_HARD_IRQ)))
+ list = this_cpu_ptr(&lazy_list);
+ else
+ list = this_cpu_ptr(&raised_list);
+
+ if (llist_add(&work->llnode, list)) {
+ if (!lazy_work || tick_nohz_tick_stopped())
arch_irq_work_raise();
}
}
@@ -108,9 +115,16 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
preempt_disable();
if (cpu != smp_processor_id()) {
+ struct llist_head *list;
+
/* Arch remote IPI send/receive backend aren't NMI safe */
WARN_ON_ONCE(in_nmi());
- if (llist_add(&work->llnode, &per_cpu(raised_list, cpu)))
+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && !(work->flags & IRQ_WORK_HARD_IRQ))
+ list = &per_cpu(lazy_list, cpu);
+ else
+ list = &per_cpu(raised_list, cpu);
+
+ if (llist_add(&work->llnode, list))
arch_send_call_function_single_ipi(cpu);
} else {
__irq_work_queue_local(work);
@@ -129,9 +143,8 @@ bool irq_work_needs_cpu(void)
raised = this_cpu_ptr(&raised_list);
lazy = this_cpu_ptr(&lazy_list);
- if (llist_empty(raised) || arch_irq_work_has_interrupt())
- if (llist_empty(lazy))
- return false;
+ if (llist_empty(raised) && llist_empty(lazy))
+ return false;
/* All work should have been flushed before going offline */
WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
@@ -145,8 +158,12 @@ static void irq_work_run_list(struct llist_head *list)
struct llist_node *llnode;
unsigned long flags;
+#ifndef CONFIG_PREEMPT_RT
+ /*
+ * nort: On RT IRQ-work may run in SOFTIRQ context.
+ */
BUG_ON(!irqs_disabled());
-
+#endif
if (llist_empty(list))
return;
@@ -178,7 +195,16 @@ static void irq_work_run_list(struct llist_head *list)
void irq_work_run(void)
{
irq_work_run_list(this_cpu_ptr(&raised_list));
- irq_work_run_list(this_cpu_ptr(&lazy_list));
+ if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
+ /*
+ * NOTE: we raise softirq via IPI for safety,
+ * and execute in irq_work_tick() to move the
+ * overhead from hard to soft irq context.
+ */
+ if (!llist_empty(this_cpu_ptr(&lazy_list)))
+ raise_softirq(TIMER_SOFTIRQ);
+ } else
+ irq_work_run_list(this_cpu_ptr(&lazy_list));
}
EXPORT_SYMBOL_GPL(irq_work_run);
@@ -188,8 +214,17 @@ void irq_work_tick(void)
if (!llist_empty(raised) && !arch_irq_work_has_interrupt())
irq_work_run_list(raised);
+
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
+ irq_work_run_list(this_cpu_ptr(&lazy_list));
+}
+
+#if defined(CONFIG_IRQ_WORK) && defined(CONFIG_PREEMPT_RT)
+void irq_work_tick_soft(void)
+{
irq_work_run_list(this_cpu_ptr(&lazy_list));
}
+#endif
/*
* Synchronize against the irq_work @entry, ensures the entry is not
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 15d70a90b50dc..e7cef4e2e01f9 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -972,7 +972,6 @@ void crash_kexec(struct pt_regs *regs)
old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu);
if (old_cpu == PANIC_CPU_INVALID) {
/* This is the 1st CPU which comes here, so go ahead. */
- printk_safe_flush_on_panic();
__crash_kexec(regs);
/*
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 35859da8bd4f7..dfff31ed644a6 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -138,6 +138,15 @@ KERNEL_ATTR_RO(vmcoreinfo);
#endif /* CONFIG_CRASH_CORE */
+#if defined(CONFIG_PREEMPT_RT)
+static ssize_t realtime_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", 1);
+}
+KERNEL_ATTR_RO(realtime);
+#endif
+
/* whether file capabilities are enabled */
static ssize_t fscaps_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
@@ -228,6 +237,9 @@ static struct attribute * kernel_attrs[] = {
#ifndef CONFIG_TINY_RCU
&rcu_expedited_attr.attr,
&rcu_normal_attr.attr,
+#endif
+#ifdef CONFIG_PREEMPT_RT
+ &realtime_attr.attr,
#endif
NULL
};
diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile
index 45452facff3b4..fa253e0db7515 100644
--- a/kernel/locking/Makefile
+++ b/kernel/locking/Makefile
@@ -3,7 +3,7 @@
# and is generally not a function of system call inputs.
KCOV_INSTRUMENT := n
-obj-y += mutex.o semaphore.o rwsem.o percpu-rwsem.o
+obj-y += semaphore.o rwsem.o percpu-rwsem.o
ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_lockdep.o = $(CC_FLAGS_FTRACE)
@@ -12,19 +12,23 @@ CFLAGS_REMOVE_mutex-debug.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_rtmutex-debug.o = $(CC_FLAGS_FTRACE)
endif
-obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
obj-$(CONFIG_LOCKDEP) += lockdep.o
ifeq ($(CONFIG_PROC_FS),y)
obj-$(CONFIG_LOCKDEP) += lockdep_proc.o
endif
obj-$(CONFIG_SMP) += spinlock.o
-obj-$(CONFIG_LOCK_SPIN_ON_OWNER) += osq_lock.o
obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
obj-$(CONFIG_QUEUED_SPINLOCKS) += qspinlock.o
obj-$(CONFIG_RT_MUTEXES) += rtmutex.o
obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
+ifneq ($(CONFIG_PREEMPT_RT),y)
+obj-y += mutex.o
+obj-$(CONFIG_LOCK_SPIN_ON_OWNER) += osq_lock.o
+obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
+endif
+obj-$(CONFIG_PREEMPT_RT) += mutex-rt.o rwsem-rt.o rwlock-rt.o
obj-$(CONFIG_QUEUED_RWLOCKS) += qrwlock.o
obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o
obj-$(CONFIG_WW_MUTEX_SELFTEST) += test-ww_mutex.o
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 35d3b6925b1ee..eed015cf5fc4a 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -4409,6 +4409,7 @@ static void check_flags(unsigned long flags)
}
}
+#ifndef CONFIG_PREEMPT_RT
/*
* We dont accurately track softirq state in e.g.
* hardirq contexts (such as on 4KSTACKS), so only
@@ -4423,6 +4424,7 @@ static void check_flags(unsigned long flags)
DEBUG_LOCKS_WARN_ON(!current->softirqs_enabled);
}
}
+#endif
if (!debug_locks)
print_irqtrace_events(current);
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
index c513031cd7e33..9fb042d610d23 100644
--- a/kernel/locking/locktorture.c
+++ b/kernel/locking/locktorture.c
@@ -16,7 +16,6 @@
#include
#include
#include
-#include
#include
#include
#include
diff --git a/kernel/locking/mutex-rt.c b/kernel/locking/mutex-rt.c
new file mode 100644
index 0000000000000..4f81595c0f521
--- /dev/null
+++ b/kernel/locking/mutex-rt.c
@@ -0,0 +1,223 @@
+/*
+ * kernel/rt.c
+ *
+ * Real-Time Preemption Support
+ *
+ * started by Ingo Molnar:
+ *
+ * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar
+ * Copyright (C) 2006, Timesys Corp., Thomas Gleixner
+ *
+ * historic credit for proving that Linux spinlocks can be implemented via
+ * RT-aware mutexes goes to many people: The Pmutex project (Dirk Grambow
+ * and others) who prototyped it on 2.4 and did lots of comparative
+ * research and analysis; TimeSys, for proving that you can implement a
+ * fully preemptible kernel via the use of IRQ threading and mutexes;
+ * Bill Huey for persuasively arguing on lkml that the mutex model is the
+ * right one; and to MontaVista, who ported pmutexes to 2.6.
+ *
+ * This code is a from-scratch implementation and is not based on pmutexes,
+ * but the idea of converting spinlocks to mutexes is used here too.
+ *
+ * lock debugging, locking tree, deadlock detection:
+ *
+ * Copyright (C) 2004, LynuxWorks, Inc., Igor Manyilov, Bill Huey
+ * Released under the General Public License (GPL).
+ *
+ * Includes portions of the generic R/W semaphore implementation from:
+ *
+ * Copyright (c) 2001 David Howells (dhowells@redhat.com).
+ * - Derived partially from idea by Andrea Arcangeli
+ * - Derived also from comments by Linus
+ *
+ * Pending ownership of locks and ownership stealing:
+ *
+ * Copyright (C) 2005, Kihon Technologies Inc., Steven Rostedt
+ *
+ * (also by Steven Rostedt)
+ * - Converted single pi_lock to individual task locks.
+ *
+ * By Esben Nielsen:
+ * Doing priority inheritance with help of the scheduler.
+ *
+ * Copyright (C) 2006, Timesys Corp., Thomas Gleixner
+ * - major rework based on Esben Nielsens initial patch
+ * - replaced thread_info references by task_struct refs
+ * - removed task->pending_owner dependency
+ * - BKL drop/reacquire for semaphore style locks to avoid deadlocks
+ * in the scheduler return path as discussed with Steven Rostedt
+ *
+ * Copyright (C) 2006, Kihon Technologies Inc.
+ * Steven Rostedt
+ * - debugged and patched Thomas Gleixner's rework.
+ * - added back the cmpxchg to the rework.
+ * - turned atomic require back on for SMP.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include