mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
Merge branch 'sched/urgent' into sched/core, to pick up dependency
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
067b4f9342
|
|
@ -56,6 +56,7 @@ stable kernels.
|
|||
| ARM | MMU-500 | #841119,#826419 | N/A |
|
||||
| | | | |
|
||||
| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |
|
||||
| Cavium | ThunderX ITS | #23144 | CAVIUM_ERRATUM_23144 |
|
||||
| Cavium | ThunderX GICv3 | #23154 | CAVIUM_ERRATUM_23154 |
|
||||
| Cavium | ThunderX Core | #27456 | CAVIUM_ERRATUM_27456 |
|
||||
| Cavium | ThunderX SMMUv2 | #27704 | N/A |
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ Required properties:
|
|||
display-timings are used instead.
|
||||
|
||||
Optional properties (required if display-timings are used):
|
||||
- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
|
||||
- display-timings : A node that describes the display timings as defined in
|
||||
Documentation/devicetree/bindings/display/display-timing.txt.
|
||||
- fsl,data-mapping : should be "spwg" or "jeida"
|
||||
|
|
|
|||
|
|
@ -1,141 +1,26 @@
|
|||
Each mount of the devpts filesystem is now distinct such that ptys
|
||||
and their indicies allocated in one mount are independent from ptys
|
||||
and their indicies in all other mounts.
|
||||
|
||||
To support containers, we now allow multiple instances of devpts filesystem,
|
||||
such that indices of ptys allocated in one instance are independent of indices
|
||||
allocated in other instances of devpts.
|
||||
All mounts of the devpts filesystem now create a /dev/pts/ptmx node
|
||||
with permissions 0000.
|
||||
|
||||
To preserve backward compatibility, this support for multiple instances is
|
||||
enabled only if:
|
||||
To retain backwards compatibility the a ptmx device node (aka any node
|
||||
created with "mknod name c 5 2") when opened will look for an instance
|
||||
of devpts under the name "pts" in the same directory as the ptmx device
|
||||
node.
|
||||
|
||||
- CONFIG_DEVPTS_MULTIPLE_INSTANCES=y, and
|
||||
- '-o newinstance' mount option is specified while mounting devpts
|
||||
|
||||
IOW, devpts now supports both single-instance and multi-instance semantics.
|
||||
|
||||
If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, there is no change in behavior and
|
||||
this referred to as the "legacy" mode. In this mode, the new mount options
|
||||
(-o newinstance and -o ptmxmode) will be ignored with a 'bogus option' message
|
||||
on console.
|
||||
|
||||
If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and devpts is mounted without the
|
||||
'newinstance' option (as in current start-up scripts) the new mount binds
|
||||
to the initial kernel mount of devpts. This mode is referred to as the
|
||||
'single-instance' mode and the current, single-instance semantics are
|
||||
preserved, i.e PTYs are common across the system.
|
||||
|
||||
The only difference between this single-instance mode and the legacy mode
|
||||
is the presence of new, '/dev/pts/ptmx' node with permissions 0000, which
|
||||
can safely be ignored.
|
||||
|
||||
If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and 'newinstance' option is specified,
|
||||
the mount is considered to be in the multi-instance mode and a new instance
|
||||
of the devpts fs is created. Any ptys created in this instance are independent
|
||||
of ptys in other instances of devpts. Like in the single-instance mode, the
|
||||
/dev/pts/ptmx node is present. To effectively use the multi-instance mode,
|
||||
open of /dev/ptmx must be a redirected to '/dev/pts/ptmx' using a symlink or
|
||||
bind-mount.
|
||||
|
||||
Eg: A container startup script could do the following:
|
||||
|
||||
$ chmod 0666 /dev/pts/ptmx
|
||||
$ rm /dev/ptmx
|
||||
$ ln -s pts/ptmx /dev/ptmx
|
||||
$ ns_exec -cm /bin/bash
|
||||
|
||||
# We are now in new container
|
||||
|
||||
$ umount /dev/pts
|
||||
$ mount -t devpts -o newinstance lxcpts /dev/pts
|
||||
$ sshd -p 1234
|
||||
|
||||
where 'ns_exec -cm /bin/bash' calls clone() with CLONE_NEWNS flag and execs
|
||||
/bin/bash in the child process. A pty created by the sshd is not visible in
|
||||
the original mount of /dev/pts.
|
||||
As an option instead of placing a /dev/ptmx device node at /dev/ptmx
|
||||
it is possible to place a symlink to /dev/pts/ptmx at /dev/ptmx or
|
||||
to bind mount /dev/ptx/ptmx to /dev/ptmx. If you opt for using
|
||||
the devpts filesystem in this manner devpts should be mounted with
|
||||
the ptmxmode=0666, or chmod 0666 /dev/pts/ptmx should be called.
|
||||
|
||||
Total count of pty pairs in all instances is limited by sysctls:
|
||||
kernel.pty.max = 4096 - global limit
|
||||
kernel.pty.reserve = 1024 - reserve for initial instance
|
||||
kernel.pty.reserve = 1024 - reserved for filesystems mounted from the initial mount namespace
|
||||
kernel.pty.nr - current count of ptys
|
||||
|
||||
Per-instance limit could be set by adding mount option "max=<count>".
|
||||
This feature was added in kernel 3.4 together with sysctl kernel.pty.reserve.
|
||||
In kernels older than 3.4 sysctl kernel.pty.max works as per-instance limit.
|
||||
|
||||
User-space changes
|
||||
------------------
|
||||
|
||||
In multi-instance mode (i.e '-o newinstance' mount option is specified at least
|
||||
once), following user-space issues should be noted.
|
||||
|
||||
1. If -o newinstance mount option is never used, /dev/pts/ptmx can be ignored
|
||||
and no change is needed to system-startup scripts.
|
||||
|
||||
2. To effectively use multi-instance mode (i.e -o newinstance is specified)
|
||||
administrators or startup scripts should "redirect" open of /dev/ptmx to
|
||||
/dev/pts/ptmx using either a bind mount or symlink.
|
||||
|
||||
$ mount -t devpts -o newinstance devpts /dev/pts
|
||||
|
||||
followed by either
|
||||
|
||||
$ rm /dev/ptmx
|
||||
$ ln -s pts/ptmx /dev/ptmx
|
||||
$ chmod 666 /dev/pts/ptmx
|
||||
or
|
||||
$ mount -o bind /dev/pts/ptmx /dev/ptmx
|
||||
|
||||
3. The '/dev/ptmx -> pts/ptmx' symlink is the preferred method since it
|
||||
enables better error-reporting and treats both single-instance and
|
||||
multi-instance mounts similarly.
|
||||
|
||||
But this method requires that system-startup scripts set the mode of
|
||||
/dev/pts/ptmx correctly (default mode is 0000). The scripts can set the
|
||||
mode by, either
|
||||
|
||||
- adding ptmxmode mount option to devpts entry in /etc/fstab, or
|
||||
- using 'chmod 0666 /dev/pts/ptmx'
|
||||
|
||||
4. If multi-instance mode mount is needed for containers, but the system
|
||||
startup scripts have not yet been updated, container-startup scripts
|
||||
should bind mount /dev/ptmx to /dev/pts/ptmx to avoid breaking single-
|
||||
instance mounts.
|
||||
|
||||
Or, in general, container-startup scripts should use:
|
||||
|
||||
mount -t devpts -o newinstance -o ptmxmode=0666 devpts /dev/pts
|
||||
if [ ! -L /dev/ptmx ]; then
|
||||
mount -o bind /dev/pts/ptmx /dev/ptmx
|
||||
fi
|
||||
|
||||
When all devpts mounts are multi-instance, /dev/ptmx can permanently be
|
||||
a symlink to pts/ptmx and the bind mount can be ignored.
|
||||
|
||||
5. A multi-instance mount that is not accompanied by the /dev/ptmx to
|
||||
/dev/pts/ptmx redirection would result in an unusable/unreachable pty.
|
||||
|
||||
mount -t devpts -o newinstance lxcpts /dev/pts
|
||||
|
||||
immediately followed by:
|
||||
|
||||
open("/dev/ptmx")
|
||||
|
||||
would create a pty, say /dev/pts/7, in the initial kernel mount.
|
||||
But /dev/pts/7 would be invisible in the new mount.
|
||||
|
||||
6. The permissions for /dev/pts/ptmx node should be specified when mounting
|
||||
/dev/pts, using the '-o ptmxmode=%o' mount option (default is 0000).
|
||||
|
||||
mount -t devpts -o newinstance -o ptmxmode=0644 devpts /dev/pts
|
||||
|
||||
The permissions can be later be changed as usual with 'chmod'.
|
||||
|
||||
chmod 666 /dev/pts/ptmx
|
||||
|
||||
7. A mount of devpts without the 'newinstance' option results in binding to
|
||||
initial kernel mount. This behavior while preserving legacy semantics,
|
||||
does not provide strict isolation in a container environment. i.e by
|
||||
mounting devpts without the 'newinstance' option, a container could
|
||||
get visibility into the 'host' or root container's devpts.
|
||||
|
||||
To workaround this and have strict isolation, all mounts of devpts,
|
||||
including the mount in the root container, should use the newinstance
|
||||
option.
|
||||
|
|
|
|||
|
|
@ -170,21 +170,92 @@ document trapinfo
|
|||
address the kernel panicked.
|
||||
end
|
||||
|
||||
define dump_log_idx
|
||||
set $idx = $arg0
|
||||
if ($argc > 1)
|
||||
set $prev_flags = $arg1
|
||||
else
|
||||
set $prev_flags = 0
|
||||
end
|
||||
set $msg = ((struct printk_log *) (log_buf + $idx))
|
||||
set $prefix = 1
|
||||
set $newline = 1
|
||||
set $log = log_buf + $idx + sizeof(*$msg)
|
||||
|
||||
# prev & LOG_CONT && !(msg->flags & LOG_PREIX)
|
||||
if (($prev_flags & 8) && !($msg->flags & 4))
|
||||
set $prefix = 0
|
||||
end
|
||||
|
||||
# msg->flags & LOG_CONT
|
||||
if ($msg->flags & 8)
|
||||
# (prev & LOG_CONT && !(prev & LOG_NEWLINE))
|
||||
if (($prev_flags & 8) && !($prev_flags & 2))
|
||||
set $prefix = 0
|
||||
end
|
||||
# (!(msg->flags & LOG_NEWLINE))
|
||||
if (!($msg->flags & 2))
|
||||
set $newline = 0
|
||||
end
|
||||
end
|
||||
|
||||
if ($prefix)
|
||||
printf "[%5lu.%06lu] ", $msg->ts_nsec / 1000000000, $msg->ts_nsec % 1000000000
|
||||
end
|
||||
if ($msg->text_len != 0)
|
||||
eval "printf \"%%%d.%ds\", $log", $msg->text_len, $msg->text_len
|
||||
end
|
||||
if ($newline)
|
||||
printf "\n"
|
||||
end
|
||||
if ($msg->dict_len > 0)
|
||||
set $dict = $log + $msg->text_len
|
||||
set $idx = 0
|
||||
set $line = 1
|
||||
while ($idx < $msg->dict_len)
|
||||
if ($line)
|
||||
printf " "
|
||||
set $line = 0
|
||||
end
|
||||
set $c = $dict[$idx]
|
||||
if ($c == '\0')
|
||||
printf "\n"
|
||||
set $line = 1
|
||||
else
|
||||
if ($c < ' ' || $c >= 127 || $c == '\\')
|
||||
printf "\\x%02x", $c
|
||||
else
|
||||
printf "%c", $c
|
||||
end
|
||||
end
|
||||
set $idx = $idx + 1
|
||||
end
|
||||
printf "\n"
|
||||
end
|
||||
end
|
||||
document dump_log_idx
|
||||
Dump a single log given its index in the log buffer. The first
|
||||
parameter is the index into log_buf, the second is optional and
|
||||
specified the previous log buffer's flags, used for properly
|
||||
formatting continued lines.
|
||||
end
|
||||
|
||||
define dmesg
|
||||
set $i = 0
|
||||
set $end_idx = (log_end - 1) & (log_buf_len - 1)
|
||||
set $i = log_first_idx
|
||||
set $end_idx = log_first_idx
|
||||
set $prev_flags = 0
|
||||
|
||||
while ($i < logged_chars)
|
||||
set $idx = (log_end - 1 - logged_chars + $i) & (log_buf_len - 1)
|
||||
|
||||
if ($idx + 100 <= $end_idx) || \
|
||||
($end_idx <= $idx && $idx + 100 < log_buf_len)
|
||||
printf "%.100s", &log_buf[$idx]
|
||||
set $i = $i + 100
|
||||
while (1)
|
||||
set $msg = ((struct printk_log *) (log_buf + $i))
|
||||
if ($msg->len == 0)
|
||||
set $i = 0
|
||||
else
|
||||
printf "%c", log_buf[$idx]
|
||||
set $i = $i + 1
|
||||
dump_log_idx $i $prev_flags
|
||||
set $i = $i + $msg->len
|
||||
set $prev_flags = $msg->flags
|
||||
end
|
||||
if ($i == $end_idx)
|
||||
loop_break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -826,7 +826,8 @@ The keyctl syscall functions are:
|
|||
(*) Compute a Diffie-Hellman shared secret or public key
|
||||
|
||||
long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params,
|
||||
char *buffer, size_t buflen);
|
||||
char *buffer, size_t buflen,
|
||||
void *reserved);
|
||||
|
||||
The params struct contains serial numbers for three keys:
|
||||
|
||||
|
|
@ -843,6 +844,8 @@ The keyctl syscall functions are:
|
|||
public key. If the base is the remote public key, the result is
|
||||
the shared secret.
|
||||
|
||||
The reserved argument must be set to NULL.
|
||||
|
||||
The buffer length must be at least the length of the prime, or zero.
|
||||
|
||||
If the buffer length is nonzero, the length of the result is
|
||||
|
|
|
|||
|
|
@ -3086,6 +3086,7 @@ M: Stephen Boyd <sboyd@codeaurora.org>
|
|||
L: linux-clk@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/clock/
|
||||
F: drivers/clk/
|
||||
X: drivers/clk/clkdev.c
|
||||
F: include/linux/clk-pr*
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -1,7 +1,7 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 7
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc1
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = Psychotic Stoned Sheep
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
vfp_flush_hwstate(thread);
|
||||
thread->vfpstate.hard = new_vfp;
|
||||
vfp_flush_hwstate(thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -547,7 +547,7 @@ static struct clk *ve_spc_clk_register(struct device *cpu_dev)
|
|||
|
||||
init.name = dev_name(cpu_dev);
|
||||
init.ops = &clk_spc_ops;
|
||||
init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
|
||||
init.flags = CLK_GET_RATE_NOCACHE;
|
||||
init.num_parents = 0;
|
||||
|
||||
return devm_clk_register(cpu_dev, &spc->hw);
|
||||
|
|
|
|||
|
|
@ -113,6 +113,18 @@ config ARCH_PHYS_ADDR_T_64BIT
|
|||
config MMU
|
||||
def_bool y
|
||||
|
||||
config ARM64_PAGE_SHIFT
|
||||
int
|
||||
default 16 if ARM64_64K_PAGES
|
||||
default 14 if ARM64_16K_PAGES
|
||||
default 12
|
||||
|
||||
config ARM64_CONT_SHIFT
|
||||
int
|
||||
default 5 if ARM64_64K_PAGES
|
||||
default 7 if ARM64_16K_PAGES
|
||||
default 4
|
||||
|
||||
config ARCH_MMAP_RND_BITS_MIN
|
||||
default 14 if ARM64_64K_PAGES
|
||||
default 16 if ARM64_16K_PAGES
|
||||
|
|
@ -426,6 +438,15 @@ config CAVIUM_ERRATUM_22375
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config CAVIUM_ERRATUM_23144
|
||||
bool "Cavium erratum 23144: ITS SYNC hang on dual socket system"
|
||||
depends on NUMA
|
||||
default y
|
||||
help
|
||||
ITS SYNC command hang for cross node io and collections/cpu mapping.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config CAVIUM_ERRATUM_23154
|
||||
bool "Cavium erratum 23154: Access to ICC_IAR1_EL1 is not sync'ed"
|
||||
default y
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ config ARM64_PTDUMP
|
|||
who are working in architecture specific areas of the kernel.
|
||||
It is probably not a good idea to enable this feature in a production
|
||||
kernel.
|
||||
If in doubt, say "N"
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config PID_IN_CONTEXTIDR
|
||||
bool "Write the current PID to the CONTEXTIDR register"
|
||||
|
|
@ -38,15 +39,15 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
|
|||
value.
|
||||
|
||||
config DEBUG_SET_MODULE_RONX
|
||||
bool "Set loadable kernel module data as NX and text as RO"
|
||||
depends on MODULES
|
||||
help
|
||||
This option helps catch unintended modifications to loadable
|
||||
kernel module's text and read-only data. It also prevents execution
|
||||
of module data. Such protection may interfere with run-time code
|
||||
patching and dynamic kernel tracing - and they might also protect
|
||||
against certain classes of kernel exploits.
|
||||
If in doubt, say "N".
|
||||
bool "Set loadable kernel module data as NX and text as RO"
|
||||
depends on MODULES
|
||||
default y
|
||||
help
|
||||
Is this is set, kernel module text and rodata will be made read-only.
|
||||
This is to help catch accidental or malicious attempts to change the
|
||||
kernel's executable code.
|
||||
|
||||
If in doubt, say Y.
|
||||
|
||||
config DEBUG_RODATA
|
||||
bool "Make kernel text and rodata read-only"
|
||||
|
|
@ -56,7 +57,7 @@ config DEBUG_RODATA
|
|||
is to help catch accidental or malicious attempts to change the
|
||||
kernel's executable code.
|
||||
|
||||
If in doubt, say Y
|
||||
If in doubt, say Y.
|
||||
|
||||
config DEBUG_ALIGN_RODATA
|
||||
depends on DEBUG_RODATA
|
||||
|
|
@ -69,7 +70,7 @@ config DEBUG_ALIGN_RODATA
|
|||
alignment and potentially wasted space. Turn on this option if
|
||||
performance is more important than memory pressure.
|
||||
|
||||
If in doubt, say N
|
||||
If in doubt, say N.
|
||||
|
||||
source "drivers/hwtracing/coresight/Kconfig"
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ head-y := arch/arm64/kernel/head.o
|
|||
|
||||
# The byte offset of the kernel image in RAM from the start of RAM.
|
||||
ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)
|
||||
TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%03x000\n", int(512 * rand())}')
|
||||
TEXT_OFFSET := $(shell awk "BEGIN {srand(); printf \"0x%06x\n\", \
|
||||
int(2 * 1024 * 1024 / (2 ^ $(CONFIG_ARM64_PAGE_SHIFT)) * \
|
||||
rand()) * (2 ^ $(CONFIG_ARM64_PAGE_SHIFT))}")
|
||||
else
|
||||
TEXT_OFFSET := 0x00080000
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -160,14 +160,14 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
|
|||
#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
#ifdef __AARCH64EB__
|
||||
#define COMPAT_ELF_PLATFORM ("v8b")
|
||||
#else
|
||||
#define COMPAT_ELF_PLATFORM ("v8l")
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
#define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3)
|
||||
|
||||
/* AArch32 registers. */
|
||||
|
|
|
|||
|
|
@ -55,8 +55,9 @@
|
|||
#define VMEMMAP_SIZE (UL(1) << (VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT))
|
||||
|
||||
/*
|
||||
* PAGE_OFFSET - the virtual address of the start of the kernel image (top
|
||||
* PAGE_OFFSET - the virtual address of the start of the linear map (top
|
||||
* (VA_BITS - 1))
|
||||
* KIMAGE_VADDR - the virtual address of the start of the kernel image
|
||||
* VA_BITS - the maximum number of bits for virtual addresses.
|
||||
* VA_START - the first kernel virtual address.
|
||||
* TASK_SIZE - the maximum size of a user space task.
|
||||
|
|
|
|||
|
|
@ -23,16 +23,8 @@
|
|||
|
||||
/* PAGE_SHIFT determines the page size */
|
||||
/* CONT_SHIFT determines the number of pages which can be tracked together */
|
||||
#ifdef CONFIG_ARM64_64K_PAGES
|
||||
#define PAGE_SHIFT 16
|
||||
#define CONT_SHIFT 5
|
||||
#elif defined(CONFIG_ARM64_16K_PAGES)
|
||||
#define PAGE_SHIFT 14
|
||||
#define CONT_SHIFT 7
|
||||
#else
|
||||
#define PAGE_SHIFT 12
|
||||
#define CONT_SHIFT 4
|
||||
#endif
|
||||
#define PAGE_SHIFT CONFIG_ARM64_PAGE_SHIFT
|
||||
#define CONT_SHIFT CONFIG_ARM64_CONT_SHIFT
|
||||
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
|
|
|
|||
|
|
@ -80,19 +80,6 @@ static inline void set_fs(mm_segment_t fs)
|
|||
|
||||
#define segment_eq(a, b) ((a) == (b))
|
||||
|
||||
/*
|
||||
* Return 1 if addr < current->addr_limit, 0 otherwise.
|
||||
*/
|
||||
#define __addr_ok(addr) \
|
||||
({ \
|
||||
unsigned long flag; \
|
||||
asm("cmp %1, %0; cset %0, lo" \
|
||||
: "=&r" (flag) \
|
||||
: "r" (addr), "0" (current_thread_info()->addr_limit) \
|
||||
: "cc"); \
|
||||
flag; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Test whether a block of memory is a valid user space address.
|
||||
* Returns 1 if the range is valid, 0 otherwise.
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#define __ARM_NR_compat_cacheflush (__ARM_NR_COMPAT_BASE+2)
|
||||
#define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE+5)
|
||||
|
||||
#define __NR_compat_syscalls 390
|
||||
#define __NR_compat_syscalls 394
|
||||
#endif
|
||||
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
|
|
|
|||
|
|
@ -801,6 +801,14 @@ __SYSCALL(__NR_execveat, compat_sys_execveat)
|
|||
__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
|
||||
#define __NR_membarrier 389
|
||||
__SYSCALL(__NR_membarrier, sys_membarrier)
|
||||
#define __NR_mlock2 390
|
||||
__SYSCALL(__NR_mlock2, sys_mlock2)
|
||||
#define __NR_copy_file_range 391
|
||||
__SYSCALL(__NR_copy_file_range, sys_copy_file_range)
|
||||
#define __NR_preadv2 392
|
||||
__SYSCALL(__NR_preadv2, compat_sys_preadv2)
|
||||
#define __NR_pwritev2 393
|
||||
__SYSCALL(__NR_pwritev2, compat_sys_pwritev2)
|
||||
|
||||
/*
|
||||
* Please add new compat syscalls above this comment and update
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/personality.h>
|
||||
|
|
@ -104,6 +106,7 @@ static const char *const compat_hwcap2_str[] = {
|
|||
static int c_show(struct seq_file *m, void *v)
|
||||
{
|
||||
int i, j;
|
||||
bool compat = personality(current->personality) == PER_LINUX32;
|
||||
|
||||
for_each_online_cpu(i) {
|
||||
struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
|
||||
|
|
@ -115,6 +118,9 @@ static int c_show(struct seq_file *m, void *v)
|
|||
* "processor". Give glibc what it expects.
|
||||
*/
|
||||
seq_printf(m, "processor\t: %d\n", i);
|
||||
if (compat)
|
||||
seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
|
||||
MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
|
||||
|
||||
seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
|
||||
loops_per_jiffy / (500000UL/HZ),
|
||||
|
|
@ -127,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
|
|||
* software which does already (at least for 32-bit).
|
||||
*/
|
||||
seq_puts(m, "Features\t:");
|
||||
if (personality(current->personality) == PER_LINUX32) {
|
||||
if (compat) {
|
||||
#ifdef CONFIG_COMPAT
|
||||
for (j = 0; compat_hwcap_str[j]; j++)
|
||||
if (compat_elf_hwcap & (1 << j))
|
||||
|
|
|
|||
|
|
@ -477,8 +477,9 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
|
|||
void __user *pc = (void __user *)instruction_pointer(regs);
|
||||
console_verbose();
|
||||
|
||||
pr_crit("Bad mode in %s handler detected, code 0x%08x -- %s\n",
|
||||
handler[reason], esr, esr_get_class_string(esr));
|
||||
pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
|
||||
handler[reason], smp_processor_id(), esr,
|
||||
esr_get_class_string(esr));
|
||||
__show_regs(regs);
|
||||
|
||||
info.si_signo = SIGILL;
|
||||
|
|
|
|||
|
|
@ -169,7 +169,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
|
|||
* Make sure stores to the GIC via the memory mapped interface
|
||||
* are now visible to the system register interface.
|
||||
*/
|
||||
dsb(st);
|
||||
if (!cpu_if->vgic_sre)
|
||||
dsb(st);
|
||||
|
||||
cpu_if->vgic_vmcr = read_gicreg(ICH_VMCR_EL2);
|
||||
|
||||
|
|
@ -190,12 +191,11 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
|
|||
if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
|
||||
continue;
|
||||
|
||||
if (cpu_if->vgic_elrsr & (1 << i)) {
|
||||
if (cpu_if->vgic_elrsr & (1 << i))
|
||||
cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
|
||||
|
||||
cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
|
||||
__gic_v3_set_lr(0, i);
|
||||
}
|
||||
|
||||
|
|
@ -236,8 +236,12 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
|
|||
|
||||
val = read_gicreg(ICC_SRE_EL2);
|
||||
write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
|
||||
isb(); /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
|
||||
write_gicreg(1, ICC_SRE_EL1);
|
||||
|
||||
if (!cpu_if->vgic_sre) {
|
||||
/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
|
||||
isb();
|
||||
write_gicreg(1, ICC_SRE_EL1);
|
||||
}
|
||||
}
|
||||
|
||||
void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -256,8 +260,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
|
|||
* been actually programmed with the value we want before
|
||||
* starting to mess with the rest of the GIC.
|
||||
*/
|
||||
write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
|
||||
isb();
|
||||
if (!cpu_if->vgic_sre) {
|
||||
write_gicreg(0, ICC_SRE_EL1);
|
||||
isb();
|
||||
}
|
||||
|
||||
val = read_gicreg(ICH_VTR_EL2);
|
||||
max_lr_idx = vtr_to_max_lr_idx(val);
|
||||
|
|
@ -306,18 +312,18 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
|
|||
* (re)distributors. This ensure the guest will read the
|
||||
* correct values from the memory-mapped interface.
|
||||
*/
|
||||
isb();
|
||||
dsb(sy);
|
||||
if (!cpu_if->vgic_sre) {
|
||||
isb();
|
||||
dsb(sy);
|
||||
}
|
||||
vcpu->arch.vgic_cpu.live_lrs = live_lrs;
|
||||
|
||||
/*
|
||||
* Prevent the guest from touching the GIC system registers if
|
||||
* SRE isn't enabled for GICv3 emulation.
|
||||
*/
|
||||
if (!cpu_if->vgic_sre) {
|
||||
write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
|
||||
ICC_SRE_EL2);
|
||||
}
|
||||
write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
|
||||
ICC_SRE_EL2);
|
||||
}
|
||||
|
||||
void __hyp_text __vgic_v3_init_lrs(void)
|
||||
|
|
|
|||
|
|
@ -134,6 +134,17 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool access_gic_sre(struct kvm_vcpu *vcpu,
|
||||
struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
if (p->is_write)
|
||||
return ignore_write(vcpu, p);
|
||||
|
||||
p->regval = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trap_raz_wi(struct kvm_vcpu *vcpu,
|
||||
struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
|
|
@ -958,7 +969,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
|||
access_gic_sgi },
|
||||
/* ICC_SRE_EL1 */
|
||||
{ Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
|
||||
trap_raz_wi },
|
||||
access_gic_sre },
|
||||
|
||||
/* CONTEXTIDR_EL1 */
|
||||
{ Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ static const struct prot_bits pte_bits[] = {
|
|||
|
||||
struct pg_level {
|
||||
const struct prot_bits *bits;
|
||||
const char *name;
|
||||
size_t num;
|
||||
u64 mask;
|
||||
};
|
||||
|
|
@ -157,15 +158,19 @@ struct pg_level {
|
|||
static struct pg_level pg_level[] = {
|
||||
{
|
||||
}, { /* pgd */
|
||||
.name = "PGD",
|
||||
.bits = pte_bits,
|
||||
.num = ARRAY_SIZE(pte_bits),
|
||||
}, { /* pud */
|
||||
.name = (CONFIG_PGTABLE_LEVELS > 3) ? "PUD" : "PGD",
|
||||
.bits = pte_bits,
|
||||
.num = ARRAY_SIZE(pte_bits),
|
||||
}, { /* pmd */
|
||||
.name = (CONFIG_PGTABLE_LEVELS > 2) ? "PMD" : "PGD",
|
||||
.bits = pte_bits,
|
||||
.num = ARRAY_SIZE(pte_bits),
|
||||
}, { /* pte */
|
||||
.name = "PTE",
|
||||
.bits = pte_bits,
|
||||
.num = ARRAY_SIZE(pte_bits),
|
||||
},
|
||||
|
|
@ -214,7 +219,8 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
|
|||
delta >>= 10;
|
||||
unit++;
|
||||
}
|
||||
seq_printf(st->seq, "%9lu%c", delta, *unit);
|
||||
seq_printf(st->seq, "%9lu%c %s", delta, *unit,
|
||||
pg_level[st->level].name);
|
||||
if (pg_level[st->level].bits)
|
||||
dump_prot(st, pg_level[st->level].bits,
|
||||
pg_level[st->level].num);
|
||||
|
|
|
|||
|
|
@ -306,6 +306,10 @@ static __init int setup_hugepagesz(char *opt)
|
|||
hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
|
||||
} else if (ps == PUD_SIZE) {
|
||||
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
|
||||
} else if (ps == (PAGE_SIZE * CONT_PTES)) {
|
||||
hugetlb_add_hstate(CONT_PTE_SHIFT);
|
||||
} else if (ps == (PMD_SIZE * CONT_PMDS)) {
|
||||
hugetlb_add_hstate((PMD_SHIFT + CONT_PMD_SHIFT) - PAGE_SHIFT);
|
||||
} else {
|
||||
hugetlb_bad_size();
|
||||
pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10);
|
||||
|
|
@ -314,3 +318,13 @@ static __init int setup_hugepagesz(char *opt)
|
|||
return 1;
|
||||
}
|
||||
__setup("hugepagesz=", setup_hugepagesz);
|
||||
|
||||
#ifdef CONFIG_ARM64_64K_PAGES
|
||||
static __init int add_default_hugepagesz(void)
|
||||
{
|
||||
if (size_to_hstate(CONT_PTES * PAGE_SIZE) == NULL)
|
||||
hugetlb_add_hstate(CONT_PMD_SHIFT);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(add_default_hugepagesz);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ struct pt_regs;
|
|||
void parisc_terminate(char *msg, struct pt_regs *regs,
|
||||
int code, unsigned long offset) __noreturn __cold;
|
||||
|
||||
void die_if_kernel(char *str, struct pt_regs *regs, long err);
|
||||
|
||||
/* mm/fault.c */
|
||||
void do_page_fault(struct pt_regs *regs, unsigned long code,
|
||||
unsigned long address);
|
||||
|
|
|
|||
|
|
@ -324,8 +324,9 @@ int init_per_cpu(int cpunum)
|
|||
per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
|
||||
per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
|
||||
|
||||
printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n",
|
||||
cpunum, coproc_cfg.revision, coproc_cfg.model);
|
||||
if (cpunum == 0)
|
||||
printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n",
|
||||
cpunum, coproc_cfg.revision, coproc_cfg.model);
|
||||
|
||||
/*
|
||||
** store status register to stack (hopefully aligned)
|
||||
|
|
|
|||
|
|
@ -309,11 +309,6 @@ void __init time_init(void)
|
|||
clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz,
|
||||
NSEC_PER_MSEC, 0);
|
||||
|
||||
#if defined(CONFIG_HAVE_UNSTABLE_SCHED_CLOCK) && defined(CONFIG_64BIT)
|
||||
/* At bootup only one 64bit CPU is online and cr16 is "stable" */
|
||||
set_sched_clock_stable();
|
||||
#endif
|
||||
|
||||
start_cpu_itimer(); /* get CPU 0 started */
|
||||
|
||||
/* register at clocksource framework */
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/ratelimit.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/hardirq.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
/* #define DEBUG_UNALIGNED 1 */
|
||||
|
||||
|
|
@ -130,8 +131,6 @@
|
|||
|
||||
int unaligned_enabled __read_mostly = 1;
|
||||
|
||||
void die_if_kernel (char *str, struct pt_regs *regs, long err);
|
||||
|
||||
static int emulate_ldh(struct pt_regs *regs, int toreg)
|
||||
{
|
||||
unsigned long saddr = regs->ior;
|
||||
|
|
@ -666,7 +665,7 @@ void handle_unaligned(struct pt_regs *regs)
|
|||
break;
|
||||
}
|
||||
|
||||
if (modify && R1(regs->iir))
|
||||
if (ret == 0 && modify && R1(regs->iir))
|
||||
regs->gr[R1(regs->iir)] = newbase;
|
||||
|
||||
|
||||
|
|
@ -677,6 +676,14 @@ void handle_unaligned(struct pt_regs *regs)
|
|||
|
||||
if (ret)
|
||||
{
|
||||
/*
|
||||
* The unaligned handler failed.
|
||||
* If we were called by __get_user() or __put_user() jump
|
||||
* to it's exception fixup handler instead of crashing.
|
||||
*/
|
||||
if (!user_mode(regs) && fixup_exception(regs))
|
||||
return;
|
||||
|
||||
printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
|
||||
die_if_kernel("Unaligned data reference", regs, 28);
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,10 @@ find_unwind_entry(unsigned long addr)
|
|||
if (addr >= kernel_unwind_table.start &&
|
||||
addr <= kernel_unwind_table.end)
|
||||
e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
|
||||
else
|
||||
else {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&unwind_lock, flags);
|
||||
list_for_each_entry(table, &unwind_tables, list) {
|
||||
if (addr >= table->start &&
|
||||
addr <= table->end)
|
||||
|
|
@ -86,6 +89,8 @@ find_unwind_entry(unsigned long addr)
|
|||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&unwind_lock, flags);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
|
@ -303,18 +308,16 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
|
|||
|
||||
insn = *(unsigned int *)npc;
|
||||
|
||||
if ((insn & 0xffffc000) == 0x37de0000 ||
|
||||
(insn & 0xffe00000) == 0x6fc00000) {
|
||||
if ((insn & 0xffffc001) == 0x37de0000 ||
|
||||
(insn & 0xffe00001) == 0x6fc00000) {
|
||||
/* ldo X(sp), sp, or stwm X,D(sp) */
|
||||
frame_size += (insn & 0x1 ? -1 << 13 : 0) |
|
||||
((insn & 0x3fff) >> 1);
|
||||
frame_size += (insn & 0x3fff) >> 1;
|
||||
dbg("analyzing func @ %lx, insn=%08x @ "
|
||||
"%lx, frame_size = %ld\n", info->ip,
|
||||
insn, npc, frame_size);
|
||||
} else if ((insn & 0xffe00008) == 0x73c00008) {
|
||||
} else if ((insn & 0xffe00009) == 0x73c00008) {
|
||||
/* std,ma X,D(sp) */
|
||||
frame_size += (insn & 0x1 ? -1 << 13 : 0) |
|
||||
(((insn >> 4) & 0x3ff) << 3);
|
||||
frame_size += ((insn >> 4) & 0x3ff) << 3;
|
||||
dbg("analyzing func @ %lx, insn=%08x @ "
|
||||
"%lx, frame_size = %ld\n", info->ip,
|
||||
insn, npc, frame_size);
|
||||
|
|
@ -333,6 +336,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
if (frame_size > e->Total_frame_size << 3)
|
||||
frame_size = e->Total_frame_size << 3;
|
||||
|
||||
if (!unwind_special(info, e->region_start, frame_size)) {
|
||||
info->prev_sp = info->sp - frame_size;
|
||||
if (e->Millicode)
|
||||
|
|
|
|||
|
|
@ -717,7 +717,7 @@
|
|||
#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
|
||||
#define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */
|
||||
#define SPRN_MMCR1 798
|
||||
#define SPRN_MMCR2 769
|
||||
#define SPRN_MMCR2 785
|
||||
#define SPRN_MMCRA 0x312
|
||||
#define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
|
||||
#define MMCRA_SDAR_DCACHE_MISS 0x40000000UL
|
||||
|
|
@ -754,13 +754,13 @@
|
|||
#define SPRN_PMC6 792
|
||||
#define SPRN_PMC7 793
|
||||
#define SPRN_PMC8 794
|
||||
#define SPRN_SIAR 780
|
||||
#define SPRN_SDAR 781
|
||||
#define SPRN_SIER 784
|
||||
#define SIER_SIPR 0x2000000 /* Sampled MSR_PR */
|
||||
#define SIER_SIHV 0x1000000 /* Sampled MSR_HV */
|
||||
#define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */
|
||||
#define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */
|
||||
#define SPRN_SIAR 796
|
||||
#define SPRN_SDAR 797
|
||||
#define SPRN_TACR 888
|
||||
#define SPRN_TCSCR 889
|
||||
#define SPRN_CSIGR 890
|
||||
|
|
|
|||
|
|
@ -656,6 +656,7 @@ unsigned char ibm_architecture_vec[] = {
|
|||
W(0xffff0000), W(0x003e0000), /* POWER6 */
|
||||
W(0xffff0000), W(0x003f0000), /* POWER7 */
|
||||
W(0xffff0000), W(0x004b0000), /* POWER8E */
|
||||
W(0xffff0000), W(0x004c0000), /* POWER8NVL */
|
||||
W(0xffff0000), W(0x004d0000), /* POWER8 */
|
||||
W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */
|
||||
W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
|
||||
|
|
|
|||
|
|
@ -159,6 +159,19 @@ static struct mmu_psize_def mmu_psize_defaults_gp[] = {
|
|||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* 'R' and 'C' update notes:
|
||||
* - Under pHyp or KVM, the updatepp path will not set C, thus it *will*
|
||||
* create writeable HPTEs without C set, because the hcall H_PROTECT
|
||||
* that we use in that case will not update C
|
||||
* - The above is however not a problem, because we also don't do that
|
||||
* fancy "no flush" variant of eviction and we use H_REMOVE which will
|
||||
* do the right thing and thus we don't have the race I described earlier
|
||||
*
|
||||
* - Under bare metal, we do have the race, so we need R and C set
|
||||
* - We make sure R is always set and never lost
|
||||
* - C is _PAGE_DIRTY, and *should* always be set for a writeable mapping
|
||||
*/
|
||||
unsigned long htab_convert_pte_flags(unsigned long pteflags)
|
||||
{
|
||||
unsigned long rflags = 0;
|
||||
|
|
@ -186,9 +199,14 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)
|
|||
rflags |= 0x1;
|
||||
}
|
||||
/*
|
||||
* Always add "C" bit for perf. Memory coherence is always enabled
|
||||
* We can't allow hardware to update hpte bits. Hence always
|
||||
* set 'R' bit and set 'C' if it is a write fault
|
||||
* Memory coherence is always enabled
|
||||
*/
|
||||
rflags |= HPTE_R_C | HPTE_R_M;
|
||||
rflags |= HPTE_R_R | HPTE_R_M;
|
||||
|
||||
if (pteflags & _PAGE_DIRTY)
|
||||
rflags |= HPTE_R_C;
|
||||
/*
|
||||
* Add in WIG bits
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -33,10 +33,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
|
|||
changed = !pmd_same(*(pmdp), entry);
|
||||
if (changed) {
|
||||
__ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry));
|
||||
/*
|
||||
* Since we are not supporting SW TLB systems, we don't
|
||||
* have any thing similar to flush_tlb_page_nohash()
|
||||
*/
|
||||
flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,11 +296,6 @@ static void __init radix_init_page_sizes(void)
|
|||
void __init radix__early_init_mmu(void)
|
||||
{
|
||||
unsigned long lpcr;
|
||||
/*
|
||||
* setup LPCR UPRT based on mmu_features
|
||||
*/
|
||||
lpcr = mfspr(SPRN_LPCR);
|
||||
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
|
||||
|
||||
#ifdef CONFIG_PPC_64K_PAGES
|
||||
/* PAGE_SIZE mappings */
|
||||
|
|
@ -343,8 +338,11 @@ void __init radix__early_init_mmu(void)
|
|||
__pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT;
|
||||
|
||||
radix_init_page_sizes();
|
||||
if (!firmware_has_feature(FW_FEATURE_LPAR))
|
||||
if (!firmware_has_feature(FW_FEATURE_LPAR)) {
|
||||
lpcr = mfspr(SPRN_LPCR);
|
||||
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
|
||||
radix_init_partition_table();
|
||||
}
|
||||
|
||||
radix_init_pgtable();
|
||||
}
|
||||
|
|
@ -353,16 +351,15 @@ void radix__early_init_mmu_secondary(void)
|
|||
{
|
||||
unsigned long lpcr;
|
||||
/*
|
||||
* setup LPCR UPRT based on mmu_features
|
||||
* update partition table control register and UPRT
|
||||
*/
|
||||
lpcr = mfspr(SPRN_LPCR);
|
||||
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
|
||||
/*
|
||||
* update partition table control register, 64 K size.
|
||||
*/
|
||||
if (!firmware_has_feature(FW_FEATURE_LPAR))
|
||||
if (!firmware_has_feature(FW_FEATURE_LPAR)) {
|
||||
lpcr = mfspr(SPRN_LPCR);
|
||||
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
|
||||
|
||||
mtspr(SPRN_PTCR,
|
||||
__pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
|
||||
}
|
||||
}
|
||||
|
||||
void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ static bool soc_has_mclk_mux0_canin(void)
|
|||
/* convenience wrappers around the common clk API */
|
||||
static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
|
||||
{
|
||||
return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
|
||||
return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
|
||||
}
|
||||
|
||||
static inline struct clk *mpc512x_clk_factor(
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
|
|||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
skip = roundup(cprm->file->f_pos - total + sz, 4) - cprm->file->f_pos;
|
||||
skip = roundup(cprm->pos - total + sz, 4) - cprm->pos;
|
||||
if (!dump_skip(cprm, skip))
|
||||
goto Eio;
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ static int ibm_read_slot_reset_state2;
|
|||
static int ibm_slot_error_detail;
|
||||
static int ibm_get_config_addr_info;
|
||||
static int ibm_get_config_addr_info2;
|
||||
static int ibm_configure_bridge;
|
||||
static int ibm_configure_pe;
|
||||
|
||||
/*
|
||||
|
|
@ -81,7 +80,14 @@ static int pseries_eeh_init(void)
|
|||
ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2");
|
||||
ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
|
||||
ibm_configure_pe = rtas_token("ibm,configure-pe");
|
||||
ibm_configure_bridge = rtas_token("ibm,configure-bridge");
|
||||
|
||||
/*
|
||||
* ibm,configure-pe and ibm,configure-bridge have the same semantics,
|
||||
* however ibm,configure-pe can be faster. If we can't find
|
||||
* ibm,configure-pe then fall back to using ibm,configure-bridge.
|
||||
*/
|
||||
if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE)
|
||||
ibm_configure_pe = rtas_token("ibm,configure-bridge");
|
||||
|
||||
/*
|
||||
* Necessary sanity check. We needn't check "get-config-addr-info"
|
||||
|
|
@ -93,8 +99,7 @@ static int pseries_eeh_init(void)
|
|||
(ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
|
||||
ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) ||
|
||||
ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE ||
|
||||
(ibm_configure_pe == RTAS_UNKNOWN_SERVICE &&
|
||||
ibm_configure_bridge == RTAS_UNKNOWN_SERVICE)) {
|
||||
ibm_configure_pe == RTAS_UNKNOWN_SERVICE) {
|
||||
pr_info("EEH functionality not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -615,29 +620,41 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
|
|||
{
|
||||
int config_addr;
|
||||
int ret;
|
||||
/* Waiting 0.2s maximum before skipping configuration */
|
||||
int max_wait = 200;
|
||||
|
||||
/* Figure out the PE address */
|
||||
config_addr = pe->config_addr;
|
||||
if (pe->addr)
|
||||
config_addr = pe->addr;
|
||||
|
||||
/* Use new configure-pe function, if supported */
|
||||
if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
|
||||
while (max_wait > 0) {
|
||||
ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
|
||||
config_addr, BUID_HI(pe->phb->buid),
|
||||
BUID_LO(pe->phb->buid));
|
||||
} else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
|
||||
ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
|
||||
config_addr, BUID_HI(pe->phb->buid),
|
||||
BUID_LO(pe->phb->buid));
|
||||
} else {
|
||||
return -EFAULT;
|
||||
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* If RTAS returns a delay value that's above 100ms, cut it
|
||||
* down to 100ms in case firmware made a mistake. For more
|
||||
* on how these delay values work see rtas_busy_delay_time
|
||||
*/
|
||||
if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
|
||||
ret <= RTAS_EXTENDED_DELAY_MAX)
|
||||
ret = RTAS_EXTENDED_DELAY_MIN+2;
|
||||
|
||||
max_wait -= rtas_busy_delay_time(ret);
|
||||
|
||||
if (max_wait < 0)
|
||||
break;
|
||||
|
||||
rtas_busy_delay(ret);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
|
||||
__func__, pe->phb->global_number, pe->addr, ret);
|
||||
|
||||
pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
|
||||
__func__, pe->phb->global_number, pe->addr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,19 +181,22 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
|
|||
struct kvm_cpuid_entry __user *entries)
|
||||
{
|
||||
int r, i;
|
||||
struct kvm_cpuid_entry *cpuid_entries;
|
||||
struct kvm_cpuid_entry *cpuid_entries = NULL;
|
||||
|
||||
r = -E2BIG;
|
||||
if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
|
||||
goto out;
|
||||
r = -ENOMEM;
|
||||
cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * cpuid->nent);
|
||||
if (!cpuid_entries)
|
||||
goto out;
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(cpuid_entries, entries,
|
||||
cpuid->nent * sizeof(struct kvm_cpuid_entry)))
|
||||
goto out_free;
|
||||
if (cpuid->nent) {
|
||||
cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) *
|
||||
cpuid->nent);
|
||||
if (!cpuid_entries)
|
||||
goto out;
|
||||
r = -EFAULT;
|
||||
if (copy_from_user(cpuid_entries, entries,
|
||||
cpuid->nent * sizeof(struct kvm_cpuid_entry)))
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < cpuid->nent; i++) {
|
||||
vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function;
|
||||
vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax;
|
||||
|
|
@ -212,9 +215,8 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
|
|||
kvm_x86_ops->cpuid_update(vcpu);
|
||||
r = kvm_update_cpuid(vcpu);
|
||||
|
||||
out_free:
|
||||
vfree(cpuid_entries);
|
||||
out:
|
||||
vfree(cpuid_entries);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -336,12 +336,12 @@ static gfn_t pse36_gfn_delta(u32 gpte)
|
|||
#ifdef CONFIG_X86_64
|
||||
static void __set_spte(u64 *sptep, u64 spte)
|
||||
{
|
||||
*sptep = spte;
|
||||
WRITE_ONCE(*sptep, spte);
|
||||
}
|
||||
|
||||
static void __update_clear_spte_fast(u64 *sptep, u64 spte)
|
||||
{
|
||||
*sptep = spte;
|
||||
WRITE_ONCE(*sptep, spte);
|
||||
}
|
||||
|
||||
static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
|
||||
|
|
@ -390,7 +390,7 @@ static void __set_spte(u64 *sptep, u64 spte)
|
|||
*/
|
||||
smp_wmb();
|
||||
|
||||
ssptep->spte_low = sspte.spte_low;
|
||||
WRITE_ONCE(ssptep->spte_low, sspte.spte_low);
|
||||
}
|
||||
|
||||
static void __update_clear_spte_fast(u64 *sptep, u64 spte)
|
||||
|
|
@ -400,7 +400,7 @@ static void __update_clear_spte_fast(u64 *sptep, u64 spte)
|
|||
ssptep = (union split_spte *)sptep;
|
||||
sspte = (union split_spte)spte;
|
||||
|
||||
ssptep->spte_low = sspte.spte_low;
|
||||
WRITE_ONCE(ssptep->spte_low, sspte.spte_low);
|
||||
|
||||
/*
|
||||
* If we map the spte from present to nonpresent, we should clear
|
||||
|
|
|
|||
|
|
@ -2314,6 +2314,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
|||
case MSR_AMD64_NB_CFG:
|
||||
case MSR_FAM10H_MMIO_CONF_BASE:
|
||||
case MSR_AMD64_BU_CFG2:
|
||||
case MSR_IA32_PERF_CTL:
|
||||
msr_info->data = 0;
|
||||
break;
|
||||
case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3:
|
||||
|
|
@ -2972,6 +2973,10 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
|
|||
| KVM_VCPUEVENT_VALID_SMM))
|
||||
return -EINVAL;
|
||||
|
||||
if (events->exception.injected &&
|
||||
(events->exception.nr > 31 || events->exception.nr == NMI_VECTOR))
|
||||
return -EINVAL;
|
||||
|
||||
process_nmi(vcpu);
|
||||
vcpu->arch.exception.pending = events->exception.injected;
|
||||
vcpu->arch.exception.nr = events->exception.nr;
|
||||
|
|
@ -3036,6 +3041,11 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
|
|||
if (dbgregs->flags)
|
||||
return -EINVAL;
|
||||
|
||||
if (dbgregs->dr6 & ~0xffffffffull)
|
||||
return -EINVAL;
|
||||
if (dbgregs->dr7 & ~0xffffffffull)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db));
|
||||
kvm_update_dr0123(vcpu);
|
||||
vcpu->arch.dr6 = dbgregs->dr6;
|
||||
|
|
@ -7815,7 +7825,7 @@ int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
|
|||
|
||||
slot = id_to_memslot(slots, id);
|
||||
if (size) {
|
||||
if (WARN_ON(slot->npages))
|
||||
if (slot->npages)
|
||||
return -EEXIST;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -331,15 +331,6 @@ static int acpi_processor_get_info(struct acpi_device *device)
|
|||
pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
|
||||
|
||||
pr->pblk = object.processor.pblk_address;
|
||||
|
||||
/*
|
||||
* We don't care about error returns - we just try to mark
|
||||
* these reserved so that nobody else is confused into thinking
|
||||
* that this region might be unused..
|
||||
*
|
||||
* (In particular, allocating the IO range for Cardbus)
|
||||
*/
|
||||
request_region(pr->throttling.address, 6, "ACPI CPU throttle");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -754,7 +754,8 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
|
|||
}
|
||||
|
||||
int acpi_video_get_levels(struct acpi_device *device,
|
||||
struct acpi_video_device_brightness **dev_br)
|
||||
struct acpi_video_device_brightness **dev_br,
|
||||
int *pmax_level)
|
||||
{
|
||||
union acpi_object *obj = NULL;
|
||||
int i, max_level = 0, count = 0, level_ac_battery = 0;
|
||||
|
|
@ -841,6 +842,8 @@ int acpi_video_get_levels(struct acpi_device *device,
|
|||
|
||||
br->count = count;
|
||||
*dev_br = br;
|
||||
if (pmax_level)
|
||||
*pmax_level = max_level;
|
||||
|
||||
out:
|
||||
kfree(obj);
|
||||
|
|
@ -869,7 +872,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
|
|||
struct acpi_video_device_brightness *br = NULL;
|
||||
int result = -EINVAL;
|
||||
|
||||
result = acpi_video_get_levels(device->dev, &br);
|
||||
result = acpi_video_get_levels(device->dev, &br, &max_level);
|
||||
if (result)
|
||||
return result;
|
||||
device->brightness = br;
|
||||
|
|
@ -1737,7 +1740,7 @@ static void acpi_video_run_bcl_for_osi(struct acpi_video_bus *video)
|
|||
|
||||
mutex_lock(&video->device_list_lock);
|
||||
list_for_each_entry(dev, &video->video_device_list, entry) {
|
||||
if (!acpi_video_device_lcd_query_levels(dev, &levels))
|
||||
if (!acpi_video_device_lcd_query_levels(dev->dev->handle, &levels))
|
||||
kfree(levels);
|
||||
}
|
||||
mutex_unlock(&video->device_list_lock);
|
||||
|
|
|
|||
|
|
@ -83,27 +83,22 @@ acpi_hw_write_multiple(u32 value,
|
|||
static u8
|
||||
acpi_hw_get_access_bit_width(struct acpi_generic_address *reg, u8 max_bit_width)
|
||||
{
|
||||
u64 address;
|
||||
|
||||
if (!reg->access_width) {
|
||||
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||
max_bit_width = 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect old register descriptors where only the bit_width field
|
||||
* makes senses. The target address is copied to handle possible
|
||||
* alignment issues.
|
||||
* makes senses.
|
||||
*/
|
||||
ACPI_MOVE_64_TO_64(&address, ®->address);
|
||||
if (!reg->bit_offset && reg->bit_width &&
|
||||
if (reg->bit_width < max_bit_width &&
|
||||
!reg->bit_offset && reg->bit_width &&
|
||||
ACPI_IS_POWER_OF_TWO(reg->bit_width) &&
|
||||
ACPI_IS_ALIGNED(reg->bit_width, 8) &&
|
||||
ACPI_IS_ALIGNED(address, reg->bit_width)) {
|
||||
ACPI_IS_ALIGNED(reg->bit_width, 8)) {
|
||||
return (reg->bit_width);
|
||||
} else {
|
||||
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
|
||||
return (32);
|
||||
} else {
|
||||
return (max_bit_width);
|
||||
}
|
||||
}
|
||||
return (max_bit_width);
|
||||
} else {
|
||||
return (1 << (reg->access_width + 2));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -676,6 +676,15 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
|
|||
if (!pr->flags.throttling)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* We don't care about error returns - we just try to mark
|
||||
* these reserved so that nobody else is confused into thinking
|
||||
* that this region might be unused..
|
||||
*
|
||||
* (In particular, allocating the IO range for Cardbus)
|
||||
*/
|
||||
request_region(pr->throttling.address, 6, "ACPI CPU throttle");
|
||||
|
||||
pr->throttling.state = 0;
|
||||
|
||||
duty_mask = pr->throttling.state_count - 1;
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ config COMMON_CLK_KEYSTONE
|
|||
config COMMON_CLK_NXP
|
||||
def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
|
||||
select REGMAP_MMIO if ARCH_LPC32XX
|
||||
select MFD_SYSCON if ARCH_LPC18XX
|
||||
---help---
|
||||
Support for clock providers on NXP platforms.
|
||||
|
||||
|
|
|
|||
|
|
@ -180,15 +180,15 @@ static int pic32mzda_clk_probe(struct platform_device *pdev)
|
|||
|
||||
/* register fixed rate clocks */
|
||||
clks[POSCCLK] = clk_register_fixed_rate(&pdev->dev, "posc_clk", NULL,
|
||||
CLK_IS_ROOT, 24000000);
|
||||
0, 24000000);
|
||||
clks[FRCCLK] = clk_register_fixed_rate(&pdev->dev, "frc_clk", NULL,
|
||||
CLK_IS_ROOT, 8000000);
|
||||
0, 8000000);
|
||||
clks[BFRCCLK] = clk_register_fixed_rate(&pdev->dev, "bfrc_clk", NULL,
|
||||
CLK_IS_ROOT, 8000000);
|
||||
0, 8000000);
|
||||
clks[LPRCCLK] = clk_register_fixed_rate(&pdev->dev, "lprc_clk", NULL,
|
||||
CLK_IS_ROOT, 32000);
|
||||
0, 32000);
|
||||
clks[UPLLCLK] = clk_register_fixed_rate(&pdev->dev, "usbphy_clk", NULL,
|
||||
CLK_IS_ROOT, 24000000);
|
||||
0, 24000000);
|
||||
/* fixed rate (optional) clock */
|
||||
if (of_find_property(np, "microchip,pic32mzda-sosc", NULL)) {
|
||||
pr_info("pic32-clk: dt requests SOSC.\n");
|
||||
|
|
|
|||
|
|
@ -1832,7 +1832,7 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier);
|
|||
unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq)
|
||||
{
|
||||
clamp_val(target_freq, policy->min, policy->max);
|
||||
target_freq = clamp_val(target_freq, policy->min, policy->max);
|
||||
|
||||
return cpufreq_driver->fast_switch(policy, target_freq);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -449,7 +449,7 @@ static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
|
|||
cpu->acpi_perf_data.states[0].core_frequency =
|
||||
policy->cpuinfo.max_freq / 1000;
|
||||
cpu->valid_pss_table = true;
|
||||
pr_info("_PPC limits will be enforced\n");
|
||||
pr_debug("_PPC limits will be enforced\n");
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -565,7 +565,8 @@ void edac_mc_reset_delay_period(unsigned long value)
|
|||
list_for_each(item, &mc_devices) {
|
||||
mci = list_entry(item, struct mem_ctl_info, link);
|
||||
|
||||
edac_mod_work(&mci->work, value);
|
||||
if (mci->op_state == OP_RUNNING_POLL)
|
||||
edac_mod_work(&mci->work, value);
|
||||
}
|
||||
mutex_unlock(&mem_ctls_mutex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,8 +239,11 @@ static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = {
|
|||
{ 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
|
||||
};
|
||||
|
||||
#define RIR_RNK_TGT(reg) GET_BITFIELD(reg, 16, 19)
|
||||
#define RIR_OFFSET(reg) GET_BITFIELD(reg, 2, 14)
|
||||
#define RIR_RNK_TGT(type, reg) (((type) == BROADWELL) ? \
|
||||
GET_BITFIELD(reg, 20, 23) : GET_BITFIELD(reg, 16, 19))
|
||||
|
||||
#define RIR_OFFSET(type, reg) (((type) == HASWELL || (type) == BROADWELL) ? \
|
||||
GET_BITFIELD(reg, 2, 15) : GET_BITFIELD(reg, 2, 14))
|
||||
|
||||
/* Device 16, functions 2-7 */
|
||||
|
||||
|
|
@ -326,6 +329,7 @@ struct pci_id_descr {
|
|||
struct pci_id_table {
|
||||
const struct pci_id_descr *descr;
|
||||
int n_devs;
|
||||
enum type type;
|
||||
};
|
||||
|
||||
struct sbridge_dev {
|
||||
|
|
@ -394,9 +398,14 @@ static const struct pci_id_descr pci_dev_descr_sbridge[] = {
|
|||
{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) },
|
||||
};
|
||||
|
||||
#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
|
||||
#define PCI_ID_TABLE_ENTRY(A, T) { \
|
||||
.descr = A, \
|
||||
.n_devs = ARRAY_SIZE(A), \
|
||||
.type = T \
|
||||
}
|
||||
|
||||
static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge),
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, SANDY_BRIDGE),
|
||||
{0,} /* 0 terminated list. */
|
||||
};
|
||||
|
||||
|
|
@ -463,7 +472,7 @@ static const struct pci_id_descr pci_dev_descr_ibridge[] = {
|
|||
};
|
||||
|
||||
static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge),
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, IVY_BRIDGE),
|
||||
{0,} /* 0 terminated list. */
|
||||
};
|
||||
|
||||
|
|
@ -536,7 +545,7 @@ static const struct pci_id_descr pci_dev_descr_haswell[] = {
|
|||
};
|
||||
|
||||
static const struct pci_id_table pci_dev_descr_haswell_table[] = {
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell),
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, HASWELL),
|
||||
{0,} /* 0 terminated list. */
|
||||
};
|
||||
|
||||
|
|
@ -580,7 +589,7 @@ static const struct pci_id_descr pci_dev_descr_knl[] = {
|
|||
};
|
||||
|
||||
static const struct pci_id_table pci_dev_descr_knl_table[] = {
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_knl),
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, KNIGHTS_LANDING),
|
||||
{0,}
|
||||
};
|
||||
|
||||
|
|
@ -648,7 +657,7 @@ static const struct pci_id_descr pci_dev_descr_broadwell[] = {
|
|||
};
|
||||
|
||||
static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell),
|
||||
PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, BROADWELL),
|
||||
{0,} /* 0 terminated list. */
|
||||
};
|
||||
|
||||
|
|
@ -1894,14 +1903,14 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
|
|||
pci_read_config_dword(pvt->pci_tad[i],
|
||||
rir_offset[j][k],
|
||||
®);
|
||||
tmp_mb = RIR_OFFSET(reg) << 6;
|
||||
tmp_mb = RIR_OFFSET(pvt->info.type, reg) << 6;
|
||||
|
||||
gb = div_u64_rem(tmp_mb, 1024, &mb);
|
||||
edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
|
||||
i, j, k,
|
||||
gb, (mb*1000)/1024,
|
||||
((u64)tmp_mb) << 20L,
|
||||
(u32)RIR_RNK_TGT(reg),
|
||||
(u32)RIR_RNK_TGT(pvt->info.type, reg),
|
||||
reg);
|
||||
}
|
||||
}
|
||||
|
|
@ -2234,7 +2243,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
|
|||
pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
|
||||
rir_offset[n_rir][idx],
|
||||
®);
|
||||
*rank = RIR_RNK_TGT(reg);
|
||||
*rank = RIR_RNK_TGT(pvt->info.type, reg);
|
||||
|
||||
edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
|
||||
n_rir,
|
||||
|
|
@ -3357,12 +3366,12 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
|
|||
#define ICPU(model, table) \
|
||||
{ X86_VENDOR_INTEL, 6, model, 0, (unsigned long)&table }
|
||||
|
||||
/* Order here must match "enum type" */
|
||||
static const struct x86_cpu_id sbridge_cpuids[] = {
|
||||
ICPU(0x2d, pci_dev_descr_sbridge_table), /* SANDY_BRIDGE */
|
||||
ICPU(0x3e, pci_dev_descr_ibridge_table), /* IVY_BRIDGE */
|
||||
ICPU(0x3f, pci_dev_descr_haswell_table), /* HASWELL */
|
||||
ICPU(0x4f, pci_dev_descr_broadwell_table), /* BROADWELL */
|
||||
ICPU(0x56, pci_dev_descr_broadwell_table), /* BROADWELL-DE */
|
||||
ICPU(0x57, pci_dev_descr_knl_table), /* KNIGHTS_LANDING */
|
||||
{ }
|
||||
};
|
||||
|
|
@ -3398,7 +3407,7 @@ static int sbridge_probe(const struct x86_cpu_id *id)
|
|||
mc, mc + 1, num_mc);
|
||||
|
||||
sbridge_dev->mc = mc++;
|
||||
rc = sbridge_register_mci(sbridge_dev, id - sbridge_cpuids);
|
||||
rc = sbridge_register_mci(sbridge_dev, ptable->type);
|
||||
if (unlikely(rc < 0))
|
||||
goto fail1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,17 @@
|
|||
*
|
||||
*/
|
||||
|
||||
static void hdlcd_crtc_cleanup(struct drm_crtc *crtc)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
|
||||
/* stop the controller on cleanup */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
|
||||
drm_crtc_cleanup(crtc);
|
||||
}
|
||||
|
||||
static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
|
||||
.destroy = drm_crtc_cleanup,
|
||||
.destroy = hdlcd_crtc_cleanup,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
.reset = drm_atomic_helper_crtc_reset,
|
||||
|
|
@ -97,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
|||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
struct drm_display_mode *m = &crtc->state->adjusted_mode;
|
||||
struct videomode vm;
|
||||
unsigned int polarities, line_length, err;
|
||||
unsigned int polarities, err;
|
||||
|
||||
vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
|
||||
vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
|
||||
|
|
@ -113,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
|||
if (m->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
polarities |= HDLCD_POLARITY_VSYNC;
|
||||
|
||||
line_length = crtc->primary->state->fb->pitches[0];
|
||||
|
||||
/* Allow max number of outstanding requests and largest burst size */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
|
||||
HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);
|
||||
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);
|
||||
|
||||
err = hdlcd_set_pxl_fmt(crtc);
|
||||
|
|
@ -144,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
|
|||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
|
||||
clk_prepare_enable(hdlcd->clk);
|
||||
hdlcd_crtc_mode_set_nofb(crtc);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
}
|
||||
|
||||
static void hdlcd_crtc_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
|
||||
if (!crtc->primary->fb)
|
||||
if (!crtc->state->active)
|
||||
return;
|
||||
|
||||
clk_disable_unprepare(hdlcd->clk);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
|
||||
drm_crtc_vblank_off(crtc);
|
||||
clk_disable_unprepare(hdlcd->clk);
|
||||
}
|
||||
|
||||
static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
|
|
@ -179,20 +182,17 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
|
|||
static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
|
||||
unsigned long flags;
|
||||
|
||||
if (crtc->state->event) {
|
||||
struct drm_pending_vblank_event *event = crtc->state->event;
|
||||
struct drm_pending_vblank_event *event = crtc->state->event;
|
||||
|
||||
if (event) {
|
||||
crtc->state->event = NULL;
|
||||
event->pipe = drm_crtc_index(crtc);
|
||||
|
||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
|
||||
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
||||
list_add_tail(&event->base.link, &hdlcd->event_list);
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
if (drm_crtc_vblank_get(crtc) == 0)
|
||||
drm_crtc_arm_vblank_event(crtc, event);
|
||||
else
|
||||
drm_crtc_send_vblank_event(crtc, event);
|
||||
spin_unlock_irq(&crtc->dev->event_lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -225,6 +225,15 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
|
|||
static int hdlcd_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
u32 src_w, src_h;
|
||||
|
||||
src_w = state->src_w >> 16;
|
||||
src_h = state->src_h >> 16;
|
||||
|
||||
/* we can't do any scaling of the plane source */
|
||||
if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -233,20 +242,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
|
|||
{
|
||||
struct hdlcd_drm_private *hdlcd;
|
||||
struct drm_gem_cma_object *gem;
|
||||
unsigned int depth, bpp;
|
||||
u32 src_w, src_h, dest_w, dest_h;
|
||||
dma_addr_t scanout_start;
|
||||
|
||||
if (!plane->state->crtc || !plane->state->fb)
|
||||
if (!plane->state->fb)
|
||||
return;
|
||||
|
||||
hdlcd = crtc_to_hdlcd_priv(plane->state->crtc);
|
||||
drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
|
||||
src_w = plane->state->src_w >> 16;
|
||||
src_h = plane->state->src_h >> 16;
|
||||
dest_w = plane->state->crtc_w;
|
||||
dest_h = plane->state->crtc_h;
|
||||
gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
|
||||
scanout_start = gem->paddr;
|
||||
scanout_start = gem->paddr + plane->state->fb->offsets[0] +
|
||||
plane->state->crtc_y * plane->state->fb->pitches[0] +
|
||||
plane->state->crtc_x * bpp / 8;
|
||||
|
||||
hdlcd = plane->dev->dev_private;
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, plane->state->fb->pitches[0]);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
|
||||
.prepare_fb = NULL,
|
||||
.cleanup_fb = NULL,
|
||||
.atomic_check = hdlcd_plane_atomic_check,
|
||||
.atomic_update = hdlcd_plane_atomic_update,
|
||||
};
|
||||
|
|
@ -294,16 +314,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
|
|||
return plane;
|
||||
}
|
||||
|
||||
void hdlcd_crtc_suspend(struct drm_crtc *crtc)
|
||||
{
|
||||
hdlcd_crtc_disable(crtc);
|
||||
}
|
||||
|
||||
void hdlcd_crtc_resume(struct drm_crtc *crtc)
|
||||
{
|
||||
hdlcd_crtc_enable(crtc);
|
||||
}
|
||||
|
||||
int hdlcd_setup_crtc(struct drm_device *drm)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
|
|
|
|||
|
|
@ -49,8 +49,6 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
|
|||
atomic_set(&hdlcd->dma_end_count, 0);
|
||||
#endif
|
||||
|
||||
INIT_LIST_HEAD(&hdlcd->event_list);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
|
||||
if (IS_ERR(hdlcd->mmio)) {
|
||||
|
|
@ -84,11 +82,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
|
|||
goto setup_fail;
|
||||
}
|
||||
|
||||
pm_runtime_enable(drm->dev);
|
||||
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to install IRQ handler\n");
|
||||
goto irq_fail;
|
||||
|
|
@ -164,24 +158,9 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
|
|||
atomic_inc(&hdlcd->vsync_count);
|
||||
|
||||
#endif
|
||||
if (irq_status & HDLCD_INTERRUPT_VSYNC) {
|
||||
bool events_sent = false;
|
||||
unsigned long flags;
|
||||
struct drm_pending_vblank_event *e, *t;
|
||||
|
||||
if (irq_status & HDLCD_INTERRUPT_VSYNC)
|
||||
drm_crtc_handle_vblank(&hdlcd->crtc);
|
||||
|
||||
spin_lock_irqsave(&drm->event_lock, flags);
|
||||
list_for_each_entry_safe(e, t, &hdlcd->event_list, base.link) {
|
||||
list_del(&e->base.link);
|
||||
drm_crtc_send_vblank_event(&hdlcd->crtc, e);
|
||||
events_sent = true;
|
||||
}
|
||||
if (events_sent)
|
||||
drm_crtc_vblank_put(&hdlcd->crtc);
|
||||
spin_unlock_irqrestore(&drm->event_lock, flags);
|
||||
}
|
||||
|
||||
/* acknowledge interrupt(s) */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
|
||||
|
||||
|
|
@ -275,6 +254,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
|
|||
static struct drm_info_list hdlcd_debugfs_list[] = {
|
||||
{ "interrupt_count", hdlcd_show_underrun_count, 0 },
|
||||
{ "clocks", hdlcd_show_pxlclock, 0 },
|
||||
{ "fb", drm_fb_cma_debugfs_show, 0 },
|
||||
};
|
||||
|
||||
static int hdlcd_debugfs_init(struct drm_minor *minor)
|
||||
|
|
@ -357,6 +337,8 @@ static int hdlcd_drm_bind(struct device *dev)
|
|||
return -ENOMEM;
|
||||
|
||||
drm->dev_private = hdlcd;
|
||||
dev_set_drvdata(dev, drm);
|
||||
|
||||
hdlcd_setup_mode_config(drm);
|
||||
ret = hdlcd_load(drm, 0);
|
||||
if (ret)
|
||||
|
|
@ -366,14 +348,18 @@ static int hdlcd_drm_bind(struct device *dev)
|
|||
if (ret)
|
||||
goto err_unload;
|
||||
|
||||
dev_set_drvdata(dev, drm);
|
||||
|
||||
ret = component_bind_all(dev, drm);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to bind all components\n");
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
ret = pm_runtime_set_active(dev);
|
||||
if (ret)
|
||||
goto err_pm_active;
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to initialise vblank\n");
|
||||
|
|
@ -399,16 +385,16 @@ static int hdlcd_drm_bind(struct device *dev)
|
|||
drm_mode_config_cleanup(drm);
|
||||
drm_vblank_cleanup(drm);
|
||||
err_vblank:
|
||||
pm_runtime_disable(drm->dev);
|
||||
err_pm_active:
|
||||
component_unbind_all(dev, drm);
|
||||
err_unregister:
|
||||
drm_dev_unregister(drm);
|
||||
err_unload:
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
drm_irq_uninstall(drm);
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
pm_runtime_disable(drm->dev);
|
||||
of_reserved_mem_device_release(drm->dev);
|
||||
err_free:
|
||||
dev_set_drvdata(dev, NULL);
|
||||
drm_dev_unref(drm);
|
||||
|
||||
return ret;
|
||||
|
|
@ -495,30 +481,34 @@ MODULE_DEVICE_TABLE(of, hdlcd_of_match);
|
|||
static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
struct drm_crtc *crtc;
|
||||
struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
if (!hdlcd)
|
||||
return 0;
|
||||
|
||||
drm_modeset_lock_all(drm);
|
||||
list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
|
||||
hdlcd_crtc_suspend(crtc);
|
||||
drm_modeset_unlock_all(drm);
|
||||
drm_kms_helper_poll_disable(drm);
|
||||
|
||||
hdlcd->state = drm_atomic_helper_suspend(drm);
|
||||
if (IS_ERR(hdlcd->state)) {
|
||||
drm_kms_helper_poll_enable(drm);
|
||||
return PTR_ERR(hdlcd->state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused hdlcd_pm_resume(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
struct drm_crtc *crtc;
|
||||
struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
if (!hdlcd)
|
||||
return 0;
|
||||
|
||||
drm_modeset_lock_all(drm);
|
||||
list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
|
||||
hdlcd_crtc_resume(crtc);
|
||||
drm_modeset_unlock_all(drm);
|
||||
drm_atomic_helper_resume(drm, hdlcd->state);
|
||||
drm_kms_helper_poll_enable(drm);
|
||||
pm_runtime_set_active(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,9 @@ struct hdlcd_drm_private {
|
|||
void __iomem *mmio;
|
||||
struct clk *clk;
|
||||
struct drm_fbdev_cma *fbdev;
|
||||
struct drm_framebuffer *fb;
|
||||
struct list_head event_list;
|
||||
struct drm_crtc crtc;
|
||||
struct drm_plane *plane;
|
||||
struct drm_atomic_state *state;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
atomic_t buffer_underrun_count;
|
||||
atomic_t bus_error_count;
|
||||
|
|
@ -36,7 +35,5 @@ static inline u32 hdlcd_read(struct hdlcd_drm_private *hdlcd, unsigned int reg)
|
|||
|
||||
int hdlcd_setup_crtc(struct drm_device *dev);
|
||||
void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd);
|
||||
void hdlcd_crtc_suspend(struct drm_crtc *crtc);
|
||||
void hdlcd_crtc_resume(struct drm_crtc *crtc);
|
||||
|
||||
#endif /* __HDLCD_DRV_H__ */
|
||||
|
|
|
|||
|
|
@ -391,12 +391,11 @@ void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc)
|
|||
{
|
||||
struct atmel_hlcdc_crtc_state *state;
|
||||
|
||||
if (crtc->state && crtc->state->mode_blob)
|
||||
drm_property_unreference_blob(crtc->state->mode_blob);
|
||||
|
||||
if (crtc->state) {
|
||||
__drm_atomic_helper_crtc_destroy_state(crtc->state);
|
||||
state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
|
||||
kfree(state);
|
||||
crtc->state = NULL;
|
||||
}
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
|
|
@ -415,8 +414,9 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
|
|||
return NULL;
|
||||
|
||||
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (state)
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
|
||||
if (!state)
|
||||
return NULL;
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
|
||||
|
||||
cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
|
||||
state->output_mode = cur->output_mode;
|
||||
|
|
|
|||
|
|
@ -351,6 +351,8 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
|||
drm_property_unreference_blob(state->mode_blob);
|
||||
state->mode_blob = NULL;
|
||||
|
||||
memset(&state->mode, 0, sizeof(state->mode));
|
||||
|
||||
if (blob) {
|
||||
if (blob->length != sizeof(struct drm_mode_modeinfo) ||
|
||||
drm_mode_convert_umode(&state->mode,
|
||||
|
|
@ -363,7 +365,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
|||
DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
|
||||
state->mode.name, state);
|
||||
} else {
|
||||
memset(&state->mode, 0, sizeof(state->mode));
|
||||
state->enable = false;
|
||||
DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
|
||||
state);
|
||||
|
|
|
|||
|
|
@ -2821,8 +2821,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
goto out;
|
||||
}
|
||||
|
||||
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
/*
|
||||
* Check whether the primary plane supports the fb pixel format.
|
||||
* Drivers not implementing the universal planes API use a
|
||||
|
|
@ -4841,7 +4839,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
|
|||
if (value == 0)
|
||||
return true;
|
||||
|
||||
return _object_find(property->dev, value, property->values[0]) != NULL;
|
||||
*ref = _object_find(property->dev, value, property->values[0]);
|
||||
return *ref != NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < property->num_values; i++)
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper,
|
|||
err_fb_info_destroy:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
err_gem_free_object:
|
||||
dev->driver->gem_free_object(&obj->base);
|
||||
drm_gem_object_unreference_unlocked(&obj->base);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fbdev_cma_create_with_funcs);
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
|
|||
return cma_obj;
|
||||
|
||||
error:
|
||||
drm->driver->gem_free_object(&cma_obj->base);
|
||||
drm_gem_object_unreference_unlocked(&cma_obj->base);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_create);
|
||||
|
|
@ -162,18 +162,12 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
|
|||
* and handle has the id what user can see.
|
||||
*/
|
||||
ret = drm_gem_handle_create(file_priv, gem_obj, handle);
|
||||
if (ret)
|
||||
goto err_handle_create;
|
||||
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_unreference_unlocked(gem_obj);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return cma_obj;
|
||||
|
||||
err_handle_create:
|
||||
drm->driver->gem_free_object(gem_obj);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1518,6 +1518,8 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
|
|||
if (out->status != MODE_OK)
|
||||
goto out;
|
||||
|
||||
drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
|
||||
int hsync_pin, int vsync_pin)
|
||||
int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
|
||||
int hsync_pin, int vsync_pin, u32 bus_flags)
|
||||
{
|
||||
struct imx_drm_crtc_helper_funcs *helper;
|
||||
struct imx_drm_crtc *imx_crtc;
|
||||
|
|
@ -110,14 +110,17 @@ int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
|
|||
helper = &imx_crtc->imx_drm_helper_funcs;
|
||||
if (helper->set_interface_pix_fmt)
|
||||
return helper->set_interface_pix_fmt(encoder->crtc,
|
||||
bus_format, hsync_pin, vsync_pin);
|
||||
bus_format, hsync_pin, vsync_pin,
|
||||
bus_flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(imx_drm_set_bus_format_pins);
|
||||
EXPORT_SYMBOL_GPL(imx_drm_set_bus_config);
|
||||
|
||||
int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format)
|
||||
{
|
||||
return imx_drm_set_bus_format_pins(encoder, bus_format, 2, 3);
|
||||
return imx_drm_set_bus_config(encoder, bus_format, 2, 3,
|
||||
DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_PIXDATA_NEGEDGE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(imx_drm_set_bus_format);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ struct imx_drm_crtc_helper_funcs {
|
|||
int (*enable_vblank)(struct drm_crtc *crtc);
|
||||
void (*disable_vblank)(struct drm_crtc *crtc);
|
||||
int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
|
||||
u32 bus_format, int hsync_pin, int vsync_pin);
|
||||
u32 bus_format, int hsync_pin, int vsync_pin,
|
||||
u32 bus_flags);
|
||||
const struct drm_crtc_helper_funcs *crtc_helper_funcs;
|
||||
const struct drm_crtc_funcs *crtc_funcs;
|
||||
};
|
||||
|
|
@ -41,8 +42,8 @@ void imx_drm_mode_config_init(struct drm_device *drm);
|
|||
|
||||
struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
|
||||
|
||||
int imx_drm_set_bus_format_pins(struct drm_encoder *encoder,
|
||||
u32 bus_format, int hsync_pin, int vsync_pin);
|
||||
int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
|
||||
int hsync_pin, int vsync_pin, u32 bus_flags);
|
||||
int imx_drm_set_bus_format(struct drm_encoder *encoder,
|
||||
u32 bus_format);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <video/of_display_timing.h>
|
||||
#include <video/of_videomode.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
|
@ -59,6 +60,7 @@ struct imx_ldb_channel {
|
|||
struct drm_encoder encoder;
|
||||
struct drm_panel *panel;
|
||||
struct device_node *child;
|
||||
struct i2c_adapter *ddc;
|
||||
int chno;
|
||||
void *edid;
|
||||
int edid_len;
|
||||
|
|
@ -107,6 +109,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
|
|||
return num_modes;
|
||||
}
|
||||
|
||||
if (!imx_ldb_ch->edid && imx_ldb_ch->ddc)
|
||||
imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);
|
||||
|
||||
if (imx_ldb_ch->edid) {
|
||||
drm_mode_connector_update_edid_property(connector,
|
||||
imx_ldb_ch->edid);
|
||||
|
|
@ -553,7 +558,8 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
|
|||
|
||||
for_each_child_of_node(np, child) {
|
||||
struct imx_ldb_channel *channel;
|
||||
struct device_node *port;
|
||||
struct device_node *ddc_node;
|
||||
struct device_node *ep;
|
||||
|
||||
ret = of_property_read_u32(child, "reg", &i);
|
||||
if (ret || i < 0 || i > 1)
|
||||
|
|
@ -576,33 +582,54 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
|
|||
* The output port is port@4 with an external 4-port mux or
|
||||
* port@2 with the internal 2-port mux.
|
||||
*/
|
||||
port = of_graph_get_port_by_id(child, imx_ldb->lvds_mux ? 4 : 2);
|
||||
if (port) {
|
||||
struct device_node *endpoint, *remote;
|
||||
ep = of_graph_get_endpoint_by_regs(child,
|
||||
imx_ldb->lvds_mux ? 4 : 2,
|
||||
-1);
|
||||
if (ep) {
|
||||
struct device_node *remote;
|
||||
|
||||
endpoint = of_get_child_by_name(port, "endpoint");
|
||||
if (endpoint) {
|
||||
remote = of_graph_get_remote_port_parent(endpoint);
|
||||
if (remote)
|
||||
channel->panel = of_drm_find_panel(remote);
|
||||
else
|
||||
return -EPROBE_DEFER;
|
||||
if (!channel->panel) {
|
||||
dev_err(dev, "panel not found: %s\n",
|
||||
remote->full_name);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
remote = of_graph_get_remote_port_parent(ep);
|
||||
of_node_put(ep);
|
||||
if (remote)
|
||||
channel->panel = of_drm_find_panel(remote);
|
||||
else
|
||||
return -EPROBE_DEFER;
|
||||
of_node_put(remote);
|
||||
if (!channel->panel) {
|
||||
dev_err(dev, "panel not found: %s\n",
|
||||
remote->full_name);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
}
|
||||
|
||||
edidp = of_get_property(child, "edid", &channel->edid_len);
|
||||
if (edidp) {
|
||||
channel->edid = kmemdup(edidp, channel->edid_len,
|
||||
GFP_KERNEL);
|
||||
} else if (!channel->panel) {
|
||||
ret = of_get_drm_display_mode(child, &channel->mode, 0);
|
||||
if (!ret)
|
||||
channel->mode_valid = 1;
|
||||
ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
|
||||
if (ddc_node) {
|
||||
channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
|
||||
of_node_put(ddc_node);
|
||||
if (!channel->ddc) {
|
||||
dev_warn(dev, "failed to get ddc i2c adapter\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
}
|
||||
|
||||
if (!channel->ddc) {
|
||||
/* if no DDC available, fallback to hardcoded EDID */
|
||||
dev_dbg(dev, "no ddc available\n");
|
||||
|
||||
edidp = of_get_property(child, "edid",
|
||||
&channel->edid_len);
|
||||
if (edidp) {
|
||||
channel->edid = kmemdup(edidp,
|
||||
channel->edid_len,
|
||||
GFP_KERNEL);
|
||||
} else if (!channel->panel) {
|
||||
/* fallback to display-timings node */
|
||||
ret = of_get_drm_display_mode(child,
|
||||
&channel->mode,
|
||||
OF_USE_NATIVE_MODE);
|
||||
if (!ret)
|
||||
channel->mode_valid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
channel->bus_format = of_get_bus_format(dev, child);
|
||||
|
|
@ -647,6 +674,7 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
|
|||
channel->encoder.funcs->destroy(&channel->encoder);
|
||||
|
||||
kfree(channel->edid);
|
||||
i2c_put_adapter(channel->ddc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -294,8 +294,10 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder)
|
|||
|
||||
switch (tve->mode) {
|
||||
case TVE_MODE_VGA:
|
||||
imx_drm_set_bus_format_pins(encoder, MEDIA_BUS_FMT_GBR888_1X24,
|
||||
tve->hsync_pin, tve->vsync_pin);
|
||||
imx_drm_set_bus_config(encoder, MEDIA_BUS_FMT_GBR888_1X24,
|
||||
tve->hsync_pin, tve->vsync_pin,
|
||||
DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_PIXDATA_NEGEDGE);
|
||||
break;
|
||||
case TVE_MODE_TVOUT:
|
||||
imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_YUV8_1X24);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ struct ipu_crtc {
|
|||
struct ipu_flip_work *flip_work;
|
||||
int irq;
|
||||
u32 bus_format;
|
||||
u32 bus_flags;
|
||||
int di_hsync_pin;
|
||||
int di_vsync_pin;
|
||||
};
|
||||
|
|
@ -271,8 +272,10 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
|
|||
else
|
||||
sig_cfg.clkflags = 0;
|
||||
|
||||
sig_cfg.enable_pol = 1;
|
||||
sig_cfg.clk_pol = 0;
|
||||
sig_cfg.enable_pol = !(ipu_crtc->bus_flags & DRM_BUS_FLAG_DE_LOW);
|
||||
/* Default to driving pixel data on negative clock edges */
|
||||
sig_cfg.clk_pol = !!(ipu_crtc->bus_flags &
|
||||
DRM_BUS_FLAG_PIXDATA_POSEDGE);
|
||||
sig_cfg.bus_format = ipu_crtc->bus_format;
|
||||
sig_cfg.v_to_h_sync = 0;
|
||||
sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
|
||||
|
|
@ -396,11 +399,12 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
|
|||
}
|
||||
|
||||
static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
|
||||
u32 bus_format, int hsync_pin, int vsync_pin)
|
||||
u32 bus_format, int hsync_pin, int vsync_pin, u32 bus_flags)
|
||||
{
|
||||
struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
|
||||
|
||||
ipu_crtc->bus_format = bus_format;
|
||||
ipu_crtc->bus_flags = bus_flags;
|
||||
ipu_crtc->di_hsync_pin = hsync_pin;
|
||||
ipu_crtc->di_vsync_pin = vsync_pin;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ static const uint32_t ipu_plane_formats[] = {
|
|||
DRM_FORMAT_RGBX8888,
|
||||
DRM_FORMAT_BGRA8888,
|
||||
DRM_FORMAT_BGRA8888,
|
||||
DRM_FORMAT_UYVY,
|
||||
DRM_FORMAT_VYUY,
|
||||
DRM_FORMAT_YUYV,
|
||||
DRM_FORMAT_YVYU,
|
||||
DRM_FORMAT_YUV420,
|
||||
|
|
@ -428,7 +430,6 @@ static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
if (crtc != plane->crtc)
|
||||
dev_dbg(plane->dev->dev, "crtc change: %p -> %p\n",
|
||||
plane->crtc, crtc);
|
||||
plane->crtc = crtc;
|
||||
|
||||
if (!ipu_plane->enabled)
|
||||
ipu_plane_enable(ipu_plane);
|
||||
|
|
@ -461,7 +462,7 @@ static void ipu_plane_destroy(struct drm_plane *plane)
|
|||
kfree(ipu_plane);
|
||||
}
|
||||
|
||||
static struct drm_plane_funcs ipu_plane_funcs = {
|
||||
static const struct drm_plane_funcs ipu_plane_funcs = {
|
||||
.update_plane = ipu_update_plane,
|
||||
.disable_plane = ipu_disable_plane,
|
||||
.destroy = ipu_plane_destroy,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ struct imx_parallel_display {
|
|||
void *edid;
|
||||
int edid_len;
|
||||
u32 bus_format;
|
||||
int mode_valid;
|
||||
struct drm_display_mode mode;
|
||||
struct drm_panel *panel;
|
||||
};
|
||||
|
|
@ -68,17 +67,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
|
|||
num_modes = drm_add_edid_modes(connector, imxpd->edid);
|
||||
}
|
||||
|
||||
if (imxpd->mode_valid) {
|
||||
struct drm_display_mode *mode = drm_mode_create(connector->dev);
|
||||
|
||||
if (!mode)
|
||||
return -EINVAL;
|
||||
drm_mode_copy(mode, &imxpd->mode);
|
||||
mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
drm_mode_probed_add(connector, mode);
|
||||
num_modes++;
|
||||
}
|
||||
|
||||
if (np) {
|
||||
struct drm_display_mode *mode = drm_mode_create(connector->dev);
|
||||
|
||||
|
|
@ -115,8 +103,8 @@ static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||
static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
|
||||
|
||||
imx_drm_set_bus_format(encoder, imxpd->bus_format);
|
||||
imx_drm_set_bus_config(encoder, imxpd->bus_format, 2, 3,
|
||||
imxpd->connector.display_info.bus_flags);
|
||||
}
|
||||
|
||||
static void imx_pd_encoder_commit(struct drm_encoder *encoder)
|
||||
|
|
@ -203,7 +191,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
|
|||
{
|
||||
struct drm_device *drm = data;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *port;
|
||||
struct device_node *ep;
|
||||
const u8 *edidp;
|
||||
struct imx_parallel_display *imxpd;
|
||||
int ret;
|
||||
|
|
@ -230,18 +218,18 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
|
|||
}
|
||||
|
||||
/* port@1 is the output port */
|
||||
port = of_graph_get_port_by_id(np, 1);
|
||||
if (port) {
|
||||
struct device_node *endpoint, *remote;
|
||||
ep = of_graph_get_endpoint_by_regs(np, 1, -1);
|
||||
if (ep) {
|
||||
struct device_node *remote;
|
||||
|
||||
endpoint = of_get_child_by_name(port, "endpoint");
|
||||
if (endpoint) {
|
||||
remote = of_graph_get_remote_port_parent(endpoint);
|
||||
if (remote)
|
||||
imxpd->panel = of_drm_find_panel(remote);
|
||||
if (!imxpd->panel)
|
||||
return -EPROBE_DEFER;
|
||||
remote = of_graph_get_remote_port_parent(ep);
|
||||
of_node_put(ep);
|
||||
if (remote) {
|
||||
imxpd->panel = of_drm_find_panel(remote);
|
||||
of_node_put(remote);
|
||||
}
|
||||
if (!imxpd->panel)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
imxpd->dev = dev;
|
||||
|
|
|
|||
|
|
@ -432,11 +432,6 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
|
|||
unsigned long pll_rate;
|
||||
unsigned int factor;
|
||||
|
||||
if (!dpi) {
|
||||
dev_err(dpi->dev, "invalid argument\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pix_rate = 1000UL * mode->clock;
|
||||
if (mode->clock <= 74000)
|
||||
factor = 8 * 3;
|
||||
|
|
|
|||
|
|
@ -695,10 +695,8 @@ static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi)
|
|||
{
|
||||
drm_encoder_cleanup(&dsi->encoder);
|
||||
/* Skip connector cleanup if creation was delegated to the bridge */
|
||||
if (dsi->conn.dev) {
|
||||
drm_connector_unregister(&dsi->conn);
|
||||
if (dsi->conn.dev)
|
||||
drm_connector_cleanup(&dsi->conn);
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp)
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
|
|||
}
|
||||
}
|
||||
|
||||
fvv = pllreffreq * testn / testm;
|
||||
fvv = pllreffreq * (n + 1) / (m + 1);
|
||||
fvv = (fvv - 800000) / 50000;
|
||||
|
||||
if (fvv > 15)
|
||||
|
|
@ -202,6 +202,14 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
|
|||
WREG_DAC(MGA1064_PIX_PLLC_M, m);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_N, n);
|
||||
WREG_DAC(MGA1064_PIX_PLLC_P, p);
|
||||
|
||||
if (mdev->unique_rev_id >= 0x04) {
|
||||
WREG_DAC(0x1a, 0x09);
|
||||
msleep(20);
|
||||
WREG_DAC(0x1a, 0x01);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ config DRM_OMAP
|
|||
tristate "OMAP DRM"
|
||||
depends on DRM
|
||||
depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
|
||||
select OMAP2_DSS
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_KMS_FB_HELPER
|
||||
select FB_SYS_FILLRECT
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/spi/spi.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include <video/omap-panel-data.h>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
|
|
|||
|
|
@ -1180,15 +1180,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
|
|||
return PTR_ERR(vdds_dsi);
|
||||
}
|
||||
|
||||
if (regulator_can_change_voltage(vdds_dsi)) {
|
||||
r = regulator_set_voltage(vdds_dsi, 1800000, 1800000);
|
||||
if (r) {
|
||||
devm_regulator_put(vdds_dsi);
|
||||
DSSERR("can't set the DSI regulator voltage\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
dsi->vdds_dsi_reg = vdds_dsi;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/gfp.h>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/of.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <sound/omap-hdmi-audio.h>
|
||||
|
||||
|
|
@ -100,7 +101,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
|
|||
|
||||
static int hdmi_init_regulator(void)
|
||||
{
|
||||
int r;
|
||||
struct regulator *reg;
|
||||
|
||||
if (hdmi.vdda_reg != NULL)
|
||||
|
|
@ -114,15 +114,6 @@ static int hdmi_init_regulator(void)
|
|||
return PTR_ERR(reg);
|
||||
}
|
||||
|
||||
if (regulator_can_change_voltage(reg)) {
|
||||
r = regulator_set_voltage(reg, 1800000, 1800000);
|
||||
if (r) {
|
||||
devm_regulator_put(reg);
|
||||
DSSWARN("can't set the regulator voltage\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
hdmi.vdda_reg = reg;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg)
|
|||
static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
|
||||
{
|
||||
DSSDBG("Enter hdmi_core_powerdown_disable\n");
|
||||
REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
|
||||
REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x1, 0, 0);
|
||||
}
|
||||
|
||||
static void hdmi_core_swreset_release(struct hdmi_core_data *core)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/of.h>
|
||||
#include <video/omapdss.h>
|
||||
#include <sound/omap-hdmi-audio.h>
|
||||
|
||||
|
|
@ -131,15 +132,6 @@ static int hdmi_init_regulator(void)
|
|||
return PTR_ERR(reg);
|
||||
}
|
||||
|
||||
if (regulator_can_change_voltage(reg)) {
|
||||
r = regulator_set_voltage(reg, 1800000, 1800000);
|
||||
if (r) {
|
||||
devm_regulator_put(reg);
|
||||
DSSWARN("can't set the regulator voltage\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
hdmi.vdda_reg = reg;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ static void hdmi_core_ddc_init(struct hdmi_core_data *core)
|
|||
{
|
||||
void __iomem *base = core->base;
|
||||
const unsigned long long iclk = 266000000; /* DSS L3 ICLK */
|
||||
const unsigned ss_scl_high = 4000; /* ns */
|
||||
const unsigned ss_scl_low = 4700; /* ns */
|
||||
const unsigned ss_scl_high = 4600; /* ns */
|
||||
const unsigned ss_scl_low = 5400; /* ns */
|
||||
const unsigned fs_scl_high = 600; /* ns */
|
||||
const unsigned fs_scl_low = 1300; /* ns */
|
||||
const unsigned sda_hold = 1000; /* ns */
|
||||
|
|
@ -458,7 +458,7 @@ static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core,
|
|||
|
||||
c = (ptr[1] >> 6) & 0x3;
|
||||
m = (ptr[1] >> 4) & 0x3;
|
||||
r = (ptr[1] >> 0) & 0x3;
|
||||
r = (ptr[1] >> 0) & 0xf;
|
||||
|
||||
itc = (ptr[2] >> 7) & 0x1;
|
||||
ec = (ptr[2] >> 4) & 0x7;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <video/omapdss.h>
|
||||
|
||||
#include "dss.h"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h> /* platform_device() */
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/shmem_fs.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pfn_t.h>
|
||||
|
|
|
|||
|
|
@ -51,15 +51,6 @@ static void sti_crtc_disabling(struct drm_crtc *crtc)
|
|||
mixer->status = STI_MIXER_DISABLING;
|
||||
}
|
||||
|
||||
static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
/* accept the provided drm_display_mode, do not fix it up */
|
||||
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
{
|
||||
|
|
@ -230,7 +221,6 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
|
||||
.enable = sti_crtc_enable,
|
||||
.disable = sti_crtc_disabling,
|
||||
.mode_fixup = sti_crtc_mode_fixup,
|
||||
.mode_set = drm_helper_crtc_mode_set,
|
||||
.mode_set_nofb = sti_crtc_mode_set_nofb,
|
||||
.mode_set_base = drm_helper_crtc_mode_set_base,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0)
|
||||
#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
|
||||
#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
|
||||
|
||||
#define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0)
|
||||
|
||||
|
|
@ -82,6 +83,7 @@ struct its_node {
|
|||
u64 flags;
|
||||
u32 ite_size;
|
||||
u32 device_ids;
|
||||
int numa_node;
|
||||
};
|
||||
|
||||
#define ITS_ITT_ALIGN SZ_256
|
||||
|
|
@ -613,11 +615,23 @@ static void its_unmask_irq(struct irq_data *d)
|
|||
static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
|
||||
bool force)
|
||||
{
|
||||
unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
|
||||
unsigned int cpu;
|
||||
const struct cpumask *cpu_mask = cpu_online_mask;
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
struct its_collection *target_col;
|
||||
u32 id = its_get_event_id(d);
|
||||
|
||||
/* lpi cannot be routed to a redistributor that is on a foreign node */
|
||||
if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
|
||||
if (its_dev->its->numa_node >= 0) {
|
||||
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
|
||||
if (!cpumask_intersects(mask_val, cpu_mask))
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
cpu = cpumask_any_and(mask_val, cpu_mask);
|
||||
|
||||
if (cpu >= nr_cpu_ids)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -1101,6 +1115,16 @@ static void its_cpu_init_collection(void)
|
|||
list_for_each_entry(its, &its_nodes, entry) {
|
||||
u64 target;
|
||||
|
||||
/* avoid cross node collections and its mapping */
|
||||
if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
|
||||
struct device_node *cpu_node;
|
||||
|
||||
cpu_node = of_get_cpu_node(cpu, NULL);
|
||||
if (its->numa_node != NUMA_NO_NODE &&
|
||||
its->numa_node != of_node_to_nid(cpu_node))
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have to bind each collection to its target
|
||||
* redistributor.
|
||||
|
|
@ -1351,9 +1375,14 @@ static void its_irq_domain_activate(struct irq_domain *domain,
|
|||
{
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
u32 event = its_get_event_id(d);
|
||||
const struct cpumask *cpu_mask = cpu_online_mask;
|
||||
|
||||
/* get the cpu_mask of local node */
|
||||
if (its_dev->its->numa_node >= 0)
|
||||
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
|
||||
|
||||
/* Bind the LPI to the first possible CPU */
|
||||
its_dev->event_map.col_map[event] = cpumask_first(cpu_online_mask);
|
||||
its_dev->event_map.col_map[event] = cpumask_first(cpu_mask);
|
||||
|
||||
/* Map the GIC IRQ and event to the device */
|
||||
its_send_mapvi(its_dev, d->hwirq, event);
|
||||
|
|
@ -1443,6 +1472,13 @@ static void __maybe_unused its_enable_quirk_cavium_22375(void *data)
|
|||
its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375;
|
||||
}
|
||||
|
||||
static void __maybe_unused its_enable_quirk_cavium_23144(void *data)
|
||||
{
|
||||
struct its_node *its = data;
|
||||
|
||||
its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_23144;
|
||||
}
|
||||
|
||||
static const struct gic_quirk its_quirks[] = {
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_22375
|
||||
{
|
||||
|
|
@ -1451,6 +1487,14 @@ static const struct gic_quirk its_quirks[] = {
|
|||
.mask = 0xffff0fff,
|
||||
.init = its_enable_quirk_cavium_22375,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_CAVIUM_ERRATUM_23144
|
||||
{
|
||||
.desc = "ITS: Cavium erratum 23144",
|
||||
.iidr = 0xa100034c, /* ThunderX pass 1.x */
|
||||
.mask = 0xffff0fff,
|
||||
.init = its_enable_quirk_cavium_23144,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
|
@ -1514,6 +1558,7 @@ static int __init its_probe(struct device_node *node,
|
|||
its->base = its_base;
|
||||
its->phys_base = res.start;
|
||||
its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
|
||||
its->numa_node = of_node_to_nid(node);
|
||||
|
||||
its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
|
||||
if (!its->cmd_base) {
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ static void gic_enable_redist(bool enable)
|
|||
|
||||
while (count--) {
|
||||
val = readl_relaxed(rbase + GICR_WAKER);
|
||||
if (enable ^ (val & GICR_WAKER_ChildrenAsleep))
|
||||
if (enable ^ (bool)(val & GICR_WAKER_ChildrenAsleep))
|
||||
break;
|
||||
cpu_relax();
|
||||
udelay(1);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ static int pic32_set_type_edge(struct irq_data *data,
|
|||
/* set polarity for external interrupts only */
|
||||
for (i = 0; i < ARRAY_SIZE(priv->ext_irqs); i++) {
|
||||
if (priv->ext_irqs[i] == data->hwirq) {
|
||||
ret = pic32_set_ext_polarity(i + 1, flow_type);
|
||||
ret = pic32_set_ext_polarity(i, flow_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1276,7 +1276,7 @@ static int mmc_select_hs200(struct mmc_card *card)
|
|||
* switch to HS200 mode if bus width is set successfully.
|
||||
*/
|
||||
err = mmc_select_bus_width(card);
|
||||
if (!err) {
|
||||
if (err >= 0) {
|
||||
val = EXT_CSD_TIMING_HS200 |
|
||||
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
|
||||
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
|
|
@ -1583,7 +1583,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||
} else if (mmc_card_hs(card)) {
|
||||
/* Select the desired bus width optionally */
|
||||
err = mmc_select_bus_width(card);
|
||||
if (!err) {
|
||||
if (err >= 0) {
|
||||
err = mmc_select_hs_ddr(card);
|
||||
if (err)
|
||||
goto free_card;
|
||||
|
|
|
|||
|
|
@ -970,8 +970,8 @@ static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {
|
|||
[SDXC_CLK_400K] = { .output = 180, .sample = 180 },
|
||||
[SDXC_CLK_25M] = { .output = 180, .sample = 75 },
|
||||
[SDXC_CLK_50M] = { .output = 150, .sample = 120 },
|
||||
[SDXC_CLK_50M_DDR] = { .output = 90, .sample = 120 },
|
||||
[SDXC_CLK_50M_DDR_8BIT] = { .output = 90, .sample = 120 },
|
||||
[SDXC_CLK_50M_DDR] = { .output = 54, .sample = 36 },
|
||||
[SDXC_CLK_50M_DDR_8BIT] = { .output = 72, .sample = 72 },
|
||||
};
|
||||
|
||||
static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
|
||||
|
|
@ -1129,11 +1129,6 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
|
|||
MMC_CAP_1_8V_DDR |
|
||||
MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
|
||||
|
||||
/* TODO MMC DDR is not working on A80 */
|
||||
if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"allwinner,sun9i-a80-mmc"))
|
||||
mmc->caps &= ~MMC_CAP_1_8V_DDR;
|
||||
|
||||
ret = mmc_of_parse(mmc);
|
||||
if (ret)
|
||||
goto error_free_dma;
|
||||
|
|
|
|||
|
|
@ -950,17 +950,14 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu)
|
|||
|
||||
/* For SPIs, we need to track the affinity per IRQ */
|
||||
if (using_spi) {
|
||||
if (i >= pdev->num_resources) {
|
||||
of_node_put(dn);
|
||||
if (i >= pdev->num_resources)
|
||||
break;
|
||||
}
|
||||
|
||||
irqs[i] = cpu;
|
||||
}
|
||||
|
||||
/* Keep track of the CPUs containing this PMU type */
|
||||
cpumask_set_cpu(cpu, &pmu->supported_cpus);
|
||||
of_node_put(dn);
|
||||
i++;
|
||||
} while (1);
|
||||
|
||||
|
|
@ -995,9 +992,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
|
|||
|
||||
armpmu_init(pmu);
|
||||
|
||||
if (!__oprofile_cpu_pmu)
|
||||
__oprofile_cpu_pmu = pmu;
|
||||
|
||||
pmu->plat_device = pdev;
|
||||
|
||||
if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
|
||||
|
|
@ -1033,6 +1027,9 @@ int arm_pmu_device_probe(struct platform_device *pdev,
|
|||
if (ret)
|
||||
goto out_destroy;
|
||||
|
||||
if (!__oprofile_cpu_pmu)
|
||||
__oprofile_cpu_pmu = pmu;
|
||||
|
||||
pr_info("enabled with %s PMU driver, %d counters available\n",
|
||||
pmu->name, pmu->num_events);
|
||||
|
||||
|
|
@ -1043,6 +1040,7 @@ int arm_pmu_device_probe(struct platform_device *pdev,
|
|||
out_free:
|
||||
pr_info("%s: failed to register PMU devices!\n",
|
||||
of_node_full_name(node));
|
||||
kfree(pmu->irq_affinity);
|
||||
kfree(pmu);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user