Few fixes for omaps mostly for various devices to get them working
properly on the new am437x and dra7 hardware for several devices such as I2C, NAND, DDR3 and USB. There's also a clock fix for omap3. And also included are two minor cosmetic fixes that are not stictly fixes for the new hardware support added recently to downgrade a GPMC warning into a debug statement, and fix the confusing comments for dra7-evm spi1 mux. Note that these are all .dts changes except for a GPMC change. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUCMlzAAoJEBvUPslcq6Vzt7YP/1bVH7aupL/OabRkbo8FTSoS Z0LQTNi5u14Pe+YS31pLGtDEO62iTf53wweUv+Xf90F98wfWUz9bR487nzS49JD/ 2htv6JZ5wcMAQgol74UN5wQR5W3nEBEKsPSc641YrZWjzCWe5gAbdfjdZqg7Ulm2 gMcavTML66Ok9lT0PxJhpre55XeEBz7QJcWT8iESvrHX2ZMXwl38Z6pVaabgRxEp 5usQOzK45tsWkDHD3iyWEyyM1JJ2nSD3O2O/UrbVyr/8uSPQZdQGXm4/KTBH5kEJ XiwHLscCcC+u9YoQHrLAHE4RpfWSv6gzFjrkwEDcBXotuaLJdeQJNDxzrvyWVUfN S0P8It+rguB6TNgqxhCqs+LqtfFZEuBJPxBKiU8QWzPSRYogfHpsEHZwThJxHqQx 94gd1tMFXVY+VgM/xe/JdBw8k5oukQTWJ9QxcD5/tRA+QH++8XOEJXrWlqAA/+uq qFE8W3+U6FUsv39hM+KWdMdhMAvqiAP7gLoItUjGMUoZtSy800zDdOEhXX3rkJMH SoQca4T/0iX6lDafyXn62kk/emAXf/cT2cCpd6v6Aj2JhMvKbD1Nm8nJwZxTQqh/ 9c72CyqqAuxtasIz/hxDB9tOiXYPihHNliVe9zDKf0con0smw6CQZ6iAVKnM62IM 3E5bXvHeK5/5a9C9i6w9 =9VRv -----END PGP SIGNATURE----- Merge tag 'omap-fixes-against-v3.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes Merge "omap fixes against v3.17-rc3" from Tony Lindgren: Few fixes for omaps mostly for various devices to get them working properly on the new am437x and dra7 hardware for several devices such as I2C, NAND, DDR3 and USB. There's also a clock fix for omap3. And also included are two minor cosmetic fixes that are not stictly fixes for the new hardware support added recently to downgrade a GPMC warning into a debug statement, and fix the confusing comments for dra7-evm spi1 mux. Note that these are all .dts changes except for a GPMC change. * tag 'omap-fixes-against-v3.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (255 commits) ARM: dts: dra7-evm: Add vtt regulator support ARM: dts: dra7-evm: Fix spi1 mux documentation ARM: dts: am43x-epos-evm: Disable QSPI to prevent conflict with GPMC-NAND ARM: OMAP2+: gpmc: Don't complain if wait pin is used without r/w monitoring ARM: dts: am43xx-epos-evm: Don't use read/write wait monitoring ARM: dts: am437x-gp-evm: Don't use read/write wait monitoring ARM: dts: am437x-gp-evm: Use BCH16 ECC scheme instead of BCH8 ARM: dts: am43x-epos-evm: Use BCH16 ECC scheme instead of BCH8 ARM: dts: am4372: fix USB regs size ARM: dts: am437x-gp: switch i2c0 to 100KHz ARM: dts: dra7-evm: Fix 8th NAND partition's name ARM: dts: dra7-evm: Fix i2c3 pinmux and frequency Linux 3.17-rc3 ... Signed-off-by: Kevin Hilman <khilman@linaro.org>
This commit is contained in:
commit
95f6e8142d
107
Documentation/devicetree/bindings/mfd/tc3589x.txt
Normal file
107
Documentation/devicetree/bindings/mfd/tc3589x.txt
Normal file
|
@ -0,0 +1,107 @@
|
|||
* Toshiba TC3589x multi-purpose expander
|
||||
|
||||
The Toshiba TC3589x series are I2C-based MFD devices which may expose the
|
||||
following built-in devices: gpio, keypad, rotator (vibrator), PWM (for
|
||||
e.g. LEDs or vibrators) The included models are:
|
||||
|
||||
- TC35890
|
||||
- TC35892
|
||||
- TC35893
|
||||
- TC35894
|
||||
- TC35895
|
||||
- TC35896
|
||||
|
||||
Required properties:
|
||||
- compatible : must be "toshiba,tc35890", "toshiba,tc35892", "toshiba,tc35893",
|
||||
"toshiba,tc35894", "toshiba,tc35895" or "toshiba,tc35896"
|
||||
- reg : I2C address of the device
|
||||
- interrupt-parent : specifies which IRQ controller we're connected to
|
||||
- interrupts : the interrupt on the parent the controller is connected to
|
||||
- interrupt-controller : marks the device node as an interrupt controller
|
||||
- #interrupt-cells : should be <1>, the first cell is the IRQ offset on this
|
||||
TC3589x interrupt controller.
|
||||
|
||||
Optional nodes:
|
||||
|
||||
- GPIO
|
||||
This GPIO module inside the TC3589x has 24 (TC35890, TC35892) or 20
|
||||
(other models) GPIO lines.
|
||||
- compatible : must be "toshiba,tc3589x-gpio"
|
||||
- interrupts : interrupt on the parent, which must be the tc3589x MFD device
|
||||
- interrupt-controller : marks the device node as an interrupt controller
|
||||
- #interrupt-cells : should be <2>, the first cell is the IRQ offset on this
|
||||
TC3589x GPIO interrupt controller, the second cell is the interrupt flags
|
||||
in accordance with <dt-bindings/interrupt-controller/irq.h>. The following
|
||||
flags are valid:
|
||||
- IRQ_TYPE_LEVEL_LOW
|
||||
- IRQ_TYPE_LEVEL_HIGH
|
||||
- IRQ_TYPE_EDGE_RISING
|
||||
- IRQ_TYPE_EDGE_FALLING
|
||||
- IRQ_TYPE_EDGE_BOTH
|
||||
- gpio-controller : marks the device node as a GPIO controller
|
||||
- #gpio-cells : should be <2>, the first cell is the GPIO offset on this
|
||||
GPIO controller, the second cell is the flags.
|
||||
|
||||
- Keypad
|
||||
This keypad is the same on all variants, supporting up to 96 different
|
||||
keys. The linux-specific properties are modeled on those already existing
|
||||
in other input drivers.
|
||||
- compatible : must be "toshiba,tc3589x-keypad"
|
||||
- debounce-delay-ms : debounce interval in milliseconds
|
||||
- keypad,num-rows : number of rows in the matrix, see
|
||||
bindings/input/matrix-keymap.txt
|
||||
- keypad,num-columns : number of columns in the matrix, see
|
||||
bindings/input/matrix-keymap.txt
|
||||
- linux,keymap: the definition can be found in
|
||||
bindings/input/matrix-keymap.txt
|
||||
- linux,no-autorepeat: do no enable autorepeat feature.
|
||||
- linux,wakeup: use any event on keypad as wakeup event.
|
||||
|
||||
Example:
|
||||
|
||||
tc35893@44 {
|
||||
compatible = "toshiba,tc35893";
|
||||
reg = <0x44>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <26 IRQ_TYPE_EDGE_RISING>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
tc3589x_gpio {
|
||||
compatible = "toshiba,tc3589x-gpio";
|
||||
interrupts = <0>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
tc3589x_keypad {
|
||||
compatible = "toshiba,tc3589x-keypad";
|
||||
interrupts = <6>;
|
||||
debounce-delay-ms = <4>;
|
||||
keypad,num-columns = <8>;
|
||||
keypad,num-rows = <8>;
|
||||
linux,no-autorepeat;
|
||||
linux,wakeup;
|
||||
linux,keymap = <0x0301006b
|
||||
0x04010066
|
||||
0x06040072
|
||||
0x040200d7
|
||||
0x0303006a
|
||||
0x0205000e
|
||||
0x0607008b
|
||||
0x0500001c
|
||||
0x0403000b
|
||||
0x03040034
|
||||
0x05020067
|
||||
0x0305006c
|
||||
0x040500e7
|
||||
0x0005009e
|
||||
0x06020073
|
||||
0x01030039
|
||||
0x07060069
|
||||
0x050500d9>;
|
||||
};
|
||||
};
|
|
@ -62,7 +62,7 @@ Example:
|
|||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <0 32 0x4>;
|
||||
interrupts = <0 16 0x4>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gsbi5_uart_default>;
|
||||
|
|
|
@ -56,10 +56,10 @@ The dma_buf buffer sharing API usage contains the following steps:
|
|||
size_t size, int flags,
|
||||
const char *exp_name)
|
||||
|
||||
If this succeeds, dma_buf_export allocates a dma_buf structure, and returns a
|
||||
pointer to the same. It also associates an anonymous file with this buffer,
|
||||
so it can be exported. On failure to allocate the dma_buf object, it returns
|
||||
NULL.
|
||||
If this succeeds, dma_buf_export_named allocates a dma_buf structure, and
|
||||
returns a pointer to the same. It also associates an anonymous file with this
|
||||
buffer, so it can be exported. On failure to allocate the dma_buf object,
|
||||
it returns NULL.
|
||||
|
||||
'exp_name' is the name of exporter - to facilitate information while
|
||||
debugging.
|
||||
|
@ -76,7 +76,7 @@ The dma_buf buffer sharing API usage contains the following steps:
|
|||
drivers and/or processes.
|
||||
|
||||
Interface:
|
||||
int dma_buf_fd(struct dma_buf *dmabuf)
|
||||
int dma_buf_fd(struct dma_buf *dmabuf, int flags)
|
||||
|
||||
This API installs an fd for the anonymous file associated with this buffer;
|
||||
returns either 'fd', or error.
|
||||
|
@ -157,7 +157,9 @@ to request use of buffer for allocation.
|
|||
"dma_buf->ops->" indirection from the users of this interface.
|
||||
|
||||
In struct dma_buf_ops, unmap_dma_buf is defined as
|
||||
void (*unmap_dma_buf)(struct dma_buf_attachment *, struct sg_table *);
|
||||
void (*unmap_dma_buf)(struct dma_buf_attachment *,
|
||||
struct sg_table *,
|
||||
enum dma_data_direction);
|
||||
|
||||
unmap_dma_buf signifies the end-of-DMA for the attachment provided. Like
|
||||
map_dma_buf, this API also must be implemented by the exporter.
|
||||
|
|
|
@ -18,7 +18,7 @@ memory image to a dump file on the local disk, or across the network to
|
|||
a remote system.
|
||||
|
||||
Kdump and kexec are currently supported on the x86, x86_64, ppc64, ia64,
|
||||
and s390x architectures.
|
||||
s390x and arm architectures.
|
||||
|
||||
When the system kernel boots, it reserves a small section of memory for
|
||||
the dump-capture kernel. This ensures that ongoing Direct Memory Access
|
||||
|
@ -112,7 +112,7 @@ There are two possible methods of using Kdump.
|
|||
2) Or use the system kernel binary itself as dump-capture kernel and there is
|
||||
no need to build a separate dump-capture kernel. This is possible
|
||||
only with the architectures which support a relocatable kernel. As
|
||||
of today, i386, x86_64, ppc64 and ia64 architectures support relocatable
|
||||
of today, i386, x86_64, ppc64, ia64 and arm architectures support relocatable
|
||||
kernel.
|
||||
|
||||
Building a relocatable kernel is advantageous from the point of view that
|
||||
|
@ -241,6 +241,13 @@ Dump-capture kernel config options (Arch Dependent, ia64)
|
|||
kernel will be aligned to 64Mb, so if the start address is not then
|
||||
any space below the alignment point will be wasted.
|
||||
|
||||
Dump-capture kernel config options (Arch Dependent, arm)
|
||||
----------------------------------------------------------
|
||||
|
||||
- To use a relocatable kernel,
|
||||
Enable "AUTO_ZRELADDR" support under "Boot" options:
|
||||
|
||||
AUTO_ZRELADDR=y
|
||||
|
||||
Extended crashkernel syntax
|
||||
===========================
|
||||
|
@ -256,6 +263,10 @@ The syntax is:
|
|||
crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset]
|
||||
range=start-[end]
|
||||
|
||||
Please note, on arm, the offset is required.
|
||||
crashkernel=<range1>:<size1>[,<range2>:<size2>,...]@offset
|
||||
range=start-[end]
|
||||
|
||||
'start' is inclusive and 'end' is exclusive.
|
||||
|
||||
For example:
|
||||
|
@ -296,6 +307,12 @@ Boot into System Kernel
|
|||
on the memory consumption of the kdump system. In general this is not
|
||||
dependent on the memory size of the production system.
|
||||
|
||||
On arm, use "crashkernel=Y@X". Note that the start address of the kernel
|
||||
will be aligned to 128MiB (0x08000000), so if the start address is not then
|
||||
any space below the alignment point may be overwritten by the dump-capture kernel,
|
||||
which means it is possible that the vmcore is not that precise as expected.
|
||||
|
||||
|
||||
Load the Dump-capture Kernel
|
||||
============================
|
||||
|
||||
|
@ -315,7 +332,8 @@ For ia64:
|
|||
- Use vmlinux or vmlinuz.gz
|
||||
For s390x:
|
||||
- Use image or bzImage
|
||||
|
||||
For arm:
|
||||
- Use zImage
|
||||
|
||||
If you are using a uncompressed vmlinux image then use following command
|
||||
to load dump-capture kernel.
|
||||
|
@ -331,6 +349,15 @@ to load dump-capture kernel.
|
|||
--initrd=<initrd-for-dump-capture-kernel> \
|
||||
--append="root=<root-dev> <arch-specific-options>"
|
||||
|
||||
If you are using a compressed zImage, then use following command
|
||||
to load dump-capture kernel.
|
||||
|
||||
kexec --type zImage -p <dump-capture-kernel-bzImage> \
|
||||
--initrd=<initrd-for-dump-capture-kernel> \
|
||||
--dtb=<dtb-for-dump-capture-kernel> \
|
||||
--append="root=<root-dev> <arch-specific-options>"
|
||||
|
||||
|
||||
Please note, that --args-linux does not need to be specified for ia64.
|
||||
It is planned to make this a no-op on that architecture, but for now
|
||||
it should be omitted
|
||||
|
@ -347,6 +374,9 @@ For ppc64:
|
|||
For s390x:
|
||||
"1 maxcpus=1 cgroup_disable=memory"
|
||||
|
||||
For arm:
|
||||
"1 maxcpus=1 reset_devices"
|
||||
|
||||
Notes on loading the dump-capture kernel:
|
||||
|
||||
* By default, the ELF headers are stored in ELF64 format to support
|
||||
|
|
|
@ -2,26 +2,26 @@ this_cpu operations
|
|||
-------------------
|
||||
|
||||
this_cpu operations are a way of optimizing access to per cpu
|
||||
variables associated with the *currently* executing processor through
|
||||
the use of segment registers (or a dedicated register where the cpu
|
||||
permanently stored the beginning of the per cpu area for a specific
|
||||
processor).
|
||||
variables associated with the *currently* executing processor. This is
|
||||
done through the use of segment registers (or a dedicated register where
|
||||
the cpu permanently stored the beginning of the per cpu area for a
|
||||
specific processor).
|
||||
|
||||
The this_cpu operations add a per cpu variable offset to the processor
|
||||
specific percpu base and encode that operation in the instruction
|
||||
this_cpu operations add a per cpu variable offset to the processor
|
||||
specific per cpu base and encode that operation in the instruction
|
||||
operating on the per cpu variable.
|
||||
|
||||
This means there are no atomicity issues between the calculation of
|
||||
This means that there are no atomicity issues between the calculation of
|
||||
the offset and the operation on the data. Therefore it is not
|
||||
necessary to disable preempt or interrupts to ensure that the
|
||||
necessary to disable preemption or interrupts to ensure that the
|
||||
processor is not changed between the calculation of the address and
|
||||
the operation on the data.
|
||||
|
||||
Read-modify-write operations are of particular interest. Frequently
|
||||
processors have special lower latency instructions that can operate
|
||||
without the typical synchronization overhead but still provide some
|
||||
sort of relaxed atomicity guarantee. The x86 for example can execute
|
||||
RMV (Read Modify Write) instructions like inc/dec/cmpxchg without the
|
||||
without the typical synchronization overhead, but still provide some
|
||||
sort of relaxed atomicity guarantees. The x86, for example, can execute
|
||||
RMW (Read Modify Write) instructions like inc/dec/cmpxchg without the
|
||||
lock prefix and the associated latency penalty.
|
||||
|
||||
Access to the variable without the lock prefix is not synchronized but
|
||||
|
@ -30,6 +30,38 @@ data specific to the currently executing processor. Only the current
|
|||
processor should be accessing that variable and therefore there are no
|
||||
concurrency issues with other processors in the system.
|
||||
|
||||
Please note that accesses by remote processors to a per cpu area are
|
||||
exceptional situations and may impact performance and/or correctness
|
||||
(remote write operations) of local RMW operations via this_cpu_*.
|
||||
|
||||
The main use of the this_cpu operations has been to optimize counter
|
||||
operations.
|
||||
|
||||
The following this_cpu() operations with implied preemption protection
|
||||
are defined. These operations can be used without worrying about
|
||||
preemption and interrupts.
|
||||
|
||||
this_cpu_add()
|
||||
this_cpu_read(pcp)
|
||||
this_cpu_write(pcp, val)
|
||||
this_cpu_add(pcp, val)
|
||||
this_cpu_and(pcp, val)
|
||||
this_cpu_or(pcp, val)
|
||||
this_cpu_add_return(pcp, val)
|
||||
this_cpu_xchg(pcp, nval)
|
||||
this_cpu_cmpxchg(pcp, oval, nval)
|
||||
this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
|
||||
this_cpu_sub(pcp, val)
|
||||
this_cpu_inc(pcp)
|
||||
this_cpu_dec(pcp)
|
||||
this_cpu_sub_return(pcp, val)
|
||||
this_cpu_inc_return(pcp)
|
||||
this_cpu_dec_return(pcp)
|
||||
|
||||
|
||||
Inner working of this_cpu operations
|
||||
------------------------------------
|
||||
|
||||
On x86 the fs: or the gs: segment registers contain the base of the
|
||||
per cpu area. It is then possible to simply use the segment override
|
||||
to relocate a per cpu relative address to the proper per cpu area for
|
||||
|
@ -48,22 +80,21 @@ results in a single instruction
|
|||
mov ax, gs:[x]
|
||||
|
||||
instead of a sequence of calculation of the address and then a fetch
|
||||
from that address which occurs with the percpu operations. Before
|
||||
from that address which occurs with the per cpu operations. Before
|
||||
this_cpu_ops such sequence also required preempt disable/enable to
|
||||
prevent the kernel from moving the thread to a different processor
|
||||
while the calculation is performed.
|
||||
|
||||
The main use of the this_cpu operations has been to optimize counter
|
||||
operations.
|
||||
Consider the following this_cpu operation:
|
||||
|
||||
this_cpu_inc(x)
|
||||
|
||||
results in the following single instruction (no lock prefix!)
|
||||
The above results in the following single instruction (no lock prefix!)
|
||||
|
||||
inc gs:[x]
|
||||
|
||||
instead of the following operations required if there is no segment
|
||||
register.
|
||||
register:
|
||||
|
||||
int *y;
|
||||
int cpu;
|
||||
|
@ -73,10 +104,10 @@ register.
|
|||
(*y)++;
|
||||
put_cpu();
|
||||
|
||||
Note that these operations can only be used on percpu data that is
|
||||
Note that these operations can only be used on per cpu data that is
|
||||
reserved for a specific processor. Without disabling preemption in the
|
||||
surrounding code this_cpu_inc() will only guarantee that one of the
|
||||
percpu counters is correctly incremented. However, there is no
|
||||
per cpu counters is correctly incremented. However, there is no
|
||||
guarantee that the OS will not move the process directly before or
|
||||
after the this_cpu instruction is executed. In general this means that
|
||||
the value of the individual counters for each processor are
|
||||
|
@ -86,9 +117,9 @@ that is of interest.
|
|||
Per cpu variables are used for performance reasons. Bouncing cache
|
||||
lines can be avoided if multiple processors concurrently go through
|
||||
the same code paths. Since each processor has its own per cpu
|
||||
variables no concurrent cacheline updates take place. The price that
|
||||
variables no concurrent cache line updates take place. The price that
|
||||
has to be paid for this optimization is the need to add up the per cpu
|
||||
counters when the value of the counter is needed.
|
||||
counters when the value of a counter is needed.
|
||||
|
||||
|
||||
Special operations:
|
||||
|
@ -100,33 +131,39 @@ Takes the offset of a per cpu variable (&x !) and returns the address
|
|||
of the per cpu variable that belongs to the currently executing
|
||||
processor. this_cpu_ptr avoids multiple steps that the common
|
||||
get_cpu/put_cpu sequence requires. No processor number is
|
||||
available. Instead the offset of the local per cpu area is simply
|
||||
added to the percpu offset.
|
||||
available. Instead, the offset of the local per cpu area is simply
|
||||
added to the per cpu offset.
|
||||
|
||||
Note that this operation is usually used in a code segment when
|
||||
preemption has been disabled. The pointer is then used to
|
||||
access local per cpu data in a critical section. When preemption
|
||||
is re-enabled this pointer is usually no longer useful since it may
|
||||
no longer point to per cpu data of the current processor.
|
||||
|
||||
|
||||
Per cpu variables and offsets
|
||||
-----------------------------
|
||||
|
||||
Per cpu variables have *offsets* to the beginning of the percpu
|
||||
Per cpu variables have *offsets* to the beginning of the per cpu
|
||||
area. They do not have addresses although they look like that in the
|
||||
code. Offsets cannot be directly dereferenced. The offset must be
|
||||
added to a base pointer of a percpu area of a processor in order to
|
||||
added to a base pointer of a per cpu area of a processor in order to
|
||||
form a valid address.
|
||||
|
||||
Therefore the use of x or &x outside of the context of per cpu
|
||||
operations is invalid and will generally be treated like a NULL
|
||||
pointer dereference.
|
||||
|
||||
In the context of per cpu operations
|
||||
DEFINE_PER_CPU(int, x);
|
||||
|
||||
x is a per cpu variable. Most this_cpu operations take a cpu
|
||||
variable.
|
||||
In the context of per cpu operations the above implies that x is a per
|
||||
cpu variable. Most this_cpu operations take a cpu variable.
|
||||
|
||||
&x is the *offset* a per cpu variable. this_cpu_ptr() takes
|
||||
the offset of a per cpu variable which makes this look a bit
|
||||
strange.
|
||||
int __percpu *p = &x;
|
||||
|
||||
&x and hence p is the *offset* of a per cpu variable. this_cpu_ptr()
|
||||
takes the offset of a per cpu variable which makes this look a bit
|
||||
strange.
|
||||
|
||||
|
||||
Operations on a field of a per cpu structure
|
||||
|
@ -152,7 +189,7 @@ If we have an offset to struct s:
|
|||
|
||||
struct s __percpu *ps = &p;
|
||||
|
||||
z = this_cpu_dec(ps->m);
|
||||
this_cpu_dec(ps->m);
|
||||
|
||||
z = this_cpu_inc_return(ps->n);
|
||||
|
||||
|
@ -172,29 +209,52 @@ if we do not make use of this_cpu ops later to manipulate fields:
|
|||
Variants of this_cpu ops
|
||||
-------------------------
|
||||
|
||||
this_cpu ops are interrupt safe. Some architecture do not support
|
||||
this_cpu ops are interrupt safe. Some architectures do not support
|
||||
these per cpu local operations. In that case the operation must be
|
||||
replaced by code that disables interrupts, then does the operations
|
||||
that are guaranteed to be atomic and then reenable interrupts. Doing
|
||||
that are guaranteed to be atomic and then re-enable interrupts. Doing
|
||||
so is expensive. If there are other reasons why the scheduler cannot
|
||||
change the processor we are executing on then there is no reason to
|
||||
disable interrupts. For that purpose the __this_cpu operations are
|
||||
provided. For example.
|
||||
disable interrupts. For that purpose the following __this_cpu operations
|
||||
are provided.
|
||||
|
||||
__this_cpu_inc(x);
|
||||
These operations have no guarantee against concurrent interrupts or
|
||||
preemption. If a per cpu variable is not used in an interrupt context
|
||||
and the scheduler cannot preempt, then they are safe. If any interrupts
|
||||
still occur while an operation is in progress and if the interrupt too
|
||||
modifies the variable, then RMW actions can not be guaranteed to be
|
||||
safe.
|
||||
|
||||
Will increment x and will not fallback to code that disables
|
||||
__this_cpu_add()
|
||||
__this_cpu_read(pcp)
|
||||
__this_cpu_write(pcp, val)
|
||||
__this_cpu_add(pcp, val)
|
||||
__this_cpu_and(pcp, val)
|
||||
__this_cpu_or(pcp, val)
|
||||
__this_cpu_add_return(pcp, val)
|
||||
__this_cpu_xchg(pcp, nval)
|
||||
__this_cpu_cmpxchg(pcp, oval, nval)
|
||||
__this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
|
||||
__this_cpu_sub(pcp, val)
|
||||
__this_cpu_inc(pcp)
|
||||
__this_cpu_dec(pcp)
|
||||
__this_cpu_sub_return(pcp, val)
|
||||
__this_cpu_inc_return(pcp)
|
||||
__this_cpu_dec_return(pcp)
|
||||
|
||||
|
||||
Will increment x and will not fall-back to code that disables
|
||||
interrupts on platforms that cannot accomplish atomicity through
|
||||
address relocation and a Read-Modify-Write operation in the same
|
||||
instruction.
|
||||
|
||||
|
||||
|
||||
&this_cpu_ptr(pp)->n vs this_cpu_ptr(&pp->n)
|
||||
--------------------------------------------
|
||||
|
||||
The first operation takes the offset and forms an address and then
|
||||
adds the offset of the n field.
|
||||
adds the offset of the n field. This may result in two add
|
||||
instructions emitted by the compiler.
|
||||
|
||||
The second one first adds the two offsets and then does the
|
||||
relocation. IMHO the second form looks cleaner and has an easier time
|
||||
|
@ -202,4 +262,73 @@ with (). The second form also is consistent with the way
|
|||
this_cpu_read() and friends are used.
|
||||
|
||||
|
||||
Christoph Lameter, April 3rd, 2013
|
||||
Remote access to per cpu data
|
||||
------------------------------
|
||||
|
||||
Per cpu data structures are designed to be used by one cpu exclusively.
|
||||
If you use the variables as intended, this_cpu_ops() are guaranteed to
|
||||
be "atomic" as no other CPU has access to these data structures.
|
||||
|
||||
There are special cases where you might need to access per cpu data
|
||||
structures remotely. It is usually safe to do a remote read access
|
||||
and that is frequently done to summarize counters. Remote write access
|
||||
something which could be problematic because this_cpu ops do not
|
||||
have lock semantics. A remote write may interfere with a this_cpu
|
||||
RMW operation.
|
||||
|
||||
Remote write accesses to percpu data structures are highly discouraged
|
||||
unless absolutely necessary. Please consider using an IPI to wake up
|
||||
the remote CPU and perform the update to its per cpu area.
|
||||
|
||||
To access per-cpu data structure remotely, typically the per_cpu_ptr()
|
||||
function is used:
|
||||
|
||||
|
||||
DEFINE_PER_CPU(struct data, datap);
|
||||
|
||||
struct data *p = per_cpu_ptr(&datap, cpu);
|
||||
|
||||
This makes it explicit that we are getting ready to access a percpu
|
||||
area remotely.
|
||||
|
||||
You can also do the following to convert the datap offset to an address
|
||||
|
||||
struct data *p = this_cpu_ptr(&datap);
|
||||
|
||||
but, passing of pointers calculated via this_cpu_ptr to other cpus is
|
||||
unusual and should be avoided.
|
||||
|
||||
Remote access are typically only for reading the status of another cpus
|
||||
per cpu data. Write accesses can cause unique problems due to the
|
||||
relaxed synchronization requirements for this_cpu operations.
|
||||
|
||||
One example that illustrates some concerns with write operations is
|
||||
the following scenario that occurs because two per cpu variables
|
||||
share a cache-line but the relaxed synchronization is applied to
|
||||
only one process updating the cache-line.
|
||||
|
||||
Consider the following example
|
||||
|
||||
|
||||
struct test {
|
||||
atomic_t a;
|
||||
int b;
|
||||
};
|
||||
|
||||
DEFINE_PER_CPU(struct test, onecacheline);
|
||||
|
||||
There is some concern about what would happen if the field 'a' is updated
|
||||
remotely from one processor and the local processor would use this_cpu ops
|
||||
to update field b. Care should be taken that such simultaneous accesses to
|
||||
data within the same cache line are avoided. Also costly synchronization
|
||||
may be necessary. IPIs are generally recommended in such scenarios instead
|
||||
of a remote write to the per cpu area of another processor.
|
||||
|
||||
Even in cases where the remote writes are rare, please bear in
|
||||
mind that a remote write will evict the cache line from the processor
|
||||
that most likely will access it. If the processor wakes up and finds a
|
||||
missing local cache line of a per cpu area, its performance and hence
|
||||
the wake up times will be affected.
|
||||
|
||||
Christoph Lameter, August 4th, 2014
|
||||
Pranith Kumar, Aug 2nd, 2014
|
||||
|
|
|
@ -9562,6 +9562,14 @@ S: Maintained
|
|||
F: Documentation/usb/ohci.txt
|
||||
F: drivers/usb/host/ohci*
|
||||
|
||||
USB OVER IP DRIVER
|
||||
M: Valentina Manea <valentina.manea.m@gmail.com>
|
||||
M: Shuah Khan <shuah.kh@samsung.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/usb/usbip/
|
||||
F: tools/usb/usbip/
|
||||
|
||||
USB PEGASUS DRIVER
|
||||
M: Petko Manolov <petkan@nucleusys.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 3
|
||||
PATCHLEVEL = 17
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc2
|
||||
EXTRAVERSION = -rc3
|
||||
NAME = Shuffling Zombie Juror
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -500,10 +500,14 @@ extern inline void writeq(u64 b, volatile void __iomem *addr)
|
|||
#define outb_p outb
|
||||
#define outw_p outw
|
||||
#define outl_p outl
|
||||
#define readb_relaxed(addr) __raw_readb(addr)
|
||||
#define readw_relaxed(addr) __raw_readw(addr)
|
||||
#define readl_relaxed(addr) __raw_readl(addr)
|
||||
#define readq_relaxed(addr) __raw_readq(addr)
|
||||
#define readb_relaxed(addr) __raw_readb(addr)
|
||||
#define readw_relaxed(addr) __raw_readw(addr)
|
||||
#define readl_relaxed(addr) __raw_readl(addr)
|
||||
#define readq_relaxed(addr) __raw_readq(addr)
|
||||
#define writeb_relaxed(b, addr) __raw_writeb(b, addr)
|
||||
#define writew_relaxed(b, addr) __raw_writew(b, addr)
|
||||
#define writel_relaxed(b, addr) __raw_writel(b, addr)
|
||||
#define writeq_relaxed(b, addr) __raw_writeq(b, addr)
|
||||
|
||||
#define mmiowb()
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <uapi/asm/unistd.h>
|
||||
|
||||
#define NR_SYSCALLS 508
|
||||
#define NR_SYSCALLS 511
|
||||
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
#define __ARCH_WANT_STAT64
|
||||
|
|
|
@ -469,5 +469,8 @@
|
|||
#define __NR_process_vm_writev 505
|
||||
#define __NR_kcmp 506
|
||||
#define __NR_finit_module 507
|
||||
#define __NR_sched_setattr 508
|
||||
#define __NR_sched_getattr 509
|
||||
#define __NR_renameat2 510
|
||||
|
||||
#endif /* _UAPI_ALPHA_UNISTD_H */
|
||||
|
|
|
@ -526,6 +526,9 @@ sys_call_table:
|
|||
.quad sys_process_vm_writev /* 505 */
|
||||
.quad sys_kcmp
|
||||
.quad sys_finit_module
|
||||
.quad sys_sched_setattr
|
||||
.quad sys_sched_getattr
|
||||
.quad sys_renameat2 /* 510 */
|
||||
|
||||
.size sys_call_table, . - sys_call_table
|
||||
.type sys_call_table, @object
|
||||
|
|
|
@ -581,6 +581,7 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
|
|||
tot_sz -= sz;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(flush_icache_range);
|
||||
|
||||
/*
|
||||
* General purpose helper to make I and D cache lines consistent.
|
||||
|
|
|
@ -1983,8 +1983,6 @@ config XIP_PHYS_ADDR
|
|||
config KEXEC
|
||||
bool "Kexec system call (EXPERIMENTAL)"
|
||||
depends on (!SMP || PM_SLEEP_SMP)
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
|
|
@ -804,7 +804,7 @@
|
|||
|
||||
usb1: usb@48390000 {
|
||||
compatible = "synopsys,dwc3";
|
||||
reg = <0x48390000 0x17000>;
|
||||
reg = <0x48390000 0x10000>;
|
||||
interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phys = <&usb2_phy1>;
|
||||
phy-names = "usb2-phy";
|
||||
|
@ -826,7 +826,7 @@
|
|||
|
||||
usb2: usb@483d0000 {
|
||||
compatible = "synopsys,dwc3";
|
||||
reg = <0x483d0000 0x17000>;
|
||||
reg = <0x483d0000 0x10000>;
|
||||
interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phys = <&usb2_phy2>;
|
||||
phy-names = "usb2-phy";
|
||||
|
|
|
@ -260,7 +260,7 @@
|
|||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c0_pins>;
|
||||
clock-frequency = <400000>;
|
||||
clock-frequency = <100000>;
|
||||
|
||||
tps65218: tps65218@24 {
|
||||
reg = <0x24>;
|
||||
|
@ -424,7 +424,7 @@
|
|||
ranges = <0 0 0 0x01000000>; /* minimum GPMC partition = 16MB */
|
||||
nand@0,0 {
|
||||
reg = <0 0 4>; /* device IO registers */
|
||||
ti,nand-ecc-opt = "bch8";
|
||||
ti,nand-ecc-opt = "bch16";
|
||||
ti,elm-id = <&elm>;
|
||||
nand-bus-width = <8>;
|
||||
gpmc,device-width = <1>;
|
||||
|
@ -443,8 +443,6 @@
|
|||
gpmc,rd-cycle-ns = <40>;
|
||||
gpmc,wr-cycle-ns = <40>;
|
||||
gpmc,wait-pin = <0>;
|
||||
gpmc,wait-on-read;
|
||||
gpmc,wait-on-write;
|
||||
gpmc,bus-turnaround-ns = <0>;
|
||||
gpmc,cycle2cycle-delay-ns = <0>;
|
||||
gpmc,clk-activation-ns = <0>;
|
||||
|
|
|
@ -435,13 +435,13 @@
|
|||
};
|
||||
|
||||
&gpmc {
|
||||
status = "okay";
|
||||
status = "okay"; /* Disable QSPI when enabling GPMC (NAND) */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&nand_flash_x8>;
|
||||
ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */
|
||||
nand@0,0 {
|
||||
reg = <0 0 0>; /* CS0, offset 0 */
|
||||
ti,nand-ecc-opt = "bch8";
|
||||
ti,nand-ecc-opt = "bch16";
|
||||
ti,elm-id = <&elm>;
|
||||
nand-bus-width = <8>;
|
||||
gpmc,device-width = <1>;
|
||||
|
@ -459,8 +459,7 @@
|
|||
gpmc,access-ns = <30>; /* tCEA + 4*/
|
||||
gpmc,rd-cycle-ns = <40>;
|
||||
gpmc,wr-cycle-ns = <40>;
|
||||
gpmc,wait-on-read = "true";
|
||||
gpmc,wait-on-write = "true";
|
||||
gpmc,wait-pin = <0>;
|
||||
gpmc,bus-turnaround-ns = <0>;
|
||||
gpmc,cycle2cycle-delay-ns = <0>;
|
||||
gpmc,clk-activation-ns = <0>;
|
||||
|
@ -557,7 +556,7 @@
|
|||
};
|
||||
|
||||
&qspi {
|
||||
status = "okay";
|
||||
status = "disabled"; /* Disable GPMC (NAND) when enabling QSPI */
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&qspi1_default>;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/dts-v1/;
|
||||
|
||||
#include "dra74x.dtsi"
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/ {
|
||||
model = "TI DRA742";
|
||||
|
@ -24,9 +25,29 @@
|
|||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
vtt_fixed: fixedregulator-vtt {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vtt_fixed";
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
enable-active-high;
|
||||
gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
&dra7_pmx_core {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vtt_pin>;
|
||||
|
||||
vtt_pin: pinmux_vtt_pin {
|
||||
pinctrl-single,pins = <
|
||||
0x3b4 (PIN_OUTPUT | MUX_MODE14) /* spi1_cs1.gpio7_11 */
|
||||
>;
|
||||
};
|
||||
|
||||
i2c1_pins: pinmux_i2c1_pins {
|
||||
pinctrl-single,pins = <
|
||||
0x400 (PIN_INPUT | MUX_MODE0) /* i2c1_sda */
|
||||
|
@ -43,20 +64,19 @@
|
|||
|
||||
i2c3_pins: pinmux_i2c3_pins {
|
||||
pinctrl-single,pins = <
|
||||
0x410 (PIN_INPUT | MUX_MODE0) /* i2c3_sda */
|
||||
0x414 (PIN_INPUT | MUX_MODE0) /* i2c3_scl */
|
||||
0x288 (PIN_INPUT | MUX_MODE9) /* gpio6_14.i2c3_sda */
|
||||
0x28c (PIN_INPUT | MUX_MODE9) /* gpio6_15.i2c3_scl */
|
||||
>;
|
||||
};
|
||||
|
||||
mcspi1_pins: pinmux_mcspi1_pins {
|
||||
pinctrl-single,pins = <
|
||||
0x3a4 (PIN_INPUT | MUX_MODE0) /* spi2_clk */
|
||||
0x3a8 (PIN_INPUT | MUX_MODE0) /* spi2_d1 */
|
||||
0x3ac (PIN_INPUT | MUX_MODE0) /* spi2_d0 */
|
||||
0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */
|
||||
0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs1 */
|
||||
0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs2 */
|
||||
0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs3 */
|
||||
0x3a4 (PIN_INPUT | MUX_MODE0) /* spi1_sclk */
|
||||
0x3a8 (PIN_INPUT | MUX_MODE0) /* spi1_d1 */
|
||||
0x3ac (PIN_INPUT | MUX_MODE0) /* spi1_d0 */
|
||||
0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs0 */
|
||||
0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs2.hdmi1_hpd */
|
||||
0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs3.hdmi1_cec */
|
||||
>;
|
||||
};
|
||||
|
||||
|
@ -284,7 +304,7 @@
|
|||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c3_pins>;
|
||||
clock-frequency = <3400000>;
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
&mcspi1 {
|
||||
|
@ -483,7 +503,7 @@
|
|||
reg = <0x001c0000 0x00020000>;
|
||||
};
|
||||
partition@7 {
|
||||
label = "NAND.u-boot-env";
|
||||
label = "NAND.u-boot-env.backup1";
|
||||
reg = <0x001e0000 0x00020000>;
|
||||
};
|
||||
partition@8 {
|
||||
|
@ -504,3 +524,8 @@
|
|||
&usb2_phy2 {
|
||||
phy-supply = <&ldousb_reg>;
|
||||
};
|
||||
|
||||
&gpio7 {
|
||||
ti,no-reset-on-init;
|
||||
ti,no-idle-on-init;
|
||||
};
|
||||
|
|
|
@ -353,7 +353,7 @@
|
|||
};
|
||||
|
||||
twl_power: power {
|
||||
compatible = "ti,twl4030-power-n900";
|
||||
compatible = "ti,twl4030-power-n900", "ti,twl4030-power-idle-osc-off";
|
||||
ti,use_poweroff;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -467,6 +467,7 @@
|
|||
ti,bit-shift = <0x1e>;
|
||||
reg = <0x0d00>;
|
||||
ti,set-bit-to-disable;
|
||||
ti,set-rate-parent;
|
||||
};
|
||||
|
||||
dpll4_m6_ck: dpll4_m6_ck {
|
||||
|
|
|
@ -472,7 +472,6 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)
|
|||
"mcr p15, 0, r0, c1, c0, 0 @ set SCTLR \n\t" \
|
||||
"isb \n\t" \
|
||||
"bl v7_flush_dcache_"__stringify(level)" \n\t" \
|
||||
"clrex \n\t" \
|
||||
"mrc p15, 0, r0, c1, c0, 1 @ get ACTLR \n\t" \
|
||||
"bic r0, r0, #(1 << 6) @ disable local coherency \n\t" \
|
||||
"mcr p15, 0, r0, c1, c0, 1 @ set ACTLR \n\t" \
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#define ARM_CPU_PART_CORTEX_A12 0x4100c0d0
|
||||
#define ARM_CPU_PART_CORTEX_A17 0x4100c0e0
|
||||
#define ARM_CPU_PART_CORTEX_A15 0x4100c0f0
|
||||
#define ARM_CPU_PART_MASK 0xff00fff0
|
||||
|
||||
#define ARM_CPU_XSCALE_ARCH_MASK 0xe000
|
||||
#define ARM_CPU_XSCALE_ARCH_V1 0x2000
|
||||
|
@ -179,7 +180,7 @@ static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
|
|||
*/
|
||||
static inline unsigned int __attribute_const__ read_cpuid_part(void)
|
||||
{
|
||||
return read_cpuid_id() & 0xff00fff0;
|
||||
return read_cpuid_id() & ARM_CPU_PART_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned int __attribute_const__ __deprecated read_cpuid_part_number(void)
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
|
|||
#define R_ARM_ABS32 2
|
||||
#define R_ARM_CALL 28
|
||||
#define R_ARM_JUMP24 29
|
||||
#define R_ARM_TARGET1 38
|
||||
#define R_ARM_V4BX 40
|
||||
#define R_ARM_PREL31 42
|
||||
#define R_ARM_MOVW_ABS_NC 43
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/cpumask.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cputype.h>
|
||||
|
||||
/*
|
||||
|
@ -25,6 +26,20 @@ static inline bool is_smp(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* smp_cpuid_part() - return part id for a given cpu
|
||||
* @cpu: logical cpu id.
|
||||
*
|
||||
* Return: part id of logical cpu passed as argument.
|
||||
*/
|
||||
static inline unsigned int smp_cpuid_part(int cpu)
|
||||
{
|
||||
struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpu);
|
||||
|
||||
return is_smp() ? cpu_info->cpuid & ARM_CPU_PART_MASK :
|
||||
read_cpuid_part();
|
||||
}
|
||||
|
||||
/* all SMP configurations have the extended CPUID registers */
|
||||
#ifndef CONFIG_MMU
|
||||
#define tlb_ops_need_broadcast() 0
|
||||
|
|
|
@ -208,26 +208,21 @@
|
|||
#endif
|
||||
.endif
|
||||
msr spsr_cxsf, \rpsr
|
||||
#if defined(CONFIG_CPU_V6)
|
||||
ldr r0, [sp]
|
||||
strex r1, r2, [sp] @ clear the exclusive monitor
|
||||
ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr
|
||||
#elif defined(CONFIG_CPU_32v6K)
|
||||
clrex @ clear the exclusive monitor
|
||||
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
|
||||
#else
|
||||
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
|
||||
#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
|
||||
@ We must avoid clrex due to Cortex-A15 erratum #830321
|
||||
sub r0, sp, #4 @ uninhabited address
|
||||
strex r1, r2, [r0] @ clear the exclusive monitor
|
||||
#endif
|
||||
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
|
||||
.endm
|
||||
|
||||
.macro restore_user_regs, fast = 0, offset = 0
|
||||
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
|
||||
ldr lr, [sp, #\offset + S_PC]! @ get pc
|
||||
msr spsr_cxsf, r1 @ save in spsr_svc
|
||||
#if defined(CONFIG_CPU_V6)
|
||||
#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
|
||||
@ We must avoid clrex due to Cortex-A15 erratum #830321
|
||||
strex r1, r2, [sp] @ clear the exclusive monitor
|
||||
#elif defined(CONFIG_CPU_32v6K)
|
||||
clrex @ clear the exclusive monitor
|
||||
#endif
|
||||
.if \fast
|
||||
ldmdb sp, {r1 - lr}^ @ get calling r1 - lr
|
||||
|
@ -261,7 +256,10 @@
|
|||
.endif
|
||||
ldr lr, [sp, #S_SP] @ top of the stack
|
||||
ldrd r0, r1, [sp, #S_LR] @ calling lr and pc
|
||||
clrex @ clear the exclusive monitor
|
||||
|
||||
@ We must avoid clrex due to Cortex-A15 erratum #830321
|
||||
strex r2, r1, [sp, #S_LR] @ clear the exclusive monitor
|
||||
|
||||
stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context
|
||||
ldmia sp, {r0 - r12}
|
||||
mov sp, lr
|
||||
|
@ -282,13 +280,16 @@
|
|||
.endm
|
||||
#else /* ifdef CONFIG_CPU_V7M */
|
||||
.macro restore_user_regs, fast = 0, offset = 0
|
||||
clrex @ clear the exclusive monitor
|
||||
mov r2, sp
|
||||
load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr
|
||||
ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr
|
||||
ldr lr, [sp, #\offset + S_PC] @ get pc
|
||||
add sp, sp, #\offset + S_SP
|
||||
msr spsr_cxsf, r1 @ save in spsr_svc
|
||||
|
||||
@ We must avoid clrex due to Cortex-A15 erratum #830321
|
||||
strex r1, r2, [sp] @ clear the exclusive monitor
|
||||
|
||||
.if \fast
|
||||
ldmdb sp, {r1 - r12} @ get calling r1 - r12
|
||||
.else
|
||||
|
|
|
@ -91,6 +91,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
|
|||
break;
|
||||
|
||||
case R_ARM_ABS32:
|
||||
case R_ARM_TARGET1:
|
||||
*(u32 *)loc += sym->st_value;
|
||||
break;
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
"mcr p15, 0, r0, c1, c0, 0 @ set SCTLR\n\t" \
|
||||
"isb\n\t"\
|
||||
"bl v7_flush_dcache_"__stringify(level)"\n\t" \
|
||||
"clrex\n\t"\
|
||||
"mrc p15, 0, r0, c1, c0, 1 @ get ACTLR\n\t" \
|
||||
"bic r0, r0, #(1 << 6) @ disable local coherency\n\t" \
|
||||
/* Dummy Load of a device register to avoid Erratum 799270 */ \
|
||||
|
|
|
@ -1207,8 +1207,7 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
|
|||
}
|
||||
}
|
||||
|
||||
if ((p->wait_on_read || p->wait_on_write) &&
|
||||
(p->wait_pin > gpmc_nr_waitpins)) {
|
||||
if (p->wait_pin > gpmc_nr_waitpins) {
|
||||
pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1288,8 +1287,8 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
|
|||
p->wait_on_write = of_property_read_bool(np,
|
||||
"gpmc,wait-on-write");
|
||||
if (!p->wait_on_read && !p->wait_on_write)
|
||||
pr_warn("%s: read/write wait monitoring not enabled!\n",
|
||||
__func__);
|
||||
pr_debug("%s: rd/wr wait monitoring not enabled!\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,12 +17,6 @@
|
|||
*/
|
||||
.align 5
|
||||
ENTRY(v6_early_abort)
|
||||
#ifdef CONFIG_CPU_V6
|
||||
sub r1, sp, #4 @ Get unused stack location
|
||||
strex r0, r1, [r1] @ Clear the exclusive monitor
|
||||
#elif defined(CONFIG_CPU_32v6K)
|
||||
clrex
|
||||
#endif
|
||||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||
/*
|
||||
|
|
|
@ -13,12 +13,6 @@
|
|||
*/
|
||||
.align 5
|
||||
ENTRY(v7_early_abort)
|
||||
/*
|
||||
* The effect of data aborts on on the exclusive access monitor are
|
||||
* UNPREDICTABLE. Do a CLREX to clear the state
|
||||
*/
|
||||
clrex
|
||||
|
||||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
|
|||
);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL(flush_icache_range);
|
||||
|
||||
void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
|
|
|
@ -549,8 +549,6 @@ source "drivers/sn/Kconfig"
|
|||
config KEXEC
|
||||
bool "kexec system call"
|
||||
depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
|
|
@ -91,8 +91,6 @@ config MMU_SUN3
|
|||
config KEXEC
|
||||
bool "kexec system call"
|
||||
depends on M68KCLASSIC
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
|
|
@ -2396,8 +2396,6 @@ source "kernel/Kconfig.preempt"
|
|||
|
||||
config KEXEC
|
||||
bool "Kexec system call"
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
|
|
@ -399,8 +399,6 @@ config PPC64_SUPPORTS_MEMORY_FAILURE
|
|||
config KEXEC
|
||||
bool "kexec system call"
|
||||
depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP))
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
|
|
@ -48,8 +48,6 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
|
|||
|
||||
config KEXEC
|
||||
def_bool y
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
|
||||
config AUDIT_ARCH
|
||||
def_bool y
|
||||
|
|
|
@ -283,7 +283,10 @@
|
|||
#define __NR_sched_setattr 345
|
||||
#define __NR_sched_getattr 346
|
||||
#define __NR_renameat2 347
|
||||
#define NR_syscalls 348
|
||||
#define __NR_seccomp 348
|
||||
#define __NR_getrandom 349
|
||||
#define __NR_memfd_create 350
|
||||
#define NR_syscalls 351
|
||||
|
||||
/*
|
||||
* There are some system calls that are not present on 64 bit, some
|
||||
|
|
|
@ -214,3 +214,6 @@ COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, fla
|
|||
COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
|
||||
COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
|
||||
COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
|
||||
COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
|
||||
|
|
|
@ -2060,6 +2060,13 @@ void s390_reset_system(void (*func)(void *), void *data)
|
|||
S390_lowcore.program_new_psw.addr =
|
||||
PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
|
||||
|
||||
/*
|
||||
* Clear subchannel ID and number to signal new kernel that no CCW or
|
||||
* SCSI IPL has been done (for kexec and kdump)
|
||||
*/
|
||||
S390_lowcore.subchannel_id = 0;
|
||||
S390_lowcore.subchannel_nr = 0;
|
||||
|
||||
/* Store status at absolute zero */
|
||||
store_status();
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/stddef.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/user.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/ioport.h>
|
||||
|
@ -61,6 +62,7 @@
|
|||
#include <asm/diag.h>
|
||||
#include <asm/os_info.h>
|
||||
#include <asm/sclp.h>
|
||||
#include <asm/sysinfo.h>
|
||||
#include "entry.h"
|
||||
|
||||
/*
|
||||
|
@ -766,6 +768,7 @@ static void __init setup_hwcaps(void)
|
|||
#endif
|
||||
|
||||
get_cpu_id(&cpu_id);
|
||||
add_device_randomness(&cpu_id, sizeof(cpu_id));
|
||||
switch (cpu_id.machine) {
|
||||
case 0x9672:
|
||||
#if !defined(CONFIG_64BIT)
|
||||
|
@ -803,6 +806,19 @@ static void __init setup_hwcaps(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add system information as device randomness
|
||||
*/
|
||||
static void __init setup_randomness(void)
|
||||
{
|
||||
struct sysinfo_3_2_2 *vmms;
|
||||
|
||||
vmms = (struct sysinfo_3_2_2 *) alloc_page(GFP_KERNEL);
|
||||
if (vmms && stsi(vmms, 3, 2, 2) == 0 && vmms->count)
|
||||
add_device_randomness(&vmms, vmms->count);
|
||||
free_page((unsigned long) vmms);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup function called from init/main.c just after the banner
|
||||
* was printed.
|
||||
|
@ -901,6 +917,9 @@ void __init setup_arch(char **cmdline_p)
|
|||
|
||||
/* Setup zfcpdump support */
|
||||
setup_zfcpdump();
|
||||
|
||||
/* Add system specific data to the random pool */
|
||||
setup_randomness();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_32BIT
|
||||
|
|
|
@ -356,3 +356,6 @@ SYSCALL(sys_finit_module,sys_finit_module,compat_sys_finit_module)
|
|||
SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */
|
||||
SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr)
|
||||
SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)
|
||||
SYSCALL(sys_seccomp,sys_seccomp,compat_sys_seccomp)
|
||||
SYSCALL(sys_getrandom,sys_getrandom,compat_sys_getrandom)
|
||||
SYSCALL(sys_memfd_create,sys_memfd_create,compat_sys_memfd_create) /* 350 */
|
||||
|
|
|
@ -598,8 +598,6 @@ source kernel/Kconfig.hz
|
|||
config KEXEC
|
||||
bool "kexec system call (EXPERIMENTAL)"
|
||||
depends on SUPERH32 && MMU
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
|
|
@ -229,6 +229,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
|
|||
|
||||
cacheop_on_each_cpu(local_flush_icache_range, (void *)&data, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(flush_icache_range);
|
||||
|
||||
void flush_icache_page(struct vm_area_struct *vma, struct page *page)
|
||||
{
|
||||
|
|
|
@ -191,8 +191,6 @@ source "kernel/Kconfig.hz"
|
|||
|
||||
config KEXEC
|
||||
bool "kexec system call"
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
---help---
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
|
|
@ -183,6 +183,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
|
|||
preempt_enable();
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(flush_icache_range);
|
||||
|
||||
|
||||
/* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */
|
||||
|
|
|
@ -254,7 +254,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
|||
|
||||
err |= setup_sigframe(frame, regs, set);
|
||||
if (err == 0)
|
||||
err |= setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
|
||||
err |= setup_return(regs, &ksig->ka, frame->retcode, frame,
|
||||
ksig->sig);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -276,7 +277,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
|||
err |= __save_altstack(&frame->sig.uc.uc_stack, regs->UCreg_sp);
|
||||
err |= setup_sigframe(&frame->sig, regs, set);
|
||||
if (err == 0)
|
||||
err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
|
||||
err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame,
|
||||
ksig->sig);
|
||||
|
||||
if (err == 0) {
|
||||
/*
|
||||
|
@ -303,7 +305,6 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
|
|||
int syscall)
|
||||
{
|
||||
struct thread_info *thread = current_thread_info();
|
||||
struct task_struct *tsk = current;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int usig = ksig->sig;
|
||||
int ret;
|
||||
|
@ -373,7 +374,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
|||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
if (get_signsl(&ksig)) {
|
||||
if (get_signal(&ksig)) {
|
||||
handle_signal(&ksig, regs, syscall);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,4 @@ obj-$(CONFIG_IA32_EMULATION) += ia32/
|
|||
obj-y += platform/
|
||||
obj-y += net/
|
||||
|
||||
ifeq ($(CONFIG_X86_64),y)
|
||||
obj-$(CONFIG_KEXEC) += purgatory/
|
||||
endif
|
||||
obj-$(CONFIG_KEXEC_FILE) += purgatory/
|
||||
|
|
|
@ -1585,9 +1585,6 @@ source kernel/Kconfig.hz
|
|||
|
||||
config KEXEC
|
||||
bool "kexec system call"
|
||||
select BUILD_BIN2C
|
||||
select CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
---help---
|
||||
kexec is a system call that implements the ability to shutdown your
|
||||
current kernel, and to start another kernel. It is like a reboot
|
||||
|
@ -1602,9 +1599,22 @@ config KEXEC
|
|||
interface is strongly in flux, so no good recommendation can be
|
||||
made.
|
||||
|
||||
config KEXEC_FILE
|
||||
bool "kexec file based system call"
|
||||
select BUILD_BIN2C
|
||||
depends on KEXEC
|
||||
depends on X86_64
|
||||
depends on CRYPTO=y
|
||||
depends on CRYPTO_SHA256=y
|
||||
---help---
|
||||
This is new version of kexec system call. This system call is
|
||||
file based and takes file descriptors as system call argument
|
||||
for kernel and initramfs as opposed to list of segments as
|
||||
accepted by previous system call.
|
||||
|
||||
config KEXEC_VERIFY_SIG
|
||||
bool "Verify kernel signature during kexec_file_load() syscall"
|
||||
depends on KEXEC
|
||||
depends on KEXEC_FILE
|
||||
---help---
|
||||
This option makes kernel signature verification mandatory for
|
||||
kexec_file_load() syscall. If kernel is signature can not be
|
||||
|
|
|
@ -184,11 +184,8 @@ archheaders:
|
|||
$(Q)$(MAKE) $(build)=arch/x86/syscalls all
|
||||
|
||||
archprepare:
|
||||
ifeq ($(CONFIG_KEXEC),y)
|
||||
# Build only for 64bit. No loaders for 32bit yet.
|
||||
ifeq ($(CONFIG_X86_64),y)
|
||||
ifeq ($(CONFIG_KEXEC_FILE),y)
|
||||
$(Q)$(MAKE) $(build)=arch/x86/purgatory arch/x86/purgatory/kexec-purgatory.c
|
||||
endif
|
||||
endif
|
||||
|
||||
###
|
||||
|
@ -254,6 +251,7 @@ archclean:
|
|||
$(Q)rm -rf $(objtree)/arch/x86_64
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
$(Q)$(MAKE) $(clean)=arch/x86/tools
|
||||
$(Q)$(MAKE) $(clean)=arch/x86/purgatory
|
||||
|
||||
PHONY += kvmconfig
|
||||
kvmconfig:
|
||||
|
|
|
@ -227,6 +227,8 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned
|
|||
|
||||
extern void io_apic_eoi(unsigned int apic, unsigned int vector);
|
||||
|
||||
extern bool mp_should_keep_irq(struct device *dev);
|
||||
|
||||
#else /* !CONFIG_X86_IO_APIC */
|
||||
|
||||
#define io_apic_assign_pci_irqs 0
|
||||
|
|
|
@ -131,8 +131,13 @@ static inline int pte_exec(pte_t pte)
|
|||
|
||||
static inline int pte_special(pte_t pte)
|
||||
{
|
||||
return (pte_flags(pte) & (_PAGE_PRESENT|_PAGE_SPECIAL)) ==
|
||||
(_PAGE_PRESENT|_PAGE_SPECIAL);
|
||||
/*
|
||||
* See CONFIG_NUMA_BALANCING pte_numa in include/asm-generic/pgtable.h.
|
||||
* On x86 we have _PAGE_BIT_NUMA == _PAGE_BIT_GLOBAL+1 ==
|
||||
* __PAGE_BIT_SOFTW1 == _PAGE_BIT_SPECIAL.
|
||||
*/
|
||||
return (pte_flags(pte) & _PAGE_SPECIAL) &&
|
||||
(pte_flags(pte) & (_PAGE_PRESENT|_PAGE_PROTNONE));
|
||||
}
|
||||
|
||||
static inline unsigned long pte_pfn(pte_t pte)
|
||||
|
|
|
@ -71,6 +71,7 @@ obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
|
|||
obj-$(CONFIG_X86_TSC) += trace_clock.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o
|
||||
obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o
|
||||
obj-$(CONFIG_KEXEC_FILE) += kexec-bzimage64.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o
|
||||
obj-y += kprobes/
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
|
@ -118,5 +119,4 @@ ifeq ($(CONFIG_X86_64),y)
|
|||
|
||||
obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o
|
||||
obj-y += vsmp_64.o
|
||||
obj-$(CONFIG_KEXEC) += kexec-bzimage64.o
|
||||
endif
|
||||
|
|
|
@ -1070,6 +1070,11 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
|
|||
}
|
||||
|
||||
if (flags & IOAPIC_MAP_ALLOC) {
|
||||
/* special handling for legacy IRQs */
|
||||
if (irq < nr_legacy_irqs() && info->count == 1 &&
|
||||
mp_irqdomain_map(domain, irq, pin) != 0)
|
||||
irq = -1;
|
||||
|
||||
if (irq > 0)
|
||||
info->count++;
|
||||
else if (info->count == 0)
|
||||
|
@ -3896,7 +3901,15 @@ int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
|
|||
info->polarity = 1;
|
||||
}
|
||||
info->node = NUMA_NO_NODE;
|
||||
info->set = 1;
|
||||
|
||||
/*
|
||||
* setup_IO_APIC_irqs() programs all legacy IRQs with default
|
||||
* trigger and polarity attributes. Don't set the flag for that
|
||||
* case so the first legacy IRQ user could reprogram the pin
|
||||
* with real trigger and polarity attributes.
|
||||
*/
|
||||
if (virq >= nr_legacy_irqs() || info->count)
|
||||
info->set = 1;
|
||||
}
|
||||
set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger,
|
||||
info->polarity);
|
||||
|
@ -3946,6 +3959,18 @@ int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool mp_should_keep_irq(struct device *dev)
|
||||
{
|
||||
if (dev->power.is_prepared)
|
||||
return true;
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
if (dev->power.runtime_status == RPM_SUSPENDING)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Enable IOAPIC early just for system timer */
|
||||
void __init pre_init_apic_IRQ0(void)
|
||||
{
|
||||
|
|
|
@ -182,8 +182,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
|
|||
crash_save_cpu(regs, safe_smp_processor_id());
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
#ifdef CONFIG_KEXEC_FILE
|
||||
static int get_nr_ram_ranges_callback(unsigned long start_pfn,
|
||||
unsigned long nr_pfn, void *arg)
|
||||
{
|
||||
|
@ -696,5 +695,4 @@ int crash_load_segments(struct kimage *image)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_X86_64 */
|
||||
#endif /* CONFIG_KEXEC_FILE */
|
||||
|
|
|
@ -203,7 +203,7 @@ void __init native_init_IRQ(void)
|
|||
set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
|
||||
}
|
||||
|
||||
if (!acpi_ioapic && !of_ioapic)
|
||||
if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs())
|
||||
setup_irq(2, &irq2);
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
|
|
|
@ -25,9 +25,11 @@
|
|||
#include <asm/debugreg.h>
|
||||
#include <asm/kexec-bzimage64.h>
|
||||
|
||||
#ifdef CONFIG_KEXEC_FILE
|
||||
static struct kexec_file_ops *kexec_file_loaders[] = {
|
||||
&kexec_bzImage64_ops,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void free_transition_pgtable(struct kimage *image)
|
||||
{
|
||||
|
@ -178,6 +180,7 @@ static void load_segments(void)
|
|||
);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KEXEC_FILE
|
||||
/* Update purgatory as needed after various image segments have been prepared */
|
||||
static int arch_update_purgatory(struct kimage *image)
|
||||
{
|
||||
|
@ -209,6 +212,12 @@ static int arch_update_purgatory(struct kimage *image)
|
|||
|
||||
return ret;
|
||||
}
|
||||
#else /* !CONFIG_KEXEC_FILE */
|
||||
static inline int arch_update_purgatory(struct kimage *image)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_KEXEC_FILE */
|
||||
|
||||
int machine_kexec_prepare(struct kimage *image)
|
||||
{
|
||||
|
@ -329,6 +338,7 @@ void arch_crash_save_vmcoreinfo(void)
|
|||
|
||||
/* arch-dependent functionality related to kexec file-based syscall */
|
||||
|
||||
#ifdef CONFIG_KEXEC_FILE
|
||||
int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
|
||||
unsigned long buf_len)
|
||||
{
|
||||
|
@ -522,3 +532,4 @@ overflow:
|
|||
(int)ELF64_R_TYPE(rel[i].r_info), value);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
#endif /* CONFIG_KEXEC_FILE */
|
||||
|
|
|
@ -68,6 +68,8 @@ static struct irqaction irq0 = {
|
|||
|
||||
void __init setup_default_timer_irq(void)
|
||||
{
|
||||
if (!nr_legacy_irqs())
|
||||
return;
|
||||
setup_irq(0, &irq0);
|
||||
}
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
|
|||
|
||||
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
|
||||
{
|
||||
if (!dev->dev.power.is_prepared && dev->irq > 0)
|
||||
if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0)
|
||||
mp_unmap_irq(dev->irq);
|
||||
}
|
||||
|
||||
|
|
|
@ -1256,7 +1256,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
|||
|
||||
static void pirq_disable_irq(struct pci_dev *dev)
|
||||
{
|
||||
if (io_apic_assign_pci_irqs && !dev->dev.power.is_prepared &&
|
||||
if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
|
||||
dev->irq) {
|
||||
mp_unmap_irq(dev->irq);
|
||||
dev->irq = 0;
|
||||
|
|
|
@ -11,6 +11,7 @@ targets += purgatory.ro
|
|||
# sure how to relocate those. Like kexec-tools, use custom flags.
|
||||
|
||||
KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large
|
||||
KBUILD_CFLAGS += -m$(BITS)
|
||||
|
||||
$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
|
||||
$(call if_changed,ld)
|
||||
|
@ -24,7 +25,4 @@ $(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
|
|||
$(call if_changed,bin2c)
|
||||
|
||||
|
||||
# No loaders for 32bits yet.
|
||||
ifeq ($(CONFIG_X86_64),y)
|
||||
obj-$(CONFIG_KEXEC) += kexec-purgatory.o
|
||||
endif
|
||||
obj-$(CONFIG_KEXEC_FILE) += kexec-purgatory.o
|
||||
|
|
|
@ -4,24 +4,23 @@ config ZONE_DMA
|
|||
config XTENSA
|
||||
def_bool y
|
||||
select ARCH_WANT_FRAME_POINTERS
|
||||
select HAVE_IDE
|
||||
select GENERIC_ATOMIC64
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select VIRT_TO_BUS
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_PCI_IOMAP
|
||||
select ARCH_WANT_IPC_PARSE_VERSION
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select BUILDTIME_EXTABLE_SORT
|
||||
select CLONE_BACKWARDS
|
||||
select IRQ_DOMAIN
|
||||
select HAVE_OPROFILE
|
||||
select COMMON_CLK
|
||||
select GENERIC_ATOMIC64
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_IRQ_TIME_ACCOUNTING
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_PERF_EVENTS
|
||||
select COMMON_CLK
|
||||
select IRQ_DOMAIN
|
||||
select MODULES_USE_ELF_RELA
|
||||
select VIRT_TO_BUS
|
||||
help
|
||||
Xtensa processors are 32-bit RISC machines designed by Tensilica
|
||||
primarily for embedded systems. These processors are both
|
||||
|
@ -62,7 +61,9 @@ config TRACE_IRQFLAGS_SUPPORT
|
|||
def_bool y
|
||||
|
||||
config MMU
|
||||
def_bool n
|
||||
bool
|
||||
default n if !XTENSA_VARIANT_CUSTOM
|
||||
default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM
|
||||
|
||||
config VARIANT_IRQ_SWITCH
|
||||
def_bool n
|
||||
|
@ -102,8 +103,40 @@ config XTENSA_VARIANT_S6000
|
|||
select VARIANT_IRQ_SWITCH
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select XTENSA_CALIBRATE_CCOUNT
|
||||
|
||||
config XTENSA_VARIANT_CUSTOM
|
||||
bool "Custom Xtensa processor configuration"
|
||||
select MAY_HAVE_SMP
|
||||
select HAVE_XTENSA_GPIO32
|
||||
help
|
||||
Select this variant to use a custom Xtensa processor configuration.
|
||||
You will be prompted for a processor variant CORENAME.
|
||||
endchoice
|
||||
|
||||
config XTENSA_VARIANT_CUSTOM_NAME
|
||||
string "Xtensa Processor Custom Core Variant Name"
|
||||
depends on XTENSA_VARIANT_CUSTOM
|
||||
help
|
||||
Provide the name of a custom Xtensa processor variant.
|
||||
This CORENAME selects arch/xtensa/variant/CORENAME.
|
||||
Dont forget you have to select MMU if you have one.
|
||||
|
||||
config XTENSA_VARIANT_NAME
|
||||
string
|
||||
default "dc232b" if XTENSA_VARIANT_DC232B
|
||||
default "dc233c" if XTENSA_VARIANT_DC233C
|
||||
default "fsf" if XTENSA_VARIANT_FSF
|
||||
default "s6000" if XTENSA_VARIANT_S6000
|
||||
default XTENSA_VARIANT_CUSTOM_NAME if XTENSA_VARIANT_CUSTOM
|
||||
|
||||
config XTENSA_VARIANT_MMU
|
||||
bool "Core variant has a Full MMU (TLB, Pages, Protection, etc)"
|
||||
depends on XTENSA_VARIANT_CUSTOM
|
||||
default y
|
||||
help
|
||||
Build a Conventional Kernel with full MMU support,
|
||||
ie: it supports a TLB with auto-loading, page protection.
|
||||
|
||||
config XTENSA_UNALIGNED_USER
|
||||
bool "Unaligned memory access in use space"
|
||||
help
|
||||
|
@ -156,13 +189,9 @@ config HOTPLUG_CPU
|
|||
|
||||
Say N if you want to disable CPU hotplug.
|
||||
|
||||
config MATH_EMULATION
|
||||
bool "Math emulation"
|
||||
help
|
||||
Can we use information of configuration file?
|
||||
|
||||
config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
|
||||
bool "Initialize Xtensa MMU inside the Linux kernel code"
|
||||
depends on MMU
|
||||
default y
|
||||
help
|
||||
Earlier version initialized the MMU in the exception vector
|
||||
|
@ -192,6 +221,7 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
|
|||
|
||||
config HIGHMEM
|
||||
bool "High Memory Support"
|
||||
depends on MMU
|
||||
help
|
||||
Linux can use the full amount of RAM in the system by
|
||||
default. However, the default MMUv2 setup only maps the
|
||||
|
@ -208,6 +238,32 @@ config HIGHMEM
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config FAST_SYSCALL_XTENSA
|
||||
bool "Enable fast atomic syscalls"
|
||||
default n
|
||||
help
|
||||
fast_syscall_xtensa is a syscall that can make atomic operations
|
||||
on UP kernel when processor has no s32c1i support.
|
||||
|
||||
This syscall is deprecated. It may have issues when called with
|
||||
invalid arguments. It is provided only for backwards compatibility.
|
||||
Only enable it if your userspace software requires it.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config FAST_SYSCALL_SPILL_REGISTERS
|
||||
bool "Enable spill registers syscall"
|
||||
default n
|
||||
help
|
||||
fast_syscall_spill_registers is a syscall that spills all active
|
||||
register windows of a calling userspace task onto its stack.
|
||||
|
||||
This syscall is deprecated. It may have issues when called with
|
||||
invalid arguments. It is provided only for backwards compatibility.
|
||||
Only enable it if your userspace software requires it.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endmenu
|
||||
|
||||
config XTENSA_CALIBRATE_CCOUNT
|
||||
|
@ -250,12 +306,14 @@ config XTENSA_PLATFORM_ISS
|
|||
|
||||
config XTENSA_PLATFORM_XT2000
|
||||
bool "XT2000"
|
||||
select HAVE_IDE
|
||||
help
|
||||
XT2000 is the name of Tensilica's feature-rich emulation platform.
|
||||
This hardware is capable of running a full Linux distribution.
|
||||
|
||||
config XTENSA_PLATFORM_S6105
|
||||
bool "S6105"
|
||||
select HAVE_IDE
|
||||
select SERIAL_CONSOLE
|
||||
select NO_IOPORT_MAP
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
# for more details.
|
||||
#
|
||||
# Copyright (C) 2001 - 2005 Tensilica Inc.
|
||||
# Copyright (C) 2014 Cadence Design Systems Inc.
|
||||
#
|
||||
# This file is included by the global makefile so that you can add your own
|
||||
# architecture-specific flags and dependencies. Remember to do have actions
|
||||
|
@ -13,11 +14,7 @@
|
|||
# Core configuration.
|
||||
# (Use VAR=<xtensa_config> to use another default compiler.)
|
||||
|
||||
variant-$(CONFIG_XTENSA_VARIANT_FSF) := fsf
|
||||
variant-$(CONFIG_XTENSA_VARIANT_DC232B) := dc232b
|
||||
variant-$(CONFIG_XTENSA_VARIANT_DC233C) := dc233c
|
||||
variant-$(CONFIG_XTENSA_VARIANT_S6000) := s6000
|
||||
variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM) := custom
|
||||
variant-y := $(patsubst "%",%,$(CONFIG_XTENSA_VARIANT_NAME))
|
||||
|
||||
VARIANT = $(variant-y)
|
||||
export VARIANT
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
|
||||
/ {
|
||||
compatible = "cdns,xtensa-kc705";
|
||||
chosen {
|
||||
bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000";
|
||||
};
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x08000000>;
|
||||
reg = <0x00000000 0x38000000>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -66,7 +66,6 @@ CONFIG_XTENSA_ARCH_LINUX_BE=y
|
|||
CONFIG_MMU=y
|
||||
# CONFIG_XTENSA_UNALIGNED_USER is not set
|
||||
# CONFIG_PREEMPT is not set
|
||||
# CONFIG_MATH_EMULATION is not set
|
||||
# CONFIG_HIGHMEM is not set
|
||||
|
||||
#
|
||||
|
|
|
@ -146,7 +146,6 @@ CONFIG_XTENSA_VARIANT_FSF=y
|
|||
# CONFIG_XTENSA_VARIANT_S6000 is not set
|
||||
# CONFIG_XTENSA_UNALIGNED_USER is not set
|
||||
# CONFIG_PREEMPT is not set
|
||||
# CONFIG_MATH_EMULATION is not set
|
||||
CONFIG_XTENSA_CALIBRATE_CCOUNT=y
|
||||
CONFIG_SERIAL_CONSOLE=y
|
||||
CONFIG_XTENSA_ISS_NETWORK=y
|
||||
|
@ -308,7 +307,7 @@ CONFIG_MISC_DEVICES=y
|
|||
# EEPROM support
|
||||
#
|
||||
# CONFIG_EEPROM_93CX6 is not set
|
||||
CONFIG_HAVE_IDE=y
|
||||
# CONFIG_HAVE_IDE is not set
|
||||
# CONFIG_IDE is not set
|
||||
|
||||
#
|
||||
|
|
|
@ -109,7 +109,6 @@ CONFIG_VARIANT_IRQ_SWITCH=y
|
|||
CONFIG_XTENSA_VARIANT_S6000=y
|
||||
# CONFIG_XTENSA_UNALIGNED_USER is not set
|
||||
CONFIG_PREEMPT=y
|
||||
# CONFIG_MATH_EMULATION is not set
|
||||
# CONFIG_HIGHMEM is not set
|
||||
CONFIG_XTENSA_CALIBRATE_CCOUNT=y
|
||||
CONFIG_SERIAL_CONSOLE=y
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
* specials for cache aliasing:
|
||||
*
|
||||
* __flush_invalidate_dcache_page_alias(vaddr,paddr)
|
||||
* __invalidate_dcache_page_alias(vaddr,paddr)
|
||||
* __invalidate_icache_page_alias(vaddr,paddr)
|
||||
*/
|
||||
|
||||
|
@ -62,6 +63,7 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
|
|||
|
||||
#if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long);
|
||||
extern void __invalidate_dcache_page_alias(unsigned long, unsigned long);
|
||||
#else
|
||||
static inline void __flush_invalidate_dcache_page_alias(unsigned long virt,
|
||||
unsigned long phys) { }
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
* Here we define all the compile-time 'special' virtual
|
||||
* addresses. The point is to have a constant address at
|
||||
* compile time, but to set the physical address only
|
||||
* in the boot process. We allocate these special addresses
|
||||
* from the end of the consistent memory region backwards.
|
||||
* in the boot process. We allocate these special addresses
|
||||
* from the start of the consistent memory region upwards.
|
||||
* Also this lets us do fail-safe vmalloc(), we
|
||||
* can guarantee that these special addresses and
|
||||
* vmalloc()-ed addresses never overlap.
|
||||
|
@ -38,7 +38,8 @@ enum fixed_addresses {
|
|||
#ifdef CONFIG_HIGHMEM
|
||||
/* reserved pte's for temporary kernel mappings */
|
||||
FIX_KMAP_BEGIN,
|
||||
FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
|
||||
FIX_KMAP_END = FIX_KMAP_BEGIN +
|
||||
(KM_TYPE_NR * NR_CPUS * DCACHE_N_COLORS) - 1,
|
||||
#endif
|
||||
__end_of_fixed_addresses
|
||||
};
|
||||
|
@ -47,7 +48,28 @@ enum fixed_addresses {
|
|||
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
|
||||
#define FIXADDR_START ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK)
|
||||
|
||||
#include <asm-generic/fixmap.h>
|
||||
#define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT))
|
||||
#define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/*
|
||||
* 'index to address' translation. If anyone tries to use the idx
|
||||
* directly without translation, we catch the bug with a NULL-deference
|
||||
* kernel oops. Illegal ranges of incoming indices are caught too.
|
||||
*/
|
||||
static __always_inline unsigned long fix_to_virt(const unsigned int idx)
|
||||
{
|
||||
BUILD_BUG_ON(idx >= __end_of_fixed_addresses);
|
||||
return __fix_to_virt(idx);
|
||||
}
|
||||
|
||||
static inline unsigned long virt_to_fix(const unsigned long vaddr)
|
||||
{
|
||||
BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
|
||||
return __virt_to_fix(vaddr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define kmap_get_fixmap_pte(vaddr) \
|
||||
pte_offset_kernel( \
|
||||
|
|
|
@ -12,19 +12,55 @@
|
|||
#ifndef _XTENSA_HIGHMEM_H
|
||||
#define _XTENSA_HIGHMEM_H
|
||||
|
||||
#include <linux/wait.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/kmap_types.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
#define PKMAP_BASE (FIXADDR_START - PMD_SIZE)
|
||||
#define LAST_PKMAP PTRS_PER_PTE
|
||||
#define PKMAP_BASE ((FIXADDR_START - \
|
||||
(LAST_PKMAP + 1) * PAGE_SIZE) & PMD_MASK)
|
||||
#define LAST_PKMAP (PTRS_PER_PTE * DCACHE_N_COLORS)
|
||||
#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
|
||||
#define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT)
|
||||
#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
|
||||
|
||||
#define kmap_prot PAGE_KERNEL
|
||||
|
||||
#if DCACHE_WAY_SIZE > PAGE_SIZE
|
||||
#define get_pkmap_color get_pkmap_color
|
||||
static inline int get_pkmap_color(struct page *page)
|
||||
{
|
||||
return DCACHE_ALIAS(page_to_phys(page));
|
||||
}
|
||||
|
||||
extern unsigned int last_pkmap_nr_arr[];
|
||||
|
||||
static inline unsigned int get_next_pkmap_nr(unsigned int color)
|
||||
{
|
||||
last_pkmap_nr_arr[color] =
|
||||
(last_pkmap_nr_arr[color] + DCACHE_N_COLORS) & LAST_PKMAP_MASK;
|
||||
return last_pkmap_nr_arr[color] + color;
|
||||
}
|
||||
|
||||
static inline int no_more_pkmaps(unsigned int pkmap_nr, unsigned int color)
|
||||
{
|
||||
return pkmap_nr < DCACHE_N_COLORS;
|
||||
}
|
||||
|
||||
static inline int get_pkmap_entries_count(unsigned int color)
|
||||
{
|
||||
return LAST_PKMAP / DCACHE_N_COLORS;
|
||||
}
|
||||
|
||||
extern wait_queue_head_t pkmap_map_wait_arr[];
|
||||
|
||||
static inline wait_queue_head_t *get_pkmap_wait_queue_head(unsigned int color)
|
||||
{
|
||||
return pkmap_map_wait_arr + color;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern pte_t *pkmap_page_table;
|
||||
|
||||
void *kmap_high(struct page *page);
|
||||
|
|
|
@ -78,7 +78,9 @@
|
|||
# define DCACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0)
|
||||
#else
|
||||
# define DCACHE_ALIAS_ORDER 0
|
||||
# define DCACHE_ALIAS(a) ((void)(a), 0)
|
||||
#endif
|
||||
#define DCACHE_N_COLORS (1 << DCACHE_ALIAS_ORDER)
|
||||
|
||||
#if ICACHE_WAY_SIZE > PAGE_SIZE
|
||||
# define ICACHE_ALIAS_ORDER (ICACHE_WAY_SHIFT - PAGE_SHIFT)
|
||||
|
@ -134,6 +136,7 @@ static inline __attribute_const__ int get_order(unsigned long size)
|
|||
#endif
|
||||
|
||||
struct page;
|
||||
struct vm_area_struct;
|
||||
extern void clear_page(void *page);
|
||||
extern void copy_page(void *to, void *from);
|
||||
|
||||
|
@ -143,8 +146,15 @@ extern void copy_page(void *to, void *from);
|
|||
*/
|
||||
|
||||
#if DCACHE_WAY_SIZE > PAGE_SIZE
|
||||
extern void clear_user_page(void*, unsigned long, struct page*);
|
||||
extern void copy_user_page(void*, void*, unsigned long, struct page*);
|
||||
extern void clear_page_alias(void *vaddr, unsigned long paddr);
|
||||
extern void copy_page_alias(void *to, void *from,
|
||||
unsigned long to_paddr, unsigned long from_paddr);
|
||||
|
||||
#define clear_user_highpage clear_user_highpage
|
||||
void clear_user_highpage(struct page *page, unsigned long vaddr);
|
||||
#define __HAVE_ARCH_COPY_USER_HIGHPAGE
|
||||
void copy_user_highpage(struct page *to, struct page *from,
|
||||
unsigned long vaddr, struct vm_area_struct *vma);
|
||||
#else
|
||||
# define clear_user_page(page, vaddr, pg) clear_page(page)
|
||||
# define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
|
||||
|
|
|
@ -67,7 +67,12 @@
|
|||
#define VMALLOC_START 0xC0000000
|
||||
#define VMALLOC_END 0xC7FEFFFF
|
||||
#define TLBTEMP_BASE_1 0xC7FF0000
|
||||
#define TLBTEMP_BASE_2 0xC7FF8000
|
||||
#define TLBTEMP_BASE_2 (TLBTEMP_BASE_1 + DCACHE_WAY_SIZE)
|
||||
#if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE
|
||||
#define TLBTEMP_SIZE (2 * DCACHE_WAY_SIZE)
|
||||
#else
|
||||
#define TLBTEMP_SIZE ICACHE_WAY_SIZE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For the Xtensa architecture, the PTE layout is as follows:
|
||||
|
|
|
@ -52,7 +52,12 @@
|
|||
*/
|
||||
.macro get_fs ad, sp
|
||||
GET_CURRENT(\ad,\sp)
|
||||
#if THREAD_CURRENT_DS > 1020
|
||||
addi \ad, \ad, TASK_THREAD
|
||||
l32i \ad, \ad, THREAD_CURRENT_DS - TASK_THREAD
|
||||
#else
|
||||
l32i \ad, \ad, THREAD_CURRENT_DS
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/*
|
||||
|
|
|
@ -28,17 +28,17 @@
|
|||
#define TCSETSW 0x5403
|
||||
#define TCSETSF 0x5404
|
||||
|
||||
#define TCGETA _IOR('t', 23, struct termio)
|
||||
#define TCSETA _IOW('t', 24, struct termio)
|
||||
#define TCSETAW _IOW('t', 25, struct termio)
|
||||
#define TCSETAF _IOW('t', 28, struct termio)
|
||||
#define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */
|
||||
#define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */
|
||||
#define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */
|
||||
#define TCSETAF 0x4012741C /* _IOW('t', 28, struct termio) */
|
||||
|
||||
#define TCSBRK _IO('t', 29)
|
||||
#define TCXONC _IO('t', 30)
|
||||
#define TCFLSH _IO('t', 31)
|
||||
|
||||
#define TIOCSWINSZ _IOW('t', 103, struct winsize)
|
||||
#define TIOCGWINSZ _IOR('t', 104, struct winsize)
|
||||
#define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */
|
||||
#define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */
|
||||
#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
|
||||
#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
|
||||
#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
|
||||
|
@ -88,7 +88,6 @@
|
|||
#define TIOCSETD _IOW('T', 35, int)
|
||||
#define TIOCGETD _IOR('T', 36, int)
|
||||
#define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/
|
||||
#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/
|
||||
#define TIOCSBRK _IO('T', 39) /* BSD compatibility */
|
||||
#define TIOCCBRK _IO('T', 40) /* BSD compatibility */
|
||||
#define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/
|
||||
|
@ -114,8 +113,10 @@
|
|||
#define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */
|
||||
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
|
||||
# define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
||||
#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config */
|
||||
#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
|
||||
#define TIOCSERGETMULTI 0x80a8545a /* Get multiport config */
|
||||
/* _IOR('T', 90, struct serial_multiport_struct) */
|
||||
#define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */
|
||||
/* _IOW('T', 91, struct serial_multiport_struct) */
|
||||
|
||||
#define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */
|
||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
||||
|
|
|
@ -739,7 +739,10 @@ __SYSCALL(334, sys_sched_setattr, 2)
|
|||
#define __NR_sched_getattr 335
|
||||
__SYSCALL(335, sys_sched_getattr, 3)
|
||||
|
||||
#define __NR_syscall_count 336
|
||||
#define __NR_renameat2 336
|
||||
__SYSCALL(336, sys_renameat2, 5)
|
||||
|
||||
#define __NR_syscall_count 337
|
||||
|
||||
/*
|
||||
* sysxtensa syscall handler
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* this archive for more details.
|
||||
*
|
||||
* Copyright (C) 2001 - 2005 Tensilica, Inc.
|
||||
* Copyright (C) 2014 Cadence Design Systems Inc.
|
||||
*
|
||||
* Rewritten by Chris Zankel <chris@zankel.net>
|
||||
*
|
||||
|
@ -174,6 +175,10 @@ ENTRY(fast_unaligned)
|
|||
s32i a0, a2, PT_AREG2
|
||||
s32i a3, a2, PT_AREG3
|
||||
|
||||
rsr a3, excsave1
|
||||
movi a4, fast_unaligned_fixup
|
||||
s32i a4, a3, EXC_TABLE_FIXUP
|
||||
|
||||
/* Keep value of SAR in a0 */
|
||||
|
||||
rsr a0, sar
|
||||
|
@ -225,10 +230,6 @@ ENTRY(fast_unaligned)
|
|||
addx8 a5, a6, a5
|
||||
jx a5 # jump into table
|
||||
|
||||
/* Invalid instruction, CRITICAL! */
|
||||
.Linvalid_instruction_load:
|
||||
j .Linvalid_instruction
|
||||
|
||||
/* Load: Load memory address. */
|
||||
|
||||
.Lload: movi a3, ~3
|
||||
|
@ -272,18 +273,6 @@ ENTRY(fast_unaligned)
|
|||
/* Set target register. */
|
||||
|
||||
1:
|
||||
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
rsr a5, lend # check if we reached LEND
|
||||
bne a7, a5, 1f
|
||||
rsr a5, lcount # and LCOUNT != 0
|
||||
beqz a5, 1f
|
||||
addi a5, a5, -1 # decrement LCOUNT and set
|
||||
rsr a7, lbeg # set PC to LBEGIN
|
||||
wsr a5, lcount
|
||||
#endif
|
||||
|
||||
1: wsr a7, epc1 # skip load instruction
|
||||
extui a4, a4, INSN_T, 4 # extract target register
|
||||
movi a5, .Lload_table
|
||||
addx8 a4, a4, a5
|
||||
|
@ -326,6 +315,35 @@ ENTRY(fast_unaligned)
|
|||
mov a3, a14 ; _j 1f; .align 8
|
||||
mov a3, a15 ; _j 1f; .align 8
|
||||
|
||||
/* We cannot handle this exception. */
|
||||
|
||||
.extern _kernel_exception
|
||||
.Linvalid_instruction_load:
|
||||
.Linvalid_instruction_store:
|
||||
|
||||
movi a4, 0
|
||||
rsr a3, excsave1
|
||||
s32i a4, a3, EXC_TABLE_FIXUP
|
||||
|
||||
/* Restore a4...a8 and SAR, set SP, and jump to default exception. */
|
||||
|
||||
l32i a8, a2, PT_AREG8
|
||||
l32i a7, a2, PT_AREG7
|
||||
l32i a6, a2, PT_AREG6
|
||||
l32i a5, a2, PT_AREG5
|
||||
l32i a4, a2, PT_AREG4
|
||||
wsr a0, sar
|
||||
mov a1, a2
|
||||
|
||||
rsr a0, ps
|
||||
bbsi.l a0, PS_UM_BIT, 2f # jump if user mode
|
||||
|
||||
movi a0, _kernel_exception
|
||||
jx a0
|
||||
|
||||
2: movi a0, _user_exception
|
||||
jx a0
|
||||
|
||||
1: # a7: instruction pointer, a4: instruction, a3: value
|
||||
|
||||
movi a6, 0 # mask: ffffffff:00000000
|
||||
|
@ -353,17 +371,6 @@ ENTRY(fast_unaligned)
|
|||
/* Get memory address */
|
||||
|
||||
1:
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
rsr a4, lend # check if we reached LEND
|
||||
bne a7, a4, 1f
|
||||
rsr a4, lcount # and LCOUNT != 0
|
||||
beqz a4, 1f
|
||||
addi a4, a4, -1 # decrement LCOUNT and set
|
||||
rsr a7, lbeg # set PC to LBEGIN
|
||||
wsr a4, lcount
|
||||
#endif
|
||||
|
||||
1: wsr a7, epc1 # skip store instruction
|
||||
movi a4, ~3
|
||||
and a4, a4, a8 # align memory address
|
||||
|
||||
|
@ -375,25 +382,25 @@ ENTRY(fast_unaligned)
|
|||
#endif
|
||||
|
||||
__ssa8r a8
|
||||
__src_b a7, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE)
|
||||
__src_b a8, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE)
|
||||
__src_b a6, a6, a5 # hi-mask 0..0F..F (BE) F..F0..0 (LE)
|
||||
#ifdef UNALIGNED_USER_EXCEPTION
|
||||
l32e a5, a4, -8
|
||||
#else
|
||||
l32i a5, a4, 0 # load lower address word
|
||||
#endif
|
||||
and a5, a5, a7 # mask
|
||||
__sh a7, a3 # shift value
|
||||
or a5, a5, a7 # or with original value
|
||||
and a5, a5, a8 # mask
|
||||
__sh a8, a3 # shift value
|
||||
or a5, a5, a8 # or with original value
|
||||
#ifdef UNALIGNED_USER_EXCEPTION
|
||||
s32e a5, a4, -8
|
||||
l32e a7, a4, -4
|
||||
l32e a8, a4, -4
|
||||
#else
|
||||
s32i a5, a4, 0 # store
|
||||
l32i a7, a4, 4 # same for upper address word
|
||||
l32i a8, a4, 4 # same for upper address word
|
||||
#endif
|
||||
__sl a5, a3
|
||||
and a6, a7, a6
|
||||
and a6, a8, a6
|
||||
or a6, a6, a5
|
||||
#ifdef UNALIGNED_USER_EXCEPTION
|
||||
s32e a6, a4, -4
|
||||
|
@ -401,9 +408,27 @@ ENTRY(fast_unaligned)
|
|||
s32i a6, a4, 4
|
||||
#endif
|
||||
|
||||
/* Done. restore stack and return */
|
||||
|
||||
.Lexit:
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
rsr a4, lend # check if we reached LEND
|
||||
bne a7, a4, 1f
|
||||
rsr a4, lcount # and LCOUNT != 0
|
||||
beqz a4, 1f
|
||||
addi a4, a4, -1 # decrement LCOUNT and set
|
||||
rsr a7, lbeg # set PC to LBEGIN
|
||||
wsr a4, lcount
|
||||
#endif
|
||||
|
||||
1: wsr a7, epc1 # skip emulated instruction
|
||||
|
||||
/* Update icount if we're single-stepping in userspace. */
|
||||
rsr a4, icountlevel
|
||||
beqz a4, 1f
|
||||
bgeui a4, LOCKLEVEL + 1, 1f
|
||||
rsr a4, icount
|
||||
addi a4, a4, 1
|
||||
wsr a4, icount
|
||||
1:
|
||||
movi a4, 0
|
||||
rsr a3, excsave1
|
||||
s32i a4, a3, EXC_TABLE_FIXUP
|
||||
|
@ -424,31 +449,40 @@ ENTRY(fast_unaligned)
|
|||
l32i a2, a2, PT_AREG2
|
||||
rfe
|
||||
|
||||
/* We cannot handle this exception. */
|
||||
ENDPROC(fast_unaligned)
|
||||
|
||||
.extern _kernel_exception
|
||||
.Linvalid_instruction_store:
|
||||
.Linvalid_instruction:
|
||||
ENTRY(fast_unaligned_fixup)
|
||||
|
||||
/* Restore a4...a8 and SAR, set SP, and jump to default exception. */
|
||||
l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
|
||||
wsr a3, excsave1
|
||||
|
||||
l32i a8, a2, PT_AREG8
|
||||
l32i a7, a2, PT_AREG7
|
||||
l32i a6, a2, PT_AREG6
|
||||
l32i a5, a2, PT_AREG5
|
||||
l32i a4, a2, PT_AREG4
|
||||
l32i a0, a2, PT_AREG2
|
||||
xsr a0, depc # restore depc and a0
|
||||
wsr a0, sar
|
||||
mov a1, a2
|
||||
|
||||
rsr a0, exccause
|
||||
s32i a0, a2, PT_DEPC # mark as a regular exception
|
||||
|
||||
rsr a0, ps
|
||||
bbsi.l a2, PS_UM_BIT, 1f # jump if user mode
|
||||
bbsi.l a0, PS_UM_BIT, 1f # jump if user mode
|
||||
|
||||
movi a0, _kernel_exception
|
||||
rsr a0, exccause
|
||||
addx4 a0, a0, a3 # find entry in table
|
||||
l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler
|
||||
l32i a3, a2, PT_AREG3
|
||||
jx a0
|
||||
1:
|
||||
rsr a0, exccause
|
||||
addx4 a0, a0, a3 # find entry in table
|
||||
l32i a0, a0, EXC_TABLE_FAST_USER # load handler
|
||||
l32i a3, a2, PT_AREG3
|
||||
jx a0
|
||||
|
||||
1: movi a0, _user_exception
|
||||
jx a0
|
||||
|
||||
ENDPROC(fast_unaligned)
|
||||
ENDPROC(fast_unaligned_fixup)
|
||||
|
||||
#endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */
|
||||
|
|
|
@ -986,6 +986,8 @@ ENDPROC(fast_syscall_unrecoverable)
|
|||
* j done
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FAST_SYSCALL_XTENSA
|
||||
|
||||
#define TRY \
|
||||
.section __ex_table, "a"; \
|
||||
.word 66f, 67f; \
|
||||
|
@ -1001,9 +1003,8 @@ ENTRY(fast_syscall_xtensa)
|
|||
movi a7, 4 # sizeof(unsigned int)
|
||||
access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
|
||||
|
||||
addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1
|
||||
_bgeui a6, SYS_XTENSA_COUNT - 1, .Lill
|
||||
_bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp
|
||||
_bgeui a6, SYS_XTENSA_COUNT, .Lill
|
||||
_bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp
|
||||
|
||||
/* Fall through for ATOMIC_CMP_SWP. */
|
||||
|
||||
|
@ -1015,27 +1016,26 @@ TRY s32i a5, a3, 0 # different, modify value
|
|||
l32i a7, a2, PT_AREG7 # restore a7
|
||||
l32i a0, a2, PT_AREG0 # restore a0
|
||||
movi a2, 1 # and return 1
|
||||
addi a6, a6, 1 # restore a6 (really necessary?)
|
||||
rfe
|
||||
|
||||
1: l32i a7, a2, PT_AREG7 # restore a7
|
||||
l32i a0, a2, PT_AREG0 # restore a0
|
||||
movi a2, 0 # return 0 (note that we cannot set
|
||||
addi a6, a6, 1 # restore a6 (really necessary?)
|
||||
rfe
|
||||
|
||||
.Lnswp: /* Atomic set, add, and exg_add. */
|
||||
|
||||
TRY l32i a7, a3, 0 # orig
|
||||
addi a6, a6, -SYS_XTENSA_ATOMIC_SET
|
||||
add a0, a4, a7 # + arg
|
||||
moveqz a0, a4, a6 # set
|
||||
addi a6, a6, SYS_XTENSA_ATOMIC_SET
|
||||
TRY s32i a0, a3, 0 # write new value
|
||||
|
||||
mov a0, a2
|
||||
mov a2, a7
|
||||
l32i a7, a0, PT_AREG7 # restore a7
|
||||
l32i a0, a0, PT_AREG0 # restore a0
|
||||
addi a6, a6, 1 # restore a6 (really necessary?)
|
||||
rfe
|
||||
|
||||
CATCH
|
||||
|
@ -1044,13 +1044,25 @@ CATCH
|
|||
movi a2, -EFAULT
|
||||
rfe
|
||||
|
||||
.Lill: l32i a7, a2, PT_AREG0 # restore a7
|
||||
.Lill: l32i a7, a2, PT_AREG7 # restore a7
|
||||
l32i a0, a2, PT_AREG0 # restore a0
|
||||
movi a2, -EINVAL
|
||||
rfe
|
||||
|
||||
ENDPROC(fast_syscall_xtensa)
|
||||
|
||||
#else /* CONFIG_FAST_SYSCALL_XTENSA */
|
||||
|
||||
ENTRY(fast_syscall_xtensa)
|
||||
|
||||
l32i a0, a2, PT_AREG0 # restore a0
|
||||
movi a2, -ENOSYS
|
||||
rfe
|
||||
|
||||
ENDPROC(fast_syscall_xtensa)
|
||||
|
||||
#endif /* CONFIG_FAST_SYSCALL_XTENSA */
|
||||
|
||||
|
||||
/* fast_syscall_spill_registers.
|
||||
*
|
||||
|
@ -1066,6 +1078,8 @@ ENDPROC(fast_syscall_xtensa)
|
|||
* Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FAST_SYSCALL_SPILL_REGISTERS
|
||||
|
||||
ENTRY(fast_syscall_spill_registers)
|
||||
|
||||
/* Register a FIXUP handler (pass current wb as a parameter) */
|
||||
|
@ -1400,6 +1414,18 @@ ENTRY(fast_syscall_spill_registers_fixup_return)
|
|||
|
||||
ENDPROC(fast_syscall_spill_registers_fixup_return)
|
||||
|
||||
#else /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */
|
||||
|
||||
ENTRY(fast_syscall_spill_registers)
|
||||
|
||||
l32i a0, a2, PT_AREG0 # restore a0
|
||||
movi a2, -ENOSYS
|
||||
rfe
|
||||
|
||||
ENDPROC(fast_syscall_spill_registers)
|
||||
|
||||
#endif /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
/*
|
||||
* We should never get here. Bail out!
|
||||
|
@ -1565,7 +1591,7 @@ ENTRY(fast_second_level_miss)
|
|||
rsr a0, excvaddr
|
||||
bltu a0, a3, 2f
|
||||
|
||||
addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
|
||||
addi a1, a0, -TLBTEMP_SIZE
|
||||
bgeu a1, a3, 2f
|
||||
|
||||
/* Check if we have to restore an ITLB mapping. */
|
||||
|
@ -1820,7 +1846,6 @@ ENTRY(_switch_to)
|
|||
|
||||
entry a1, 16
|
||||
|
||||
mov a10, a2 # preserve 'prev' (a2)
|
||||
mov a11, a3 # and 'next' (a3)
|
||||
|
||||
l32i a4, a2, TASK_THREAD_INFO
|
||||
|
@ -1828,8 +1853,14 @@ ENTRY(_switch_to)
|
|||
|
||||
save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
|
||||
|
||||
s32i a0, a10, THREAD_RA # save return address
|
||||
s32i a1, a10, THREAD_SP # save stack pointer
|
||||
#if THREAD_RA > 1020 || THREAD_SP > 1020
|
||||
addi a10, a2, TASK_THREAD
|
||||
s32i a0, a10, THREAD_RA - TASK_THREAD # save return address
|
||||
s32i a1, a10, THREAD_SP - TASK_THREAD # save stack pointer
|
||||
#else
|
||||
s32i a0, a2, THREAD_RA # save return address
|
||||
s32i a1, a2, THREAD_SP # save stack pointer
|
||||
#endif
|
||||
|
||||
/* Disable ints while we manipulate the stack pointer. */
|
||||
|
||||
|
@ -1870,7 +1901,6 @@ ENTRY(_switch_to)
|
|||
load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
|
||||
|
||||
wsr a14, ps
|
||||
mov a2, a10 # return 'prev'
|
||||
rsync
|
||||
|
||||
retw
|
||||
|
|
|
@ -49,9 +49,8 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
|
|||
|
||||
/* We currently don't support coherent memory outside KSEG */
|
||||
|
||||
if (ret < XCHAL_KSEG_CACHED_VADDR
|
||||
|| ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)
|
||||
BUG();
|
||||
BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR ||
|
||||
ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
|
||||
|
||||
|
||||
if (ret != 0) {
|
||||
|
@ -68,10 +67,11 @@ EXPORT_SYMBOL(dma_alloc_coherent);
|
|||
void dma_free_coherent(struct device *hwdev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle)
|
||||
{
|
||||
long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
|
||||
unsigned long addr = (unsigned long)vaddr +
|
||||
XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
|
||||
|
||||
if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
|
||||
BUG();
|
||||
BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR ||
|
||||
addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
|
||||
|
||||
free_pages(addr, get_order(size));
|
||||
}
|
||||
|
|
|
@ -571,6 +571,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
|
|||
};
|
||||
on_each_cpu(ipi_flush_icache_range, &fd, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(flush_icache_range);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -101,9 +101,8 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
|
|||
#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
|
||||
#ifdef CONFIG_XTENSA_UNALIGNED_USER
|
||||
{ EXCCAUSE_UNALIGNED, USER, fast_unaligned },
|
||||
#else
|
||||
{ EXCCAUSE_UNALIGNED, 0, do_unaligned_user },
|
||||
#endif
|
||||
{ EXCCAUSE_UNALIGNED, 0, do_unaligned_user },
|
||||
{ EXCCAUSE_UNALIGNED, KRNL, fast_unaligned },
|
||||
#endif
|
||||
#ifdef CONFIG_MMU
|
||||
|
@ -264,7 +263,6 @@ do_illegal_instruction(struct pt_regs *regs)
|
|||
*/
|
||||
|
||||
#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
|
||||
#ifndef CONFIG_XTENSA_UNALIGNED_USER
|
||||
void
|
||||
do_unaligned_user (struct pt_regs *regs)
|
||||
{
|
||||
|
@ -286,7 +284,6 @@ do_unaligned_user (struct pt_regs *regs)
|
|||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
do_debug(struct pt_regs *regs)
|
||||
|
|
|
@ -454,8 +454,14 @@ _DoubleExceptionVector_WindowOverflow:
|
|||
s32i a0, a2, PT_DEPC
|
||||
|
||||
_DoubleExceptionVector_handle_exception:
|
||||
addi a0, a0, -EXCCAUSE_UNALIGNED
|
||||
beqz a0, 2f
|
||||
addx4 a0, a0, a3
|
||||
l32i a0, a0, EXC_TABLE_FAST_USER
|
||||
l32i a0, a0, EXC_TABLE_FAST_USER + 4 * EXCCAUSE_UNALIGNED
|
||||
xsr a3, excsave1
|
||||
jx a0
|
||||
2:
|
||||
movi a0, user_exception
|
||||
xsr a3, excsave1
|
||||
jx a0
|
||||
|
||||
|
|
|
@ -269,13 +269,13 @@ SECTIONS
|
|||
.UserExceptionVector.literal)
|
||||
SECTION_VECTOR (_DoubleExceptionVector_literal,
|
||||
.DoubleExceptionVector.literal,
|
||||
DOUBLEEXC_VECTOR_VADDR - 40,
|
||||
DOUBLEEXC_VECTOR_VADDR - 48,
|
||||
SIZEOF(.UserExceptionVector.text),
|
||||
.UserExceptionVector.text)
|
||||
SECTION_VECTOR (_DoubleExceptionVector_text,
|
||||
.DoubleExceptionVector.text,
|
||||
DOUBLEEXC_VECTOR_VADDR,
|
||||
40,
|
||||
48,
|
||||
.DoubleExceptionVector.literal)
|
||||
|
||||
. = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
|
||||
|
|
|
@ -59,9 +59,68 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && defined(CONFIG_HIGHMEM)
|
||||
#error "HIGHMEM is not supported on cores with aliasing cache."
|
||||
#endif
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
static inline void kmap_invalidate_coherent(struct page *page,
|
||||
unsigned long vaddr)
|
||||
{
|
||||
if (!DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) {
|
||||
unsigned long kvaddr;
|
||||
|
||||
if (!PageHighMem(page)) {
|
||||
kvaddr = (unsigned long)page_to_virt(page);
|
||||
|
||||
__invalidate_dcache_page(kvaddr);
|
||||
} else {
|
||||
kvaddr = TLBTEMP_BASE_1 +
|
||||
(page_to_phys(page) & DCACHE_ALIAS_MASK);
|
||||
|
||||
__invalidate_dcache_page_alias(kvaddr,
|
||||
page_to_phys(page));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void *coherent_kvaddr(struct page *page, unsigned long base,
|
||||
unsigned long vaddr, unsigned long *paddr)
|
||||
{
|
||||
if (PageHighMem(page) || !DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) {
|
||||
*paddr = page_to_phys(page);
|
||||
return (void *)(base + (vaddr & DCACHE_ALIAS_MASK));
|
||||
} else {
|
||||
*paddr = 0;
|
||||
return page_to_virt(page);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_user_highpage(struct page *page, unsigned long vaddr)
|
||||
{
|
||||
unsigned long paddr;
|
||||
void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr);
|
||||
|
||||
pagefault_disable();
|
||||
kmap_invalidate_coherent(page, vaddr);
|
||||
set_bit(PG_arch_1, &page->flags);
|
||||
clear_page_alias(kvaddr, paddr);
|
||||
pagefault_enable();
|
||||
}
|
||||
|
||||
void copy_user_highpage(struct page *dst, struct page *src,
|
||||
unsigned long vaddr, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long dst_paddr, src_paddr;
|
||||
void *dst_vaddr = coherent_kvaddr(dst, TLBTEMP_BASE_1, vaddr,
|
||||
&dst_paddr);
|
||||
void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr,
|
||||
&src_paddr);
|
||||
|
||||
pagefault_disable();
|
||||
kmap_invalidate_coherent(dst, vaddr);
|
||||
set_bit(PG_arch_1, &dst->flags);
|
||||
copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr);
|
||||
pagefault_enable();
|
||||
}
|
||||
|
||||
#endif /* DCACHE_WAY_SIZE > PAGE_SIZE */
|
||||
|
||||
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
|
||||
|
||||
|
@ -103,7 +162,8 @@ void flush_dcache_page(struct page *page)
|
|||
if (!alias && !mapping)
|
||||
return;
|
||||
|
||||
__flush_invalidate_dcache_page((long)page_address(page));
|
||||
virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
|
||||
__flush_invalidate_dcache_page_alias(virt, phys);
|
||||
|
||||
virt = TLBTEMP_BASE_1 + (temp & DCACHE_ALIAS_MASK);
|
||||
|
||||
|
@ -168,13 +228,12 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)
|
|||
#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
|
||||
|
||||
if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) {
|
||||
|
||||
unsigned long paddr = (unsigned long) page_address(page);
|
||||
unsigned long phys = page_to_phys(page);
|
||||
unsigned long tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
|
||||
|
||||
__flush_invalidate_dcache_page(paddr);
|
||||
unsigned long tmp;
|
||||
|
||||
tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
|
||||
__flush_invalidate_dcache_page_alias(tmp, phys);
|
||||
tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
|
||||
__flush_invalidate_dcache_page_alias(tmp, phys);
|
||||
__invalidate_icache_page_alias(tmp, phys);
|
||||
|
||||
|
|
|
@ -14,23 +14,45 @@
|
|||
|
||||
static pte_t *kmap_pte;
|
||||
|
||||
#if DCACHE_WAY_SIZE > PAGE_SIZE
|
||||
unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS];
|
||||
wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS];
|
||||
|
||||
static void __init kmap_waitqueues_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i)
|
||||
init_waitqueue_head(pkmap_map_wait_arr + i);
|
||||
}
|
||||
#else
|
||||
static inline void kmap_waitqueues_init(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline enum fixed_addresses kmap_idx(int type, unsigned long color)
|
||||
{
|
||||
return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS +
|
||||
color;
|
||||
}
|
||||
|
||||
void *kmap_atomic(struct page *page)
|
||||
{
|
||||
enum fixed_addresses idx;
|
||||
unsigned long vaddr;
|
||||
int type;
|
||||
|
||||
pagefault_disable();
|
||||
if (!PageHighMem(page))
|
||||
return page_address(page);
|
||||
|
||||
type = kmap_atomic_idx_push();
|
||||
idx = type + KM_TYPE_NR * smp_processor_id();
|
||||
idx = kmap_idx(kmap_atomic_idx_push(),
|
||||
DCACHE_ALIAS(page_to_phys(page)));
|
||||
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
||||
#ifdef CONFIG_DEBUG_HIGHMEM
|
||||
BUG_ON(!pte_none(*(kmap_pte - idx)));
|
||||
BUG_ON(!pte_none(*(kmap_pte + idx)));
|
||||
#endif
|
||||
set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC));
|
||||
set_pte(kmap_pte + idx, mk_pte(page, PAGE_KERNEL_EXEC));
|
||||
|
||||
return (void *)vaddr;
|
||||
}
|
||||
|
@ -38,12 +60,10 @@ EXPORT_SYMBOL(kmap_atomic);
|
|||
|
||||
void __kunmap_atomic(void *kvaddr)
|
||||
{
|
||||
int idx, type;
|
||||
|
||||
if (kvaddr >= (void *)FIXADDR_START &&
|
||||
kvaddr < (void *)FIXADDR_TOP) {
|
||||
type = kmap_atomic_idx();
|
||||
idx = type + KM_TYPE_NR * smp_processor_id();
|
||||
int idx = kmap_idx(kmap_atomic_idx(),
|
||||
DCACHE_ALIAS((unsigned long)kvaddr));
|
||||
|
||||
/*
|
||||
* Force other mappings to Oops if they'll try to access this
|
||||
|
@ -51,7 +71,7 @@ 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.
|
||||
*/
|
||||
pte_clear(&init_mm, kvaddr, kmap_pte - idx);
|
||||
pte_clear(&init_mm, kvaddr, kmap_pte + idx);
|
||||
local_flush_tlb_kernel_range((unsigned long)kvaddr,
|
||||
(unsigned long)kvaddr + PAGE_SIZE);
|
||||
|
||||
|
@ -69,4 +89,5 @@ void __init kmap_init(void)
|
|||
/* cache the first kmap pte */
|
||||
kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
|
||||
kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
|
||||
kmap_waitqueues_init();
|
||||
}
|
||||
|
|
|
@ -110,41 +110,24 @@ ENTRY(__tlbtemp_mapping_start)
|
|||
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
|
||||
|
||||
/*
|
||||
* clear_user_page (void *addr, unsigned long vaddr, struct page *page)
|
||||
* a2 a3 a4
|
||||
* clear_page_alias(void *addr, unsigned long paddr)
|
||||
* a2 a3
|
||||
*/
|
||||
|
||||
ENTRY(clear_user_page)
|
||||
ENTRY(clear_page_alias)
|
||||
|
||||
entry a1, 32
|
||||
|
||||
/* Mark page dirty and determine alias. */
|
||||
/* Skip setting up a temporary DTLB if not aliased low page. */
|
||||
|
||||
movi a7, (1 << PG_ARCH_1)
|
||||
l32i a5, a4, PAGE_FLAGS
|
||||
xor a6, a2, a3
|
||||
extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
|
||||
extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
|
||||
or a5, a5, a7
|
||||
slli a3, a3, PAGE_SHIFT
|
||||
s32i a5, a4, PAGE_FLAGS
|
||||
movi a5, PAGE_OFFSET
|
||||
movi a6, 0
|
||||
beqz a3, 1f
|
||||
|
||||
/* Skip setting up a temporary DTLB if not aliased. */
|
||||
|
||||
beqz a6, 1f
|
||||
|
||||
/* Invalidate kernel page. */
|
||||
|
||||
mov a10, a2
|
||||
call8 __invalidate_dcache_page
|
||||
|
||||
/* Setup a temporary DTLB with the color of the VPN */
|
||||
|
||||
movi a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
|
||||
movi a5, TLBTEMP_BASE_1 # virt
|
||||
add a6, a2, a4 # ppn
|
||||
add a2, a5, a3 # add 'color'
|
||||
/* Setup a temporary DTLB for the addr. */
|
||||
|
||||
addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
|
||||
mov a4, a2
|
||||
wdtlb a6, a2
|
||||
dsync
|
||||
|
||||
|
@ -165,62 +148,43 @@ ENTRY(clear_user_page)
|
|||
|
||||
/* We need to invalidate the temporary idtlb entry, if any. */
|
||||
|
||||
1: addi a2, a2, -PAGE_SIZE
|
||||
idtlb a2
|
||||
1: idtlb a4
|
||||
dsync
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(clear_user_page)
|
||||
ENDPROC(clear_page_alias)
|
||||
|
||||
/*
|
||||
* copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
|
||||
* a2 a3 a4 a5
|
||||
* copy_page_alias(void *to, void *from,
|
||||
* a2 a3
|
||||
* unsigned long to_paddr, unsigned long from_paddr)
|
||||
* a4 a5
|
||||
*/
|
||||
|
||||
ENTRY(copy_user_page)
|
||||
ENTRY(copy_page_alias)
|
||||
|
||||
entry a1, 32
|
||||
|
||||
/* Mark page dirty and determine alias for destination. */
|
||||
/* Skip setting up a temporary DTLB for destination if not aliased. */
|
||||
|
||||
movi a8, (1 << PG_ARCH_1)
|
||||
l32i a9, a5, PAGE_FLAGS
|
||||
xor a6, a2, a4
|
||||
xor a7, a3, a4
|
||||
extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
|
||||
extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
|
||||
extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
|
||||
or a9, a9, a8
|
||||
slli a4, a4, PAGE_SHIFT
|
||||
s32i a9, a5, PAGE_FLAGS
|
||||
movi a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
|
||||
movi a6, 0
|
||||
movi a7, 0
|
||||
beqz a4, 1f
|
||||
|
||||
beqz a6, 1f
|
||||
|
||||
/* Invalidate dcache */
|
||||
|
||||
mov a10, a2
|
||||
call8 __invalidate_dcache_page
|
||||
|
||||
/* Setup a temporary DTLB with a matching color. */
|
||||
|
||||
movi a8, TLBTEMP_BASE_1 # base
|
||||
add a6, a2, a5 # ppn
|
||||
add a2, a8, a4 # add 'color'
|
||||
/* Setup a temporary DTLB for destination. */
|
||||
|
||||
addi a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE)
|
||||
wdtlb a6, a2
|
||||
dsync
|
||||
|
||||
/* Skip setting up a temporary DTLB for destination if not aliased. */
|
||||
/* Skip setting up a temporary DTLB for source if not aliased. */
|
||||
|
||||
1: beqz a7, 1f
|
||||
1: beqz a5, 1f
|
||||
|
||||
/* Setup a temporary DTLB with a matching color. */
|
||||
/* Setup a temporary DTLB for source. */
|
||||
|
||||
movi a8, TLBTEMP_BASE_2 # base
|
||||
add a7, a3, a5 # ppn
|
||||
add a3, a8, a4
|
||||
addi a7, a5, PAGE_KERNEL
|
||||
addi a8, a3, 1 # way1
|
||||
|
||||
wdtlb a7, a8
|
||||
|
@ -271,7 +235,7 @@ ENTRY(copy_user_page)
|
|||
|
||||
retw
|
||||
|
||||
ENDPROC(copy_user_page)
|
||||
ENDPROC(copy_page_alias)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -300,6 +264,30 @@ ENTRY(__flush_invalidate_dcache_page_alias)
|
|||
retw
|
||||
|
||||
ENDPROC(__flush_invalidate_dcache_page_alias)
|
||||
|
||||
/*
|
||||
* void __invalidate_dcache_page_alias (addr, phys)
|
||||
* a2 a3
|
||||
*/
|
||||
|
||||
ENTRY(__invalidate_dcache_page_alias)
|
||||
|
||||
entry sp, 16
|
||||
|
||||
movi a7, 0 # required for exception handler
|
||||
addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
|
||||
mov a4, a2
|
||||
wdtlb a6, a2
|
||||
dsync
|
||||
|
||||
___invalidate_dcache_page a2 a3
|
||||
|
||||
idtlb a4
|
||||
dsync
|
||||
|
||||
retw
|
||||
|
||||
ENDPROC(__invalidate_dcache_page_alias)
|
||||
#endif
|
||||
|
||||
ENTRY(__tlbtemp_mapping_itlb)
|
||||
|
|
|
@ -18,32 +18,38 @@
|
|||
#include <asm/io.h>
|
||||
|
||||
#if defined(CONFIG_HIGHMEM)
|
||||
static void * __init init_pmd(unsigned long vaddr)
|
||||
static void * __init init_pmd(unsigned long vaddr, unsigned long n_pages)
|
||||
{
|
||||
pgd_t *pgd = pgd_offset_k(vaddr);
|
||||
pmd_t *pmd = pmd_offset(pgd, vaddr);
|
||||
pte_t *pte;
|
||||
unsigned long i;
|
||||
|
||||
if (pmd_none(*pmd)) {
|
||||
unsigned i;
|
||||
pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE);
|
||||
n_pages = ALIGN(n_pages, PTRS_PER_PTE);
|
||||
|
||||
for (i = 0; i < 1024; i++)
|
||||
pte_clear(NULL, 0, pte + i);
|
||||
pr_debug("%s: vaddr: 0x%08lx, n_pages: %ld\n",
|
||||
__func__, vaddr, n_pages);
|
||||
|
||||
set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK));
|
||||
BUG_ON(pte != pte_offset_kernel(pmd, 0));
|
||||
pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n",
|
||||
__func__, vaddr, pmd, pte);
|
||||
return pte;
|
||||
} else {
|
||||
return pte_offset_kernel(pmd, 0);
|
||||
pte = alloc_bootmem_low_pages(n_pages * sizeof(pte_t));
|
||||
|
||||
for (i = 0; i < n_pages; ++i)
|
||||
pte_clear(NULL, 0, pte + i);
|
||||
|
||||
for (i = 0; i < n_pages; i += PTRS_PER_PTE, ++pmd) {
|
||||
pte_t *cur_pte = pte + i;
|
||||
|
||||
BUG_ON(!pmd_none(*pmd));
|
||||
set_pmd(pmd, __pmd(((unsigned long)cur_pte) & PAGE_MASK));
|
||||
BUG_ON(cur_pte != pte_offset_kernel(pmd, 0));
|
||||
pr_debug("%s: pmd: 0x%p, pte: 0x%p\n",
|
||||
__func__, pmd, cur_pte);
|
||||
}
|
||||
return pte;
|
||||
}
|
||||
|
||||
static void __init fixedrange_init(void)
|
||||
{
|
||||
BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE);
|
||||
init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK);
|
||||
init_pmd(__fix_to_virt(0), __end_of_fixed_addresses);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -52,7 +58,7 @@ void __init paging_init(void)
|
|||
memset(swapper_pg_dir, 0, PAGE_SIZE);
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
fixedrange_init();
|
||||
pkmap_page_table = init_pmd(PKMAP_BASE);
|
||||
pkmap_page_table = init_pmd(PKMAP_BASE, LAST_PKMAP);
|
||||
kmap_init();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -520,7 +520,7 @@ void bio_integrity_endio(struct bio *bio, int error)
|
|||
*/
|
||||
if (error) {
|
||||
bio->bi_end_io = bip->bip_end_io;
|
||||
bio_endio(bio, error);
|
||||
bio_endio_nodec(bio, error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1252,7 +1252,6 @@ void blk_rq_set_block_pc(struct request *rq)
|
|||
rq->__sector = (sector_t) -1;
|
||||
rq->bio = rq->biotail = NULL;
|
||||
memset(rq->__cmd, 0, sizeof(rq->__cmd));
|
||||
rq->cmd = rq->__cmd;
|
||||
}
|
||||
EXPORT_SYMBOL(blk_rq_set_block_pc);
|
||||
|
||||
|
|
|
@ -112,18 +112,22 @@ static void blk_mq_usage_counter_release(struct percpu_ref *ref)
|
|||
*/
|
||||
void blk_mq_freeze_queue(struct request_queue *q)
|
||||
{
|
||||
bool freeze;
|
||||
|
||||
spin_lock_irq(q->queue_lock);
|
||||
q->mq_freeze_depth++;
|
||||
freeze = !q->mq_freeze_depth++;
|
||||
spin_unlock_irq(q->queue_lock);
|
||||
|
||||
percpu_ref_kill(&q->mq_usage_counter);
|
||||
blk_mq_run_queues(q, false);
|
||||
if (freeze) {
|
||||
percpu_ref_kill(&q->mq_usage_counter);
|
||||
blk_mq_run_queues(q, false);
|
||||
}
|
||||
wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter));
|
||||
}
|
||||
|
||||
static void blk_mq_unfreeze_queue(struct request_queue *q)
|
||||
{
|
||||
bool wake = false;
|
||||
bool wake;
|
||||
|
||||
spin_lock_irq(q->queue_lock);
|
||||
wake = !--q->mq_freeze_depth;
|
||||
|
@ -172,6 +176,8 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx,
|
|||
/* tag was already set */
|
||||
rq->errors = 0;
|
||||
|
||||
rq->cmd = rq->__cmd;
|
||||
|
||||
rq->extra_len = 0;
|
||||
rq->sense_len = 0;
|
||||
rq->resid_len = 0;
|
||||
|
@ -1068,13 +1074,17 @@ static void blk_mq_bio_to_request(struct request *rq, struct bio *bio)
|
|||
blk_account_io_start(rq, 1);
|
||||
}
|
||||
|
||||
static inline bool hctx_allow_merges(struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
return (hctx->flags & BLK_MQ_F_SHOULD_MERGE) &&
|
||||
!blk_queue_nomerges(hctx->queue);
|
||||
}
|
||||
|
||||
static inline bool blk_mq_merge_queue_io(struct blk_mq_hw_ctx *hctx,
|
||||
struct blk_mq_ctx *ctx,
|
||||
struct request *rq, struct bio *bio)
|
||||
{
|
||||
struct request_queue *q = hctx->queue;
|
||||
|
||||
if (!(hctx->flags & BLK_MQ_F_SHOULD_MERGE)) {
|
||||
if (!hctx_allow_merges(hctx)) {
|
||||
blk_mq_bio_to_request(rq, bio);
|
||||
spin_lock(&ctx->lock);
|
||||
insert_rq:
|
||||
|
@ -1082,6 +1092,8 @@ insert_rq:
|
|||
spin_unlock(&ctx->lock);
|
||||
return false;
|
||||
} else {
|
||||
struct request_queue *q = hctx->queue;
|
||||
|
||||
spin_lock(&ctx->lock);
|
||||
if (!blk_mq_attempt_merge(q, ctx, bio)) {
|
||||
blk_mq_bio_to_request(rq, bio);
|
||||
|
@ -1574,7 +1586,7 @@ static int blk_mq_init_hw_queues(struct request_queue *q,
|
|||
hctx->tags = set->tags[i];
|
||||
|
||||
/*
|
||||
* Allocate space for all possible cpus to avoid allocation in
|
||||
* Allocate space for all possible cpus to avoid allocation at
|
||||
* runtime
|
||||
*/
|
||||
hctx->ctxs = kmalloc_node(nr_cpu_ids * sizeof(void *),
|
||||
|
@ -1662,8 +1674,8 @@ static void blk_mq_map_swqueue(struct request_queue *q)
|
|||
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
/*
|
||||
* If not software queues are mapped to this hardware queue,
|
||||
* disable it and free the request entries
|
||||
* If no software queues are mapped to this hardware queue,
|
||||
* disable it and free the request entries.
|
||||
*/
|
||||
if (!hctx->nr_ctx) {
|
||||
struct blk_mq_tag_set *set = q->tag_set;
|
||||
|
@ -1713,14 +1725,10 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q)
|
|||
{
|
||||
struct blk_mq_tag_set *set = q->tag_set;
|
||||
|
||||
blk_mq_freeze_queue(q);
|
||||
|
||||
mutex_lock(&set->tag_list_lock);
|
||||
list_del_init(&q->tag_set_list);
|
||||
blk_mq_update_tag_set_depth(set);
|
||||
mutex_unlock(&set->tag_list_lock);
|
||||
|
||||
blk_mq_unfreeze_queue(q);
|
||||
}
|
||||
|
||||
static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set,
|
||||
|
|
|
@ -1272,15 +1272,22 @@ __cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
|
|||
rb_insert_color(&cfqg->rb_node, &st->rb);
|
||||
}
|
||||
|
||||
/*
|
||||
* This has to be called only on activation of cfqg
|
||||
*/
|
||||
static void
|
||||
cfq_update_group_weight(struct cfq_group *cfqg)
|
||||
{
|
||||
BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
|
||||
|
||||
if (cfqg->new_weight) {
|
||||
cfqg->weight = cfqg->new_weight;
|
||||
cfqg->new_weight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cfq_update_group_leaf_weight(struct cfq_group *cfqg)
|
||||
{
|
||||
BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
|
||||
|
||||
if (cfqg->new_leaf_weight) {
|
||||
cfqg->leaf_weight = cfqg->new_leaf_weight;
|
||||
|
@ -1299,7 +1306,12 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
|
|||
/* add to the service tree */
|
||||
BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
|
||||
|
||||
cfq_update_group_weight(cfqg);
|
||||
/*
|
||||
* Update leaf_weight. We cannot update weight at this point
|
||||
* because cfqg might already have been activated and is
|
||||
* contributing its current weight to the parent's child_weight.
|
||||
*/
|
||||
cfq_update_group_leaf_weight(cfqg);
|
||||
__cfq_group_service_tree_add(st, cfqg);
|
||||
|
||||
/*
|
||||
|
@ -1323,6 +1335,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
|
|||
*/
|
||||
while ((parent = cfqg_parent(pos))) {
|
||||
if (propagate) {
|
||||
cfq_update_group_weight(pos);
|
||||
propagate = !parent->nr_active++;
|
||||
parent->children_weight += pos->weight;
|
||||
}
|
||||
|
|
|
@ -279,7 +279,6 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
|
|||
r = blk_rq_unmap_user(bio);
|
||||
if (!ret)
|
||||
ret = r;
|
||||
blk_put_request(rq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -297,8 +296,6 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
|
|||
|
||||
if (hdr->interface_id != 'S')
|
||||
return -EINVAL;
|
||||
if (hdr->cmd_len > BLK_MAX_CDB)
|
||||
return -EINVAL;
|
||||
|
||||
if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
|
||||
return -EIO;
|
||||
|
@ -317,16 +314,23 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
|
|||
if (hdr->flags & SG_FLAG_Q_AT_HEAD)
|
||||
at_head = 1;
|
||||
|
||||
ret = -ENOMEM;
|
||||
rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
|
||||
if (!rq)
|
||||
return -ENOMEM;
|
||||
goto out;
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
if (blk_fill_sghdr_rq(q, rq, hdr, mode)) {
|
||||
blk_put_request(rq);
|
||||
return -EFAULT;
|
||||
if (hdr->cmd_len > BLK_MAX_CDB) {
|
||||
rq->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
|
||||
if (!rq->cmd)
|
||||
goto out_put_request;
|
||||
}
|
||||
|
||||
ret = -EFAULT;
|
||||
if (blk_fill_sghdr_rq(q, rq, hdr, mode))
|
||||
goto out_free_cdb;
|
||||
|
||||
ret = 0;
|
||||
if (hdr->iovec_count) {
|
||||
size_t iov_data_len;
|
||||
struct iovec *iov = NULL;
|
||||
|
@ -335,7 +339,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
|
|||
0, NULL, &iov);
|
||||
if (ret < 0) {
|
||||
kfree(iov);
|
||||
goto out;
|
||||
goto out_free_cdb;
|
||||
}
|
||||
|
||||
iov_data_len = ret;
|
||||
|
@ -358,7 +362,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
|
|||
GFP_KERNEL);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
goto out_free_cdb;
|
||||
|
||||
bio = rq->bio;
|
||||
memset(sense, 0, sizeof(sense));
|
||||
|
@ -376,9 +380,14 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
|
|||
|
||||
hdr->duration = jiffies_to_msecs(jiffies - start_time);
|
||||
|
||||
return blk_complete_sghdr_rq(rq, hdr, bio);
|
||||
out:
|
||||
ret = blk_complete_sghdr_rq(rq, hdr, bio);
|
||||
|
||||
out_free_cdb:
|
||||
if (rq->cmd != rq->__cmd)
|
||||
kfree(rq->cmd);
|
||||
out_put_request:
|
||||
blk_put_request(rq);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -448,6 +457,11 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
|
|||
}
|
||||
|
||||
rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT);
|
||||
if (!rq) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
cmdlen = COMMAND_SIZE(opcode);
|
||||
|
||||
|
@ -501,7 +515,6 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
|
|||
memset(sense, 0, sizeof(sense));
|
||||
rq->sense = sense;
|
||||
rq->sense_len = 0;
|
||||
blk_rq_set_block_pc(rq);
|
||||
|
||||
blk_execute_rq(q, disk, rq, 0);
|
||||
|
||||
|
@ -521,7 +534,8 @@ out:
|
|||
|
||||
error:
|
||||
kfree(buffer);
|
||||
blk_put_request(rq);
|
||||
if (rq)
|
||||
blk_put_request(rq);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
|
||||
|
|
|
@ -196,6 +196,17 @@ static struct lpss_device_desc byt_i2c_dev_desc = {
|
|||
.setup = lpss_i2c_setup,
|
||||
};
|
||||
|
||||
static struct lpss_shared_clock bsw_pwm_clock = {
|
||||
.name = "pwm_clk",
|
||||
.rate = 19200000,
|
||||
};
|
||||
|
||||
static struct lpss_device_desc bsw_pwm_dev_desc = {
|
||||
.clk_required = true,
|
||||
.save_ctx = true,
|
||||
.shared_clock = &bsw_pwm_clock,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define LPSS_ADDR(desc) (0UL)
|
||||
|
@ -225,6 +236,12 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
|
|||
{ "INT33B2", },
|
||||
{ "INT33FC", },
|
||||
|
||||
/* Braswell LPSS devices */
|
||||
{ "80862288", LPSS_ADDR(bsw_pwm_dev_desc) },
|
||||
{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
|
||||
{ "8086228E", LPSS_ADDR(byt_spi_dev_desc) },
|
||||
{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
|
||||
|
||||
{ "INT3430", LPSS_ADDR(lpt_dev_desc) },
|
||||
{ "INT3431", LPSS_ADDR(lpt_dev_desc) },
|
||||
{ "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) },
|
||||
|
|
|
@ -197,6 +197,8 @@ static bool advance_transaction(struct acpi_ec *ec)
|
|||
t->rdata[t->ri++] = acpi_ec_read_data(ec);
|
||||
if (t->rlen == t->ri) {
|
||||
t->flags |= ACPI_EC_COMMAND_COMPLETE;
|
||||
if (t->command == ACPI_EC_COMMAND_QUERY)
|
||||
pr_debug("hardware QR_EC completion\n");
|
||||
wakeup = true;
|
||||
}
|
||||
} else
|
||||
|
@ -208,7 +210,20 @@ static bool advance_transaction(struct acpi_ec *ec)
|
|||
}
|
||||
return wakeup;
|
||||
} else {
|
||||
if ((status & ACPI_EC_FLAG_IBF) == 0) {
|
||||
/*
|
||||
* There is firmware refusing to respond QR_EC when SCI_EVT
|
||||
* is not set, for which case, we complete the QR_EC
|
||||
* without issuing it to the firmware.
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=86211
|
||||
*/
|
||||
if (!(status & ACPI_EC_FLAG_SCI) &&
|
||||
(t->command == ACPI_EC_COMMAND_QUERY)) {
|
||||
t->flags |= ACPI_EC_COMMAND_POLL;
|
||||
t->rdata[t->ri++] = 0x00;
|
||||
t->flags |= ACPI_EC_COMMAND_COMPLETE;
|
||||
pr_debug("software QR_EC completion\n");
|
||||
wakeup = true;
|
||||
} else if ((status & ACPI_EC_FLAG_IBF) == 0) {
|
||||
acpi_ec_write_cmd(ec, t->command);
|
||||
t->flags |= ACPI_EC_COMMAND_POLL;
|
||||
} else
|
||||
|
@ -288,11 +303,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
|
|||
/* following two actions should be kept atomic */
|
||||
ec->curr = t;
|
||||
start_transaction(ec);
|
||||
if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
|
||||
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
|
||||
spin_unlock_irqrestore(&ec->lock, tmp);
|
||||
ret = ec_poll(ec);
|
||||
spin_lock_irqsave(&ec->lock, tmp);
|
||||
if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
|
||||
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
|
||||
ec->curr = NULL;
|
||||
spin_unlock_irqrestore(&ec->lock, tmp);
|
||||
return ret;
|
||||
|
|
|
@ -484,6 +484,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
|||
/* Keep IOAPIC pin configuration when suspending */
|
||||
if (dev->dev.power.is_prepared)
|
||||
return;
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
if (dev->dev.power.runtime_status == RPM_SUSPENDING)
|
||||
return;
|
||||
#endif
|
||||
|
||||
entry = acpi_pci_irq_lookup(dev, pin);
|
||||
if (!entry)
|
||||
|
|
|
@ -922,12 +922,17 @@ static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
|
|||
device->driver->ops.notify(device, event);
|
||||
}
|
||||
|
||||
static acpi_status acpi_device_notify_fixed(void *data)
|
||||
static void acpi_device_notify_fixed(void *data)
|
||||
{
|
||||
struct acpi_device *device = data;
|
||||
|
||||
/* Fixed hardware devices have no handles */
|
||||
acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
|
||||
}
|
||||
|
||||
static acpi_status acpi_device_fixed_event(void *data)
|
||||
{
|
||||
acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
|
@ -938,12 +943,12 @@ static int acpi_device_install_notify_handler(struct acpi_device *device)
|
|||
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
|
||||
status =
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||
acpi_device_notify_fixed,
|
||||
acpi_device_fixed_event,
|
||||
device);
|
||||
else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
|
||||
status =
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||
acpi_device_notify_fixed,
|
||||
acpi_device_fixed_event,
|
||||
device);
|
||||
else
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
|
@ -960,10 +965,10 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device)
|
|||
{
|
||||
if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
|
||||
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||
acpi_device_notify_fixed);
|
||||
acpi_device_fixed_event);
|
||||
else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
|
||||
acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||
acpi_device_notify_fixed);
|
||||
acpi_device_fixed_event);
|
||||
else
|
||||
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
|
||||
acpi_device_notify);
|
||||
|
@ -975,7 +980,7 @@ static int acpi_device_probe(struct device *dev)
|
|||
struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
|
||||
int ret;
|
||||
|
||||
if (acpi_dev->handler)
|
||||
if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (!acpi_drv->ops.add)
|
||||
|
|
|
@ -442,12 +442,15 @@ static int rd_nr;
|
|||
int rd_size = CONFIG_BLK_DEV_RAM_SIZE;
|
||||
static int max_part;
|
||||
static int part_shift;
|
||||
static int part_show = 0;
|
||||
module_param(rd_nr, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
|
||||
module_param(rd_size, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
|
||||
module_param(max_part, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk");
|
||||
module_param(part_show, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(part_show, "Control RAM disk visibility in /proc/partitions");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
|
||||
MODULE_ALIAS("rd");
|
||||
|
@ -501,7 +504,8 @@ static struct brd_device *brd_alloc(int i)
|
|||
disk->fops = &brd_fops;
|
||||
disk->private_data = brd;
|
||||
disk->queue = brd->brd_queue;
|
||||
disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
|
||||
if (!part_show)
|
||||
disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
|
||||
sprintf(disk->disk_name, "ram%d", i);
|
||||
set_capacity(disk, rd_size * 2);
|
||||
|
||||
|
|
|
@ -1203,7 +1203,6 @@ static struct platform_driver ace_platform_driver = {
|
|||
.probe = ace_probe,
|
||||
.remove = ace_remove,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "xsysace",
|
||||
.of_match_table = ace_of_match,
|
||||
},
|
||||
|
|
|
@ -378,7 +378,6 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
|
|||
/* Should NEVER happen. Return bio error if it does. */
|
||||
if (unlikely(ret)) {
|
||||
pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
|
||||
atomic64_inc(&zram->stats.failed_reads);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -547,8 +546,6 @@ out:
|
|||
zcomp_strm_release(zram->comp, zstrm);
|
||||
if (is_partial_io(bvec))
|
||||
kfree(uncmem);
|
||||
if (ret)
|
||||
atomic64_inc(&zram->stats.failed_writes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -566,6 +563,13 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
|
|||
ret = zram_bvec_write(zram, bvec, index, offset);
|
||||
}
|
||||
|
||||
if (unlikely(ret)) {
|
||||
if (rw == READ)
|
||||
atomic64_inc(&zram->stats.failed_reads);
|
||||
else
|
||||
atomic64_inc(&zram->stats.failed_writes);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ struct zram_stats {
|
|||
atomic64_t compr_data_size; /* compressed size of pages stored */
|
||||
atomic64_t num_reads; /* failed + successful */
|
||||
atomic64_t num_writes; /* --do-- */
|
||||
atomic64_t failed_reads; /* should NEVER! happen */
|
||||
atomic64_t failed_reads; /* can happen when memory is too low */
|
||||
atomic64_t failed_writes; /* can happen when memory is too low */
|
||||
atomic64_t invalid_io; /* non-page-aligned I/O requests */
|
||||
atomic64_t notify_free; /* no. of swap slot free notifications */
|
||||
|
|
|
@ -660,6 +660,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
|
|||
ICPU(0x3f, core_params),
|
||||
ICPU(0x45, core_params),
|
||||
ICPU(0x46, core_params),
|
||||
ICPU(0x4c, byt_params),
|
||||
ICPU(0x4f, core_params),
|
||||
ICPU(0x56, core_params),
|
||||
{}
|
||||
|
@ -688,7 +689,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
|
|||
|
||||
add_timer_on(&cpu->timer, cpunum);
|
||||
|
||||
pr_info("Intel pstate controlling: cpu %d\n", cpunum);
|
||||
pr_debug("Intel pstate controlling: cpu %d\n", cpunum);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -501,7 +501,7 @@ static int check_mem_type(void __iomem *dmc_reg)
|
|||
return val >> 8;
|
||||
}
|
||||
|
||||
static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
|
||||
static int s5pv210_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
unsigned long mem_type;
|
||||
int ret;
|
||||
|
|
|
@ -138,25 +138,18 @@ static int bl_enter_powerdown(struct cpuidle_device *dev,
|
|||
return idx;
|
||||
}
|
||||
|
||||
static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
|
||||
static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id)
|
||||
{
|
||||
struct cpuinfo_arm *cpu_info;
|
||||
struct cpumask *cpumask;
|
||||
unsigned long cpuid;
|
||||
int cpu;
|
||||
|
||||
cpumask = kzalloc(cpumask_size(), GFP_KERNEL);
|
||||
if (!cpumask)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
cpu_info = &per_cpu(cpu_data, cpu);
|
||||
cpuid = is_smp() ? cpu_info->cpuid : read_cpuid_id();
|
||||
|
||||
/* read cpu id part number */
|
||||
if ((cpuid & 0xFFF0) == cpu_id)
|
||||
for_each_possible_cpu(cpu)
|
||||
if (smp_cpuid_part(cpu) == part_id)
|
||||
cpumask_set_cpu(cpu, cpumask);
|
||||
}
|
||||
|
||||
drv->cpumask = cpumask;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue