mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 22:14:04 +02:00
Merge tag 'lsk-v3.10-15.05-android' into develop-3.10
This commit is contained in:
commit
3ca9efa2f8
|
|
@ -42,15 +42,48 @@ Description:
|
|||
The invalid_io file is read-only and specifies the number of
|
||||
non-page-size-aligned I/O requests issued to this device.
|
||||
|
||||
What: /sys/block/zram<id>/failed_reads
|
||||
Date: February 2014
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The failed_reads file is read-only and specifies the number of
|
||||
failed reads happened on this device.
|
||||
|
||||
What: /sys/block/zram<id>/failed_writes
|
||||
Date: February 2014
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The failed_writes file is read-only and specifies the number of
|
||||
failed writes happened on this device.
|
||||
|
||||
What: /sys/block/zram<id>/max_comp_streams
|
||||
Date: February 2014
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The max_comp_streams file is read-write and specifies the
|
||||
number of backend's zcomp_strm compression streams (number of
|
||||
concurrent compress operations).
|
||||
|
||||
What: /sys/block/zram<id>/comp_algorithm
|
||||
Date: February 2014
|
||||
Contact: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
|
||||
Description:
|
||||
The comp_algorithm file is read-write and lets to show
|
||||
available and selected compression algorithms, change
|
||||
compression algorithm selection.
|
||||
|
||||
What: /sys/block/zram<id>/notify_free
|
||||
Date: August 2010
|
||||
Contact: Nitin Gupta <ngupta@vflare.org>
|
||||
Description:
|
||||
The notify_free file is read-only and specifies the number of
|
||||
swap slot free notifications received by this device. These
|
||||
notifications are send to a swap block device when a swap slot
|
||||
is freed. This statistic is applicable only when this disk is
|
||||
being used as a swap disk.
|
||||
The notify_free file is read-only. Depending on device usage
|
||||
scenario it may account a) the number of pages freed because
|
||||
of swap slot free notifications or b) the number of pages freed
|
||||
because of REQ_DISCARD requests sent by bio. The former ones
|
||||
are sent to a swap block device when a swap slot is freed, which
|
||||
implies that this disk is being used as a swap disk. The latter
|
||||
ones are sent by filesystem mounted with discard option,
|
||||
whenever some data blocks are getting discarded.
|
||||
|
||||
What: /sys/block/zram<id>/discard
|
||||
Date: August 2010
|
||||
|
|
@ -97,3 +130,22 @@ Description:
|
|||
efficiency can be calculated using compr_data_size and this
|
||||
statistic.
|
||||
Unit: bytes
|
||||
|
||||
What: /sys/block/zram<id>/mem_used_max
|
||||
Date: August 2014
|
||||
Contact: Minchan Kim <minchan@kernel.org>
|
||||
Description:
|
||||
The mem_used_max file is read/write and specifies the amount
|
||||
of maximum memory zram have consumed to store compressed data.
|
||||
For resetting the value, you should write "0". Otherwise,
|
||||
you could see -EINVAL.
|
||||
Unit: bytes
|
||||
|
||||
What: /sys/block/zram<id>/mem_limit
|
||||
Date: August 2014
|
||||
Contact: Minchan Kim <minchan@kernel.org>
|
||||
Description:
|
||||
The mem_limit file is read/write and specifies the maximum
|
||||
amount of memory ZRAM can use to store the compressed data. The
|
||||
limit could be changed in run time and "0" means disable the
|
||||
limit. No limit is the initial state. Unit: bytes
|
||||
|
|
|
|||
129
Documentation/blockdev/zram.txt
Normal file
129
Documentation/blockdev/zram.txt
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
zram: Compressed RAM based block devices
|
||||
----------------------------------------
|
||||
|
||||
* Introduction
|
||||
|
||||
The zram module creates RAM based block devices named /dev/zram<id>
|
||||
(<id> = 0, 1, ...). Pages written to these disks are compressed and stored
|
||||
in memory itself. These disks allow very fast I/O and compression provides
|
||||
good amounts of memory savings. Some of the usecases include /tmp storage,
|
||||
use as swap disks, various caches under /var and maybe many more :)
|
||||
|
||||
Statistics for individual zram devices are exported through sysfs nodes at
|
||||
/sys/block/zram<id>/
|
||||
|
||||
* Usage
|
||||
|
||||
Following shows a typical sequence of steps for using zram.
|
||||
|
||||
1) Load Module:
|
||||
modprobe zram num_devices=4
|
||||
This creates 4 devices: /dev/zram{0,1,2,3}
|
||||
(num_devices parameter is optional. Default: 1)
|
||||
|
||||
2) Set max number of compression streams
|
||||
Compression backend may use up to max_comp_streams compression streams,
|
||||
thus allowing up to max_comp_streams concurrent compression operations.
|
||||
By default, compression backend uses single compression stream.
|
||||
|
||||
Examples:
|
||||
#show max compression streams number
|
||||
cat /sys/block/zram0/max_comp_streams
|
||||
|
||||
#set max compression streams number to 3
|
||||
echo 3 > /sys/block/zram0/max_comp_streams
|
||||
|
||||
Note:
|
||||
In order to enable compression backend's multi stream support max_comp_streams
|
||||
must be initially set to desired concurrency level before ZRAM device
|
||||
initialisation. Once the device initialised as a single stream compression
|
||||
backend (max_comp_streams equals to 1), you will see error if you try to change
|
||||
the value of max_comp_streams because single stream compression backend
|
||||
implemented as a special case by lock overhead issue and does not support
|
||||
dynamic max_comp_streams. Only multi stream backend supports dynamic
|
||||
max_comp_streams adjustment.
|
||||
|
||||
3) Select compression algorithm
|
||||
Using comp_algorithm device attribute one can see available and
|
||||
currently selected (shown in square brackets) compression algortithms,
|
||||
change selected compression algorithm (once the device is initialised
|
||||
there is no way to change compression algorithm).
|
||||
|
||||
Examples:
|
||||
#show supported compression algorithms
|
||||
cat /sys/block/zram0/comp_algorithm
|
||||
lzo [lz4]
|
||||
|
||||
#select lzo compression algorithm
|
||||
echo lzo > /sys/block/zram0/comp_algorithm
|
||||
|
||||
4) Set Disksize
|
||||
Set disk size by writing the value to sysfs node 'disksize'.
|
||||
The value can be either in bytes or you can use mem suffixes.
|
||||
Examples:
|
||||
# Initialize /dev/zram0 with 50MB disksize
|
||||
echo $((50*1024*1024)) > /sys/block/zram0/disksize
|
||||
|
||||
# Using mem suffixes
|
||||
echo 256K > /sys/block/zram0/disksize
|
||||
echo 512M > /sys/block/zram0/disksize
|
||||
echo 1G > /sys/block/zram0/disksize
|
||||
|
||||
Note:
|
||||
There is little point creating a zram of greater than twice the size of memory
|
||||
since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the
|
||||
size of the disk when not in use so a huge zram is wasteful.
|
||||
|
||||
5) Set memory limit: Optional
|
||||
Set memory limit by writing the value to sysfs node 'mem_limit'.
|
||||
The value can be either in bytes or you can use mem suffixes.
|
||||
In addition, you could change the value in runtime.
|
||||
Examples:
|
||||
# limit /dev/zram0 with 50MB memory
|
||||
echo $((50*1024*1024)) > /sys/block/zram0/mem_limit
|
||||
|
||||
# Using mem suffixes
|
||||
echo 256K > /sys/block/zram0/mem_limit
|
||||
echo 512M > /sys/block/zram0/mem_limit
|
||||
echo 1G > /sys/block/zram0/mem_limit
|
||||
|
||||
# To disable memory limit
|
||||
echo 0 > /sys/block/zram0/mem_limit
|
||||
|
||||
6) Activate:
|
||||
mkswap /dev/zram0
|
||||
swapon /dev/zram0
|
||||
|
||||
mkfs.ext4 /dev/zram1
|
||||
mount /dev/zram1 /tmp
|
||||
|
||||
7) Stats:
|
||||
Per-device statistics are exported as various nodes under
|
||||
/sys/block/zram<id>/
|
||||
disksize
|
||||
num_reads
|
||||
num_writes
|
||||
invalid_io
|
||||
notify_free
|
||||
discard
|
||||
zero_pages
|
||||
orig_data_size
|
||||
compr_data_size
|
||||
mem_used_total
|
||||
mem_used_max
|
||||
|
||||
8) Deactivate:
|
||||
swapoff /dev/zram0
|
||||
umount /dev/zram1
|
||||
|
||||
9) Reset:
|
||||
Write any positive value to 'reset' sysfs node
|
||||
echo 1 > /sys/block/zram0/reset
|
||||
echo 1 > /sys/block/zram1/reset
|
||||
|
||||
This frees all the memory allocated for the given device and
|
||||
resets the disksize to zero. You must set the disksize again
|
||||
before reusing the device.
|
||||
|
||||
Nitin Gupta
|
||||
ngupta@vflare.org
|
||||
|
|
@ -38,7 +38,7 @@ dma_apbx: dma-apbx@80024000 {
|
|||
80 81 68 69
|
||||
70 71 72 73
|
||||
74 75 76 77>;
|
||||
interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
|
||||
interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
|
||||
"saif0", "saif1", "i2c0", "i2c1",
|
||||
"auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
|
||||
"auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -1,6 +1,6 @@
|
|||
VERSION = 3
|
||||
PATCHLEVEL = 10
|
||||
SUBLEVEL = 74
|
||||
SUBLEVEL = 79
|
||||
EXTRAVERSION =
|
||||
NAME = TOSSUG Baby Fish
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ CONFIG_ANDROID_BINDER_IPC=y
|
|||
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
|
||||
CONFIG_ARMV7_COMPAT=y
|
||||
CONFIG_ASHMEM=y
|
||||
CONFIG_AUDIT=y
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_CGROUPS=y
|
||||
|
|
@ -51,6 +52,7 @@ CONFIG_IP_NF_MATCH_AH=y
|
|||
CONFIG_IP_NF_MATCH_ECN=y
|
||||
CONFIG_IP_NF_MATCH_TTL=y
|
||||
CONFIG_IP_NF_RAW=y
|
||||
CONFIG_IP_NF_SECURITY=y
|
||||
CONFIG_IP_NF_TARGET_MASQUERADE=y
|
||||
CONFIG_IP_NF_TARGET_NETMAP=y
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=y
|
||||
|
|
@ -85,10 +87,12 @@ CONFIG_NETFILTER_XT_MATCH_TIME=y
|
|||
CONFIG_NETFILTER_XT_MATCH_U32=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=y
|
||||
|
|
@ -110,6 +114,7 @@ CONFIG_NF_CONNTRACK_IRC=y
|
|||
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
|
||||
CONFIG_NF_CONNTRACK_PPTP=y
|
||||
CONFIG_NF_CONNTRACK_SANE=y
|
||||
CONFIG_NF_CONNTRACK_SECMARK=y
|
||||
CONFIG_NF_CONNTRACK_TFTP=y
|
||||
CONFIG_NF_CT_NETLINK=y
|
||||
CONFIG_NF_CT_PROTO_DCCP=y
|
||||
|
|
@ -130,6 +135,11 @@ CONFIG_PREEMPT=y
|
|||
CONFIG_RESOURCE_COUNTERS=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RT_GROUP_SCHED=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
CONFIG_SND=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_SWITCH=y
|
||||
CONFIG_SYNC=y
|
||||
|
|
|
|||
|
|
@ -156,6 +156,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -131,6 +131,15 @@ SYSCALL_DEFINE0(rt_sigreturn)
|
|||
/* Don't restart from sigreturn */
|
||||
syscall_wont_restart(regs);
|
||||
|
||||
/*
|
||||
* Ensure that sigreturn always returns to user mode (in case the
|
||||
* regs saved on user stack got fudged between save and sigreturn)
|
||||
* Otherwise it is easy to panic the kernel with a custom
|
||||
* signal handler and/or restorer which clobberes the status32/ret
|
||||
* to return to a bogus location in kernel mode.
|
||||
*/
|
||||
regs->status32 |= STATUS_U_MASK;
|
||||
|
||||
return regs->r0;
|
||||
|
||||
badframe:
|
||||
|
|
@ -234,8 +243,11 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
|
|||
|
||||
/*
|
||||
* handler returns using sigreturn stub provided already by userpsace
|
||||
* If not, nuke the process right away
|
||||
*/
|
||||
BUG_ON(!(ka->sa.sa_flags & SA_RESTORER));
|
||||
if(!(ka->sa.sa_flags & SA_RESTORER))
|
||||
return 1;
|
||||
|
||||
regs->blink = (unsigned long)ka->sa.sa_restorer;
|
||||
|
||||
/* User Stack for signal handler will be above the frame just carved */
|
||||
|
|
@ -302,12 +314,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
int failed;
|
||||
|
||||
/* Set up the stack frame */
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
failed = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
|
||||
if (ret)
|
||||
if (failed)
|
||||
force_sigsegv(sig, current);
|
||||
else
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
|
|
|
|||
|
|
@ -160,6 +160,8 @@ void do_page_fault(struct pt_regs *regs, int write, unsigned long address,
|
|||
/* TBD: switch to pagefault_out_of_memory() */
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ soc {
|
|||
0xf0000000 0 0xf0000000 0x8000000 /* Device Bus, NOR 128MiB */>;
|
||||
|
||||
internal-regs {
|
||||
rtc@10300 {
|
||||
/* No crystal connected to the internal RTC */
|
||||
status = "disabled";
|
||||
};
|
||||
serial@12000 {
|
||||
clock-frequency = <250000000>;
|
||||
status = "okay";
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ uart1: serial@12100 {
|
|||
|
||||
uart2: serial@12200 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x12000 0x100>;
|
||||
reg = <0x12200 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <9>;
|
||||
clocks = <&core_clk 0>;
|
||||
|
|
@ -84,7 +84,7 @@ uart2: serial@12200 {
|
|||
|
||||
uart3: serial@12300 {
|
||||
compatible = "ns16550a";
|
||||
reg = <0x12100 0x100>;
|
||||
reg = <0x12300 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <10>;
|
||||
clocks = <&core_clk 0>;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,11 @@ timer {
|
|||
<1 14 0xf08>,
|
||||
<1 11 0xf08>,
|
||||
<1 10 0xf08>;
|
||||
/* Unfortunately we need this since some versions of U-Boot
|
||||
* on Exynos don't set the CNTFRQ register, so we need the
|
||||
* value from DT.
|
||||
*/
|
||||
clock-frequency = <24000000>;
|
||||
};
|
||||
|
||||
combiner:interrupt-controller@10440000 {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ usbphy0: usbphy@8007c000 {
|
|||
|
||||
ahb@80080000 {
|
||||
usb0: usb@80080000 {
|
||||
dr_mode = "host";
|
||||
vbus-supply = <®_usb0_vbus>;
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -393,6 +393,7 @@ slcdc@53fc0000 {
|
|||
|
||||
pwm4: pwm@53fc8000 {
|
||||
compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
|
||||
#pwm-cells = <2>;
|
||||
reg = <0x53fc8000 0x4000>;
|
||||
clocks = <&clks 108>, <&clks 52>;
|
||||
clock-names = "ipg", "per";
|
||||
|
|
|
|||
|
|
@ -691,7 +691,7 @@ dma_apbx: dma-apbx@80024000 {
|
|||
80 81 68 69
|
||||
70 71 72 73
|
||||
74 75 76 77>;
|
||||
interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
|
||||
interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
|
||||
"saif0", "saif1", "i2c0", "i2c1",
|
||||
"auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
|
||||
"auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
|
|||
the loader. We need to make sure that it is out of the way of the program
|
||||
that it will "exec", and that there is sufficient room for the brk. */
|
||||
|
||||
#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
|
||||
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
|
||||
|
||||
/* When the program starts, a1 contains a pointer to a function to be
|
||||
registered with atexit, as per the SVR4 ABI. A value of 0 means we
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/gpio.h>
|
||||
|
||||
#define GLENFARCLAS_PMIC_IRQ_BASE IRQ_BOARD_START
|
||||
#define BANFF_PMIC_IRQ_BASE (IRQ_BOARD_START + 64)
|
||||
|
||||
#define PCA935X_GPIO_BASE GPIO_BOARD_START
|
||||
#define CODEC_GPIO_BASE (GPIO_BOARD_START + 8)
|
||||
|
|
|
|||
|
|
@ -558,6 +558,7 @@ static struct wm831x_touch_pdata touch_pdata = {
|
|||
|
||||
static struct wm831x_pdata crag_pmic_pdata = {
|
||||
.wm831x_num = 1,
|
||||
.irq_base = BANFF_PMIC_IRQ_BASE,
|
||||
.gpio_base = BANFF_PMIC_GPIO_BASE,
|
||||
.soft_shutdown = true,
|
||||
|
||||
|
|
|
|||
|
|
@ -168,6 +168,32 @@ endmenu
|
|||
|
||||
menu "Kernel Features"
|
||||
|
||||
menu "ARM errata workarounds"
|
||||
|
||||
config ARM64_ERRATUM_845719
|
||||
bool "Cortex-A53: 845719: a load might read incorrect data"
|
||||
depends on COMPAT
|
||||
default n
|
||||
help
|
||||
This option adds an alternative code sequence to work around ARM
|
||||
erratum 845719 on Cortex-A53 parts up to r0p4.
|
||||
|
||||
When running a compat (AArch32) userspace on an affected Cortex-A53
|
||||
part, a load at EL0 from a virtual address that matches the bottom 32
|
||||
bits of the virtual address used by a recent load at (AArch64) EL1
|
||||
might return incorrect data.
|
||||
|
||||
The workaround is to write the contextidr_el1 register on exception
|
||||
return to a 32-bit task.
|
||||
Please note that this does not necessarily enable the workaround,
|
||||
as it depends on the alternative framework, which will only patch
|
||||
the kernel if an affected CPU is detected.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
config ARM64_64K_PAGES
|
||||
bool "Enable 64KB pages support"
|
||||
help
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ CFLAGS_REMOVE_return_address.o = -pg
|
|||
arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \
|
||||
entry-fpsimd.o process.o ptrace.o setup.o signal.o \
|
||||
sys.o stacktrace.o time.o traps.o io.o vdso.o \
|
||||
hyp-stub.o psci.o cpu_ops.o insn.o return_address.o \
|
||||
hyp-stub.o psci.o psci-call.o cpu_ops.o insn.o return_address.o \
|
||||
opcodes.o
|
||||
|
||||
arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
|
||||
|
|
|
|||
|
|
@ -89,6 +89,17 @@
|
|||
ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
|
||||
.if \el == 0
|
||||
ldr x23, [sp, #S_SP] // load return stack pointer
|
||||
#ifdef CONFIG_ARM64_ERRATUM_845719
|
||||
tbz x22, #4, 1f
|
||||
#ifdef CONFIG_PID_IN_CONTEXTIDR
|
||||
mrs x29, contextidr_el1
|
||||
msr contextidr_el1, x29
|
||||
1:
|
||||
#else
|
||||
msr contextidr_el1, xzr
|
||||
1:
|
||||
#endif
|
||||
#endif
|
||||
.endif
|
||||
.if \ret
|
||||
ldr x1, [sp, #S_X1] // preserve x0 (syscall return)
|
||||
|
|
|
|||
28
arch/arm64/kernel/psci-call.S
Normal file
28
arch/arm64/kernel/psci-call.S
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Copyright (C) 2015 ARM Limited
|
||||
*
|
||||
* Author: Will Deacon <will.deacon@arm.com>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/* int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) */
|
||||
ENTRY(__invoke_psci_fn_hvc)
|
||||
hvc #0
|
||||
ret
|
||||
ENDPROC(__invoke_psci_fn_hvc)
|
||||
|
||||
/* int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1, u64 arg2) */
|
||||
ENTRY(__invoke_psci_fn_smc)
|
||||
smc #0
|
||||
ret
|
||||
ENDPROC(__invoke_psci_fn_smc)
|
||||
|
|
@ -59,6 +59,9 @@ static struct psci_operations psci_ops;
|
|||
static int (*invoke_psci_fn)(u64, u64, u64, u64);
|
||||
typedef int (*psci_initcall_t)(const struct device_node *);
|
||||
|
||||
asmlinkage int __invoke_psci_fn_hvc(u64, u64, u64, u64);
|
||||
asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64);
|
||||
|
||||
enum psci_function {
|
||||
PSCI_FN_CPU_SUSPEND,
|
||||
PSCI_FN_CPU_ON,
|
||||
|
|
@ -111,40 +114,6 @@ static void psci_power_state_unpack(u32 power_state,
|
|||
PSCI_0_2_POWER_STATE_AFFL_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following two functions are invoked via the invoke_psci_fn pointer
|
||||
* and will not be inlined, allowing us to piggyback on the AAPCS.
|
||||
*/
|
||||
static noinline int __invoke_psci_fn_hvc(u64 function_id, u64 arg0, u64 arg1,
|
||||
u64 arg2)
|
||||
{
|
||||
asm volatile(
|
||||
__asmeq("%0", "x0")
|
||||
__asmeq("%1", "x1")
|
||||
__asmeq("%2", "x2")
|
||||
__asmeq("%3", "x3")
|
||||
"hvc #0\n"
|
||||
: "+r" (function_id)
|
||||
: "r" (arg0), "r" (arg1), "r" (arg2));
|
||||
|
||||
return function_id;
|
||||
}
|
||||
|
||||
static noinline int __invoke_psci_fn_smc(u64 function_id, u64 arg0, u64 arg1,
|
||||
u64 arg2)
|
||||
{
|
||||
asm volatile(
|
||||
__asmeq("%0", "x0")
|
||||
__asmeq("%1", "x1")
|
||||
__asmeq("%2", "x2")
|
||||
__asmeq("%3", "x3")
|
||||
"smc #0\n"
|
||||
: "+r" (function_id)
|
||||
: "r" (arg0), "r" (arg1), "r" (arg2));
|
||||
|
||||
return function_id;
|
||||
}
|
||||
|
||||
static int psci_get_version(void)
|
||||
{
|
||||
int err;
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ u64 sched_clock(void)
|
|||
return (tsc * sched_clock_multiplier) >> SCHED_CLOCK_SHIFT;
|
||||
}
|
||||
|
||||
void time_init(void)
|
||||
void __init time_init(void)
|
||||
{
|
||||
u64 tmp = (u64)NSEC_PER_SEC << SCHED_CLOCK_SHIFT;
|
||||
|
||||
|
|
|
|||
|
|
@ -176,6 +176,8 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -172,6 +172,8 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
|
|||
*/
|
||||
if (fault & VM_FAULT_OOM) {
|
||||
goto out_of_memory;
|
||||
} else if (fault & VM_FAULT_SIGSEGV) {
|
||||
goto bad_area;
|
||||
} else if (fault & VM_FAULT_SIGBUS) {
|
||||
signal = SIGBUS;
|
||||
goto bad_area;
|
||||
|
|
|
|||
|
|
@ -200,6 +200,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -153,6 +153,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto map_err;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto bus_err;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -141,6 +141,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -224,6 +224,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef __ASM_SUSPEND_H
|
||||
#define __ASM_SUSPEND_H
|
||||
|
||||
/* References to section boundaries */
|
||||
extern const void __nosave_begin, __nosave_end;
|
||||
|
||||
#endif /* __ASM_SUSPEND_H */
|
||||
|
|
@ -157,6 +157,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Author: Hu Hongbing <huhb@lemote.com>
|
||||
* Wu Zhangjin <wuzhangjin@gmail.com>
|
||||
*/
|
||||
#include <asm/suspend.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/dsp.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ LEAF(swsusp_arch_suspend)
|
|||
END(swsusp_arch_suspend)
|
||||
|
||||
LEAF(swsusp_arch_resume)
|
||||
/* Avoid TLB mismatch during and after kernel resume */
|
||||
jal local_flush_tlb_all
|
||||
PTR_L t0, restore_pblist
|
||||
0:
|
||||
PTR_L t1, PBE_ADDRESS(t0) /* source */
|
||||
|
|
@ -43,7 +45,6 @@ LEAF(swsusp_arch_resume)
|
|||
bne t1, t3, 1b
|
||||
PTR_L t0, PBE_NEXT(t0)
|
||||
bnez t0, 0b
|
||||
jal local_flush_tlb_all /* Avoid TLB mismatch after kernel resume */
|
||||
PTR_LA t0, saved_regs
|
||||
PTR_L ra, PT_R31(t0)
|
||||
PTR_L sp, PT_R29(t0)
|
||||
|
|
|
|||
|
|
@ -262,6 +262,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -171,6 +171,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -220,6 +220,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
|
|||
*/
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto bad_area;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@
|
|||
|
||||
#include <linux/mm.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
/* References to section boundaries */
|
||||
extern const void __nosave_begin, __nosave_end;
|
||||
#include <asm/sections.h>
|
||||
|
||||
/*
|
||||
* pfn_is_nosave - check if given pfn is in the 'nosave' section
|
||||
|
|
|
|||
|
|
@ -425,6 +425,8 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
*/
|
||||
fault = handle_mm_fault(mm, vma, address, flags);
|
||||
if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
|
||||
if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
rc = mm_fault_error(regs, address, fault);
|
||||
if (rc >= MM_FAULT_RETURN)
|
||||
goto bail;
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
|
|||
sp = regs->gpr[1];
|
||||
perf_callchain_store(entry, next_ip);
|
||||
|
||||
for (;;) {
|
||||
while (entry->nr < PERF_MAX_STACK_DEPTH) {
|
||||
fp = (unsigned long __user *) sp;
|
||||
if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
|
|||
if (*flt & VM_FAULT_OOM) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unlock;
|
||||
} else if (*flt & VM_FAULT_SIGBUS) {
|
||||
} else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) {
|
||||
ret = -EFAULT;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ static void spufs_prune_dir(struct dentry *dir)
|
|||
struct dentry *dentry, *tmp;
|
||||
|
||||
mutex_lock(&dir->d_inode->i_mutex);
|
||||
list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
|
||||
list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
|
||||
spin_lock(&dentry->d_lock);
|
||||
if (!(d_unhashed(dentry)) && dentry->d_inode) {
|
||||
dget_dlock(dentry);
|
||||
|
|
|
|||
|
|
@ -9,12 +9,9 @@
|
|||
#include <linux/pfn.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/ctl_reg.h>
|
||||
|
||||
/*
|
||||
* References to section boundaries
|
||||
*/
|
||||
extern const void __nosave_begin, __nosave_end;
|
||||
#include <asm/ipl.h>
|
||||
|
||||
/*
|
||||
* The restore of the saved pages in an hibernation image will set
|
||||
|
|
@ -138,6 +135,8 @@ int pfn_is_nosave(unsigned long pfn)
|
|||
{
|
||||
unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin));
|
||||
unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end));
|
||||
unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1;
|
||||
unsigned long stext_pfn = PFN_DOWN(__pa(&_stext));
|
||||
|
||||
/* Always save lowcore pages (LC protection might be enabled). */
|
||||
if (pfn <= LC_PAGES)
|
||||
|
|
@ -145,6 +144,8 @@ int pfn_is_nosave(unsigned long pfn)
|
|||
if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn)
|
||||
return 1;
|
||||
/* Skip memory holes and read-only pages (NSS, DCSS, ...). */
|
||||
if (pfn >= stext_pfn && pfn <= eshared_pfn)
|
||||
return ipl_info.type == IPL_TYPE_NSS ? 1 : 0;
|
||||
if (tprot(PFN_PHYS(pfn)))
|
||||
return 1;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -328,6 +328,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
|
|||
for (n = mem->count - 1; n > 0 ; n--)
|
||||
memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0]));
|
||||
|
||||
memset(&mem->vm[0], 0, sizeof(mem->vm[0]));
|
||||
mem->vm[0].cpus_total = cpus;
|
||||
mem->vm[0].cpus_configured = cpus;
|
||||
mem->vm[0].cpus_standby = 0;
|
||||
|
|
|
|||
|
|
@ -244,6 +244,12 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
|
|||
do_no_context(regs);
|
||||
else
|
||||
pagefault_out_of_memory();
|
||||
} else if (fault & VM_FAULT_SIGSEGV) {
|
||||
/* Kernel mode? Handle exceptions or die */
|
||||
if (!user_mode(regs))
|
||||
do_no_context(regs);
|
||||
else
|
||||
do_sigsegv(regs, SEGV_MAPERR);
|
||||
} else if (fault & VM_FAULT_SIGBUS) {
|
||||
/* Kernel mode? Handle exceptions or die */
|
||||
if (!user_mode(regs))
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <asm-generic/sections.h>
|
||||
|
||||
extern long __nosave_begin, __nosave_end;
|
||||
extern long __machvec_start, __machvec_end;
|
||||
extern char __uncached_start, __uncached_end;
|
||||
extern char __start_eh_frame[], __stop_eh_frame[];
|
||||
|
|
|
|||
|
|
@ -353,6 +353,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
|||
} else {
|
||||
if (fault & VM_FAULT_SIGBUS)
|
||||
do_sigbus(regs, error_code, address);
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
bad_area(regs, error_code, address);
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -443,6 +443,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -9,11 +9,9 @@
|
|||
#include <asm/hibernate.h>
|
||||
#include <asm/visasm.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/tlb.h>
|
||||
|
||||
/* References to section boundaries */
|
||||
extern const void __nosave_begin, __nosave_end;
|
||||
|
||||
struct saved_context saved_context;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -446,6 +446,8 @@ static int handle_page_fault(struct pt_regs *regs,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ int handle_page_fault(unsigned long address, unsigned long ip,
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM) {
|
||||
goto out_of_memory;
|
||||
} else if (fault & VM_FAULT_SIGSEGV) {
|
||||
goto out;
|
||||
} else if (fault & VM_FAULT_SIGBUS) {
|
||||
err = -EACCES;
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -36,8 +36,5 @@ extern int puv3_pm_enter(suspend_state_t state);
|
|||
/* Defined in hibernate_asm.S */
|
||||
extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist);
|
||||
|
||||
/* References to section boundaries */
|
||||
extern const void __nosave_begin, __nosave_end;
|
||||
|
||||
extern struct pbe *restore_pblist;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#include "mach/pm.h"
|
||||
|
|
|
|||
|
|
@ -2450,7 +2450,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
|
|||
* Not recognized on AMD in compat mode (but is recognized in legacy
|
||||
* mode).
|
||||
*/
|
||||
if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
|
||||
if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA)
|
||||
&& !vendor_intel(ctxt))
|
||||
return emulate_ud(ctxt);
|
||||
|
||||
|
|
@ -2463,25 +2463,13 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
|
|||
setup_syscalls_segments(ctxt, &cs, &ss);
|
||||
|
||||
ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
|
||||
switch (ctxt->mode) {
|
||||
case X86EMUL_MODE_PROT32:
|
||||
if ((msr_data & 0xfffc) == 0x0)
|
||||
return emulate_gp(ctxt, 0);
|
||||
break;
|
||||
case X86EMUL_MODE_PROT64:
|
||||
if (msr_data == 0x0)
|
||||
return emulate_gp(ctxt, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ((msr_data & 0xfffc) == 0x0)
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
|
||||
cs_sel = (u16)msr_data;
|
||||
cs_sel &= ~SELECTOR_RPL_MASK;
|
||||
cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK;
|
||||
ss_sel = cs_sel + 8;
|
||||
ss_sel &= ~SELECTOR_RPL_MASK;
|
||||
if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) {
|
||||
if (efer & EFER_LMA) {
|
||||
cs.d = 0;
|
||||
cs.l = 1;
|
||||
}
|
||||
|
|
@ -2490,10 +2478,11 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
|
|||
ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
|
||||
|
||||
ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data);
|
||||
ctxt->_eip = msr_data;
|
||||
ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data;
|
||||
|
||||
ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
|
||||
*reg_write(ctxt, VCPU_REGS_RSP) = msr_data;
|
||||
*reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data :
|
||||
(u32)msr_data;
|
||||
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -812,11 +812,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
|
|||
unsigned int fault)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
int code = BUS_ADRERR;
|
||||
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
/* Kernel mode? Handle exceptions or die: */
|
||||
if (!(error_code & PF_USER)) {
|
||||
no_context(regs, error_code, address, SIGBUS, BUS_ADRERR);
|
||||
|
|
@ -847,7 +844,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
|||
unsigned long address, unsigned int fault)
|
||||
{
|
||||
if (fatal_signal_pending(current) && !(error_code & PF_USER)) {
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
no_context(regs, error_code, address, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
|
@ -855,14 +851,11 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
|||
if (fault & VM_FAULT_OOM) {
|
||||
/* Kernel mode? Handle exceptions or die: */
|
||||
if (!(error_code & PF_USER)) {
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
no_context(regs, error_code, address,
|
||||
SIGSEGV, SEGV_MAPERR);
|
||||
return;
|
||||
}
|
||||
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
||||
/*
|
||||
* We ran out of memory, call the OOM killer, and return the
|
||||
* userspace (which will retry the fault, or kill us if we got
|
||||
|
|
@ -873,6 +866,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
|||
if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
|
||||
VM_FAULT_HWPOISON_LARGE))
|
||||
do_sigbus(regs, error_code, address, fault);
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
bad_area_nosemaphore(regs, error_code, address);
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
|
@ -1193,6 +1188,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|||
return;
|
||||
|
||||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
up_read(&mm->mmap_sem);
|
||||
mm_fault_error(regs, error_code, address, fault);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,11 @@
|
|||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mmzone.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
/* Defined in hibernate_asm_32.S */
|
||||
extern int restore_image(void);
|
||||
|
||||
/* References to section boundaries */
|
||||
extern const void __nosave_begin, __nosave_end;
|
||||
|
||||
/* Pointer to the temporary resume page tables */
|
||||
pgd_t *resume_pg_dir;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@
|
|||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
/* References to section boundaries */
|
||||
extern const void __nosave_begin, __nosave_end;
|
||||
|
||||
/* Defined in hibernate_asm_64.S */
|
||||
extern int restore_image(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -287,6 +287,36 @@ menu "Executable file formats"
|
|||
|
||||
source "fs/Kconfig.binfmt"
|
||||
|
||||
config XTFPGA_LCD
|
||||
bool "Enable XTFPGA LCD driver"
|
||||
depends on XTENSA_PLATFORM_XTFPGA
|
||||
default n
|
||||
help
|
||||
There's a 2x16 LCD on most of XTFPGA boards, kernel may output
|
||||
progress messages there during bootup/shutdown. It may be useful
|
||||
during board bringup.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config XTFPGA_LCD_BASE_ADDR
|
||||
hex "XTFPGA LCD base address"
|
||||
depends on XTFPGA_LCD
|
||||
default "0x0d0c0000"
|
||||
help
|
||||
Base address of the LCD controller inside KIO region.
|
||||
Different boards from XTFPGA family have LCD controller at different
|
||||
addresses. Please consult prototyping user guide for your board for
|
||||
the correct address. Wrong address here may lead to hardware lockup.
|
||||
|
||||
config XTFPGA_LCD_8BIT_ACCESS
|
||||
bool "Use 8-bit access to XTFPGA LCD"
|
||||
depends on XTFPGA_LCD
|
||||
default n
|
||||
help
|
||||
LCD may be connected with 4- or 8-bit interface, 8-bit access may
|
||||
only be used with 8-bit interface. Please consult prototyping user
|
||||
guide for your board for the correct interface width.
|
||||
|
||||
endmenu
|
||||
|
||||
source "net/Kconfig"
|
||||
|
|
|
|||
|
|
@ -715,7 +715,7 @@ __SYSCALL(323, sys_process_vm_writev, 6)
|
|||
__SYSCALL(324, sys_name_to_handle_at, 5)
|
||||
#define __NR_open_by_handle_at 325
|
||||
__SYSCALL(325, sys_open_by_handle_at, 3)
|
||||
#define __NR_sync_file_range 326
|
||||
#define __NR_sync_file_range2 326
|
||||
__SYSCALL(326, sys_sync_file_range2, 6)
|
||||
#define __NR_perf_event_open 327
|
||||
__SYSCALL(327, sys_perf_event_open, 5)
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ void do_page_fault(struct pt_regs *regs)
|
|||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
BUG();
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@
|
|||
#
|
||||
# Note 2! The CFLAGS definitions are in the main makefile...
|
||||
|
||||
obj-y = setup.o lcd.o
|
||||
obj-y += setup.o
|
||||
obj-$(CONFIG_XTFPGA_LCD) += lcd.o
|
||||
|
|
|
|||
|
|
@ -44,9 +44,6 @@
|
|||
|
||||
/* UART */
|
||||
#define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020)
|
||||
/* LCD instruction and data addresses. */
|
||||
#define LCD_INSTR_ADDR ((char *)IOADDR(0x0D040000))
|
||||
#define LCD_DATA_ADDR ((char *)IOADDR(0x0D040004))
|
||||
|
||||
/* Misc. */
|
||||
#define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000)
|
||||
|
|
|
|||
|
|
@ -11,10 +11,25 @@
|
|||
#ifndef __XTENSA_XTAVNET_LCD_H
|
||||
#define __XTENSA_XTAVNET_LCD_H
|
||||
|
||||
#ifdef CONFIG_XTFPGA_LCD
|
||||
/* Display string STR at position POS on the LCD. */
|
||||
void lcd_disp_at_pos(char *str, unsigned char pos);
|
||||
|
||||
/* Shift the contents of the LCD display left or right. */
|
||||
void lcd_shiftleft(void);
|
||||
void lcd_shiftright(void);
|
||||
#else
|
||||
static inline void lcd_disp_at_pos(char *str, unsigned char pos)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void lcd_shiftleft(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void lcd_shiftright(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,50 +1,63 @@
|
|||
/*
|
||||
* Driver for the LCD display on the Tensilica LX60 Board.
|
||||
* Driver for the LCD display on the Tensilica XTFPGA board family.
|
||||
* http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*
|
||||
* Copyright (C) 2001, 2006 Tensilica Inc.
|
||||
* Copyright (C) 2015 Cadence Design Systems Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* FIXME: this code is from the examples from the LX60 user guide.
|
||||
*
|
||||
* The lcd_pause function does busy waiting, which is probably not
|
||||
* great. Maybe the code could be changed to use kernel timers, or
|
||||
* change the hardware to not need to wait.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <platform/hardware.h>
|
||||
#include <platform/lcd.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define LCD_PAUSE_ITERATIONS 4000
|
||||
/* LCD instruction and data addresses. */
|
||||
#define LCD_INSTR_ADDR ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR))
|
||||
#define LCD_DATA_ADDR (LCD_INSTR_ADDR + 4)
|
||||
|
||||
#define LCD_CLEAR 0x1
|
||||
#define LCD_DISPLAY_ON 0xc
|
||||
|
||||
/* 8bit and 2 lines display */
|
||||
#define LCD_DISPLAY_MODE8BIT 0x38
|
||||
#define LCD_DISPLAY_MODE4BIT 0x28
|
||||
#define LCD_DISPLAY_POS 0x80
|
||||
#define LCD_SHIFT_LEFT 0x18
|
||||
#define LCD_SHIFT_RIGHT 0x1c
|
||||
|
||||
static void lcd_put_byte(u8 *addr, u8 data)
|
||||
{
|
||||
#ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS
|
||||
ACCESS_ONCE(*addr) = data;
|
||||
#else
|
||||
ACCESS_ONCE(*addr) = data & 0xf0;
|
||||
ACCESS_ONCE(*addr) = (data << 4) & 0xf0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int __init lcd_init(void)
|
||||
{
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
|
||||
ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
|
||||
mdelay(5);
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
|
||||
ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
|
||||
udelay(200);
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
|
||||
ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
|
||||
udelay(50);
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_ON;
|
||||
#ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS
|
||||
ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT;
|
||||
udelay(50);
|
||||
*LCD_INSTR_ADDR = LCD_CLEAR;
|
||||
lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT);
|
||||
udelay(50);
|
||||
#endif
|
||||
lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON);
|
||||
udelay(50);
|
||||
lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR);
|
||||
mdelay(10);
|
||||
lcd_disp_at_pos("XTENSA LINUX", 0);
|
||||
return 0;
|
||||
|
|
@ -52,10 +65,10 @@ static int __init lcd_init(void)
|
|||
|
||||
void lcd_disp_at_pos(char *str, unsigned char pos)
|
||||
{
|
||||
*LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos;
|
||||
lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos);
|
||||
udelay(100);
|
||||
while (*str != 0) {
|
||||
*LCD_DATA_ADDR = *str;
|
||||
lcd_put_byte(LCD_DATA_ADDR, *str);
|
||||
udelay(200);
|
||||
str++;
|
||||
}
|
||||
|
|
@ -63,13 +76,13 @@ void lcd_disp_at_pos(char *str, unsigned char pos)
|
|||
|
||||
void lcd_shiftleft(void)
|
||||
{
|
||||
*LCD_INSTR_ADDR = LCD_SHIFT_LEFT;
|
||||
lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT);
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
void lcd_shiftright(void)
|
||||
{
|
||||
*LCD_INSTR_ADDR = LCD_SHIFT_RIGHT;
|
||||
lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT);
|
||||
udelay(50);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -539,8 +539,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
|
|||
return_ACPI_STATUS(AE_NOT_EXIST);
|
||||
}
|
||||
|
||||
obj_desc->region.address =
|
||||
(acpi_physical_address) ACPI_TO_INTEGER(table);
|
||||
obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
|
||||
obj_desc->region.length = table->length;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
|
||||
|
|
|
|||
|
|
@ -301,8 +301,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
|
|||
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
|
||||
"%4.4s %p Attempted physical table override failed",
|
||||
table_header->signature,
|
||||
ACPI_CAST_PTR(void,
|
||||
table_desc->address)));
|
||||
ACPI_PHYSADDR_TO_PTR(table_desc->address)));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
|
@ -318,7 +317,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
|
|||
ACPI_INFO((AE_INFO,
|
||||
"%4.4s %p %s table override, new table: %p",
|
||||
table_header->signature,
|
||||
ACPI_CAST_PTR(void, table_desc->address),
|
||||
ACPI_PHYSADDR_TO_PTR(table_desc->address),
|
||||
override_type, new_table));
|
||||
|
||||
/* We can now unmap/delete the original table (if fully mapped) */
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
|
|||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_find_root_pointer(acpi_size *table_address)
|
||||
acpi_status acpi_find_root_pointer(acpi_physical_address * table_address)
|
||||
{
|
||||
u8 *table_ptr;
|
||||
u8 *mem_rover;
|
||||
|
|
@ -176,7 +176,8 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address)
|
|||
physical_address +=
|
||||
(u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
|
||||
|
||||
*table_address = physical_address;
|
||||
*table_address =
|
||||
(acpi_physical_address) physical_address;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
}
|
||||
|
|
@ -209,7 +210,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address)
|
|||
(ACPI_HI_RSDP_WINDOW_BASE +
|
||||
ACPI_PTR_DIFF(mem_rover, table_ptr));
|
||||
|
||||
*table_address = physical_address;
|
||||
*table_address = (acpi_physical_address) physical_address;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -978,7 +978,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
|
|||
return -EINVAL;
|
||||
|
||||
drv->safe_state_index = -1;
|
||||
for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
|
||||
for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) {
|
||||
drv->states[i].name[0] = '\0';
|
||||
drv->states[i].desc[0] = '\0';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ source "drivers/block/paride/Kconfig"
|
|||
|
||||
source "drivers/block/mtip32xx/Kconfig"
|
||||
|
||||
source "drivers/block/zram/Kconfig"
|
||||
|
||||
config BLK_CPQ_DA
|
||||
tristate "Compaq SMART2 support"
|
||||
depends on PCI && VIRT_TO_BUS
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ obj-$(CONFIG_BLK_DEV_RBD) += rbd.o
|
|||
obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/
|
||||
|
||||
obj-$(CONFIG_BLK_DEV_RSXX) += rsxx/
|
||||
obj-$(CONFIG_ZRAM) += zram/
|
||||
|
||||
nvme-y := nvme-core.o nvme-scsi.o
|
||||
swim_mod-y := swim.o swim_asm.o
|
||||
|
|
|
|||
|
|
@ -815,10 +815,6 @@ static int __init nbd_init(void)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
|
||||
if (!nbd_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
part_shift = 0;
|
||||
if (max_part > 0) {
|
||||
part_shift = fls(max_part);
|
||||
|
|
@ -840,6 +836,10 @@ static int __init nbd_init(void)
|
|||
if (nbds_max > 1UL << (MINORBITS - part_shift))
|
||||
return -EINVAL;
|
||||
|
||||
nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL);
|
||||
if (!nbd_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < nbds_max; i++) {
|
||||
struct gendisk *disk = alloc_disk(1 << part_shift);
|
||||
if (!disk)
|
||||
|
|
|
|||
|
|
@ -2115,6 +2115,11 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
|
|||
result, xferred);
|
||||
if (!img_request->result)
|
||||
img_request->result = result;
|
||||
/*
|
||||
* Need to end I/O on the entire obj_request worth of
|
||||
* bytes in case of error.
|
||||
*/
|
||||
xferred = obj_request->length;
|
||||
}
|
||||
|
||||
/* Image object requests don't own their page array */
|
||||
|
|
|
|||
|
|
@ -14,7 +14,16 @@ config ZRAM
|
|||
disks and maybe many more.
|
||||
|
||||
See zram.txt for more information.
|
||||
Project home: <https://compcache.googlecode.com/>
|
||||
|
||||
config ZRAM_LZ4_COMPRESS
|
||||
bool "Enable LZ4 algorithm support"
|
||||
depends on ZRAM
|
||||
select LZ4_COMPRESS
|
||||
select LZ4_DECOMPRESS
|
||||
default n
|
||||
help
|
||||
This option enables LZ4 compression algorithm support. Compression
|
||||
algorithm can be changed using `comp_algorithm' device attribute.
|
||||
|
||||
config ZRAM_DEBUG
|
||||
bool "Compressed RAM block device debug support"
|
||||
5
drivers/block/zram/Makefile
Normal file
5
drivers/block/zram/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
zram-y := zcomp_lzo.o zcomp.o zram_drv.o
|
||||
|
||||
zram-$(CONFIG_ZRAM_LZ4_COMPRESS) += zcomp_lz4.o
|
||||
|
||||
obj-$(CONFIG_ZRAM) += zram.o
|
||||
353
drivers/block/zram/zcomp.c
Normal file
353
drivers/block/zram/zcomp.c
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "zcomp.h"
|
||||
#include "zcomp_lzo.h"
|
||||
#ifdef CONFIG_ZRAM_LZ4_COMPRESS
|
||||
#include "zcomp_lz4.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* single zcomp_strm backend
|
||||
*/
|
||||
struct zcomp_strm_single {
|
||||
struct mutex strm_lock;
|
||||
struct zcomp_strm *zstrm;
|
||||
};
|
||||
|
||||
/*
|
||||
* multi zcomp_strm backend
|
||||
*/
|
||||
struct zcomp_strm_multi {
|
||||
/* protect strm list */
|
||||
spinlock_t strm_lock;
|
||||
/* max possible number of zstrm streams */
|
||||
int max_strm;
|
||||
/* number of available zstrm streams */
|
||||
int avail_strm;
|
||||
/* list of available strms */
|
||||
struct list_head idle_strm;
|
||||
wait_queue_head_t strm_wait;
|
||||
};
|
||||
|
||||
static struct zcomp_backend *backends[] = {
|
||||
&zcomp_lzo,
|
||||
#ifdef CONFIG_ZRAM_LZ4_COMPRESS
|
||||
&zcomp_lz4,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct zcomp_backend *find_backend(const char *compress)
|
||||
{
|
||||
int i = 0;
|
||||
while (backends[i]) {
|
||||
if (sysfs_streq(compress, backends[i]->name))
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
return backends[i];
|
||||
}
|
||||
|
||||
static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
|
||||
{
|
||||
if (zstrm->private)
|
||||
comp->backend->destroy(zstrm->private);
|
||||
free_pages((unsigned long)zstrm->buffer, 1);
|
||||
kfree(zstrm);
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate new zcomp_strm structure with ->private initialized by
|
||||
* backend, return NULL on error
|
||||
*/
|
||||
static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
|
||||
if (!zstrm)
|
||||
return NULL;
|
||||
|
||||
zstrm->private = comp->backend->create();
|
||||
/*
|
||||
* allocate 2 pages. 1 for compressed data, plus 1 extra for the
|
||||
* case when compressed size is larger than the original one
|
||||
*/
|
||||
zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
|
||||
if (!zstrm->private || !zstrm->buffer) {
|
||||
zcomp_strm_free(comp, zstrm);
|
||||
zstrm = NULL;
|
||||
}
|
||||
return zstrm;
|
||||
}
|
||||
|
||||
/*
|
||||
* get idle zcomp_strm or wait until other process release
|
||||
* (zcomp_strm_release()) one for us
|
||||
*/
|
||||
static struct zcomp_strm *zcomp_strm_multi_find(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_multi *zs = comp->stream;
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
while (1) {
|
||||
spin_lock(&zs->strm_lock);
|
||||
if (!list_empty(&zs->idle_strm)) {
|
||||
zstrm = list_entry(zs->idle_strm.next,
|
||||
struct zcomp_strm, list);
|
||||
list_del(&zstrm->list);
|
||||
spin_unlock(&zs->strm_lock);
|
||||
return zstrm;
|
||||
}
|
||||
/* zstrm streams limit reached, wait for idle stream */
|
||||
if (zs->avail_strm >= zs->max_strm) {
|
||||
spin_unlock(&zs->strm_lock);
|
||||
wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
|
||||
continue;
|
||||
}
|
||||
/* allocate new zstrm stream */
|
||||
zs->avail_strm++;
|
||||
spin_unlock(&zs->strm_lock);
|
||||
|
||||
zstrm = zcomp_strm_alloc(comp);
|
||||
if (!zstrm) {
|
||||
spin_lock(&zs->strm_lock);
|
||||
zs->avail_strm--;
|
||||
spin_unlock(&zs->strm_lock);
|
||||
wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return zstrm;
|
||||
}
|
||||
|
||||
/* add stream back to idle list and wake up waiter or free the stream */
|
||||
static void zcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm)
|
||||
{
|
||||
struct zcomp_strm_multi *zs = comp->stream;
|
||||
|
||||
spin_lock(&zs->strm_lock);
|
||||
if (zs->avail_strm <= zs->max_strm) {
|
||||
list_add(&zstrm->list, &zs->idle_strm);
|
||||
spin_unlock(&zs->strm_lock);
|
||||
wake_up(&zs->strm_wait);
|
||||
return;
|
||||
}
|
||||
|
||||
zs->avail_strm--;
|
||||
spin_unlock(&zs->strm_lock);
|
||||
zcomp_strm_free(comp, zstrm);
|
||||
}
|
||||
|
||||
/* change max_strm limit */
|
||||
static bool zcomp_strm_multi_set_max_streams(struct zcomp *comp, int num_strm)
|
||||
{
|
||||
struct zcomp_strm_multi *zs = comp->stream;
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
spin_lock(&zs->strm_lock);
|
||||
zs->max_strm = num_strm;
|
||||
/*
|
||||
* if user has lowered the limit and there are idle streams,
|
||||
* immediately free as much streams (and memory) as we can.
|
||||
*/
|
||||
while (zs->avail_strm > num_strm && !list_empty(&zs->idle_strm)) {
|
||||
zstrm = list_entry(zs->idle_strm.next,
|
||||
struct zcomp_strm, list);
|
||||
list_del(&zstrm->list);
|
||||
zcomp_strm_free(comp, zstrm);
|
||||
zs->avail_strm--;
|
||||
}
|
||||
spin_unlock(&zs->strm_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void zcomp_strm_multi_destroy(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_multi *zs = comp->stream;
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
while (!list_empty(&zs->idle_strm)) {
|
||||
zstrm = list_entry(zs->idle_strm.next,
|
||||
struct zcomp_strm, list);
|
||||
list_del(&zstrm->list);
|
||||
zcomp_strm_free(comp, zstrm);
|
||||
}
|
||||
kfree(zs);
|
||||
}
|
||||
|
||||
static int zcomp_strm_multi_create(struct zcomp *comp, int max_strm)
|
||||
{
|
||||
struct zcomp_strm *zstrm;
|
||||
struct zcomp_strm_multi *zs;
|
||||
|
||||
comp->destroy = zcomp_strm_multi_destroy;
|
||||
comp->strm_find = zcomp_strm_multi_find;
|
||||
comp->strm_release = zcomp_strm_multi_release;
|
||||
comp->set_max_streams = zcomp_strm_multi_set_max_streams;
|
||||
zs = kmalloc(sizeof(struct zcomp_strm_multi), GFP_KERNEL);
|
||||
if (!zs)
|
||||
return -ENOMEM;
|
||||
|
||||
comp->stream = zs;
|
||||
spin_lock_init(&zs->strm_lock);
|
||||
INIT_LIST_HEAD(&zs->idle_strm);
|
||||
init_waitqueue_head(&zs->strm_wait);
|
||||
zs->max_strm = max_strm;
|
||||
zs->avail_strm = 1;
|
||||
|
||||
zstrm = zcomp_strm_alloc(comp);
|
||||
if (!zstrm) {
|
||||
kfree(zs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
list_add(&zstrm->list, &zs->idle_strm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_single *zs = comp->stream;
|
||||
mutex_lock(&zs->strm_lock);
|
||||
return zs->zstrm;
|
||||
}
|
||||
|
||||
static void zcomp_strm_single_release(struct zcomp *comp,
|
||||
struct zcomp_strm *zstrm)
|
||||
{
|
||||
struct zcomp_strm_single *zs = comp->stream;
|
||||
mutex_unlock(&zs->strm_lock);
|
||||
}
|
||||
|
||||
static bool zcomp_strm_single_set_max_streams(struct zcomp *comp, int num_strm)
|
||||
{
|
||||
/* zcomp_strm_single support only max_comp_streams == 1 */
|
||||
return false;
|
||||
}
|
||||
|
||||
static void zcomp_strm_single_destroy(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_single *zs = comp->stream;
|
||||
zcomp_strm_free(comp, zs->zstrm);
|
||||
kfree(zs);
|
||||
}
|
||||
|
||||
static int zcomp_strm_single_create(struct zcomp *comp)
|
||||
{
|
||||
struct zcomp_strm_single *zs;
|
||||
|
||||
comp->destroy = zcomp_strm_single_destroy;
|
||||
comp->strm_find = zcomp_strm_single_find;
|
||||
comp->strm_release = zcomp_strm_single_release;
|
||||
comp->set_max_streams = zcomp_strm_single_set_max_streams;
|
||||
zs = kmalloc(sizeof(struct zcomp_strm_single), GFP_KERNEL);
|
||||
if (!zs)
|
||||
return -ENOMEM;
|
||||
|
||||
comp->stream = zs;
|
||||
mutex_init(&zs->strm_lock);
|
||||
zs->zstrm = zcomp_strm_alloc(comp);
|
||||
if (!zs->zstrm) {
|
||||
kfree(zs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* show available compressors */
|
||||
ssize_t zcomp_available_show(const char *comp, char *buf)
|
||||
{
|
||||
ssize_t sz = 0;
|
||||
int i = 0;
|
||||
|
||||
while (backends[i]) {
|
||||
if (sysfs_streq(comp, backends[i]->name))
|
||||
sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
|
||||
"[%s] ", backends[i]->name);
|
||||
else
|
||||
sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2,
|
||||
"%s ", backends[i]->name);
|
||||
i++;
|
||||
}
|
||||
sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n");
|
||||
return sz;
|
||||
}
|
||||
|
||||
bool zcomp_set_max_streams(struct zcomp *comp, int num_strm)
|
||||
{
|
||||
return comp->set_max_streams(comp, num_strm);
|
||||
}
|
||||
|
||||
struct zcomp_strm *zcomp_strm_find(struct zcomp *comp)
|
||||
{
|
||||
return comp->strm_find(comp);
|
||||
}
|
||||
|
||||
void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm)
|
||||
{
|
||||
comp->strm_release(comp, zstrm);
|
||||
}
|
||||
|
||||
int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
|
||||
const unsigned char *src, size_t *dst_len)
|
||||
{
|
||||
return comp->backend->compress(src, zstrm->buffer, dst_len,
|
||||
zstrm->private);
|
||||
}
|
||||
|
||||
int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
|
||||
size_t src_len, unsigned char *dst)
|
||||
{
|
||||
return comp->backend->decompress(src, src_len, dst);
|
||||
}
|
||||
|
||||
void zcomp_destroy(struct zcomp *comp)
|
||||
{
|
||||
comp->destroy(comp);
|
||||
kfree(comp);
|
||||
}
|
||||
|
||||
/*
|
||||
* search available compressors for requested algorithm.
|
||||
* allocate new zcomp and initialize it. return compressing
|
||||
* backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
|
||||
* if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
|
||||
* case of allocation error.
|
||||
*/
|
||||
struct zcomp *zcomp_create(const char *compress, int max_strm)
|
||||
{
|
||||
struct zcomp *comp;
|
||||
struct zcomp_backend *backend;
|
||||
|
||||
backend = find_backend(compress);
|
||||
if (!backend)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
|
||||
if (!comp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
comp->backend = backend;
|
||||
if (max_strm > 1)
|
||||
zcomp_strm_multi_create(comp, max_strm);
|
||||
else
|
||||
zcomp_strm_single_create(comp);
|
||||
if (!comp->stream) {
|
||||
kfree(comp);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
68
drivers/block/zram/zcomp.h
Normal file
68
drivers/block/zram/zcomp.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _ZCOMP_H_
|
||||
#define _ZCOMP_H_
|
||||
|
||||
#include <linux/mutex.h>
|
||||
|
||||
struct zcomp_strm {
|
||||
/* compression/decompression buffer */
|
||||
void *buffer;
|
||||
/*
|
||||
* The private data of the compression stream, only compression
|
||||
* stream backend can touch this (e.g. compression algorithm
|
||||
* working memory)
|
||||
*/
|
||||
void *private;
|
||||
/* used in multi stream backend, protected by backend strm_lock */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/* static compression backend */
|
||||
struct zcomp_backend {
|
||||
int (*compress)(const unsigned char *src, unsigned char *dst,
|
||||
size_t *dst_len, void *private);
|
||||
|
||||
int (*decompress)(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst);
|
||||
|
||||
void *(*create)(void);
|
||||
void (*destroy)(void *private);
|
||||
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/* dynamic per-device compression frontend */
|
||||
struct zcomp {
|
||||
void *stream;
|
||||
struct zcomp_backend *backend;
|
||||
|
||||
struct zcomp_strm *(*strm_find)(struct zcomp *comp);
|
||||
void (*strm_release)(struct zcomp *comp, struct zcomp_strm *zstrm);
|
||||
bool (*set_max_streams)(struct zcomp *comp, int num_strm);
|
||||
void (*destroy)(struct zcomp *comp);
|
||||
};
|
||||
|
||||
ssize_t zcomp_available_show(const char *comp, char *buf);
|
||||
|
||||
struct zcomp *zcomp_create(const char *comp, int max_strm);
|
||||
void zcomp_destroy(struct zcomp *comp);
|
||||
|
||||
struct zcomp_strm *zcomp_strm_find(struct zcomp *comp);
|
||||
void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm);
|
||||
|
||||
int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
|
||||
const unsigned char *src, size_t *dst_len);
|
||||
|
||||
int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
|
||||
size_t src_len, unsigned char *dst);
|
||||
|
||||
bool zcomp_set_max_streams(struct zcomp *comp, int num_strm);
|
||||
#endif /* _ZCOMP_H_ */
|
||||
47
drivers/block/zram/zcomp_lz4.c
Normal file
47
drivers/block/zram/zcomp_lz4.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/lz4.h>
|
||||
|
||||
#include "zcomp_lz4.h"
|
||||
|
||||
static void *zcomp_lz4_create(void)
|
||||
{
|
||||
return kzalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void zcomp_lz4_destroy(void *private)
|
||||
{
|
||||
kfree(private);
|
||||
}
|
||||
|
||||
static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
|
||||
size_t *dst_len, void *private)
|
||||
{
|
||||
/* return : Success if return 0 */
|
||||
return lz4_compress(src, PAGE_SIZE, dst, dst_len, private);
|
||||
}
|
||||
|
||||
static int zcomp_lz4_decompress(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst)
|
||||
{
|
||||
size_t dst_len = PAGE_SIZE;
|
||||
/* return : Success if return 0 */
|
||||
return lz4_decompress_unknownoutputsize(src, src_len, dst, &dst_len);
|
||||
}
|
||||
|
||||
struct zcomp_backend zcomp_lz4 = {
|
||||
.compress = zcomp_lz4_compress,
|
||||
.decompress = zcomp_lz4_decompress,
|
||||
.create = zcomp_lz4_create,
|
||||
.destroy = zcomp_lz4_destroy,
|
||||
.name = "lz4",
|
||||
};
|
||||
17
drivers/block/zram/zcomp_lz4.h
Normal file
17
drivers/block/zram/zcomp_lz4.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _ZCOMP_LZ4_H_
|
||||
#define _ZCOMP_LZ4_H_
|
||||
|
||||
#include "zcomp.h"
|
||||
|
||||
extern struct zcomp_backend zcomp_lz4;
|
||||
|
||||
#endif /* _ZCOMP_LZ4_H_ */
|
||||
47
drivers/block/zram/zcomp_lzo.c
Normal file
47
drivers/block/zram/zcomp_lzo.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/lzo.h>
|
||||
|
||||
#include "zcomp_lzo.h"
|
||||
|
||||
static void *lzo_create(void)
|
||||
{
|
||||
return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void lzo_destroy(void *private)
|
||||
{
|
||||
kfree(private);
|
||||
}
|
||||
|
||||
static int lzo_compress(const unsigned char *src, unsigned char *dst,
|
||||
size_t *dst_len, void *private)
|
||||
{
|
||||
int ret = lzo1x_1_compress(src, PAGE_SIZE, dst, dst_len, private);
|
||||
return ret == LZO_E_OK ? 0 : ret;
|
||||
}
|
||||
|
||||
static int lzo_decompress(const unsigned char *src, size_t src_len,
|
||||
unsigned char *dst)
|
||||
{
|
||||
size_t dst_len = PAGE_SIZE;
|
||||
int ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
|
||||
return ret == LZO_E_OK ? 0 : ret;
|
||||
}
|
||||
|
||||
struct zcomp_backend zcomp_lzo = {
|
||||
.compress = lzo_compress,
|
||||
.decompress = lzo_decompress,
|
||||
.create = lzo_create,
|
||||
.destroy = lzo_destroy,
|
||||
.name = "lzo",
|
||||
};
|
||||
17
drivers/block/zram/zcomp_lzo.h
Normal file
17
drivers/block/zram/zcomp_lzo.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Sergey Senozhatsky.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef _ZCOMP_LZO_H_
|
||||
#define _ZCOMP_LZO_H_
|
||||
|
||||
#include "zcomp.h"
|
||||
|
||||
extern struct zcomp_backend zcomp_lzo;
|
||||
|
||||
#endif /* _ZCOMP_LZO_H_ */
|
||||
1162
drivers/block/zram/zram_drv.c
Normal file
1162
drivers/block/zram/zram_drv.c
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -2,6 +2,7 @@
|
|||
* Compressed RAM block device
|
||||
*
|
||||
* Copyright (C) 2008, 2009, 2010 Nitin Gupta
|
||||
* 2012, 2013 Minchan Kim
|
||||
*
|
||||
* This code is released using a dual license strategy: BSD/GPL
|
||||
* You can choose the licence that better fits your requirements.
|
||||
|
|
@ -9,16 +10,15 @@
|
|||
* Released under the terms of 3-clause BSD License
|
||||
* Released under the terms of GNU General Public License Version 2.0
|
||||
*
|
||||
* Project home: http://compcache.googlecode.com
|
||||
*/
|
||||
|
||||
#ifndef _ZRAM_DRV_H_
|
||||
#define _ZRAM_DRV_H_
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/zsmalloc.h>
|
||||
|
||||
#include "../zsmalloc/zsmalloc.h"
|
||||
#include "zcomp.h"
|
||||
|
||||
/*
|
||||
* Some arbitrary value. This is just to catch
|
||||
|
|
@ -43,7 +43,6 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
|
|||
/*-- End of configurable params */
|
||||
|
||||
#define SECTOR_SHIFT 9
|
||||
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
|
||||
#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
|
||||
#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT)
|
||||
#define ZRAM_LOGICAL_BLOCK_SHIFT 12
|
||||
|
|
@ -51,10 +50,24 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
|
|||
#define ZRAM_SECTOR_PER_LOGICAL_BLOCK \
|
||||
(1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT))
|
||||
|
||||
/* Flags for zram pages (table[page_no].flags) */
|
||||
|
||||
/*
|
||||
* The lower ZRAM_FLAG_SHIFT bits of table.value is for
|
||||
* object size (excluding header), the higher bits is for
|
||||
* zram_pageflags.
|
||||
*
|
||||
* zram is mainly used for memory efficiency so we want to keep memory
|
||||
* footprint small so we can squeeze size and flags into a field.
|
||||
* The lower ZRAM_FLAG_SHIFT bits is for object size (excluding header),
|
||||
* the higher bits is for zram_pageflags.
|
||||
*/
|
||||
#define ZRAM_FLAG_SHIFT 24
|
||||
|
||||
/* Flags for zram pages (table[page_no].value) */
|
||||
enum zram_pageflags {
|
||||
/* Page consists entirely of zeros */
|
||||
ZRAM_ZERO,
|
||||
ZRAM_ZERO = ZRAM_FLAG_SHIFT,
|
||||
ZRAM_ACCESS, /* page is now accessed */
|
||||
|
||||
__NR_ZRAM_PAGEFLAGS,
|
||||
};
|
||||
|
|
@ -62,43 +75,35 @@ enum zram_pageflags {
|
|||
/*-- Data structures */
|
||||
|
||||
/* Allocated for each disk page */
|
||||
struct table {
|
||||
struct zram_table_entry {
|
||||
unsigned long handle;
|
||||
u16 size; /* object size (excluding header) */
|
||||
u8 count; /* object ref count (not yet used) */
|
||||
u8 flags;
|
||||
} __aligned(4);
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
struct zram_stats {
|
||||
u64 compr_size; /* compressed size of pages stored */
|
||||
u64 num_reads; /* failed + successful */
|
||||
u64 num_writes; /* --do-- */
|
||||
u64 failed_reads; /* should NEVER! happen */
|
||||
u64 failed_writes; /* can happen when memory is too low */
|
||||
u64 invalid_io; /* non-page-aligned I/O requests */
|
||||
u64 notify_free; /* no. of swap slot free notifications */
|
||||
u32 pages_zero; /* no. of zero filled pages */
|
||||
u32 pages_stored; /* no. of pages currently stored */
|
||||
u32 good_compress; /* % of pages with compression ratio<=50% */
|
||||
u32 bad_compress; /* % of pages with compression ratio>=75% */
|
||||
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; /* 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 */
|
||||
atomic64_t zero_pages; /* no. of zero filled pages */
|
||||
atomic64_t pages_stored; /* no. of pages currently stored */
|
||||
atomic_long_t max_used_pages; /* no. of maximum pages stored */
|
||||
};
|
||||
|
||||
struct zram_meta {
|
||||
void *compress_workmem;
|
||||
void *compress_buffer;
|
||||
struct table *table;
|
||||
struct zram_table_entry *table;
|
||||
struct zs_pool *mem_pool;
|
||||
};
|
||||
|
||||
struct zram {
|
||||
struct zram_meta *meta;
|
||||
spinlock_t stat64_lock; /* protect 64-bit stats */
|
||||
struct rw_semaphore lock; /* protect compression buffers, table,
|
||||
* 32bit stat counters against concurrent
|
||||
* notifications, reads and writes */
|
||||
struct request_queue *queue;
|
||||
struct gendisk *disk;
|
||||
int init_done;
|
||||
struct zcomp *comp;
|
||||
|
||||
/* Prevent concurrent execution of device init, reset and R/W request */
|
||||
struct rw_semaphore init_lock;
|
||||
/*
|
||||
|
|
@ -106,19 +111,13 @@ struct zram {
|
|||
* we can store in a disk.
|
||||
*/
|
||||
u64 disksize; /* bytes */
|
||||
|
||||
int max_comp_streams;
|
||||
struct zram_stats stats;
|
||||
/*
|
||||
* the number of pages zram can consume for storing compressed data
|
||||
*/
|
||||
unsigned long limit_pages;
|
||||
|
||||
char compressor[10];
|
||||
};
|
||||
|
||||
extern struct zram *zram_devices;
|
||||
unsigned int zram_get_num_devices(void);
|
||||
#ifdef CONFIG_SYSFS
|
||||
extern struct attribute_group zram_disk_attr_group;
|
||||
#endif
|
||||
|
||||
extern void zram_reset_device(struct zram *zram);
|
||||
extern struct zram_meta *zram_meta_alloc(u64 disksize);
|
||||
extern void zram_meta_free(struct zram_meta *meta);
|
||||
extern void zram_init_device(struct zram *zram, struct zram_meta *meta);
|
||||
|
||||
#endif
|
||||
|
|
@ -77,6 +77,8 @@ static struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x0CF3, 0x3004) },
|
||||
{ USB_DEVICE(0x0CF3, 0x3008) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311D) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311E) },
|
||||
{ USB_DEVICE(0x0CF3, 0x311F) },
|
||||
{ USB_DEVICE(0x0CF3, 0x817a) },
|
||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
||||
{ USB_DEVICE(0x04CA, 0x3004) },
|
||||
|
|
@ -120,6 +122,8 @@ static struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ static struct usb_driver btusb_driver;
|
|||
#define BTUSB_WRONG_SCO_MTU 0x40
|
||||
#define BTUSB_ATH3012 0x80
|
||||
#define BTUSB_INTEL 0x100
|
||||
#define BTUSB_INTEL_BOOT 0x200
|
||||
|
||||
static struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
|
|
@ -113,6 +114,13 @@ static struct usb_device_id btusb_table[] = {
|
|||
/*Broadcom devices with vendor specific id */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
|
||||
|
||||
/* IMC Networks - Broadcom based */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
|
||||
|
||||
/* Intel Bluetooth USB Bootloader (RAM module) */
|
||||
{ USB_DEVICE(0x8087, 0x0a5a),
|
||||
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
|
@ -141,6 +149,8 @@ static struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
|
|
@ -1444,6 +1454,9 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
if (id->driver_info & BTUSB_INTEL)
|
||||
hdev->setup = btusb_setup_intel;
|
||||
|
||||
if (id->driver_info & BTUSB_INTEL_BOOT)
|
||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||
|
||||
/* Interface numbers are hardcoded in the specification */
|
||||
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ static void cpufreq_interactive_timer(unsigned long data)
|
|||
spin_lock_irqsave(&pcpu->target_freq_lock, flags);
|
||||
do_div(cputime_speedadj, delta_time);
|
||||
loadadjfreq = (unsigned int)cputime_speedadj * 100;
|
||||
cpu_load = loadadjfreq / pcpu->target_freq;
|
||||
cpu_load = loadadjfreq / pcpu->policy->cur;
|
||||
tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime;
|
||||
|
||||
#ifdef CONFIG_ARCH_ROCKCHIP
|
||||
|
|
|
|||
|
|
@ -487,6 +487,7 @@ static int omap_dma_terminate_all(struct omap_chan *c)
|
|||
* c->desc is NULL and exit.)
|
||||
*/
|
||||
if (c->desc) {
|
||||
omap_dma_desc_free(&c->desc->vd);
|
||||
c->desc = NULL;
|
||||
/* Avoid stopping the dma twice */
|
||||
if (!c->paused)
|
||||
|
|
|
|||
|
|
@ -270,8 +270,9 @@ static const u32 correrrthrsld[] = {
|
|||
* sbridge structs
|
||||
*/
|
||||
|
||||
#define NUM_CHANNELS 4
|
||||
#define MAX_DIMMS 3 /* Max DIMMS per channel */
|
||||
#define NUM_CHANNELS 4
|
||||
#define MAX_DIMMS 3 /* Max DIMMS per channel */
|
||||
#define CHANNEL_UNSPECIFIED 0xf /* Intel IA32 SDM 15-14 */
|
||||
|
||||
struct sbridge_info {
|
||||
u32 mcmtr;
|
||||
|
|
@ -1451,6 +1452,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
|
|||
|
||||
/* FIXME: need support for channel mask */
|
||||
|
||||
if (channel == CHANNEL_UNSPECIFIED)
|
||||
channel = -1;
|
||||
|
||||
/* Call the helper to output message */
|
||||
edac_mc_handle_error(tp_event, mci, core_err_cnt,
|
||||
m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,22 @@ gator-$(CONFIG_ARM) += gator_events_armv6.o \
|
|||
|
||||
gator-$(CONFIG_ARM64) +=
|
||||
|
||||
$(obj)/gator_main.o: $(obj)/gator_src_md5.h
|
||||
|
||||
clean-files := gator_src_md5.h
|
||||
|
||||
# Note, in the recipe below we use "cd $(srctree) && cd $(src)" rather than
|
||||
# "cd $(srctree)/$(src)" because under DKMS $(src) is an absolute path, and we
|
||||
# can't just use $(src) because for normal kernel builds this is relative to
|
||||
# $(srctree)
|
||||
|
||||
chk_events.h = :
|
||||
quiet_chk_events.h = echo ' CHK $@'
|
||||
silent_chk_events.h = :
|
||||
$(obj)/gator_src_md5.h: FORCE
|
||||
@$($(quiet)chk_events.h)
|
||||
$(Q)cd $(srctree) && cd $(src) ; $(CONFIG_SHELL) -c "echo 'static char *gator_src_md5 = \"'\`ls *.c *.h mali/*.h | grep -Ev '^(gator_src_md5\.c|gator\.mod\.c)$$' | LC_ALL=C sort | xargs cat | md5sum | cut -b 1-32\`'\";'" > $(abspath $@)
|
||||
|
||||
else
|
||||
|
||||
all:
|
||||
|
|
@ -73,7 +89,7 @@ all:
|
|||
$(error)
|
||||
|
||||
clean:
|
||||
rm -f *.o .*.cmd modules.order Module.symvers gator.ko gator.mod.c
|
||||
rm -f *.o .*.cmd gator_src_md5.h modules.order Module.symvers gator.ko gator.mod.c
|
||||
rm -rf .tmp_versions
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) ARM Limited 2010-2014. All rights reserved.
|
||||
* Copyright (C) ARM Limited 2010-2015. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
@ -21,25 +21,26 @@
|
|||
#define GATOR_IKS_SUPPORT defined(CONFIG_BL_SWITCHER)
|
||||
|
||||
/* cpu ids */
|
||||
#define ARM1136 0xb36
|
||||
#define ARM1156 0xb56
|
||||
#define ARM1176 0xb76
|
||||
#define ARM11MPCORE 0xb02
|
||||
#define CORTEX_A5 0xc05
|
||||
#define CORTEX_A7 0xc07
|
||||
#define CORTEX_A8 0xc08
|
||||
#define CORTEX_A9 0xc09
|
||||
#define CORTEX_A15 0xc0f
|
||||
#define CORTEX_A17 0xc0e
|
||||
#define SCORPION 0x00f
|
||||
#define SCORPIONMP 0x02d
|
||||
#define KRAITSIM 0x049
|
||||
#define KRAIT 0x04d
|
||||
#define KRAIT_S4_PRO 0x06f
|
||||
#define CORTEX_A53 0xd03
|
||||
#define CORTEX_A57 0xd07
|
||||
#define AARCH64 0xd0f
|
||||
#define OTHER 0xfff
|
||||
#define ARM1136 0x41b36
|
||||
#define ARM1156 0x41b56
|
||||
#define ARM1176 0x41b76
|
||||
#define ARM11MPCORE 0x41b02
|
||||
#define CORTEX_A5 0x41c05
|
||||
#define CORTEX_A7 0x41c07
|
||||
#define CORTEX_A8 0x41c08
|
||||
#define CORTEX_A9 0x41c09
|
||||
#define CORTEX_A15 0x41c0f
|
||||
#define CORTEX_A12 0x41c0d
|
||||
#define CORTEX_A17 0x41c0e
|
||||
#define SCORPION 0x5100f
|
||||
#define SCORPIONMP 0x5102d
|
||||
#define KRAITSIM 0x51049
|
||||
#define KRAIT 0x5104d
|
||||
#define KRAIT_S4_PRO 0x5106f
|
||||
#define CORTEX_A53 0x41d03
|
||||
#define CORTEX_A57 0x41d07
|
||||
#define CORTEX_A72 0x41d08
|
||||
#define OTHER 0xfffff
|
||||
|
||||
/* gpu enums */
|
||||
#define MALI_4xx 1
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) ARM Limited 2010-2014. All rights reserved.
|
||||
* Copyright (C) ARM Limited 2010-2015. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) ARM Limited 2012-2014. All rights reserved.
|
||||
* Copyright (C) ARM Limited 2012-2015. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) ARM Limited 2010-2014. All rights reserved.
|
||||
* Copyright (C) ARM Limited 2010-2015. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) ARM Limited 2010-2014. All rights reserved.
|
||||
* Copyright (C) ARM Limited 2010-2015. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) ARM Limited 2010-2014. All rights reserved.
|
||||
* Copyright (C) ARM Limited 2010-2015. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) ARM Limited 2010-2014. All rights reserved.
|
||||
* Copyright (C) ARM Limited 2010-2015. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) ARM Limited 2010-2014. All rights reserved.
|
||||
* Copyright (C) ARM Limited 2010-2015. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user