Merge 4.10-rc4 into char-misc-next
We want the char/misc fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
commit
39461ffdfc
4
.mailmap
4
.mailmap
|
@ -137,6 +137,7 @@ Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
|
||||||
Rudolf Marek <R.Marek@sh.cvut.cz>
|
Rudolf Marek <R.Marek@sh.cvut.cz>
|
||||||
Rui Saraiva <rmps@joel.ist.utl.pt>
|
Rui Saraiva <rmps@joel.ist.utl.pt>
|
||||||
Sachin P Sant <ssant@in.ibm.com>
|
Sachin P Sant <ssant@in.ibm.com>
|
||||||
|
Sarangdhar Joshi <spjoshi@codeaurora.org>
|
||||||
Sam Ravnborg <sam@mars.ravnborg.org>
|
Sam Ravnborg <sam@mars.ravnborg.org>
|
||||||
Santosh Shilimkar <ssantosh@kernel.org>
|
Santosh Shilimkar <ssantosh@kernel.org>
|
||||||
Santosh Shilimkar <santosh.shilimkar@oracle.org>
|
Santosh Shilimkar <santosh.shilimkar@oracle.org>
|
||||||
|
@ -150,10 +151,13 @@ Shuah Khan <shuah@kernel.org> <shuah.kh@samsung.com>
|
||||||
Simon Kelley <simon@thekelleys.org.uk>
|
Simon Kelley <simon@thekelleys.org.uk>
|
||||||
Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
|
Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
|
||||||
Stephen Hemminger <shemminger@osdl.org>
|
Stephen Hemminger <shemminger@osdl.org>
|
||||||
|
Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
|
||||||
|
Subhash Jadavani <subhashj@codeaurora.org>
|
||||||
Sudeep Holla <sudeep.holla@arm.com> Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
|
Sudeep Holla <sudeep.holla@arm.com> Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
|
||||||
Sumit Semwal <sumit.semwal@ti.com>
|
Sumit Semwal <sumit.semwal@ti.com>
|
||||||
Tejun Heo <htejun@gmail.com>
|
Tejun Heo <htejun@gmail.com>
|
||||||
Thomas Graf <tgraf@suug.ch>
|
Thomas Graf <tgraf@suug.ch>
|
||||||
|
Thomas Pedersen <twp@codeaurora.org>
|
||||||
Tony Luck <tony.luck@intel.com>
|
Tony Luck <tony.luck@intel.com>
|
||||||
Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
|
Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
|
||||||
Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
|
Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
What: /sys/devices/.../deferred_probe
|
|
||||||
Date: August 2016
|
|
||||||
Contact: Ben Hutchings <ben.hutchings@codethink.co.uk>
|
|
||||||
Description:
|
|
||||||
The /sys/devices/.../deferred_probe attribute is
|
|
||||||
present for all devices. If a driver detects during
|
|
||||||
probing a device that a related device is not yet
|
|
||||||
ready, it may defer probing of the first device. The
|
|
||||||
kernel will retry probing the first device after any
|
|
||||||
other device is successfully probed. This attribute
|
|
||||||
reads as 1 if probing of this device is currently
|
|
||||||
deferred, or 0 otherwise.
|
|
|
@ -62,6 +62,9 @@ wants to support one of the below features, it should adapt the bindings below.
|
||||||
"irq" and "wakeup" names are recognized by I2C core, other names are
|
"irq" and "wakeup" names are recognized by I2C core, other names are
|
||||||
left to individual drivers.
|
left to individual drivers.
|
||||||
|
|
||||||
|
- host-notify
|
||||||
|
device uses SMBus host notify protocol instead of interrupt line.
|
||||||
|
|
||||||
- multi-master
|
- multi-master
|
||||||
states that there is another master active on this bus. The OS can use
|
states that there is another master active on this bus. The OS can use
|
||||||
this information to adapt power management to keep the arbitration awake
|
this information to adapt power management to keep the arbitration awake
|
||||||
|
@ -81,6 +84,11 @@ Binding may contain optional "interrupts" property, describing interrupts
|
||||||
used by the device. I2C core will assign "irq" interrupt (or the very first
|
used by the device. I2C core will assign "irq" interrupt (or the very first
|
||||||
interrupt if not using interrupt names) as primary interrupt for the slave.
|
interrupt if not using interrupt names) as primary interrupt for the slave.
|
||||||
|
|
||||||
|
Alternatively, devices supporting SMbus Host Notify, and connected to
|
||||||
|
adapters that support this feature, may use "host-notify" property. I2C
|
||||||
|
core will create a virtual interrupt for Host Notify and assign it as
|
||||||
|
primary interrupt for the slave.
|
||||||
|
|
||||||
Also, if device is marked as a wakeup source, I2C core will set up "wakeup"
|
Also, if device is marked as a wakeup source, I2C core will set up "wakeup"
|
||||||
interrupt for the device. If "wakeup" interrupt name is not present in the
|
interrupt for the device. If "wakeup" interrupt name is not present in the
|
||||||
binding, then primary interrupt will be used as wakeup interrupt.
|
binding, then primary interrupt will be used as wakeup interrupt.
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
Page fragments
|
||||||
|
--------------
|
||||||
|
|
||||||
|
A page fragment is an arbitrary-length arbitrary-offset area of memory
|
||||||
|
which resides within a 0 or higher order compound page. Multiple
|
||||||
|
fragments within that page are individually refcounted, in the page's
|
||||||
|
reference counter.
|
||||||
|
|
||||||
|
The page_frag functions, page_frag_alloc and page_frag_free, provide a
|
||||||
|
simple allocation framework for page fragments. This is used by the
|
||||||
|
network stack and network device drivers to provide a backing region of
|
||||||
|
memory for use as either an sk_buff->head, or to be used in the "frags"
|
||||||
|
portion of skb_shared_info.
|
||||||
|
|
||||||
|
In order to make use of the page fragment APIs a backing page fragment
|
||||||
|
cache is needed. This provides a central point for the fragment allocation
|
||||||
|
and tracks allows multiple calls to make use of a cached page. The
|
||||||
|
advantage to doing this is that multiple calls to get_page can be avoided
|
||||||
|
which can be expensive at allocation time. However due to the nature of
|
||||||
|
this caching it is required that any calls to the cache be protected by
|
||||||
|
either a per-cpu limitation, or a per-cpu limitation and forcing interrupts
|
||||||
|
to be disabled when executing the fragment allocation.
|
||||||
|
|
||||||
|
The network stack uses two separate caches per CPU to handle fragment
|
||||||
|
allocation. The netdev_alloc_cache is used by callers making use of the
|
||||||
|
__netdev_alloc_frag and __netdev_alloc_skb calls. The napi_alloc_cache is
|
||||||
|
used by callers of the __napi_alloc_frag and __napi_alloc_skb calls. The
|
||||||
|
main difference between these two calls is the context in which they may be
|
||||||
|
called. The "netdev" prefixed functions are usable in any context as these
|
||||||
|
functions will disable interrupts, while the "napi" prefixed functions are
|
||||||
|
only usable within the softirq context.
|
||||||
|
|
||||||
|
Many network device drivers use a similar methodology for allocating page
|
||||||
|
fragments, but the page fragments are cached at the ring or descriptor
|
||||||
|
level. In order to enable these cases it is necessary to provide a generic
|
||||||
|
way of tearing down a page cache. For this reason __page_frag_cache_drain
|
||||||
|
was implemented. It allows for freeing multiple references from a single
|
||||||
|
page via a single call. The advantage to doing this is that it allows for
|
||||||
|
cleaning up the multiple references that were added to a page in order to
|
||||||
|
avoid calling get_page per allocation.
|
||||||
|
|
||||||
|
Alexander Duyck, Nov 29, 2016.
|
20
MAINTAINERS
20
MAINTAINERS
|
@ -81,7 +81,6 @@ Descriptions of section entries:
|
||||||
Q: Patchwork web based patch tracking system site
|
Q: Patchwork web based patch tracking system site
|
||||||
T: SCM tree type and location.
|
T: SCM tree type and location.
|
||||||
Type is one of: git, hg, quilt, stgit, topgit
|
Type is one of: git, hg, quilt, stgit, topgit
|
||||||
B: Bug tracking system location.
|
|
||||||
S: Status, one of the following:
|
S: Status, one of the following:
|
||||||
Supported: Someone is actually paid to look after this.
|
Supported: Someone is actually paid to look after this.
|
||||||
Maintained: Someone actually looks after it.
|
Maintained: Someone actually looks after it.
|
||||||
|
@ -2194,14 +2193,6 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||||
S: Supported
|
S: Supported
|
||||||
F: sound/soc/atmel
|
F: sound/soc/atmel
|
||||||
|
|
||||||
ATMEL DMA DRIVER
|
|
||||||
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
|
||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
|
||||||
S: Supported
|
|
||||||
F: drivers/dma/at_hdmac.c
|
|
||||||
F: drivers/dma/at_hdmac_regs.h
|
|
||||||
F: include/linux/platform_data/dma-atmel.h
|
|
||||||
|
|
||||||
ATMEL XDMA DRIVER
|
ATMEL XDMA DRIVER
|
||||||
M: Ludovic Desroches <ludovic.desroches@atmel.com>
|
M: Ludovic Desroches <ludovic.desroches@atmel.com>
|
||||||
L: linux-arm-kernel@lists.infradead.org
|
L: linux-arm-kernel@lists.infradead.org
|
||||||
|
@ -4117,7 +4108,7 @@ F: drivers/gpu/drm/cirrus/
|
||||||
RADEON and AMDGPU DRM DRIVERS
|
RADEON and AMDGPU DRM DRIVERS
|
||||||
M: Alex Deucher <alexander.deucher@amd.com>
|
M: Alex Deucher <alexander.deucher@amd.com>
|
||||||
M: Christian König <christian.koenig@amd.com>
|
M: Christian König <christian.koenig@amd.com>
|
||||||
L: dri-devel@lists.freedesktop.org
|
L: amd-gfx@lists.freedesktop.org
|
||||||
T: git git://people.freedesktop.org/~agd5f/linux
|
T: git git://people.freedesktop.org/~agd5f/linux
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/gpu/drm/radeon/
|
F: drivers/gpu/drm/radeon/
|
||||||
|
@ -8179,6 +8170,15 @@ S: Maintained
|
||||||
F: drivers/tty/serial/atmel_serial.c
|
F: drivers/tty/serial/atmel_serial.c
|
||||||
F: include/linux/atmel_serial.h
|
F: include/linux/atmel_serial.h
|
||||||
|
|
||||||
|
MICROCHIP / ATMEL DMA DRIVER
|
||||||
|
M: Ludovic Desroches <ludovic.desroches@microchip.com>
|
||||||
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
|
L: dmaengine@vger.kernel.org
|
||||||
|
S: Supported
|
||||||
|
F: drivers/dma/at_hdmac.c
|
||||||
|
F: drivers/dma/at_hdmac_regs.h
|
||||||
|
F: include/linux/platform_data/dma-atmel.h
|
||||||
|
|
||||||
MICROCHIP / ATMEL ISC DRIVER
|
MICROCHIP / ATMEL ISC DRIVER
|
||||||
M: Songjun Wu <songjun.wu@microchip.com>
|
M: Songjun Wu <songjun.wu@microchip.com>
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 10
|
PATCHLEVEL = 10
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc3
|
EXTRAVERSION = -rc4
|
||||||
NAME = Roaring Lionus
|
NAME = Roaring Lionus
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
|
|
@ -164,22 +164,25 @@ lr .req x30 // link register
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
|
* Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
|
||||||
* <symbol> is within the range +/- 4 GB of the PC.
|
* <symbol> is within the range +/- 4 GB of the PC when running
|
||||||
|
* in core kernel context. In module context, a movz/movk sequence
|
||||||
|
* is used, since modules may be loaded far away from the kernel
|
||||||
|
* when KASLR is in effect.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* @dst: destination register (64 bit wide)
|
* @dst: destination register (64 bit wide)
|
||||||
* @sym: name of the symbol
|
* @sym: name of the symbol
|
||||||
* @tmp: optional scratch register to be used if <dst> == sp, which
|
|
||||||
* is not allowed in an adrp instruction
|
|
||||||
*/
|
*/
|
||||||
.macro adr_l, dst, sym, tmp=
|
.macro adr_l, dst, sym
|
||||||
.ifb \tmp
|
#ifndef MODULE
|
||||||
adrp \dst, \sym
|
adrp \dst, \sym
|
||||||
add \dst, \dst, :lo12:\sym
|
add \dst, \dst, :lo12:\sym
|
||||||
.else
|
#else
|
||||||
adrp \tmp, \sym
|
movz \dst, #:abs_g3:\sym
|
||||||
add \dst, \tmp, :lo12:\sym
|
movk \dst, #:abs_g2_nc:\sym
|
||||||
.endif
|
movk \dst, #:abs_g1_nc:\sym
|
||||||
|
movk \dst, #:abs_g0_nc:\sym
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -190,6 +193,7 @@ lr .req x30 // link register
|
||||||
* the address
|
* the address
|
||||||
*/
|
*/
|
||||||
.macro ldr_l, dst, sym, tmp=
|
.macro ldr_l, dst, sym, tmp=
|
||||||
|
#ifndef MODULE
|
||||||
.ifb \tmp
|
.ifb \tmp
|
||||||
adrp \dst, \sym
|
adrp \dst, \sym
|
||||||
ldr \dst, [\dst, :lo12:\sym]
|
ldr \dst, [\dst, :lo12:\sym]
|
||||||
|
@ -197,6 +201,15 @@ lr .req x30 // link register
|
||||||
adrp \tmp, \sym
|
adrp \tmp, \sym
|
||||||
ldr \dst, [\tmp, :lo12:\sym]
|
ldr \dst, [\tmp, :lo12:\sym]
|
||||||
.endif
|
.endif
|
||||||
|
#else
|
||||||
|
.ifb \tmp
|
||||||
|
adr_l \dst, \sym
|
||||||
|
ldr \dst, [\dst]
|
||||||
|
.else
|
||||||
|
adr_l \tmp, \sym
|
||||||
|
ldr \dst, [\tmp]
|
||||||
|
.endif
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -206,8 +219,13 @@ lr .req x30 // link register
|
||||||
* while <src> needs to be preserved.
|
* while <src> needs to be preserved.
|
||||||
*/
|
*/
|
||||||
.macro str_l, src, sym, tmp
|
.macro str_l, src, sym, tmp
|
||||||
|
#ifndef MODULE
|
||||||
adrp \tmp, \sym
|
adrp \tmp, \sym
|
||||||
str \src, [\tmp, :lo12:\sym]
|
str \src, [\tmp, :lo12:\sym]
|
||||||
|
#else
|
||||||
|
adr_l \tmp, \sym
|
||||||
|
str \src, [\tmp]
|
||||||
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -239,7 +239,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||||
ncontig = find_num_contig(vma->vm_mm, addr, cpte,
|
ncontig = find_num_contig(vma->vm_mm, addr, cpte,
|
||||||
*cpte, &pgsize);
|
*cpte, &pgsize);
|
||||||
for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) {
|
for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) {
|
||||||
changed = ptep_set_access_flags(vma, addr, cpte,
|
changed |= ptep_set_access_flags(vma, addr, cpte,
|
||||||
pfn_pte(pfn,
|
pfn_pte(pfn,
|
||||||
hugeprot),
|
hugeprot),
|
||||||
dirty);
|
dirty);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include "ctype.h"
|
#include "ctype.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
int memcmp(const void *s1, const void *s2, size_t len)
|
int memcmp(const void *s1, const void *s2, size_t len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,4 +18,13 @@ int memcmp(const void *s1, const void *s2, size_t len);
|
||||||
#define memset(d,c,l) __builtin_memset(d,c,l)
|
#define memset(d,c,l) __builtin_memset(d,c,l)
|
||||||
#define memcmp __builtin_memcmp
|
#define memcmp __builtin_memcmp
|
||||||
|
|
||||||
|
extern int strcmp(const char *str1, const char *str2);
|
||||||
|
extern int strncmp(const char *cs, const char *ct, size_t count);
|
||||||
|
extern size_t strlen(const char *s);
|
||||||
|
extern char *strstr(const char *s1, const char *s2);
|
||||||
|
extern size_t strnlen(const char *s, size_t maxlen);
|
||||||
|
extern unsigned int atou(const char *s);
|
||||||
|
extern unsigned long long simple_strtoull(const char *cp, char **endp,
|
||||||
|
unsigned int base);
|
||||||
|
|
||||||
#endif /* BOOT_STRING_H */
|
#endif /* BOOT_STRING_H */
|
||||||
|
|
|
@ -1020,7 +1020,8 @@ struct {
|
||||||
const char *basename;
|
const char *basename;
|
||||||
struct simd_skcipher_alg *simd;
|
struct simd_skcipher_alg *simd;
|
||||||
} aesni_simd_skciphers2[] = {
|
} aesni_simd_skciphers2[] = {
|
||||||
#if IS_ENABLED(CONFIG_CRYPTO_PCBC)
|
#if (defined(MODULE) && IS_ENABLED(CONFIG_CRYPTO_PCBC)) || \
|
||||||
|
IS_BUILTIN(CONFIG_CRYPTO_PCBC)
|
||||||
{
|
{
|
||||||
.algname = "pcbc(aes)",
|
.algname = "pcbc(aes)",
|
||||||
.drvname = "pcbc-aes-aesni",
|
.drvname = "pcbc-aes-aesni",
|
||||||
|
|
|
@ -254,23 +254,6 @@ ENTRY(__switch_to_asm)
|
||||||
jmp __switch_to
|
jmp __switch_to
|
||||||
END(__switch_to_asm)
|
END(__switch_to_asm)
|
||||||
|
|
||||||
/*
|
|
||||||
* The unwinder expects the last frame on the stack to always be at the same
|
|
||||||
* offset from the end of the page, which allows it to validate the stack.
|
|
||||||
* Calling schedule_tail() directly would break that convention because its an
|
|
||||||
* asmlinkage function so its argument has to be pushed on the stack. This
|
|
||||||
* wrapper creates a proper "end of stack" frame header before the call.
|
|
||||||
*/
|
|
||||||
ENTRY(schedule_tail_wrapper)
|
|
||||||
FRAME_BEGIN
|
|
||||||
|
|
||||||
pushl %eax
|
|
||||||
call schedule_tail
|
|
||||||
popl %eax
|
|
||||||
|
|
||||||
FRAME_END
|
|
||||||
ret
|
|
||||||
ENDPROC(schedule_tail_wrapper)
|
|
||||||
/*
|
/*
|
||||||
* A newly forked process directly context switches into this address.
|
* A newly forked process directly context switches into this address.
|
||||||
*
|
*
|
||||||
|
@ -279,15 +262,24 @@ ENDPROC(schedule_tail_wrapper)
|
||||||
* edi: kernel thread arg
|
* edi: kernel thread arg
|
||||||
*/
|
*/
|
||||||
ENTRY(ret_from_fork)
|
ENTRY(ret_from_fork)
|
||||||
call schedule_tail_wrapper
|
FRAME_BEGIN /* help unwinder find end of stack */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* schedule_tail() is asmlinkage so we have to put its 'prev' argument
|
||||||
|
* on the stack.
|
||||||
|
*/
|
||||||
|
pushl %eax
|
||||||
|
call schedule_tail
|
||||||
|
popl %eax
|
||||||
|
|
||||||
testl %ebx, %ebx
|
testl %ebx, %ebx
|
||||||
jnz 1f /* kernel threads are uncommon */
|
jnz 1f /* kernel threads are uncommon */
|
||||||
|
|
||||||
2:
|
2:
|
||||||
/* When we fork, we trace the syscall return in the child, too. */
|
/* When we fork, we trace the syscall return in the child, too. */
|
||||||
movl %esp, %eax
|
leal FRAME_OFFSET(%esp), %eax
|
||||||
call syscall_return_slowpath
|
call syscall_return_slowpath
|
||||||
|
FRAME_END
|
||||||
jmp restore_all
|
jmp restore_all
|
||||||
|
|
||||||
/* kernel thread */
|
/* kernel thread */
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <asm/smap.h>
|
#include <asm/smap.h>
|
||||||
#include <asm/pgtable_types.h>
|
#include <asm/pgtable_types.h>
|
||||||
#include <asm/export.h>
|
#include <asm/export.h>
|
||||||
|
#include <asm/frame.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
|
||||||
.code64
|
.code64
|
||||||
|
@ -408,17 +409,19 @@ END(__switch_to_asm)
|
||||||
* r12: kernel thread arg
|
* r12: kernel thread arg
|
||||||
*/
|
*/
|
||||||
ENTRY(ret_from_fork)
|
ENTRY(ret_from_fork)
|
||||||
|
FRAME_BEGIN /* help unwinder find end of stack */
|
||||||
movq %rax, %rdi
|
movq %rax, %rdi
|
||||||
call schedule_tail /* rdi: 'prev' task parameter */
|
call schedule_tail /* rdi: 'prev' task parameter */
|
||||||
|
|
||||||
testq %rbx, %rbx /* from kernel_thread? */
|
testq %rbx, %rbx /* from kernel_thread? */
|
||||||
jnz 1f /* kernel threads are uncommon */
|
jnz 1f /* kernel threads are uncommon */
|
||||||
|
|
||||||
2:
|
2:
|
||||||
movq %rsp, %rdi
|
leaq FRAME_OFFSET(%rsp),%rdi /* pt_regs pointer */
|
||||||
call syscall_return_slowpath /* returns with IRQs disabled */
|
call syscall_return_slowpath /* returns with IRQs disabled */
|
||||||
TRACE_IRQS_ON /* user mode is traced as IRQS on */
|
TRACE_IRQS_ON /* user mode is traced as IRQS on */
|
||||||
SWAPGS
|
SWAPGS
|
||||||
|
FRAME_END
|
||||||
jmp restore_regs_and_iret
|
jmp restore_regs_and_iret
|
||||||
|
|
||||||
1:
|
1:
|
||||||
|
|
|
@ -505,6 +505,10 @@ int x86_pmu_hw_config(struct perf_event *event)
|
||||||
|
|
||||||
if (event->attr.precise_ip > precise)
|
if (event->attr.precise_ip > precise)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* There's no sense in having PEBS for non sampling events: */
|
||||||
|
if (!is_sampling_event(event))
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* check that PEBS LBR correction does not conflict with
|
* check that PEBS LBR correction does not conflict with
|
||||||
|
|
|
@ -3987,7 +3987,7 @@ __init int intel_pmu_init(void)
|
||||||
x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
|
x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
|
||||||
x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
|
x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
|
||||||
}
|
}
|
||||||
x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
|
x86_pmu.intel_ctrl = (1ULL << x86_pmu.num_counters) - 1;
|
||||||
|
|
||||||
if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
|
if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
|
||||||
WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
|
WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
|
||||||
|
|
|
@ -434,6 +434,7 @@ static struct pmu cstate_core_pmu = {
|
||||||
.stop = cstate_pmu_event_stop,
|
.stop = cstate_pmu_event_stop,
|
||||||
.read = cstate_pmu_event_update,
|
.read = cstate_pmu_event_update,
|
||||||
.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
|
.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
|
||||||
|
.module = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pmu cstate_pkg_pmu = {
|
static struct pmu cstate_pkg_pmu = {
|
||||||
|
@ -447,6 +448,7 @@ static struct pmu cstate_pkg_pmu = {
|
||||||
.stop = cstate_pmu_event_stop,
|
.stop = cstate_pmu_event_stop,
|
||||||
.read = cstate_pmu_event_update,
|
.read = cstate_pmu_event_update,
|
||||||
.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
|
.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
|
||||||
|
.module = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct cstate_model nhm_cstates __initconst = {
|
static const struct cstate_model nhm_cstates __initconst = {
|
||||||
|
|
|
@ -1389,9 +1389,13 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* log dropped samples number */
|
/* log dropped samples number */
|
||||||
if (error[bit])
|
if (error[bit]) {
|
||||||
perf_log_lost_samples(event, error[bit]);
|
perf_log_lost_samples(event, error[bit]);
|
||||||
|
|
||||||
|
if (perf_event_account_interrupt(event))
|
||||||
|
x86_pmu_stop(event, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (counts[bit]) {
|
if (counts[bit]) {
|
||||||
__intel_pmu_pebs_event(event, iregs, base,
|
__intel_pmu_pebs_event(event, iregs, base,
|
||||||
top, bit, counts[bit]);
|
top, bit, counts[bit]);
|
||||||
|
|
|
@ -697,6 +697,7 @@ static int __init init_rapl_pmus(void)
|
||||||
rapl_pmus->pmu.start = rapl_pmu_event_start;
|
rapl_pmus->pmu.start = rapl_pmu_event_start;
|
||||||
rapl_pmus->pmu.stop = rapl_pmu_event_stop;
|
rapl_pmus->pmu.stop = rapl_pmu_event_stop;
|
||||||
rapl_pmus->pmu.read = rapl_pmu_event_read;
|
rapl_pmus->pmu.read = rapl_pmu_event_read;
|
||||||
|
rapl_pmus->pmu.module = THIS_MODULE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -733,6 +733,7 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
|
||||||
.start = uncore_pmu_event_start,
|
.start = uncore_pmu_event_start,
|
||||||
.stop = uncore_pmu_event_stop,
|
.stop = uncore_pmu_event_stop,
|
||||||
.read = uncore_pmu_event_read,
|
.read = uncore_pmu_event_read,
|
||||||
|
.module = THIS_MODULE,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
pmu->pmu = *pmu->type->pmu;
|
pmu->pmu = *pmu->type->pmu;
|
||||||
|
|
|
@ -2686,7 +2686,7 @@ static struct intel_uncore_type *hswep_msr_uncores[] = {
|
||||||
|
|
||||||
void hswep_uncore_cpu_init(void)
|
void hswep_uncore_cpu_init(void)
|
||||||
{
|
{
|
||||||
int pkg = topology_phys_to_logical_pkg(0);
|
int pkg = boot_cpu_data.logical_proc_id;
|
||||||
|
|
||||||
if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
|
if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
|
||||||
hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
|
hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */
|
#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */
|
||||||
#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */
|
#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */
|
||||||
#define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */
|
#define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */
|
||||||
#define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Annidale */
|
#define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Anniedale */
|
||||||
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C
|
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C
|
||||||
#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */
|
#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,21 @@ struct extended_sigtable {
|
||||||
|
|
||||||
#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
|
#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
|
||||||
|
|
||||||
|
static inline u32 intel_get_microcode_revision(void)
|
||||||
|
{
|
||||||
|
u32 rev, dummy;
|
||||||
|
|
||||||
|
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
|
||||||
|
|
||||||
|
/* As documented in the SDM: Do a CPUID 1 here */
|
||||||
|
native_cpuid_eax(1);
|
||||||
|
|
||||||
|
/* get the current revision from MSR 0x8B */
|
||||||
|
native_rdmsr(MSR_IA32_UCODE_REV, dummy, rev);
|
||||||
|
|
||||||
|
return rev;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MICROCODE_INTEL
|
#ifdef CONFIG_MICROCODE_INTEL
|
||||||
extern void __init load_ucode_intel_bsp(void);
|
extern void __init load_ucode_intel_bsp(void);
|
||||||
extern void load_ucode_intel_ap(void);
|
extern void load_ucode_intel_ap(void);
|
||||||
|
|
|
@ -219,6 +219,24 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define native_cpuid_reg(reg) \
|
||||||
|
static inline unsigned int native_cpuid_##reg(unsigned int op) \
|
||||||
|
{ \
|
||||||
|
unsigned int eax = op, ebx, ecx = 0, edx; \
|
||||||
|
\
|
||||||
|
native_cpuid(&eax, &ebx, &ecx, &edx); \
|
||||||
|
\
|
||||||
|
return reg; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Native CPUID functions returning a single datum.
|
||||||
|
*/
|
||||||
|
native_cpuid_reg(eax)
|
||||||
|
native_cpuid_reg(ebx)
|
||||||
|
native_cpuid_reg(ecx)
|
||||||
|
native_cpuid_reg(edx)
|
||||||
|
|
||||||
static inline void load_cr3(pgd_t *pgdir)
|
static inline void load_cr3(pgd_t *pgdir)
|
||||||
{
|
{
|
||||||
write_cr3(__pa(pgdir));
|
write_cr3(__pa(pgdir));
|
||||||
|
|
|
@ -58,7 +58,7 @@ get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
|
||||||
if (task == current)
|
if (task == current)
|
||||||
return __builtin_frame_address(0);
|
return __builtin_frame_address(0);
|
||||||
|
|
||||||
return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
|
return &((struct inactive_task_frame *)task->thread.sp)->bp;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline unsigned long *
|
static inline unsigned long *
|
||||||
|
|
|
@ -36,7 +36,10 @@ static inline void prepare_switch_to(struct task_struct *prev,
|
||||||
|
|
||||||
asmlinkage void ret_from_fork(void);
|
asmlinkage void ret_from_fork(void);
|
||||||
|
|
||||||
/* data that is pointed to by thread.sp */
|
/*
|
||||||
|
* This is the structure pointed to by thread.sp for an inactive task. The
|
||||||
|
* order of the fields must match the code in __switch_to_asm().
|
||||||
|
*/
|
||||||
struct inactive_task_frame {
|
struct inactive_task_frame {
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
unsigned long r15;
|
unsigned long r15;
|
||||||
|
@ -48,6 +51,11 @@ struct inactive_task_frame {
|
||||||
unsigned long di;
|
unsigned long di;
|
||||||
#endif
|
#endif
|
||||||
unsigned long bx;
|
unsigned long bx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These two fields must be together. They form a stack frame header,
|
||||||
|
* needed by get_frame_pointer().
|
||||||
|
*/
|
||||||
unsigned long bp;
|
unsigned long bp;
|
||||||
unsigned long ret_addr;
|
unsigned long ret_addr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -309,15 +309,8 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
|
||||||
|
|
||||||
/* get information required for multi-node processors */
|
/* get information required for multi-node processors */
|
||||||
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
|
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
|
||||||
u32 eax, ebx, ecx, edx;
|
|
||||||
|
|
||||||
cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
|
node_id = cpuid_ecx(0x8000001e) & 7;
|
||||||
node_id = ecx & 7;
|
|
||||||
|
|
||||||
/* get compute unit information */
|
|
||||||
smp_num_siblings = ((ebx >> 8) & 3) + 1;
|
|
||||||
c->x86_max_cores /= smp_num_siblings;
|
|
||||||
c->cpu_core_id = ebx & 0xff;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may have multiple LLCs if L3 caches exist, so check if we
|
* We may have multiple LLCs if L3 caches exist, so check if we
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ static __init int setup_disablecpuid(char *arg)
|
||||||
{
|
{
|
||||||
int bit;
|
int bit;
|
||||||
|
|
||||||
if (get_option(&arg, &bit) && bit < NCAPINTS*32)
|
if (get_option(&arg, &bit) && bit >= 0 && bit < NCAPINTS * 32)
|
||||||
setup_clear_cpu_cap(bit);
|
setup_clear_cpu_cap(bit);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <asm/bugs.h>
|
#include <asm/bugs.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
#include <asm/intel-family.h>
|
#include <asm/intel-family.h>
|
||||||
|
#include <asm/microcode_intel.h>
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
#include <linux/topology.h>
|
#include <linux/topology.h>
|
||||||
|
@ -78,14 +79,8 @@ static void early_init_intel(struct cpuinfo_x86 *c)
|
||||||
(c->x86 == 0x6 && c->x86_model >= 0x0e))
|
(c->x86 == 0x6 && c->x86_model >= 0x0e))
|
||||||
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
|
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
|
||||||
|
|
||||||
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) {
|
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64))
|
||||||
unsigned lower_word;
|
c->microcode = intel_get_microcode_revision();
|
||||||
|
|
||||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
|
||||||
/* Required by the SDM */
|
|
||||||
sync_core();
|
|
||||||
rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atom erratum AAE44/AAF40/AAG38/AAH41:
|
* Atom erratum AAE44/AAF40/AAG38/AAH41:
|
||||||
|
|
|
@ -150,7 +150,7 @@ static struct ucode_patch *__alloc_microcode_buf(void *data, unsigned int size)
|
||||||
{
|
{
|
||||||
struct ucode_patch *p;
|
struct ucode_patch *p;
|
||||||
|
|
||||||
p = kzalloc(size, GFP_KERNEL);
|
p = kzalloc(sizeof(struct ucode_patch), GFP_KERNEL);
|
||||||
if (!p)
|
if (!p)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
@ -368,26 +368,6 @@ next:
|
||||||
return patch;
|
return patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpuid_1(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* According to the Intel SDM, Volume 3, 9.11.7:
|
|
||||||
*
|
|
||||||
* CPUID returns a value in a model specific register in
|
|
||||||
* addition to its usual register return values. The
|
|
||||||
* semantics of CPUID cause it to deposit an update ID value
|
|
||||||
* in the 64-bit model-specific register at address 08BH
|
|
||||||
* (IA32_BIOS_SIGN_ID). If no update is present in the
|
|
||||||
* processor, the value in the MSR remains unmodified.
|
|
||||||
*
|
|
||||||
* Use native_cpuid -- this code runs very early and we don't
|
|
||||||
* want to mess with paravirt.
|
|
||||||
*/
|
|
||||||
unsigned int eax = 1, ebx, ecx = 0, edx;
|
|
||||||
|
|
||||||
native_cpuid(&eax, &ebx, &ecx, &edx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int collect_cpu_info_early(struct ucode_cpu_info *uci)
|
static int collect_cpu_info_early(struct ucode_cpu_info *uci)
|
||||||
{
|
{
|
||||||
unsigned int val[2];
|
unsigned int val[2];
|
||||||
|
@ -410,15 +390,8 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
|
||||||
native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
|
native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
|
||||||
csig.pf = 1 << ((val[1] >> 18) & 7);
|
csig.pf = 1 << ((val[1] >> 18) & 7);
|
||||||
}
|
}
|
||||||
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
|
|
||||||
|
|
||||||
/* As documented in the SDM: Do a CPUID 1 here */
|
csig.rev = intel_get_microcode_revision();
|
||||||
cpuid_1();
|
|
||||||
|
|
||||||
/* get the current revision from MSR 0x8B */
|
|
||||||
native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
|
||||||
|
|
||||||
csig.rev = val[1];
|
|
||||||
|
|
||||||
uci->cpu_sig = csig;
|
uci->cpu_sig = csig;
|
||||||
uci->valid = 1;
|
uci->valid = 1;
|
||||||
|
@ -602,7 +575,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci)
|
||||||
static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
||||||
{
|
{
|
||||||
struct microcode_intel *mc;
|
struct microcode_intel *mc;
|
||||||
unsigned int val[2];
|
u32 rev;
|
||||||
|
|
||||||
mc = uci->mc;
|
mc = uci->mc;
|
||||||
if (!mc)
|
if (!mc)
|
||||||
|
@ -610,21 +583,16 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
||||||
|
|
||||||
/* write microcode via MSR 0x79 */
|
/* write microcode via MSR 0x79 */
|
||||||
native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
||||||
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
|
|
||||||
|
|
||||||
/* As documented in the SDM: Do a CPUID 1 here */
|
rev = intel_get_microcode_revision();
|
||||||
cpuid_1();
|
if (rev != mc->hdr.rev)
|
||||||
|
|
||||||
/* get the current revision from MSR 0x8B */
|
|
||||||
native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
|
||||||
if (val[1] != mc->hdr.rev)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
/* Flush global tlb. This is precaution. */
|
/* Flush global tlb. This is precaution. */
|
||||||
flush_tlb_early();
|
flush_tlb_early();
|
||||||
#endif
|
#endif
|
||||||
uci->cpu_sig.rev = val[1];
|
uci->cpu_sig.rev = rev;
|
||||||
|
|
||||||
if (early)
|
if (early)
|
||||||
print_ucode(uci);
|
print_ucode(uci);
|
||||||
|
@ -804,8 +772,8 @@ static int apply_microcode_intel(int cpu)
|
||||||
struct microcode_intel *mc;
|
struct microcode_intel *mc;
|
||||||
struct ucode_cpu_info *uci;
|
struct ucode_cpu_info *uci;
|
||||||
struct cpuinfo_x86 *c;
|
struct cpuinfo_x86 *c;
|
||||||
unsigned int val[2];
|
|
||||||
static int prev_rev;
|
static int prev_rev;
|
||||||
|
u32 rev;
|
||||||
|
|
||||||
/* We should bind the task to the CPU */
|
/* We should bind the task to the CPU */
|
||||||
if (WARN_ON(raw_smp_processor_id() != cpu))
|
if (WARN_ON(raw_smp_processor_id() != cpu))
|
||||||
|
@ -822,33 +790,28 @@ static int apply_microcode_intel(int cpu)
|
||||||
|
|
||||||
/* write microcode via MSR 0x79 */
|
/* write microcode via MSR 0x79 */
|
||||||
wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
||||||
wrmsrl(MSR_IA32_UCODE_REV, 0);
|
|
||||||
|
|
||||||
/* As documented in the SDM: Do a CPUID 1 here */
|
rev = intel_get_microcode_revision();
|
||||||
cpuid_1();
|
|
||||||
|
|
||||||
/* get the current revision from MSR 0x8B */
|
if (rev != mc->hdr.rev) {
|
||||||
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
|
||||||
|
|
||||||
if (val[1] != mc->hdr.rev) {
|
|
||||||
pr_err("CPU%d update to revision 0x%x failed\n",
|
pr_err("CPU%d update to revision 0x%x failed\n",
|
||||||
cpu, mc->hdr.rev);
|
cpu, mc->hdr.rev);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val[1] != prev_rev) {
|
if (rev != prev_rev) {
|
||||||
pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
|
pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
|
||||||
val[1],
|
rev,
|
||||||
mc->hdr.date & 0xffff,
|
mc->hdr.date & 0xffff,
|
||||||
mc->hdr.date >> 24,
|
mc->hdr.date >> 24,
|
||||||
(mc->hdr.date >> 16) & 0xff);
|
(mc->hdr.date >> 16) & 0xff);
|
||||||
prev_rev = val[1];
|
prev_rev = rev;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = &cpu_data(cpu);
|
c = &cpu_data(cpu);
|
||||||
|
|
||||||
uci->cpu_sig.rev = val[1];
|
uci->cpu_sig.rev = rev;
|
||||||
c->microcode = val[1];
|
c->microcode = rev;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -860,7 +823,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
||||||
u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
|
u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
|
||||||
int new_rev = uci->cpu_sig.rev;
|
int new_rev = uci->cpu_sig.rev;
|
||||||
unsigned int leftover = size;
|
unsigned int leftover = size;
|
||||||
unsigned int curr_mc_size = 0;
|
unsigned int curr_mc_size = 0, new_mc_size = 0;
|
||||||
unsigned int csig, cpf;
|
unsigned int csig, cpf;
|
||||||
|
|
||||||
while (leftover) {
|
while (leftover) {
|
||||||
|
@ -901,6 +864,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
||||||
vfree(new_mc);
|
vfree(new_mc);
|
||||||
new_rev = mc_header.rev;
|
new_rev = mc_header.rev;
|
||||||
new_mc = mc;
|
new_mc = mc;
|
||||||
|
new_mc_size = mc_size;
|
||||||
mc = NULL; /* trigger new vmalloc */
|
mc = NULL; /* trigger new vmalloc */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,7 +890,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
||||||
* permanent memory. So it will be loaded early when a CPU is hot added
|
* permanent memory. So it will be loaded early when a CPU is hot added
|
||||||
* or resumes.
|
* or resumes.
|
||||||
*/
|
*/
|
||||||
save_mc_for_early(new_mc, curr_mc_size);
|
save_mc_for_early(new_mc, new_mc_size);
|
||||||
|
|
||||||
pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
|
pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
|
||||||
cpu, new_rev, uci->cpu_sig.rev);
|
cpu, new_rev, uci->cpu_sig.rev);
|
||||||
|
|
|
@ -694,6 +694,7 @@ unsigned long native_calibrate_tsc(void)
|
||||||
crystal_khz = 24000; /* 24.0 MHz */
|
crystal_khz = 24000; /* 24.0 MHz */
|
||||||
break;
|
break;
|
||||||
case INTEL_FAM6_SKYLAKE_X:
|
case INTEL_FAM6_SKYLAKE_X:
|
||||||
|
case INTEL_FAM6_ATOM_DENVERTON:
|
||||||
crystal_khz = 25000; /* 25.0 MHz */
|
crystal_khz = 25000; /* 25.0 MHz */
|
||||||
break;
|
break;
|
||||||
case INTEL_FAM6_ATOM_GOLDMONT:
|
case INTEL_FAM6_ATOM_GOLDMONT:
|
||||||
|
|
|
@ -6,6 +6,21 @@
|
||||||
|
|
||||||
#define FRAME_HEADER_SIZE (sizeof(long) * 2)
|
#define FRAME_HEADER_SIZE (sizeof(long) * 2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This disables KASAN checking when reading a value from another task's stack,
|
||||||
|
* since the other task could be running on another CPU and could have poisoned
|
||||||
|
* the stack in the meantime.
|
||||||
|
*/
|
||||||
|
#define READ_ONCE_TASK_STACK(task, x) \
|
||||||
|
({ \
|
||||||
|
unsigned long val; \
|
||||||
|
if (task == current) \
|
||||||
|
val = READ_ONCE(x); \
|
||||||
|
else \
|
||||||
|
val = READ_ONCE_NOCHECK(x); \
|
||||||
|
val; \
|
||||||
|
})
|
||||||
|
|
||||||
static void unwind_dump(struct unwind_state *state, unsigned long *sp)
|
static void unwind_dump(struct unwind_state *state, unsigned long *sp)
|
||||||
{
|
{
|
||||||
static bool dumped_before = false;
|
static bool dumped_before = false;
|
||||||
|
@ -48,7 +63,8 @@ unsigned long unwind_get_return_address(struct unwind_state *state)
|
||||||
if (state->regs && user_mode(state->regs))
|
if (state->regs && user_mode(state->regs))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, *addr_p,
|
addr = READ_ONCE_TASK_STACK(state->task, *addr_p);
|
||||||
|
addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, addr,
|
||||||
addr_p);
|
addr_p);
|
||||||
|
|
||||||
return __kernel_text_address(addr) ? addr : 0;
|
return __kernel_text_address(addr) ? addr : 0;
|
||||||
|
@ -162,7 +178,7 @@ bool unwind_next_frame(struct unwind_state *state)
|
||||||
if (state->regs)
|
if (state->regs)
|
||||||
next_bp = (unsigned long *)state->regs->bp;
|
next_bp = (unsigned long *)state->regs->bp;
|
||||||
else
|
else
|
||||||
next_bp = (unsigned long *)*state->bp;
|
next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task,*state->bp);
|
||||||
|
|
||||||
/* is the next frame pointer an encoded pointer to pt_regs? */
|
/* is the next frame pointer an encoded pointer to pt_regs? */
|
||||||
regs = decode_frame_pointer(next_bp);
|
regs = decode_frame_pointer(next_bp);
|
||||||
|
@ -207,6 +223,16 @@ bool unwind_next_frame(struct unwind_state *state)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bad_address:
|
bad_address:
|
||||||
|
/*
|
||||||
|
* When unwinding a non-current task, the task might actually be
|
||||||
|
* running on another CPU, in which case it could be modifying its
|
||||||
|
* stack while we're reading it. This is generally not a problem and
|
||||||
|
* can be ignored as long as the caller understands that unwinding
|
||||||
|
* another task will not always succeed.
|
||||||
|
*/
|
||||||
|
if (state->task != current)
|
||||||
|
goto the_end;
|
||||||
|
|
||||||
if (state->regs) {
|
if (state->regs) {
|
||||||
printk_deferred_once(KERN_WARNING
|
printk_deferred_once(KERN_WARNING
|
||||||
"WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
|
"WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
|
||||||
|
|
|
@ -818,6 +818,20 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
|
||||||
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
|
return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
|
||||||
|
struct segmented_address addr,
|
||||||
|
void *data,
|
||||||
|
unsigned int size)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
ulong linear;
|
||||||
|
|
||||||
|
rc = linearize(ctxt, addr, size, true, &linear);
|
||||||
|
if (rc != X86EMUL_CONTINUE)
|
||||||
|
return rc;
|
||||||
|
return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prefetch the remaining bytes of the instruction without crossing page
|
* Prefetch the remaining bytes of the instruction without crossing page
|
||||||
* boundary if they are not in fetch_cache yet.
|
* boundary if they are not in fetch_cache yet.
|
||||||
|
@ -1571,7 +1585,6 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||||
&ctxt->exception);
|
&ctxt->exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does not support long mode */
|
|
||||||
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||||
u16 selector, int seg, u8 cpl,
|
u16 selector, int seg, u8 cpl,
|
||||||
enum x86_transfer_type transfer,
|
enum x86_transfer_type transfer,
|
||||||
|
@ -1608,20 +1621,34 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||||
|
|
||||||
rpl = selector & 3;
|
rpl = selector & 3;
|
||||||
|
|
||||||
/* NULL selector is not valid for TR, CS and SS (except for long mode) */
|
|
||||||
if ((seg == VCPU_SREG_CS
|
|
||||||
|| (seg == VCPU_SREG_SS
|
|
||||||
&& (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl))
|
|
||||||
|| seg == VCPU_SREG_TR)
|
|
||||||
&& null_selector)
|
|
||||||
goto exception;
|
|
||||||
|
|
||||||
/* TR should be in GDT only */
|
/* TR should be in GDT only */
|
||||||
if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
|
if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
|
||||||
goto exception;
|
goto exception;
|
||||||
|
|
||||||
if (null_selector) /* for NULL selector skip all following checks */
|
/* NULL selector is not valid for TR, CS and (except for long mode) SS */
|
||||||
|
if (null_selector) {
|
||||||
|
if (seg == VCPU_SREG_CS || seg == VCPU_SREG_TR)
|
||||||
|
goto exception;
|
||||||
|
|
||||||
|
if (seg == VCPU_SREG_SS) {
|
||||||
|
if (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl)
|
||||||
|
goto exception;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ctxt->ops->set_segment expects the CPL to be in
|
||||||
|
* SS.DPL, so fake an expand-up 32-bit data segment.
|
||||||
|
*/
|
||||||
|
seg_desc.type = 3;
|
||||||
|
seg_desc.p = 1;
|
||||||
|
seg_desc.s = 1;
|
||||||
|
seg_desc.dpl = cpl;
|
||||||
|
seg_desc.d = 1;
|
||||||
|
seg_desc.g = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip all following checks */
|
||||||
goto load;
|
goto load;
|
||||||
|
}
|
||||||
|
|
||||||
ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
|
ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
|
||||||
if (ret != X86EMUL_CONTINUE)
|
if (ret != X86EMUL_CONTINUE)
|
||||||
|
@ -1737,6 +1764,21 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
|
||||||
u16 selector, int seg)
|
u16 selector, int seg)
|
||||||
{
|
{
|
||||||
u8 cpl = ctxt->ops->cpl(ctxt);
|
u8 cpl = ctxt->ops->cpl(ctxt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* None of MOV, POP and LSS can load a NULL selector in CPL=3, but
|
||||||
|
* they can load it at CPL<3 (Intel's manual says only LSS can,
|
||||||
|
* but it's wrong).
|
||||||
|
*
|
||||||
|
* However, the Intel manual says that putting IST=1/DPL=3 in
|
||||||
|
* an interrupt gate will result in SS=3 (the AMD manual instead
|
||||||
|
* says it doesn't), so allow SS=3 in __load_segment_descriptor
|
||||||
|
* and only forbid it here.
|
||||||
|
*/
|
||||||
|
if (seg == VCPU_SREG_SS && selector == 3 &&
|
||||||
|
ctxt->mode == X86EMUL_MODE_PROT64)
|
||||||
|
return emulate_exception(ctxt, GP_VECTOR, 0, true);
|
||||||
|
|
||||||
return __load_segment_descriptor(ctxt, selector, seg, cpl,
|
return __load_segment_descriptor(ctxt, selector, seg, cpl,
|
||||||
X86_TRANSFER_NONE, NULL);
|
X86_TRANSFER_NONE, NULL);
|
||||||
}
|
}
|
||||||
|
@ -3685,8 +3727,8 @@ static int emulate_store_desc_ptr(struct x86_emulate_ctxt *ctxt,
|
||||||
}
|
}
|
||||||
/* Disable writeback. */
|
/* Disable writeback. */
|
||||||
ctxt->dst.type = OP_NONE;
|
ctxt->dst.type = OP_NONE;
|
||||||
return segmented_write(ctxt, ctxt->dst.addr.mem,
|
return segmented_write_std(ctxt, ctxt->dst.addr.mem,
|
||||||
&desc_ptr, 2 + ctxt->op_bytes);
|
&desc_ptr, 2 + ctxt->op_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int em_sgdt(struct x86_emulate_ctxt *ctxt)
|
static int em_sgdt(struct x86_emulate_ctxt *ctxt)
|
||||||
|
@ -3932,7 +3974,7 @@ static int em_fxsave(struct x86_emulate_ctxt *ctxt)
|
||||||
else
|
else
|
||||||
size = offsetof(struct fxregs_state, xmm_space[0]);
|
size = offsetof(struct fxregs_state, xmm_space[0]);
|
||||||
|
|
||||||
return segmented_write(ctxt, ctxt->memop.addr.mem, &fx_state, size);
|
return segmented_write_std(ctxt, ctxt->memop.addr.mem, &fx_state, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
|
static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
|
||||||
|
@ -3974,7 +4016,7 @@ static int em_fxrstor(struct x86_emulate_ctxt *ctxt)
|
||||||
if (rc != X86EMUL_CONTINUE)
|
if (rc != X86EMUL_CONTINUE)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = segmented_read(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
|
rc = segmented_read_std(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
|
||||||
if (rc != X86EMUL_CONTINUE)
|
if (rc != X86EMUL_CONTINUE)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
|
|
@ -2426,3 +2426,9 @@ void kvm_lapic_init(void)
|
||||||
jump_label_rate_limit(&apic_hw_disabled, HZ);
|
jump_label_rate_limit(&apic_hw_disabled, HZ);
|
||||||
jump_label_rate_limit(&apic_sw_disabled, HZ);
|
jump_label_rate_limit(&apic_sw_disabled, HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kvm_lapic_exit(void)
|
||||||
|
{
|
||||||
|
static_key_deferred_flush(&apic_hw_disabled);
|
||||||
|
static_key_deferred_flush(&apic_sw_disabled);
|
||||||
|
}
|
||||||
|
|
|
@ -110,6 +110,7 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
|
int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
|
||||||
void kvm_lapic_init(void);
|
void kvm_lapic_init(void);
|
||||||
|
void kvm_lapic_exit(void);
|
||||||
|
|
||||||
#define VEC_POS(v) ((v) & (32 - 1))
|
#define VEC_POS(v) ((v) & (32 - 1))
|
||||||
#define REG_POS(v) (((v) >> 5) << 4)
|
#define REG_POS(v) (((v) >> 5) << 4)
|
||||||
|
|
|
@ -3342,6 +3342,8 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
|
||||||
|
|
||||||
switch (cap->cap) {
|
switch (cap->cap) {
|
||||||
case KVM_CAP_HYPERV_SYNIC:
|
case KVM_CAP_HYPERV_SYNIC:
|
||||||
|
if (!irqchip_in_kernel(vcpu->kvm))
|
||||||
|
return -EINVAL;
|
||||||
return kvm_hv_activate_synic(vcpu);
|
return kvm_hv_activate_synic(vcpu);
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -6045,6 +6047,7 @@ out:
|
||||||
|
|
||||||
void kvm_arch_exit(void)
|
void kvm_arch_exit(void)
|
||||||
{
|
{
|
||||||
|
kvm_lapic_exit();
|
||||||
perf_unregister_guest_info_callbacks(&kvm_guest_cbs);
|
perf_unregister_guest_info_callbacks(&kvm_guest_cbs);
|
||||||
|
|
||||||
if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
|
if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
|
||||||
|
|
|
@ -293,7 +293,7 @@ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs)
|
||||||
* We were not able to extract an address from the instruction,
|
* We were not able to extract an address from the instruction,
|
||||||
* probably because there was something invalid in it.
|
* probably because there was something invalid in it.
|
||||||
*/
|
*/
|
||||||
if (info->si_addr == (void *)-1) {
|
if (info->si_addr == (void __user *)-1) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1172,6 +1172,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||||
set_memory_ro((unsigned long)header, header->pages);
|
set_memory_ro((unsigned long)header, header->pages);
|
||||||
prog->bpf_func = (void *)image;
|
prog->bpf_func = (void *)image;
|
||||||
prog->jited = 1;
|
prog->jited = 1;
|
||||||
|
} else {
|
||||||
|
prog = orig_prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_addrs:
|
out_addrs:
|
||||||
|
|
|
@ -210,6 +210,70 @@ int __init efi_memblock_x86_reserve_range(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define OVERFLOW_ADDR_SHIFT (64 - EFI_PAGE_SHIFT)
|
||||||
|
#define OVERFLOW_ADDR_MASK (U64_MAX << OVERFLOW_ADDR_SHIFT)
|
||||||
|
#define U64_HIGH_BIT (~(U64_MAX >> 1))
|
||||||
|
|
||||||
|
static bool __init efi_memmap_entry_valid(const efi_memory_desc_t *md, int i)
|
||||||
|
{
|
||||||
|
u64 end = (md->num_pages << EFI_PAGE_SHIFT) + md->phys_addr - 1;
|
||||||
|
u64 end_hi = 0;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
if (md->num_pages == 0) {
|
||||||
|
end = 0;
|
||||||
|
} else if (md->num_pages > EFI_PAGES_MAX ||
|
||||||
|
EFI_PAGES_MAX - md->num_pages <
|
||||||
|
(md->phys_addr >> EFI_PAGE_SHIFT)) {
|
||||||
|
end_hi = (md->num_pages & OVERFLOW_ADDR_MASK)
|
||||||
|
>> OVERFLOW_ADDR_SHIFT;
|
||||||
|
|
||||||
|
if ((md->phys_addr & U64_HIGH_BIT) && !(end & U64_HIGH_BIT))
|
||||||
|
end_hi += 1;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_warn_once(FW_BUG "Invalid EFI memory map entries:\n");
|
||||||
|
|
||||||
|
if (end_hi) {
|
||||||
|
pr_warn("mem%02u: %s range=[0x%016llx-0x%llx%016llx] (invalid)\n",
|
||||||
|
i, efi_md_typeattr_format(buf, sizeof(buf), md),
|
||||||
|
md->phys_addr, end_hi, end);
|
||||||
|
} else {
|
||||||
|
pr_warn("mem%02u: %s range=[0x%016llx-0x%016llx] (invalid)\n",
|
||||||
|
i, efi_md_typeattr_format(buf, sizeof(buf), md),
|
||||||
|
md->phys_addr, end);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init efi_clean_memmap(void)
|
||||||
|
{
|
||||||
|
efi_memory_desc_t *out = efi.memmap.map;
|
||||||
|
const efi_memory_desc_t *in = out;
|
||||||
|
const efi_memory_desc_t *end = efi.memmap.map_end;
|
||||||
|
int i, n_removal;
|
||||||
|
|
||||||
|
for (i = n_removal = 0; in < end; i++) {
|
||||||
|
if (efi_memmap_entry_valid(in, i)) {
|
||||||
|
if (out != in)
|
||||||
|
memcpy(out, in, efi.memmap.desc_size);
|
||||||
|
out = (void *)out + efi.memmap.desc_size;
|
||||||
|
} else {
|
||||||
|
n_removal++;
|
||||||
|
}
|
||||||
|
in = (void *)in + efi.memmap.desc_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_removal > 0) {
|
||||||
|
u64 size = efi.memmap.nr_map - n_removal;
|
||||||
|
|
||||||
|
pr_warn("Removing %d invalid memory map entries.\n", n_removal);
|
||||||
|
efi_memmap_install(efi.memmap.phys_map, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void __init efi_print_memmap(void)
|
void __init efi_print_memmap(void)
|
||||||
{
|
{
|
||||||
efi_memory_desc_t *md;
|
efi_memory_desc_t *md;
|
||||||
|
@ -472,6 +536,8 @@ void __init efi_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
efi_clean_memmap();
|
||||||
|
|
||||||
if (efi_enabled(EFI_DBG))
|
if (efi_enabled(EFI_DBG))
|
||||||
efi_print_memmap();
|
efi_print_memmap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
|
||||||
|
|
||||||
new_size = efi.memmap.desc_size * num_entries;
|
new_size = efi.memmap.desc_size * num_entries;
|
||||||
|
|
||||||
new_phys = memblock_alloc(new_size, 0);
|
new_phys = efi_memmap_alloc(num_entries);
|
||||||
if (!new_phys) {
|
if (!new_phys) {
|
||||||
pr_err("Could not allocate boot services memmap\n");
|
pr_err("Could not allocate boot services memmap\n");
|
||||||
return;
|
return;
|
||||||
|
@ -355,7 +355,7 @@ void __init efi_free_boot_services(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
new_size = efi.memmap.desc_size * num_entries;
|
new_size = efi.memmap.desc_size * num_entries;
|
||||||
new_phys = memblock_alloc(new_size, 0);
|
new_phys = efi_memmap_alloc(num_entries);
|
||||||
if (!new_phys) {
|
if (!new_phys) {
|
||||||
pr_err("Failed to allocate new EFI memmap\n");
|
pr_err("Failed to allocate new EFI memmap\n");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -15,7 +15,7 @@ obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_msic_power_btn.o
|
||||||
obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o
|
obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o
|
||||||
obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
|
obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
|
||||||
# SPI Devices
|
# SPI Devices
|
||||||
obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_spidev.o
|
obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_mrfld_spidev.o
|
||||||
# I2C Devices
|
# I2C Devices
|
||||||
obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
|
obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
|
||||||
obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
|
obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
* of the License.
|
* of the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/err.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/sfi.h>
|
#include <linux/sfi.h>
|
||||||
#include <linux/spi/pxa2xx_spi.h>
|
#include <linux/spi/pxa2xx_spi.h>
|
||||||
|
@ -34,6 +35,9 @@ static void __init *spidev_platform_data(void *info)
|
||||||
{
|
{
|
||||||
struct spi_board_info *spi_info = info;
|
struct spi_board_info *spi_info = info;
|
||||||
|
|
||||||
|
if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
spi_info->mode = SPI_MODE_0;
|
spi_info->mode = SPI_MODE_0;
|
||||||
spi_info->controller_data = &spidev_spi_chip;
|
spi_info->controller_data = &spidev_spi_chip;
|
||||||
|
|
|
@ -301,13 +301,6 @@ int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
|
||||||
if ((sector | nr_sects) & bs_mask)
|
if ((sector | nr_sects) & bs_mask)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (discard) {
|
|
||||||
ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
|
|
||||||
BLKDEV_DISCARD_ZERO, biop);
|
|
||||||
if (ret == 0 || (ret && ret != -EOPNOTSUPP))
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
|
ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
|
||||||
biop);
|
biop);
|
||||||
if (ret == 0 || (ret && ret != -EOPNOTSUPP))
|
if (ret == 0 || (ret && ret != -EOPNOTSUPP))
|
||||||
|
@ -370,6 +363,12 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
|
||||||
struct bio *bio = NULL;
|
struct bio *bio = NULL;
|
||||||
struct blk_plug plug;
|
struct blk_plug plug;
|
||||||
|
|
||||||
|
if (discard) {
|
||||||
|
if (!blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
|
||||||
|
BLKDEV_DISCARD_ZERO))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
blk_start_plug(&plug);
|
blk_start_plug(&plug);
|
||||||
ret = __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
|
ret = __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
|
||||||
&bio, discard);
|
&bio, discard);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
static inline sector_t blk_zone_start(struct request_queue *q,
|
static inline sector_t blk_zone_start(struct request_queue *q,
|
||||||
sector_t sector)
|
sector_t sector)
|
||||||
{
|
{
|
||||||
sector_t zone_mask = blk_queue_zone_size(q) - 1;
|
sector_t zone_mask = blk_queue_zone_sectors(q) - 1;
|
||||||
|
|
||||||
return sector & ~zone_mask;
|
return sector & ~zone_mask;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ int blkdev_reset_zones(struct block_device *bdev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Check alignment (handle eventual smaller last zone) */
|
/* Check alignment (handle eventual smaller last zone) */
|
||||||
zone_sectors = blk_queue_zone_size(q);
|
zone_sectors = blk_queue_zone_sectors(q);
|
||||||
if (sector & (zone_sectors - 1))
|
if (sector & (zone_sectors - 1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
|
@ -434,7 +434,7 @@ static bool part_zone_aligned(struct gendisk *disk,
|
||||||
struct block_device *bdev,
|
struct block_device *bdev,
|
||||||
sector_t from, sector_t size)
|
sector_t from, sector_t size)
|
||||||
{
|
{
|
||||||
unsigned int zone_size = bdev_zone_size(bdev);
|
unsigned int zone_sectors = bdev_zone_sectors(bdev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this function is called, then the disk is a zoned block device
|
* If this function is called, then the disk is a zoned block device
|
||||||
|
@ -446,7 +446,7 @@ static bool part_zone_aligned(struct gendisk *disk,
|
||||||
* regular block devices (no zone operation) and their zone size will
|
* regular block devices (no zone operation) and their zone size will
|
||||||
* be reported as 0. Allow this case.
|
* be reported as 0. Allow this case.
|
||||||
*/
|
*/
|
||||||
if (!zone_size)
|
if (!zone_sectors)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -455,24 +455,24 @@ static bool part_zone_aligned(struct gendisk *disk,
|
||||||
* use it. Check the zone size too: it should be a power of 2 number
|
* use it. Check the zone size too: it should be a power of 2 number
|
||||||
* of sectors.
|
* of sectors.
|
||||||
*/
|
*/
|
||||||
if (WARN_ON_ONCE(!is_power_of_2(zone_size))) {
|
if (WARN_ON_ONCE(!is_power_of_2(zone_sectors))) {
|
||||||
u32 rem;
|
u32 rem;
|
||||||
|
|
||||||
div_u64_rem(from, zone_size, &rem);
|
div_u64_rem(from, zone_sectors, &rem);
|
||||||
if (rem)
|
if (rem)
|
||||||
return false;
|
return false;
|
||||||
if ((from + size) < get_capacity(disk)) {
|
if ((from + size) < get_capacity(disk)) {
|
||||||
div_u64_rem(size, zone_size, &rem);
|
div_u64_rem(size, zone_sectors, &rem);
|
||||||
if (rem)
|
if (rem)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (from & (zone_size - 1))
|
if (from & (zone_sectors - 1))
|
||||||
return false;
|
return false;
|
||||||
if ((from + size) < get_capacity(disk) &&
|
if ((from + size) < get_capacity(disk) &&
|
||||||
(size & (zone_size - 1)))
|
(size & (zone_sectors - 1)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,9 +132,9 @@ config HT16K33
|
||||||
tristate "Holtek Ht16K33 LED controller with keyscan"
|
tristate "Holtek Ht16K33 LED controller with keyscan"
|
||||||
depends on FB && OF && I2C && INPUT
|
depends on FB && OF && I2C && INPUT
|
||||||
select FB_SYS_FOPS
|
select FB_SYS_FOPS
|
||||||
select FB_CFB_FILLRECT
|
select FB_SYS_FILLRECT
|
||||||
select FB_CFB_COPYAREA
|
select FB_SYS_COPYAREA
|
||||||
select FB_CFB_IMAGEBLIT
|
select FB_SYS_IMAGEBLIT
|
||||||
select INPUT_MATRIXKMAP
|
select INPUT_MATRIXKMAP
|
||||||
select FB_BACKLIGHT
|
select FB_BACKLIGHT
|
||||||
help
|
help
|
||||||
|
|
|
@ -141,8 +141,6 @@ extern void device_unblock_probing(void);
|
||||||
extern struct kset *devices_kset;
|
extern struct kset *devices_kset;
|
||||||
extern void devices_kset_move_last(struct device *dev);
|
extern void devices_kset_move_last(struct device *dev);
|
||||||
|
|
||||||
extern struct device_attribute dev_attr_deferred_probe;
|
|
||||||
|
|
||||||
#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
|
#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
|
||||||
extern void module_add_driver(struct module *mod, struct device_driver *drv);
|
extern void module_add_driver(struct module *mod, struct device_driver *drv);
|
||||||
extern void module_remove_driver(struct device_driver *drv);
|
extern void module_remove_driver(struct device_driver *drv);
|
||||||
|
|
|
@ -1060,14 +1060,8 @@ static int device_add_attrs(struct device *dev)
|
||||||
goto err_remove_dev_groups;
|
goto err_remove_dev_groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = device_create_file(dev, &dev_attr_deferred_probe);
|
|
||||||
if (error)
|
|
||||||
goto err_remove_online;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_remove_online:
|
|
||||||
device_remove_file(dev, &dev_attr_online);
|
|
||||||
err_remove_dev_groups:
|
err_remove_dev_groups:
|
||||||
device_remove_groups(dev, dev->groups);
|
device_remove_groups(dev, dev->groups);
|
||||||
err_remove_type_groups:
|
err_remove_type_groups:
|
||||||
|
@ -1085,7 +1079,6 @@ static void device_remove_attrs(struct device *dev)
|
||||||
struct class *class = dev->class;
|
struct class *class = dev->class;
|
||||||
const struct device_type *type = dev->type;
|
const struct device_type *type = dev->type;
|
||||||
|
|
||||||
device_remove_file(dev, &dev_attr_deferred_probe);
|
|
||||||
device_remove_file(dev, &dev_attr_online);
|
device_remove_file(dev, &dev_attr_online);
|
||||||
device_remove_groups(dev, dev->groups);
|
device_remove_groups(dev, dev->groups);
|
||||||
|
|
||||||
|
|
|
@ -53,19 +53,6 @@ static LIST_HEAD(deferred_probe_pending_list);
|
||||||
static LIST_HEAD(deferred_probe_active_list);
|
static LIST_HEAD(deferred_probe_active_list);
|
||||||
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
|
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
|
||||||
|
|
||||||
static ssize_t deferred_probe_show(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
bool value;
|
|
||||||
|
|
||||||
mutex_lock(&deferred_probe_mutex);
|
|
||||||
value = !list_empty(&dev->p->deferred_probe);
|
|
||||||
mutex_unlock(&deferred_probe_mutex);
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", value);
|
|
||||||
}
|
|
||||||
DEVICE_ATTR_RO(deferred_probe);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In some cases, like suspend to RAM or hibernation, It might be reasonable
|
* In some cases, like suspend to RAM or hibernation, It might be reasonable
|
||||||
* to prohibit probing of devices as it could be unsafe.
|
* to prohibit probing of devices as it could be unsafe.
|
||||||
|
|
|
@ -1042,6 +1042,7 @@ static int __init nbd_init(void)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < nbds_max; i++) {
|
for (i = 0; i < nbds_max; i++) {
|
||||||
|
struct request_queue *q;
|
||||||
struct gendisk *disk = alloc_disk(1 << part_shift);
|
struct gendisk *disk = alloc_disk(1 << part_shift);
|
||||||
if (!disk)
|
if (!disk)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1067,12 +1068,13 @@ static int __init nbd_init(void)
|
||||||
* every gendisk to have its very own request_queue struct.
|
* every gendisk to have its very own request_queue struct.
|
||||||
* These structs are big so we dynamically allocate them.
|
* These structs are big so we dynamically allocate them.
|
||||||
*/
|
*/
|
||||||
disk->queue = blk_mq_init_queue(&nbd_dev[i].tag_set);
|
q = blk_mq_init_queue(&nbd_dev[i].tag_set);
|
||||||
if (!disk->queue) {
|
if (IS_ERR(q)) {
|
||||||
blk_mq_free_tag_set(&nbd_dev[i].tag_set);
|
blk_mq_free_tag_set(&nbd_dev[i].tag_set);
|
||||||
put_disk(disk);
|
put_disk(disk);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
disk->queue = q;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the block layer that we are not a rotational device
|
* Tell the block layer that we are not a rotational device
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct virtblk_req {
|
||||||
struct virtio_blk_outhdr out_hdr;
|
struct virtio_blk_outhdr out_hdr;
|
||||||
struct virtio_scsi_inhdr in_hdr;
|
struct virtio_scsi_inhdr in_hdr;
|
||||||
u8 status;
|
u8 status;
|
||||||
|
u8 sense[SCSI_SENSE_BUFFERSIZE];
|
||||||
struct scatterlist sg[];
|
struct scatterlist sg[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,7 +103,8 @@ static int __virtblk_add_req(struct virtqueue *vq,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
|
if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
|
||||||
sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
|
memcpy(vbr->sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
|
||||||
|
sg_init_one(&sense, vbr->sense, SCSI_SENSE_BUFFERSIZE);
|
||||||
sgs[num_out + num_in++] = &sense;
|
sgs[num_out + num_in++] = &sense;
|
||||||
sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
|
sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
|
||||||
sgs[num_out + num_in++] = &inhdr;
|
sgs[num_out + num_in++] = &inhdr;
|
||||||
|
@ -628,11 +630,12 @@ static int virtblk_probe(struct virtio_device *vdev)
|
||||||
if (err)
|
if (err)
|
||||||
goto out_put_disk;
|
goto out_put_disk;
|
||||||
|
|
||||||
q = vblk->disk->queue = blk_mq_init_queue(&vblk->tag_set);
|
q = blk_mq_init_queue(&vblk->tag_set);
|
||||||
if (IS_ERR(q)) {
|
if (IS_ERR(q)) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_free_tags;
|
goto out_free_tags;
|
||||||
}
|
}
|
||||||
|
vblk->disk->queue = q;
|
||||||
|
|
||||||
q->queuedata = vblk;
|
q->queuedata = vblk;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <linux/genhd.h>
|
#include <linux/genhd.h>
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/backing-dev.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
@ -112,6 +113,14 @@ static inline bool is_partial_io(struct bio_vec *bvec)
|
||||||
return bvec->bv_len != PAGE_SIZE;
|
return bvec->bv_len != PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void zram_revalidate_disk(struct zram *zram)
|
||||||
|
{
|
||||||
|
revalidate_disk(zram->disk);
|
||||||
|
/* revalidate_disk reset the BDI_CAP_STABLE_WRITES so set again */
|
||||||
|
zram->disk->queue->backing_dev_info.capabilities |=
|
||||||
|
BDI_CAP_STABLE_WRITES;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if request is within bounds and aligned on zram logical blocks.
|
* Check if request is within bounds and aligned on zram logical blocks.
|
||||||
*/
|
*/
|
||||||
|
@ -1095,15 +1104,9 @@ static ssize_t disksize_store(struct device *dev,
|
||||||
zram->comp = comp;
|
zram->comp = comp;
|
||||||
zram->disksize = disksize;
|
zram->disksize = disksize;
|
||||||
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
|
set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
|
||||||
|
zram_revalidate_disk(zram);
|
||||||
up_write(&zram->init_lock);
|
up_write(&zram->init_lock);
|
||||||
|
|
||||||
/*
|
|
||||||
* Revalidate disk out of the init_lock to avoid lockdep splat.
|
|
||||||
* It's okay because disk's capacity is protected by init_lock
|
|
||||||
* so that revalidate_disk always sees up-to-date capacity.
|
|
||||||
*/
|
|
||||||
revalidate_disk(zram->disk);
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
out_destroy_comp:
|
out_destroy_comp:
|
||||||
|
@ -1149,7 +1152,7 @@ static ssize_t reset_store(struct device *dev,
|
||||||
/* Make sure all the pending I/O are finished */
|
/* Make sure all the pending I/O are finished */
|
||||||
fsync_bdev(bdev);
|
fsync_bdev(bdev);
|
||||||
zram_reset_device(zram);
|
zram_reset_device(zram);
|
||||||
revalidate_disk(zram->disk);
|
zram_revalidate_disk(zram);
|
||||||
bdput(bdev);
|
bdput(bdev);
|
||||||
|
|
||||||
mutex_lock(&bdev->bd_mutex);
|
mutex_lock(&bdev->bd_mutex);
|
||||||
|
|
|
@ -381,9 +381,6 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
|
||||||
char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
|
char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!pfn_valid(PFN_DOWN(p)))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
read = 0;
|
read = 0;
|
||||||
if (p < (unsigned long) high_memory) {
|
if (p < (unsigned long) high_memory) {
|
||||||
low_count = count;
|
low_count = count;
|
||||||
|
@ -412,6 +409,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
|
||||||
* by the kernel or data corruption may occur
|
* by the kernel or data corruption may occur
|
||||||
*/
|
*/
|
||||||
kbuf = xlate_dev_kmem_ptr((void *)p);
|
kbuf = xlate_dev_kmem_ptr((void *)p);
|
||||||
|
if (!virt_addr_valid(kbuf))
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
if (copy_to_user(buf, kbuf, sz))
|
if (copy_to_user(buf, kbuf, sz))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -482,6 +481,8 @@ static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
|
||||||
* corruption may occur.
|
* corruption may occur.
|
||||||
*/
|
*/
|
||||||
ptr = xlate_dev_kmem_ptr((void *)p);
|
ptr = xlate_dev_kmem_ptr((void *)p);
|
||||||
|
if (!virt_addr_valid(ptr))
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
copied = copy_from_user(ptr, buf, sz);
|
copied = copy_from_user(ptr, buf, sz);
|
||||||
if (copied) {
|
if (copied) {
|
||||||
|
@ -512,9 +513,6 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
|
||||||
char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
|
char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!pfn_valid(PFN_DOWN(p)))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
if (p < (unsigned long) high_memory) {
|
if (p < (unsigned long) high_memory) {
|
||||||
unsigned long to_write = min_t(unsigned long, count,
|
unsigned long to_write = min_t(unsigned long, count,
|
||||||
(unsigned long)high_memory - p);
|
(unsigned long)high_memory - p);
|
||||||
|
|
|
@ -290,6 +290,7 @@ static int register_device(int minor, struct pp_struct *pp)
|
||||||
struct pardevice *pdev = NULL;
|
struct pardevice *pdev = NULL;
|
||||||
char *name;
|
char *name;
|
||||||
struct pardev_cb ppdev_cb;
|
struct pardev_cb ppdev_cb;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
|
name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
|
@ -298,8 +299,8 @@ static int register_device(int minor, struct pp_struct *pp)
|
||||||
port = parport_find_number(minor);
|
port = parport_find_number(minor);
|
||||||
if (!port) {
|
if (!port) {
|
||||||
pr_warn("%s: no associated port!\n", name);
|
pr_warn("%s: no associated port!\n", name);
|
||||||
kfree(name);
|
rc = -ENXIO;
|
||||||
return -ENXIO;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ppdev_cb, 0, sizeof(ppdev_cb));
|
memset(&ppdev_cb, 0, sizeof(ppdev_cb));
|
||||||
|
@ -308,16 +309,18 @@ static int register_device(int minor, struct pp_struct *pp)
|
||||||
ppdev_cb.private = pp;
|
ppdev_cb.private = pp;
|
||||||
pdev = parport_register_dev_model(port, name, &ppdev_cb, minor);
|
pdev = parport_register_dev_model(port, name, &ppdev_cb, minor);
|
||||||
parport_put_port(port);
|
parport_put_port(port);
|
||||||
kfree(name);
|
|
||||||
|
|
||||||
if (!pdev) {
|
if (!pdev) {
|
||||||
pr_warn("%s: failed to register device!\n", name);
|
pr_warn("%s: failed to register device!\n", name);
|
||||||
return -ENXIO;
|
rc = -ENXIO;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pp->pdev = pdev;
|
pp->pdev = pdev;
|
||||||
dev_dbg(&pdev->dev, "registered pardevice\n");
|
dev_dbg(&pdev->dev, "registered pardevice\n");
|
||||||
return 0;
|
err:
|
||||||
|
kfree(name);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ieee1284_phase init_phase(int mode)
|
static enum ieee1284_phase init_phase(int mode)
|
||||||
|
|
|
@ -24,5 +24,5 @@ config DW_DMAC_PCI
|
||||||
select DW_DMAC_CORE
|
select DW_DMAC_CORE
|
||||||
help
|
help
|
||||||
Support the Synopsys DesignWare AHB DMA controller on the
|
Support the Synopsys DesignWare AHB DMA controller on the
|
||||||
platfroms that enumerate it as a PCI device. For example,
|
platforms that enumerate it as a PCI device. For example,
|
||||||
Intel Medfield has integrated this GPDMA controller.
|
Intel Medfield has integrated this GPDMA controller.
|
||||||
|
|
|
@ -64,6 +64,8 @@
|
||||||
#define PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e
|
#define PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e
|
||||||
#define PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f
|
#define PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f
|
||||||
|
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IOAT_SKX 0x2021
|
||||||
|
|
||||||
#define IOAT_VER_1_2 0x12 /* Version 1.2 */
|
#define IOAT_VER_1_2 0x12 /* Version 1.2 */
|
||||||
#define IOAT_VER_2_0 0x20 /* Version 2.0 */
|
#define IOAT_VER_2_0 0x20 /* Version 2.0 */
|
||||||
#define IOAT_VER_3_0 0x30 /* Version 3.0 */
|
#define IOAT_VER_3_0 0x30 /* Version 3.0 */
|
||||||
|
|
|
@ -106,6 +106,8 @@ static struct pci_device_id ioat_pci_tbl[] = {
|
||||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX8) },
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX8) },
|
||||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX9) },
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX9) },
|
||||||
|
|
||||||
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SKX) },
|
||||||
|
|
||||||
/* I/OAT v3.3 platforms */
|
/* I/OAT v3.3 platforms */
|
||||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) },
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) },
|
||||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) },
|
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) },
|
||||||
|
@ -243,10 +245,15 @@ static bool is_bdx_ioat(struct pci_dev *pdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_skx_ioat(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
return (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_SKX) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool is_xeon_cb32(struct pci_dev *pdev)
|
static bool is_xeon_cb32(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
return is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev) ||
|
return is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev) ||
|
||||||
is_hsw_ioat(pdev) || is_bdx_ioat(pdev);
|
is_hsw_ioat(pdev) || is_bdx_ioat(pdev) || is_skx_ioat(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_bwd_ioat(struct pci_dev *pdev)
|
bool is_bwd_ioat(struct pci_dev *pdev)
|
||||||
|
@ -693,7 +700,7 @@ static int ioat_alloc_chan_resources(struct dma_chan *c)
|
||||||
/* doing 2 32bit writes to mmio since 1 64b write doesn't work */
|
/* doing 2 32bit writes to mmio since 1 64b write doesn't work */
|
||||||
ioat_chan->completion =
|
ioat_chan->completion =
|
||||||
dma_pool_zalloc(ioat_chan->ioat_dma->completion_pool,
|
dma_pool_zalloc(ioat_chan->ioat_dma->completion_pool,
|
||||||
GFP_KERNEL, &ioat_chan->completion_dma);
|
GFP_NOWAIT, &ioat_chan->completion_dma);
|
||||||
if (!ioat_chan->completion)
|
if (!ioat_chan->completion)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -703,7 +710,7 @@ static int ioat_alloc_chan_resources(struct dma_chan *c)
|
||||||
ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
|
ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
|
||||||
|
|
||||||
order = IOAT_MAX_ORDER;
|
order = IOAT_MAX_ORDER;
|
||||||
ring = ioat_alloc_ring(c, order, GFP_KERNEL);
|
ring = ioat_alloc_ring(c, order, GFP_NOWAIT);
|
||||||
if (!ring)
|
if (!ring)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -1357,6 +1364,8 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
|
|
||||||
device->version = readb(device->reg_base + IOAT_VER_OFFSET);
|
device->version = readb(device->reg_base + IOAT_VER_OFFSET);
|
||||||
if (device->version >= IOAT_VER_3_0) {
|
if (device->version >= IOAT_VER_3_0) {
|
||||||
|
if (is_skx_ioat(pdev))
|
||||||
|
device->version = IOAT_VER_3_2;
|
||||||
err = ioat3_dma_probe(device, ioat_dca_enabled);
|
err = ioat3_dma_probe(device, ioat_dca_enabled);
|
||||||
|
|
||||||
if (device->version >= IOAT_VER_3_3)
|
if (device->version >= IOAT_VER_3_3)
|
||||||
|
|
|
@ -938,6 +938,23 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
|
||||||
d->ccr |= CCR_DST_AMODE_POSTINC;
|
d->ccr |= CCR_DST_AMODE_POSTINC;
|
||||||
if (port_window) {
|
if (port_window) {
|
||||||
d->ccr |= CCR_SRC_AMODE_DBLIDX;
|
d->ccr |= CCR_SRC_AMODE_DBLIDX;
|
||||||
|
|
||||||
|
if (port_window_bytes >= 64)
|
||||||
|
d->csdp |= CSDP_SRC_BURST_64;
|
||||||
|
else if (port_window_bytes >= 32)
|
||||||
|
d->csdp |= CSDP_SRC_BURST_32;
|
||||||
|
else if (port_window_bytes >= 16)
|
||||||
|
d->csdp |= CSDP_SRC_BURST_16;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
d->ccr |= CCR_SRC_AMODE_CONSTANT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
|
||||||
|
|
||||||
|
d->ccr |= CCR_SRC_AMODE_POSTINC;
|
||||||
|
if (port_window) {
|
||||||
|
d->ccr |= CCR_DST_AMODE_DBLIDX;
|
||||||
d->ei = 1;
|
d->ei = 1;
|
||||||
/*
|
/*
|
||||||
* One frame covers the port_window and by configure
|
* One frame covers the port_window and by configure
|
||||||
|
@ -948,27 +965,11 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
|
||||||
d->fi = -(port_window_bytes - 1);
|
d->fi = -(port_window_bytes - 1);
|
||||||
|
|
||||||
if (port_window_bytes >= 64)
|
if (port_window_bytes >= 64)
|
||||||
d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
|
d->csdp |= CSDP_DST_BURST_64;
|
||||||
else if (port_window_bytes >= 32)
|
else if (port_window_bytes >= 32)
|
||||||
d->csdp = CSDP_SRC_BURST_32 | CSDP_SRC_PACKED;
|
d->csdp |= CSDP_DST_BURST_32;
|
||||||
else if (port_window_bytes >= 16)
|
else if (port_window_bytes >= 16)
|
||||||
d->csdp = CSDP_SRC_BURST_16 | CSDP_SRC_PACKED;
|
d->csdp |= CSDP_DST_BURST_16;
|
||||||
} else {
|
|
||||||
d->ccr |= CCR_SRC_AMODE_CONSTANT;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
|
|
||||||
|
|
||||||
d->ccr |= CCR_SRC_AMODE_POSTINC;
|
|
||||||
if (port_window) {
|
|
||||||
d->ccr |= CCR_DST_AMODE_DBLIDX;
|
|
||||||
|
|
||||||
if (port_window_bytes >= 64)
|
|
||||||
d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
|
|
||||||
else if (port_window_bytes >= 32)
|
|
||||||
d->csdp = CSDP_DST_BURST_32 | CSDP_DST_PACKED;
|
|
||||||
else if (port_window_bytes >= 16)
|
|
||||||
d->csdp = CSDP_DST_BURST_16 | CSDP_DST_PACKED;
|
|
||||||
} else {
|
} else {
|
||||||
d->ccr |= CCR_DST_AMODE_CONSTANT;
|
d->ccr |= CCR_DST_AMODE_CONSTANT;
|
||||||
}
|
}
|
||||||
|
@ -1017,7 +1018,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
|
||||||
osg->addr = sg_dma_address(sgent);
|
osg->addr = sg_dma_address(sgent);
|
||||||
osg->en = en;
|
osg->en = en;
|
||||||
osg->fn = sg_dma_len(sgent) / frame_bytes;
|
osg->fn = sg_dma_len(sgent) / frame_bytes;
|
||||||
if (port_window && dir == DMA_MEM_TO_DEV) {
|
if (port_window && dir == DMA_DEV_TO_MEM) {
|
||||||
osg->ei = 1;
|
osg->ei = 1;
|
||||||
/*
|
/*
|
||||||
* One frame covers the port_window and by configure
|
* One frame covers the port_window and by configure
|
||||||
|
@ -1452,6 +1453,7 @@ static int omap_dma_probe(struct platform_device *pdev)
|
||||||
struct omap_dmadev *od;
|
struct omap_dmadev *od;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
int rc, i, irq;
|
int rc, i, irq;
|
||||||
|
u32 lch_count;
|
||||||
|
|
||||||
od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
|
od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
|
||||||
if (!od)
|
if (!od)
|
||||||
|
@ -1494,20 +1496,31 @@ static int omap_dma_probe(struct platform_device *pdev)
|
||||||
spin_lock_init(&od->lock);
|
spin_lock_init(&od->lock);
|
||||||
spin_lock_init(&od->irq_lock);
|
spin_lock_init(&od->irq_lock);
|
||||||
|
|
||||||
if (!pdev->dev.of_node) {
|
/* Number of DMA requests */
|
||||||
od->dma_requests = od->plat->dma_attr->lch_count;
|
od->dma_requests = OMAP_SDMA_REQUESTS;
|
||||||
if (unlikely(!od->dma_requests))
|
if (pdev->dev.of_node && of_property_read_u32(pdev->dev.of_node,
|
||||||
od->dma_requests = OMAP_SDMA_REQUESTS;
|
"dma-requests",
|
||||||
} else if (of_property_read_u32(pdev->dev.of_node, "dma-requests",
|
&od->dma_requests)) {
|
||||||
&od->dma_requests)) {
|
|
||||||
dev_info(&pdev->dev,
|
dev_info(&pdev->dev,
|
||||||
"Missing dma-requests property, using %u.\n",
|
"Missing dma-requests property, using %u.\n",
|
||||||
OMAP_SDMA_REQUESTS);
|
OMAP_SDMA_REQUESTS);
|
||||||
od->dma_requests = OMAP_SDMA_REQUESTS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
od->lch_map = devm_kcalloc(&pdev->dev, od->dma_requests,
|
/* Number of available logical channels */
|
||||||
sizeof(*od->lch_map), GFP_KERNEL);
|
if (!pdev->dev.of_node) {
|
||||||
|
lch_count = od->plat->dma_attr->lch_count;
|
||||||
|
if (unlikely(!lch_count))
|
||||||
|
lch_count = OMAP_SDMA_CHANNELS;
|
||||||
|
} else if (of_property_read_u32(pdev->dev.of_node, "dma-channels",
|
||||||
|
&lch_count)) {
|
||||||
|
dev_info(&pdev->dev,
|
||||||
|
"Missing dma-channels property, using %u.\n",
|
||||||
|
OMAP_SDMA_CHANNELS);
|
||||||
|
lch_count = OMAP_SDMA_CHANNELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
od->lch_map = devm_kcalloc(&pdev->dev, lch_count, sizeof(*od->lch_map),
|
||||||
|
GFP_KERNEL);
|
||||||
if (!od->lch_map)
|
if (!od->lch_map)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -448,6 +448,9 @@ struct dma_pl330_chan {
|
||||||
|
|
||||||
/* for cyclic capability */
|
/* for cyclic capability */
|
||||||
bool cyclic;
|
bool cyclic;
|
||||||
|
|
||||||
|
/* for runtime pm tracking */
|
||||||
|
bool active;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pl330_dmac {
|
struct pl330_dmac {
|
||||||
|
@ -2033,6 +2036,7 @@ static void pl330_tasklet(unsigned long data)
|
||||||
_stop(pch->thread);
|
_stop(pch->thread);
|
||||||
spin_unlock(&pch->thread->dmac->lock);
|
spin_unlock(&pch->thread->dmac->lock);
|
||||||
power_down = true;
|
power_down = true;
|
||||||
|
pch->active = false;
|
||||||
} else {
|
} else {
|
||||||
/* Make sure the PL330 Channel thread is active */
|
/* Make sure the PL330 Channel thread is active */
|
||||||
spin_lock(&pch->thread->dmac->lock);
|
spin_lock(&pch->thread->dmac->lock);
|
||||||
|
@ -2052,6 +2056,7 @@ static void pl330_tasklet(unsigned long data)
|
||||||
desc->status = PREP;
|
desc->status = PREP;
|
||||||
list_move_tail(&desc->node, &pch->work_list);
|
list_move_tail(&desc->node, &pch->work_list);
|
||||||
if (power_down) {
|
if (power_down) {
|
||||||
|
pch->active = true;
|
||||||
spin_lock(&pch->thread->dmac->lock);
|
spin_lock(&pch->thread->dmac->lock);
|
||||||
_start(pch->thread);
|
_start(pch->thread);
|
||||||
spin_unlock(&pch->thread->dmac->lock);
|
spin_unlock(&pch->thread->dmac->lock);
|
||||||
|
@ -2166,6 +2171,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct pl330_dmac *pl330 = pch->dmac;
|
struct pl330_dmac *pl330 = pch->dmac;
|
||||||
LIST_HEAD(list);
|
LIST_HEAD(list);
|
||||||
|
bool power_down = false;
|
||||||
|
|
||||||
pm_runtime_get_sync(pl330->ddma.dev);
|
pm_runtime_get_sync(pl330->ddma.dev);
|
||||||
spin_lock_irqsave(&pch->lock, flags);
|
spin_lock_irqsave(&pch->lock, flags);
|
||||||
|
@ -2176,6 +2182,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
||||||
pch->thread->req[0].desc = NULL;
|
pch->thread->req[0].desc = NULL;
|
||||||
pch->thread->req[1].desc = NULL;
|
pch->thread->req[1].desc = NULL;
|
||||||
pch->thread->req_running = -1;
|
pch->thread->req_running = -1;
|
||||||
|
power_down = pch->active;
|
||||||
|
pch->active = false;
|
||||||
|
|
||||||
/* Mark all desc done */
|
/* Mark all desc done */
|
||||||
list_for_each_entry(desc, &pch->submitted_list, node) {
|
list_for_each_entry(desc, &pch->submitted_list, node) {
|
||||||
|
@ -2193,6 +2201,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
|
||||||
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
|
list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
|
||||||
spin_unlock_irqrestore(&pch->lock, flags);
|
spin_unlock_irqrestore(&pch->lock, flags);
|
||||||
pm_runtime_mark_last_busy(pl330->ddma.dev);
|
pm_runtime_mark_last_busy(pl330->ddma.dev);
|
||||||
|
if (power_down)
|
||||||
|
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
||||||
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
pm_runtime_put_autosuspend(pl330->ddma.dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2357,6 +2367,7 @@ static void pl330_issue_pending(struct dma_chan *chan)
|
||||||
* updated on work_list emptiness status.
|
* updated on work_list emptiness status.
|
||||||
*/
|
*/
|
||||||
WARN_ON(list_empty(&pch->submitted_list));
|
WARN_ON(list_empty(&pch->submitted_list));
|
||||||
|
pch->active = true;
|
||||||
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
||||||
}
|
}
|
||||||
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
|
list_splice_tail_init(&pch->submitted_list, &pch->work_list);
|
||||||
|
|
|
@ -986,6 +986,7 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
|
||||||
{
|
{
|
||||||
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
|
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
|
||||||
struct rcar_dmac *dmac = to_rcar_dmac(chan->device);
|
struct rcar_dmac *dmac = to_rcar_dmac(chan->device);
|
||||||
|
struct rcar_dmac_chan_map *map = &rchan->map;
|
||||||
struct rcar_dmac_desc_page *page, *_page;
|
struct rcar_dmac_desc_page *page, *_page;
|
||||||
struct rcar_dmac_desc *desc;
|
struct rcar_dmac_desc *desc;
|
||||||
LIST_HEAD(list);
|
LIST_HEAD(list);
|
||||||
|
@ -1019,6 +1020,13 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
|
||||||
free_page((unsigned long)page);
|
free_page((unsigned long)page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove slave mapping if present. */
|
||||||
|
if (map->slave.xfer_size) {
|
||||||
|
dma_unmap_resource(chan->device->dev, map->addr,
|
||||||
|
map->slave.xfer_size, map->dir, 0);
|
||||||
|
map->slave.xfer_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
pm_runtime_put(chan->device->dev);
|
pm_runtime_put(chan->device->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -880,7 +880,7 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
|
||||||
struct virt_dma_desc *vdesc;
|
struct virt_dma_desc *vdesc;
|
||||||
enum dma_status status;
|
enum dma_status status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 residue;
|
u32 residue = 0;
|
||||||
|
|
||||||
status = dma_cookie_status(c, cookie, state);
|
status = dma_cookie_status(c, cookie, state);
|
||||||
if ((status == DMA_COMPLETE) || (!state))
|
if ((status == DMA_COMPLETE) || (!state))
|
||||||
|
@ -888,16 +888,12 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
|
||||||
|
|
||||||
spin_lock_irqsave(&chan->vchan.lock, flags);
|
spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||||
vdesc = vchan_find_desc(&chan->vchan, cookie);
|
vdesc = vchan_find_desc(&chan->vchan, cookie);
|
||||||
if (cookie == chan->desc->vdesc.tx.cookie) {
|
if (chan->desc && cookie == chan->desc->vdesc.tx.cookie)
|
||||||
residue = stm32_dma_desc_residue(chan, chan->desc,
|
residue = stm32_dma_desc_residue(chan, chan->desc,
|
||||||
chan->next_sg);
|
chan->next_sg);
|
||||||
} else if (vdesc) {
|
else if (vdesc)
|
||||||
residue = stm32_dma_desc_residue(chan,
|
residue = stm32_dma_desc_residue(chan,
|
||||||
to_stm32_dma_desc(vdesc), 0);
|
to_stm32_dma_desc(vdesc), 0);
|
||||||
} else {
|
|
||||||
residue = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dma_set_residue(state, residue);
|
dma_set_residue(state, residue);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
||||||
|
@ -972,21 +968,18 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
|
||||||
struct stm32_dma_chan *chan;
|
struct stm32_dma_chan *chan;
|
||||||
struct dma_chan *c;
|
struct dma_chan *c;
|
||||||
|
|
||||||
if (dma_spec->args_count < 3)
|
if (dma_spec->args_count < 4)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cfg.channel_id = dma_spec->args[0];
|
cfg.channel_id = dma_spec->args[0];
|
||||||
cfg.request_line = dma_spec->args[1];
|
cfg.request_line = dma_spec->args[1];
|
||||||
cfg.stream_config = dma_spec->args[2];
|
cfg.stream_config = dma_spec->args[2];
|
||||||
cfg.threshold = 0;
|
cfg.threshold = dma_spec->args[3];
|
||||||
|
|
||||||
if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >=
|
if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >=
|
||||||
STM32_DMA_MAX_REQUEST_ID))
|
STM32_DMA_MAX_REQUEST_ID))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (dma_spec->args_count > 3)
|
|
||||||
cfg.threshold = dma_spec->args[3];
|
|
||||||
|
|
||||||
chan = &dmadev->chan[cfg.channel_id];
|
chan = &dmadev->chan[cfg.channel_id];
|
||||||
|
|
||||||
c = dma_get_slave_channel(&chan->vchan.chan);
|
c = dma_get_slave_channel(&chan->vchan.chan);
|
||||||
|
|
|
@ -149,6 +149,7 @@ static int ti_am335x_xbar_probe(struct platform_device *pdev)
|
||||||
match = of_match_node(ti_am335x_master_match, dma_node);
|
match = of_match_node(ti_am335x_master_match, dma_node);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
dev_err(&pdev->dev, "DMA master is not supported\n");
|
dev_err(&pdev->dev, "DMA master is not supported\n");
|
||||||
|
of_node_put(dma_node);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,6 +340,7 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
|
||||||
match = of_match_node(ti_dra7_master_match, dma_node);
|
match = of_match_node(ti_dra7_master_match, dma_node);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
dev_err(&pdev->dev, "DMA master is not supported\n");
|
dev_err(&pdev->dev, "DMA master is not supported\n");
|
||||||
|
of_node_put(dma_node);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -453,7 +453,7 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id)
|
||||||
dev_err(&edev->dev, "out of memory in extcon_set_state\n");
|
dev_err(&edev->dev, "out of memory in extcon_set_state\n");
|
||||||
kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
|
kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
|
||||||
|
|
||||||
return 0;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = name_show(&edev->dev, NULL, prop_buf);
|
length = name_show(&edev->dev, NULL, prop_buf);
|
||||||
|
|
|
@ -71,8 +71,7 @@ void __init efi_fake_memmap(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate memory for new EFI memmap */
|
/* allocate memory for new EFI memmap */
|
||||||
new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map,
|
new_memmap_phy = efi_memmap_alloc(new_nr_map);
|
||||||
PAGE_SIZE);
|
|
||||||
if (!new_memmap_phy)
|
if (!new_memmap_phy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -39,14 +39,6 @@ efi_status_t efi_file_close(void *handle);
|
||||||
|
|
||||||
unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
|
unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
|
||||||
|
|
||||||
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
|
|
||||||
unsigned long orig_fdt_size,
|
|
||||||
void *fdt, int new_fdt_size, char *cmdline_ptr,
|
|
||||||
u64 initrd_addr, u64 initrd_size,
|
|
||||||
efi_memory_desc_t *memory_map,
|
|
||||||
unsigned long map_size, unsigned long desc_size,
|
|
||||||
u32 desc_ver);
|
|
||||||
|
|
||||||
efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
void *handle,
|
void *handle,
|
||||||
unsigned long *new_fdt_addr,
|
unsigned long *new_fdt_addr,
|
||||||
|
|
|
@ -16,13 +16,10 @@
|
||||||
|
|
||||||
#include "efistub.h"
|
#include "efistub.h"
|
||||||
|
|
||||||
efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
|
static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
|
||||||
unsigned long orig_fdt_size,
|
unsigned long orig_fdt_size,
|
||||||
void *fdt, int new_fdt_size, char *cmdline_ptr,
|
void *fdt, int new_fdt_size, char *cmdline_ptr,
|
||||||
u64 initrd_addr, u64 initrd_size,
|
u64 initrd_addr, u64 initrd_size)
|
||||||
efi_memory_desc_t *memory_map,
|
|
||||||
unsigned long map_size, unsigned long desc_size,
|
|
||||||
u32 desc_ver)
|
|
||||||
{
|
{
|
||||||
int node, num_rsv;
|
int node, num_rsv;
|
||||||
int status;
|
int status;
|
||||||
|
@ -101,25 +98,23 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
|
||||||
if (status)
|
if (status)
|
||||||
goto fdt_set_fail;
|
goto fdt_set_fail;
|
||||||
|
|
||||||
fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
|
fdt_val64 = U64_MAX; /* placeholder */
|
||||||
status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
|
status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
|
||||||
&fdt_val64, sizeof(fdt_val64));
|
&fdt_val64, sizeof(fdt_val64));
|
||||||
if (status)
|
if (status)
|
||||||
goto fdt_set_fail;
|
goto fdt_set_fail;
|
||||||
|
|
||||||
fdt_val32 = cpu_to_fdt32(map_size);
|
fdt_val32 = U32_MAX; /* placeholder */
|
||||||
status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
|
status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
|
||||||
&fdt_val32, sizeof(fdt_val32));
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
if (status)
|
if (status)
|
||||||
goto fdt_set_fail;
|
goto fdt_set_fail;
|
||||||
|
|
||||||
fdt_val32 = cpu_to_fdt32(desc_size);
|
|
||||||
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
|
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
|
||||||
&fdt_val32, sizeof(fdt_val32));
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
if (status)
|
if (status)
|
||||||
goto fdt_set_fail;
|
goto fdt_set_fail;
|
||||||
|
|
||||||
fdt_val32 = cpu_to_fdt32(desc_ver);
|
|
||||||
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
|
status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
|
||||||
&fdt_val32, sizeof(fdt_val32));
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -148,6 +143,43 @@ fdt_set_fail:
|
||||||
return EFI_LOAD_ERROR;
|
return EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
|
||||||
|
{
|
||||||
|
int node = fdt_path_offset(fdt, "/chosen");
|
||||||
|
u64 fdt_val64;
|
||||||
|
u32 fdt_val32;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (node < 0)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
fdt_val64 = cpu_to_fdt64((unsigned long)*map->map);
|
||||||
|
err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-start",
|
||||||
|
&fdt_val64, sizeof(fdt_val64));
|
||||||
|
if (err)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
fdt_val32 = cpu_to_fdt32(*map->map_size);
|
||||||
|
err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-size",
|
||||||
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
|
if (err)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
fdt_val32 = cpu_to_fdt32(*map->desc_size);
|
||||||
|
err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-size",
|
||||||
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
|
if (err)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
fdt_val32 = cpu_to_fdt32(*map->desc_ver);
|
||||||
|
err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-ver",
|
||||||
|
&fdt_val32, sizeof(fdt_val32));
|
||||||
|
if (err)
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef EFI_FDT_ALIGN
|
#ifndef EFI_FDT_ALIGN
|
||||||
#define EFI_FDT_ALIGN EFI_PAGE_SIZE
|
#define EFI_FDT_ALIGN EFI_PAGE_SIZE
|
||||||
#endif
|
#endif
|
||||||
|
@ -243,20 +275,10 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Now that we have done our final memory allocation (and free)
|
|
||||||
* we can get the memory map key needed for
|
|
||||||
* exit_boot_services().
|
|
||||||
*/
|
|
||||||
status = efi_get_memory_map(sys_table, &map);
|
|
||||||
if (status != EFI_SUCCESS)
|
|
||||||
goto fail_free_new_fdt;
|
|
||||||
|
|
||||||
status = update_fdt(sys_table,
|
status = update_fdt(sys_table,
|
||||||
(void *)fdt_addr, fdt_size,
|
(void *)fdt_addr, fdt_size,
|
||||||
(void *)*new_fdt_addr, new_fdt_size,
|
(void *)*new_fdt_addr, new_fdt_size,
|
||||||
cmdline_ptr, initrd_addr, initrd_size,
|
cmdline_ptr, initrd_addr, initrd_size);
|
||||||
memory_map, map_size, desc_size, desc_ver);
|
|
||||||
|
|
||||||
/* Succeeding the first time is the expected case. */
|
/* Succeeding the first time is the expected case. */
|
||||||
if (status == EFI_SUCCESS)
|
if (status == EFI_SUCCESS)
|
||||||
|
@ -266,20 +288,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
/*
|
/*
|
||||||
* We need to allocate more space for the new
|
* We need to allocate more space for the new
|
||||||
* device tree, so free existing buffer that is
|
* device tree, so free existing buffer that is
|
||||||
* too small. Also free memory map, as we will need
|
* too small.
|
||||||
* to get new one that reflects the free/alloc we do
|
|
||||||
* on the device tree buffer.
|
|
||||||
*/
|
*/
|
||||||
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
||||||
sys_table->boottime->free_pool(memory_map);
|
|
||||||
new_fdt_size += EFI_PAGE_SIZE;
|
new_fdt_size += EFI_PAGE_SIZE;
|
||||||
} else {
|
} else {
|
||||||
pr_efi_err(sys_table, "Unable to construct new device tree.\n");
|
pr_efi_err(sys_table, "Unable to construct new device tree.\n");
|
||||||
goto fail_free_mmap;
|
goto fail_free_new_fdt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sys_table->boottime->free_pool(memory_map);
|
|
||||||
priv.runtime_map = runtime_map;
|
priv.runtime_map = runtime_map;
|
||||||
priv.runtime_entry_count = &runtime_entry_count;
|
priv.runtime_entry_count = &runtime_entry_count;
|
||||||
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
|
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
|
||||||
|
@ -288,6 +306,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
if (status == EFI_SUCCESS) {
|
if (status == EFI_SUCCESS) {
|
||||||
efi_set_virtual_address_map_t *svam;
|
efi_set_virtual_address_map_t *svam;
|
||||||
|
|
||||||
|
status = update_fdt_memmap((void *)*new_fdt_addr, &map);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
/*
|
||||||
|
* The kernel won't get far without the memory map, but
|
||||||
|
* may still be able to print something meaningful so
|
||||||
|
* return success here.
|
||||||
|
*/
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Install the new virtual address map */
|
/* Install the new virtual address map */
|
||||||
svam = sys_table->runtime->set_virtual_address_map;
|
svam = sys_table->runtime->set_virtual_address_map;
|
||||||
status = svam(runtime_entry_count * desc_size, desc_size,
|
status = svam(runtime_entry_count * desc_size, desc_size,
|
||||||
|
@ -319,9 +347,6 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||||
|
|
||||||
pr_efi_err(sys_table, "Exit boot services failed.\n");
|
pr_efi_err(sys_table, "Exit boot services failed.\n");
|
||||||
|
|
||||||
fail_free_mmap:
|
|
||||||
sys_table->boottime->free_pool(memory_map);
|
|
||||||
|
|
||||||
fail_free_new_fdt:
|
fail_free_new_fdt:
|
||||||
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
efi_free(sys_table, new_fdt_size, *new_fdt_addr);
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,44 @@
|
||||||
#include <linux/efi.h>
|
#include <linux/efi.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <asm/early_ioremap.h>
|
#include <asm/early_ioremap.h>
|
||||||
|
#include <linux/memblock.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size)
|
||||||
|
{
|
||||||
|
return memblock_alloc(size, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
|
||||||
|
{
|
||||||
|
unsigned int order = get_order(size);
|
||||||
|
struct page *p = alloc_pages(GFP_KERNEL, order);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return PFN_PHYS(page_to_pfn(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_memmap_alloc - Allocate memory for the EFI memory map
|
||||||
|
* @num_entries: Number of entries in the allocated map.
|
||||||
|
*
|
||||||
|
* Depending on whether mm_init() has already been invoked or not,
|
||||||
|
* either memblock or "normal" page allocation is used.
|
||||||
|
*
|
||||||
|
* Returns the physical address of the allocated memory map on
|
||||||
|
* success, zero on failure.
|
||||||
|
*/
|
||||||
|
phys_addr_t __init efi_memmap_alloc(unsigned int num_entries)
|
||||||
|
{
|
||||||
|
unsigned long size = num_entries * efi.memmap.desc_size;
|
||||||
|
|
||||||
|
if (slab_is_available())
|
||||||
|
return __efi_memmap_alloc_late(size);
|
||||||
|
|
||||||
|
return __efi_memmap_alloc_early(size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __efi_memmap_init - Common code for mapping the EFI memory map
|
* __efi_memmap_init - Common code for mapping the EFI memory map
|
||||||
|
|
|
@ -205,7 +205,7 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
|
static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
|
||||||
{
|
{
|
||||||
struct irq_chip_generic *gc;
|
struct irq_chip_generic *gc;
|
||||||
struct irq_chip_type *ct;
|
struct irq_chip_type *ct;
|
||||||
|
|
|
@ -1317,12 +1317,12 @@ void gpiochip_remove(struct gpio_chip *chip)
|
||||||
|
|
||||||
/* FIXME: should the legacy sysfs handling be moved to gpio_device? */
|
/* FIXME: should the legacy sysfs handling be moved to gpio_device? */
|
||||||
gpiochip_sysfs_unregister(gdev);
|
gpiochip_sysfs_unregister(gdev);
|
||||||
|
gpiochip_free_hogs(chip);
|
||||||
/* Numb the device, cancelling all outstanding operations */
|
/* Numb the device, cancelling all outstanding operations */
|
||||||
gdev->chip = NULL;
|
gdev->chip = NULL;
|
||||||
gpiochip_irqchip_remove(chip);
|
gpiochip_irqchip_remove(chip);
|
||||||
acpi_gpiochip_remove(chip);
|
acpi_gpiochip_remove(chip);
|
||||||
gpiochip_remove_pin_ranges(chip);
|
gpiochip_remove_pin_ranges(chip);
|
||||||
gpiochip_free_hogs(chip);
|
|
||||||
of_gpiochip_remove(chip);
|
of_gpiochip_remove(chip);
|
||||||
/*
|
/*
|
||||||
* We accept no more calls into the driver from this point, so
|
* We accept no more calls into the driver from this point, so
|
||||||
|
|
|
@ -840,6 +840,9 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
|
||||||
else if (type == CGS_UCODE_ID_SMU_SK)
|
else if (type == CGS_UCODE_ID_SMU_SK)
|
||||||
strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
|
strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
|
||||||
break;
|
break;
|
||||||
|
case CHIP_POLARIS12:
|
||||||
|
strcpy(fw_name, "amdgpu/polaris12_smc.bin");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DRM_ERROR("SMC firmware not supported\n");
|
DRM_ERROR("SMC firmware not supported\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -73,6 +73,7 @@ static const char *amdgpu_asic_name[] = {
|
||||||
"STONEY",
|
"STONEY",
|
||||||
"POLARIS10",
|
"POLARIS10",
|
||||||
"POLARIS11",
|
"POLARIS11",
|
||||||
|
"POLARIS12",
|
||||||
"LAST",
|
"LAST",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1277,6 +1278,7 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
|
||||||
case CHIP_FIJI:
|
case CHIP_FIJI:
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
case CHIP_CARRIZO:
|
case CHIP_CARRIZO:
|
||||||
case CHIP_STONEY:
|
case CHIP_STONEY:
|
||||||
if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
|
if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
|
||||||
|
|
|
@ -418,6 +418,13 @@ static const struct pci_device_id pciidlist[] = {
|
||||||
{0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
|
{0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
|
||||||
{0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
|
{0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
|
||||||
{0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
|
{0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
|
||||||
|
/* Polaris12 */
|
||||||
|
{0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
|
||||||
|
{0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
|
||||||
|
{0x1002, 0x6985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
|
||||||
|
{0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
|
||||||
|
{0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
|
||||||
|
{0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
|
||||||
|
|
||||||
{0, 0, 0}
|
{0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
|
@ -98,6 +98,7 @@ static int amdgpu_pp_early_init(void *handle)
|
||||||
switch (adev->asic_type) {
|
switch (adev->asic_type) {
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
case CHIP_TONGA:
|
case CHIP_TONGA:
|
||||||
case CHIP_FIJI:
|
case CHIP_FIJI:
|
||||||
case CHIP_TOPAZ:
|
case CHIP_TOPAZ:
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#define FIRMWARE_STONEY "amdgpu/stoney_uvd.bin"
|
#define FIRMWARE_STONEY "amdgpu/stoney_uvd.bin"
|
||||||
#define FIRMWARE_POLARIS10 "amdgpu/polaris10_uvd.bin"
|
#define FIRMWARE_POLARIS10 "amdgpu/polaris10_uvd.bin"
|
||||||
#define FIRMWARE_POLARIS11 "amdgpu/polaris11_uvd.bin"
|
#define FIRMWARE_POLARIS11 "amdgpu/polaris11_uvd.bin"
|
||||||
|
#define FIRMWARE_POLARIS12 "amdgpu/polaris12_uvd.bin"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amdgpu_uvd_cs_ctx - Command submission parser context
|
* amdgpu_uvd_cs_ctx - Command submission parser context
|
||||||
|
@ -98,6 +99,7 @@ MODULE_FIRMWARE(FIRMWARE_FIJI);
|
||||||
MODULE_FIRMWARE(FIRMWARE_STONEY);
|
MODULE_FIRMWARE(FIRMWARE_STONEY);
|
||||||
MODULE_FIRMWARE(FIRMWARE_POLARIS10);
|
MODULE_FIRMWARE(FIRMWARE_POLARIS10);
|
||||||
MODULE_FIRMWARE(FIRMWARE_POLARIS11);
|
MODULE_FIRMWARE(FIRMWARE_POLARIS11);
|
||||||
|
MODULE_FIRMWARE(FIRMWARE_POLARIS12);
|
||||||
|
|
||||||
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
|
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
|
||||||
|
|
||||||
|
@ -149,6 +151,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
fw_name = FIRMWARE_POLARIS11;
|
fw_name = FIRMWARE_POLARIS11;
|
||||||
break;
|
break;
|
||||||
|
case CHIP_POLARIS12:
|
||||||
|
fw_name = FIRMWARE_POLARIS12;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#define FIRMWARE_STONEY "amdgpu/stoney_vce.bin"
|
#define FIRMWARE_STONEY "amdgpu/stoney_vce.bin"
|
||||||
#define FIRMWARE_POLARIS10 "amdgpu/polaris10_vce.bin"
|
#define FIRMWARE_POLARIS10 "amdgpu/polaris10_vce.bin"
|
||||||
#define FIRMWARE_POLARIS11 "amdgpu/polaris11_vce.bin"
|
#define FIRMWARE_POLARIS11 "amdgpu/polaris11_vce.bin"
|
||||||
|
#define FIRMWARE_POLARIS12 "amdgpu/polaris12_vce.bin"
|
||||||
|
|
||||||
#ifdef CONFIG_DRM_AMDGPU_CIK
|
#ifdef CONFIG_DRM_AMDGPU_CIK
|
||||||
MODULE_FIRMWARE(FIRMWARE_BONAIRE);
|
MODULE_FIRMWARE(FIRMWARE_BONAIRE);
|
||||||
|
@ -66,6 +67,7 @@ MODULE_FIRMWARE(FIRMWARE_FIJI);
|
||||||
MODULE_FIRMWARE(FIRMWARE_STONEY);
|
MODULE_FIRMWARE(FIRMWARE_STONEY);
|
||||||
MODULE_FIRMWARE(FIRMWARE_POLARIS10);
|
MODULE_FIRMWARE(FIRMWARE_POLARIS10);
|
||||||
MODULE_FIRMWARE(FIRMWARE_POLARIS11);
|
MODULE_FIRMWARE(FIRMWARE_POLARIS11);
|
||||||
|
MODULE_FIRMWARE(FIRMWARE_POLARIS12);
|
||||||
|
|
||||||
static void amdgpu_vce_idle_work_handler(struct work_struct *work);
|
static void amdgpu_vce_idle_work_handler(struct work_struct *work);
|
||||||
|
|
||||||
|
@ -121,6 +123,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
fw_name = FIRMWARE_POLARIS11;
|
fw_name = FIRMWARE_POLARIS11;
|
||||||
break;
|
break;
|
||||||
|
case CHIP_POLARIS12:
|
||||||
|
fw_name = FIRMWARE_POLARIS12;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -167,6 +167,7 @@ static void dce_v11_0_init_golden_registers(struct amdgpu_device *adev)
|
||||||
(const u32)ARRAY_SIZE(stoney_golden_settings_a11));
|
(const u32)ARRAY_SIZE(stoney_golden_settings_a11));
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
amdgpu_program_register_sequence(adev,
|
amdgpu_program_register_sequence(adev,
|
||||||
polaris11_golden_settings_a11,
|
polaris11_golden_settings_a11,
|
||||||
(const u32)ARRAY_SIZE(polaris11_golden_settings_a11));
|
(const u32)ARRAY_SIZE(polaris11_golden_settings_a11));
|
||||||
|
@ -608,6 +609,7 @@ static int dce_v11_0_get_num_crtc (struct amdgpu_device *adev)
|
||||||
num_crtc = 6;
|
num_crtc = 6;
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
num_crtc = 5;
|
num_crtc = 5;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1589,6 +1591,7 @@ static int dce_v11_0_audio_init(struct amdgpu_device *adev)
|
||||||
adev->mode_info.audio.num_pins = 8;
|
adev->mode_info.audio.num_pins = 8;
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
adev->mode_info.audio.num_pins = 6;
|
adev->mode_info.audio.num_pins = 6;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2388,7 +2391,8 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc)
|
||||||
int pll;
|
int pll;
|
||||||
|
|
||||||
if ((adev->asic_type == CHIP_POLARIS10) ||
|
if ((adev->asic_type == CHIP_POLARIS10) ||
|
||||||
(adev->asic_type == CHIP_POLARIS11)) {
|
(adev->asic_type == CHIP_POLARIS11) ||
|
||||||
|
(adev->asic_type == CHIP_POLARIS12)) {
|
||||||
struct amdgpu_encoder *amdgpu_encoder =
|
struct amdgpu_encoder *amdgpu_encoder =
|
||||||
to_amdgpu_encoder(amdgpu_crtc->encoder);
|
to_amdgpu_encoder(amdgpu_crtc->encoder);
|
||||||
struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
|
struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
|
||||||
|
@ -2822,7 +2826,8 @@ static int dce_v11_0_crtc_mode_set(struct drm_crtc *crtc,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if ((adev->asic_type == CHIP_POLARIS10) ||
|
if ((adev->asic_type == CHIP_POLARIS10) ||
|
||||||
(adev->asic_type == CHIP_POLARIS11)) {
|
(adev->asic_type == CHIP_POLARIS11) ||
|
||||||
|
(adev->asic_type == CHIP_POLARIS12)) {
|
||||||
struct amdgpu_encoder *amdgpu_encoder =
|
struct amdgpu_encoder *amdgpu_encoder =
|
||||||
to_amdgpu_encoder(amdgpu_crtc->encoder);
|
to_amdgpu_encoder(amdgpu_crtc->encoder);
|
||||||
int encoder_mode =
|
int encoder_mode =
|
||||||
|
@ -2992,6 +2997,7 @@ static int dce_v11_0_early_init(void *handle)
|
||||||
adev->mode_info.num_dig = 6;
|
adev->mode_info.num_dig = 6;
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
adev->mode_info.num_hpd = 5;
|
adev->mode_info.num_hpd = 5;
|
||||||
adev->mode_info.num_dig = 5;
|
adev->mode_info.num_dig = 5;
|
||||||
break;
|
break;
|
||||||
|
@ -3101,7 +3107,8 @@ static int dce_v11_0_hw_init(void *handle)
|
||||||
amdgpu_atombios_crtc_powergate_init(adev);
|
amdgpu_atombios_crtc_powergate_init(adev);
|
||||||
amdgpu_atombios_encoder_init_dig(adev);
|
amdgpu_atombios_encoder_init_dig(adev);
|
||||||
if ((adev->asic_type == CHIP_POLARIS10) ||
|
if ((adev->asic_type == CHIP_POLARIS10) ||
|
||||||
(adev->asic_type == CHIP_POLARIS11)) {
|
(adev->asic_type == CHIP_POLARIS11) ||
|
||||||
|
(adev->asic_type == CHIP_POLARIS12)) {
|
||||||
amdgpu_atombios_crtc_set_dce_clock(adev, adev->clock.default_dispclk,
|
amdgpu_atombios_crtc_set_dce_clock(adev, adev->clock.default_dispclk,
|
||||||
DCE_CLOCK_TYPE_DISPCLK, ATOM_GCK_DFS);
|
DCE_CLOCK_TYPE_DISPCLK, ATOM_GCK_DFS);
|
||||||
amdgpu_atombios_crtc_set_dce_clock(adev, 0,
|
amdgpu_atombios_crtc_set_dce_clock(adev, 0,
|
||||||
|
|
|
@ -139,6 +139,13 @@ MODULE_FIRMWARE("amdgpu/polaris10_mec.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris10_mec2.bin");
|
MODULE_FIRMWARE("amdgpu/polaris10_mec2.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris10_rlc.bin");
|
MODULE_FIRMWARE("amdgpu/polaris10_rlc.bin");
|
||||||
|
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_ce.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_pfp.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_me.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_mec.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_mec2.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_rlc.bin");
|
||||||
|
|
||||||
static const struct amdgpu_gds_reg_offset amdgpu_gds_reg_offset[] =
|
static const struct amdgpu_gds_reg_offset amdgpu_gds_reg_offset[] =
|
||||||
{
|
{
|
||||||
{mmGDS_VMID0_BASE, mmGDS_VMID0_SIZE, mmGDS_GWS_VMID0, mmGDS_OA_VMID0},
|
{mmGDS_VMID0_BASE, mmGDS_VMID0_SIZE, mmGDS_GWS_VMID0, mmGDS_OA_VMID0},
|
||||||
|
@ -689,6 +696,7 @@ static void gfx_v8_0_init_golden_registers(struct amdgpu_device *adev)
|
||||||
(const u32)ARRAY_SIZE(tonga_golden_common_all));
|
(const u32)ARRAY_SIZE(tonga_golden_common_all));
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
amdgpu_program_register_sequence(adev,
|
amdgpu_program_register_sequence(adev,
|
||||||
golden_settings_polaris11_a11,
|
golden_settings_polaris11_a11,
|
||||||
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
|
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
|
||||||
|
@ -903,6 +911,9 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
chip_name = "polaris10";
|
chip_name = "polaris10";
|
||||||
break;
|
break;
|
||||||
|
case CHIP_POLARIS12:
|
||||||
|
chip_name = "polaris12";
|
||||||
|
break;
|
||||||
case CHIP_STONEY:
|
case CHIP_STONEY:
|
||||||
chip_name = "stoney";
|
chip_name = "stoney";
|
||||||
break;
|
break;
|
||||||
|
@ -1768,6 +1779,7 @@ static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
|
||||||
gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
|
gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
ret = amdgpu_atombios_get_gfx_info(adev);
|
ret = amdgpu_atombios_get_gfx_info(adev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2682,6 +2694,7 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
|
||||||
PIPE_CONFIG(ADDR_SURF_P4_16x16) |
|
PIPE_CONFIG(ADDR_SURF_P4_16x16) |
|
||||||
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
|
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
|
||||||
|
@ -3503,6 +3516,7 @@ gfx_v8_0_raster_config(struct amdgpu_device *adev, u32 *rconf, u32 *rconf1)
|
||||||
*rconf1 |= 0x0;
|
*rconf1 |= 0x0;
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
*rconf |= RB_MAP_PKR0(2) | RB_XSEL2(1) | SE_MAP(2) |
|
*rconf |= RB_MAP_PKR0(2) | RB_XSEL2(1) | SE_MAP(2) |
|
||||||
SE_XSEL(1) | SE_YSEL(1);
|
SE_XSEL(1) | SE_YSEL(1);
|
||||||
*rconf1 |= 0x0;
|
*rconf1 |= 0x0;
|
||||||
|
@ -4021,7 +4035,8 @@ static void gfx_v8_0_init_pg(struct amdgpu_device *adev)
|
||||||
cz_enable_cp_power_gating(adev, true);
|
cz_enable_cp_power_gating(adev, true);
|
||||||
else
|
else
|
||||||
cz_enable_cp_power_gating(adev, false);
|
cz_enable_cp_power_gating(adev, false);
|
||||||
} else if (adev->asic_type == CHIP_POLARIS11) {
|
} else if ((adev->asic_type == CHIP_POLARIS11) ||
|
||||||
|
(adev->asic_type == CHIP_POLARIS12)) {
|
||||||
gfx_v8_0_init_csb(adev);
|
gfx_v8_0_init_csb(adev);
|
||||||
gfx_v8_0_init_save_restore_list(adev);
|
gfx_v8_0_init_save_restore_list(adev);
|
||||||
gfx_v8_0_enable_save_restore_machine(adev);
|
gfx_v8_0_enable_save_restore_machine(adev);
|
||||||
|
@ -4095,7 +4110,8 @@ static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev)
|
||||||
RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
|
RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
|
||||||
WREG32(mmRLC_CGCG_CGLS_CTRL, tmp);
|
WREG32(mmRLC_CGCG_CGLS_CTRL, tmp);
|
||||||
if (adev->asic_type == CHIP_POLARIS11 ||
|
if (adev->asic_type == CHIP_POLARIS11 ||
|
||||||
adev->asic_type == CHIP_POLARIS10) {
|
adev->asic_type == CHIP_POLARIS10 ||
|
||||||
|
adev->asic_type == CHIP_POLARIS12) {
|
||||||
tmp = RREG32(mmRLC_CGCG_CGLS_CTRL_3D);
|
tmp = RREG32(mmRLC_CGCG_CGLS_CTRL_3D);
|
||||||
tmp &= ~0x3;
|
tmp &= ~0x3;
|
||||||
WREG32(mmRLC_CGCG_CGLS_CTRL_3D, tmp);
|
WREG32(mmRLC_CGCG_CGLS_CTRL_3D, tmp);
|
||||||
|
@ -4283,6 +4299,7 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)
|
||||||
amdgpu_ring_write(ring, 0x0000002A);
|
amdgpu_ring_write(ring, 0x0000002A);
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
amdgpu_ring_write(ring, 0x16000012);
|
amdgpu_ring_write(ring, 0x16000012);
|
||||||
amdgpu_ring_write(ring, 0x00000000);
|
amdgpu_ring_write(ring, 0x00000000);
|
||||||
break;
|
break;
|
||||||
|
@ -4664,7 +4681,8 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
|
||||||
(adev->asic_type == CHIP_FIJI) ||
|
(adev->asic_type == CHIP_FIJI) ||
|
||||||
(adev->asic_type == CHIP_STONEY) ||
|
(adev->asic_type == CHIP_STONEY) ||
|
||||||
(adev->asic_type == CHIP_POLARIS11) ||
|
(adev->asic_type == CHIP_POLARIS11) ||
|
||||||
(adev->asic_type == CHIP_POLARIS10)) {
|
(adev->asic_type == CHIP_POLARIS10) ||
|
||||||
|
(adev->asic_type == CHIP_POLARIS12)) {
|
||||||
WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
|
WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
|
||||||
AMDGPU_DOORBELL_KIQ << 2);
|
AMDGPU_DOORBELL_KIQ << 2);
|
||||||
WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
|
WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
|
||||||
|
@ -4700,7 +4718,8 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
|
||||||
mqd->cp_hqd_persistent_state = tmp;
|
mqd->cp_hqd_persistent_state = tmp;
|
||||||
if (adev->asic_type == CHIP_STONEY ||
|
if (adev->asic_type == CHIP_STONEY ||
|
||||||
adev->asic_type == CHIP_POLARIS11 ||
|
adev->asic_type == CHIP_POLARIS11 ||
|
||||||
adev->asic_type == CHIP_POLARIS10) {
|
adev->asic_type == CHIP_POLARIS10 ||
|
||||||
|
adev->asic_type == CHIP_POLARIS12) {
|
||||||
tmp = RREG32(mmCP_ME1_PIPE3_INT_CNTL);
|
tmp = RREG32(mmCP_ME1_PIPE3_INT_CNTL);
|
||||||
tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE3_INT_CNTL, GENERIC2_INT_ENABLE, 1);
|
tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE3_INT_CNTL, GENERIC2_INT_ENABLE, 1);
|
||||||
WREG32(mmCP_ME1_PIPE3_INT_CNTL, tmp);
|
WREG32(mmCP_ME1_PIPE3_INT_CNTL, tmp);
|
||||||
|
@ -5279,7 +5298,8 @@ static int gfx_v8_0_late_init(void *handle)
|
||||||
static void gfx_v8_0_enable_gfx_static_mg_power_gating(struct amdgpu_device *adev,
|
static void gfx_v8_0_enable_gfx_static_mg_power_gating(struct amdgpu_device *adev,
|
||||||
bool enable)
|
bool enable)
|
||||||
{
|
{
|
||||||
if (adev->asic_type == CHIP_POLARIS11)
|
if ((adev->asic_type == CHIP_POLARIS11) ||
|
||||||
|
(adev->asic_type == CHIP_POLARIS12))
|
||||||
/* Send msg to SMU via Powerplay */
|
/* Send msg to SMU via Powerplay */
|
||||||
amdgpu_set_powergating_state(adev,
|
amdgpu_set_powergating_state(adev,
|
||||||
AMD_IP_BLOCK_TYPE_SMC,
|
AMD_IP_BLOCK_TYPE_SMC,
|
||||||
|
@ -5353,6 +5373,7 @@ static int gfx_v8_0_set_powergating_state(void *handle,
|
||||||
gfx_v8_0_enable_gfx_dynamic_mg_power_gating(adev, false);
|
gfx_v8_0_enable_gfx_dynamic_mg_power_gating(adev, false);
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG) && enable)
|
if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG) && enable)
|
||||||
gfx_v8_0_enable_gfx_static_mg_power_gating(adev, true);
|
gfx_v8_0_enable_gfx_static_mg_power_gating(adev, true);
|
||||||
else
|
else
|
||||||
|
|
|
@ -46,6 +46,7 @@ static int gmc_v8_0_wait_for_idle(void *handle);
|
||||||
MODULE_FIRMWARE("amdgpu/tonga_mc.bin");
|
MODULE_FIRMWARE("amdgpu/tonga_mc.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris11_mc.bin");
|
MODULE_FIRMWARE("amdgpu/polaris11_mc.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris10_mc.bin");
|
MODULE_FIRMWARE("amdgpu/polaris10_mc.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_mc.bin");
|
||||||
|
|
||||||
static const u32 golden_settings_tonga_a11[] =
|
static const u32 golden_settings_tonga_a11[] =
|
||||||
{
|
{
|
||||||
|
@ -130,6 +131,7 @@ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
|
||||||
(const u32)ARRAY_SIZE(golden_settings_tonga_a11));
|
(const u32)ARRAY_SIZE(golden_settings_tonga_a11));
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
amdgpu_program_register_sequence(adev,
|
amdgpu_program_register_sequence(adev,
|
||||||
golden_settings_polaris11_a11,
|
golden_settings_polaris11_a11,
|
||||||
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
|
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
|
||||||
|
@ -225,6 +227,9 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
chip_name = "polaris10";
|
chip_name = "polaris10";
|
||||||
break;
|
break;
|
||||||
|
case CHIP_POLARIS12:
|
||||||
|
chip_name = "polaris12";
|
||||||
|
break;
|
||||||
case CHIP_FIJI:
|
case CHIP_FIJI:
|
||||||
case CHIP_CARRIZO:
|
case CHIP_CARRIZO:
|
||||||
case CHIP_STONEY:
|
case CHIP_STONEY:
|
||||||
|
|
|
@ -60,6 +60,8 @@ MODULE_FIRMWARE("amdgpu/polaris10_sdma.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris10_sdma1.bin");
|
MODULE_FIRMWARE("amdgpu/polaris10_sdma1.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris11_sdma.bin");
|
MODULE_FIRMWARE("amdgpu/polaris11_sdma.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris11_sdma1.bin");
|
MODULE_FIRMWARE("amdgpu/polaris11_sdma1.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_sdma.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_sdma1.bin");
|
||||||
|
|
||||||
|
|
||||||
static const u32 sdma_offsets[SDMA_MAX_INSTANCE] =
|
static const u32 sdma_offsets[SDMA_MAX_INSTANCE] =
|
||||||
|
@ -206,6 +208,7 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
|
||||||
(const u32)ARRAY_SIZE(golden_settings_tonga_a11));
|
(const u32)ARRAY_SIZE(golden_settings_tonga_a11));
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
amdgpu_program_register_sequence(adev,
|
amdgpu_program_register_sequence(adev,
|
||||||
golden_settings_polaris11_a11,
|
golden_settings_polaris11_a11,
|
||||||
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
|
(const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
|
||||||
|
@ -278,6 +281,9 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
chip_name = "polaris10";
|
chip_name = "polaris10";
|
||||||
break;
|
break;
|
||||||
|
case CHIP_POLARIS12:
|
||||||
|
chip_name = "polaris12";
|
||||||
|
break;
|
||||||
case CHIP_CARRIZO:
|
case CHIP_CARRIZO:
|
||||||
chip_name = "carrizo";
|
chip_name = "carrizo";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -56,7 +56,6 @@
|
||||||
#define BIOS_SCRATCH_4 0x5cd
|
#define BIOS_SCRATCH_4 0x5cd
|
||||||
|
|
||||||
MODULE_FIRMWARE("radeon/tahiti_smc.bin");
|
MODULE_FIRMWARE("radeon/tahiti_smc.bin");
|
||||||
MODULE_FIRMWARE("radeon/tahiti_k_smc.bin");
|
|
||||||
MODULE_FIRMWARE("radeon/pitcairn_smc.bin");
|
MODULE_FIRMWARE("radeon/pitcairn_smc.bin");
|
||||||
MODULE_FIRMWARE("radeon/pitcairn_k_smc.bin");
|
MODULE_FIRMWARE("radeon/pitcairn_k_smc.bin");
|
||||||
MODULE_FIRMWARE("radeon/verde_smc.bin");
|
MODULE_FIRMWARE("radeon/verde_smc.bin");
|
||||||
|
@ -3488,19 +3487,6 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
|
||||||
(adev->pdev->device == 0x6817) ||
|
(adev->pdev->device == 0x6817) ||
|
||||||
(adev->pdev->device == 0x6806))
|
(adev->pdev->device == 0x6806))
|
||||||
max_mclk = 120000;
|
max_mclk = 120000;
|
||||||
} else if (adev->asic_type == CHIP_VERDE) {
|
|
||||||
if ((adev->pdev->revision == 0x81) ||
|
|
||||||
(adev->pdev->revision == 0x83) ||
|
|
||||||
(adev->pdev->revision == 0x87) ||
|
|
||||||
(adev->pdev->device == 0x6820) ||
|
|
||||||
(adev->pdev->device == 0x6821) ||
|
|
||||||
(adev->pdev->device == 0x6822) ||
|
|
||||||
(adev->pdev->device == 0x6823) ||
|
|
||||||
(adev->pdev->device == 0x682A) ||
|
|
||||||
(adev->pdev->device == 0x682B)) {
|
|
||||||
max_sclk = 75000;
|
|
||||||
max_mclk = 80000;
|
|
||||||
}
|
|
||||||
} else if (adev->asic_type == CHIP_OLAND) {
|
} else if (adev->asic_type == CHIP_OLAND) {
|
||||||
if ((adev->pdev->revision == 0xC7) ||
|
if ((adev->pdev->revision == 0xC7) ||
|
||||||
(adev->pdev->revision == 0x80) ||
|
(adev->pdev->revision == 0x80) ||
|
||||||
|
@ -7687,49 +7673,49 @@ static int si_dpm_init_microcode(struct amdgpu_device *adev)
|
||||||
chip_name = "tahiti";
|
chip_name = "tahiti";
|
||||||
break;
|
break;
|
||||||
case CHIP_PITCAIRN:
|
case CHIP_PITCAIRN:
|
||||||
if ((adev->pdev->revision == 0x81) ||
|
if ((adev->pdev->revision == 0x81) &&
|
||||||
(adev->pdev->device == 0x6810) ||
|
((adev->pdev->device == 0x6810) ||
|
||||||
(adev->pdev->device == 0x6811) ||
|
(adev->pdev->device == 0x6811)))
|
||||||
(adev->pdev->device == 0x6816) ||
|
|
||||||
(adev->pdev->device == 0x6817) ||
|
|
||||||
(adev->pdev->device == 0x6806))
|
|
||||||
chip_name = "pitcairn_k";
|
chip_name = "pitcairn_k";
|
||||||
else
|
else
|
||||||
chip_name = "pitcairn";
|
chip_name = "pitcairn";
|
||||||
break;
|
break;
|
||||||
case CHIP_VERDE:
|
case CHIP_VERDE:
|
||||||
if ((adev->pdev->revision == 0x81) ||
|
if (((adev->pdev->device == 0x6820) &&
|
||||||
(adev->pdev->revision == 0x83) ||
|
((adev->pdev->revision == 0x81) ||
|
||||||
(adev->pdev->revision == 0x87) ||
|
(adev->pdev->revision == 0x83))) ||
|
||||||
(adev->pdev->device == 0x6820) ||
|
((adev->pdev->device == 0x6821) &&
|
||||||
(adev->pdev->device == 0x6821) ||
|
((adev->pdev->revision == 0x83) ||
|
||||||
(adev->pdev->device == 0x6822) ||
|
(adev->pdev->revision == 0x87))) ||
|
||||||
(adev->pdev->device == 0x6823) ||
|
((adev->pdev->revision == 0x87) &&
|
||||||
(adev->pdev->device == 0x682A) ||
|
((adev->pdev->device == 0x6823) ||
|
||||||
(adev->pdev->device == 0x682B))
|
(adev->pdev->device == 0x682b))))
|
||||||
chip_name = "verde_k";
|
chip_name = "verde_k";
|
||||||
else
|
else
|
||||||
chip_name = "verde";
|
chip_name = "verde";
|
||||||
break;
|
break;
|
||||||
case CHIP_OLAND:
|
case CHIP_OLAND:
|
||||||
if ((adev->pdev->revision == 0xC7) ||
|
if (((adev->pdev->revision == 0x81) &&
|
||||||
(adev->pdev->revision == 0x80) ||
|
((adev->pdev->device == 0x6600) ||
|
||||||
(adev->pdev->revision == 0x81) ||
|
(adev->pdev->device == 0x6604) ||
|
||||||
(adev->pdev->revision == 0x83) ||
|
(adev->pdev->device == 0x6605) ||
|
||||||
(adev->pdev->revision == 0x87) ||
|
(adev->pdev->device == 0x6610))) ||
|
||||||
(adev->pdev->device == 0x6604) ||
|
((adev->pdev->revision == 0x83) &&
|
||||||
(adev->pdev->device == 0x6605))
|
(adev->pdev->device == 0x6610)))
|
||||||
chip_name = "oland_k";
|
chip_name = "oland_k";
|
||||||
else
|
else
|
||||||
chip_name = "oland";
|
chip_name = "oland";
|
||||||
break;
|
break;
|
||||||
case CHIP_HAINAN:
|
case CHIP_HAINAN:
|
||||||
if ((adev->pdev->revision == 0x81) ||
|
if (((adev->pdev->revision == 0x81) &&
|
||||||
(adev->pdev->revision == 0x83) ||
|
(adev->pdev->device == 0x6660)) ||
|
||||||
(adev->pdev->revision == 0xC3) ||
|
((adev->pdev->revision == 0x83) &&
|
||||||
(adev->pdev->device == 0x6664) ||
|
((adev->pdev->device == 0x6660) ||
|
||||||
(adev->pdev->device == 0x6665) ||
|
(adev->pdev->device == 0x6663) ||
|
||||||
(adev->pdev->device == 0x6667))
|
(adev->pdev->device == 0x6665) ||
|
||||||
|
(adev->pdev->device == 0x6667))) ||
|
||||||
|
((adev->pdev->revision == 0xc3) &&
|
||||||
|
(adev->pdev->device == 0x6665)))
|
||||||
chip_name = "hainan_k";
|
chip_name = "hainan_k";
|
||||||
else
|
else
|
||||||
chip_name = "hainan";
|
chip_name = "hainan";
|
||||||
|
|
|
@ -791,15 +791,10 @@ static int uvd_v5_0_set_clockgating_state(void *handle,
|
||||||
{
|
{
|
||||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||||
bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
|
bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
|
||||||
static int curstate = -1;
|
|
||||||
|
|
||||||
if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
|
if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (curstate == state)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
curstate = state;
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
/* wait for STATUS to clear */
|
/* wait for STATUS to clear */
|
||||||
if (uvd_v5_0_wait_for_idle(handle))
|
if (uvd_v5_0_wait_for_idle(handle))
|
||||||
|
|
|
@ -320,11 +320,12 @@ static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
|
||||||
{
|
{
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
/* Fiji, Stoney, Polaris10, Polaris11 are single pipe */
|
/* Fiji, Stoney, Polaris10, Polaris11, Polaris12 are single pipe */
|
||||||
if ((adev->asic_type == CHIP_FIJI) ||
|
if ((adev->asic_type == CHIP_FIJI) ||
|
||||||
(adev->asic_type == CHIP_STONEY) ||
|
(adev->asic_type == CHIP_STONEY) ||
|
||||||
(adev->asic_type == CHIP_POLARIS10) ||
|
(adev->asic_type == CHIP_POLARIS10) ||
|
||||||
(adev->asic_type == CHIP_POLARIS11))
|
(adev->asic_type == CHIP_POLARIS11) ||
|
||||||
|
(adev->asic_type == CHIP_POLARIS12))
|
||||||
return AMDGPU_VCE_HARVEST_VCE1;
|
return AMDGPU_VCE_HARVEST_VCE1;
|
||||||
|
|
||||||
/* Tonga and CZ are dual or single pipe */
|
/* Tonga and CZ are dual or single pipe */
|
||||||
|
|
|
@ -88,6 +88,7 @@ MODULE_FIRMWARE("amdgpu/polaris10_smc.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin");
|
MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris11_smc.bin");
|
MODULE_FIRMWARE("amdgpu/polaris11_smc.bin");
|
||||||
MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin");
|
MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin");
|
||||||
|
MODULE_FIRMWARE("amdgpu/polaris12_smc.bin");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Indirect registers accessor
|
* Indirect registers accessor
|
||||||
|
@ -312,6 +313,7 @@ static void vi_init_golden_registers(struct amdgpu_device *adev)
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -671,6 +673,7 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
|
||||||
case CHIP_TONGA:
|
case CHIP_TONGA:
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
case CHIP_CARRIZO:
|
case CHIP_CARRIZO:
|
||||||
case CHIP_STONEY:
|
case CHIP_STONEY:
|
||||||
asic_register_table = cz_allowed_read_registers;
|
asic_register_table = cz_allowed_read_registers;
|
||||||
|
@ -994,6 +997,11 @@ static int vi_common_early_init(void *handle)
|
||||||
adev->pg_flags = 0;
|
adev->pg_flags = 0;
|
||||||
adev->external_rev_id = adev->rev_id + 0x50;
|
adev->external_rev_id = adev->rev_id + 0x50;
|
||||||
break;
|
break;
|
||||||
|
case CHIP_POLARIS12:
|
||||||
|
adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG;
|
||||||
|
adev->pg_flags = 0;
|
||||||
|
adev->external_rev_id = adev->rev_id + 0x64;
|
||||||
|
break;
|
||||||
case CHIP_CARRIZO:
|
case CHIP_CARRIZO:
|
||||||
adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
|
adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
|
||||||
AMD_CG_SUPPORT_GFX_MGCG |
|
AMD_CG_SUPPORT_GFX_MGCG |
|
||||||
|
@ -1346,6 +1354,7 @@ static int vi_common_set_clockgating_state(void *handle,
|
||||||
case CHIP_TONGA:
|
case CHIP_TONGA:
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
vi_common_set_clockgating_state_by_smu(adev, state);
|
vi_common_set_clockgating_state_by_smu(adev, state);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1429,6 +1438,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
amdgpu_ip_block_add(adev, &vi_common_ip_block);
|
amdgpu_ip_block_add(adev, &vi_common_ip_block);
|
||||||
amdgpu_ip_block_add(adev, &gmc_v8_1_ip_block);
|
amdgpu_ip_block_add(adev, &gmc_v8_1_ip_block);
|
||||||
amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
|
amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#ifndef __AMD_SHARED_H__
|
#ifndef __AMD_SHARED_H__
|
||||||
#define __AMD_SHARED_H__
|
#define __AMD_SHARED_H__
|
||||||
|
|
||||||
#define AMD_MAX_USEC_TIMEOUT 100000 /* 100 ms */
|
#define AMD_MAX_USEC_TIMEOUT 200000 /* 200 ms */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Supported ASIC types
|
* Supported ASIC types
|
||||||
|
@ -46,6 +46,7 @@ enum amd_asic_type {
|
||||||
CHIP_STONEY,
|
CHIP_STONEY,
|
||||||
CHIP_POLARIS10,
|
CHIP_POLARIS10,
|
||||||
CHIP_POLARIS11,
|
CHIP_POLARIS11,
|
||||||
|
CHIP_POLARIS12,
|
||||||
CHIP_LAST,
|
CHIP_LAST,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
polaris_set_asic_special_caps(hwmgr);
|
polaris_set_asic_special_caps(hwmgr);
|
||||||
hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
|
hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
|
||||||
break;
|
break;
|
||||||
|
@ -745,7 +746,7 @@ int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
|
||||||
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
|
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
|
||||||
PHM_PlatformCaps_TablelessHardwareInterface);
|
PHM_PlatformCaps_TablelessHardwareInterface);
|
||||||
|
|
||||||
if (hwmgr->chip_id == CHIP_POLARIS11)
|
if ((hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12))
|
||||||
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
|
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
|
||||||
PHM_PlatformCaps_SPLLShutdownSupport);
|
PHM_PlatformCaps_SPLLShutdownSupport);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -521,7 +521,7 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr)
|
||||||
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
|
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
|
||||||
result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris10);
|
result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris10);
|
||||||
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
|
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
|
||||||
} else if (hwmgr->chip_id == CHIP_POLARIS11) {
|
} else if ((hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12)) {
|
||||||
result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11);
|
result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11);
|
||||||
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
|
PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
|
||||||
result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11);
|
result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11);
|
||||||
|
|
|
@ -65,6 +65,7 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
|
||||||
break;
|
break;
|
||||||
case CHIP_POLARIS11:
|
case CHIP_POLARIS11:
|
||||||
case CHIP_POLARIS10:
|
case CHIP_POLARIS10:
|
||||||
|
case CHIP_POLARIS12:
|
||||||
polaris10_smum_init(smumgr);
|
polaris10_smum_init(smumgr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1259,8 +1259,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
|
||||||
|
|
||||||
if (!nonblock) {
|
if (!nonblock) {
|
||||||
ret = drm_atomic_helper_wait_for_fences(dev, state, true);
|
ret = drm_atomic_helper_wait_for_fences(dev, state, true);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
drm_atomic_helper_cleanup_planes(dev, state);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -51,6 +51,9 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
|
||||||
struct drm_crtc_state *crtc_state;
|
struct drm_crtc_state *crtc_state;
|
||||||
struct drm_rect clip = { 0, };
|
struct drm_rect clip = { 0, };
|
||||||
|
|
||||||
|
if (!state->crtc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
|
crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
|
||||||
if (IS_ERR(crtc_state))
|
if (IS_ERR(crtc_state))
|
||||||
return PTR_ERR(crtc_state);
|
return PTR_ERR(crtc_state);
|
||||||
|
|
|
@ -38,6 +38,11 @@
|
||||||
* - TV Panel encoding via ENCT
|
* - TV Panel encoding via ENCT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* HHI Registers */
|
||||||
|
#define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
|
||||||
|
#define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
|
||||||
|
#define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */
|
||||||
|
|
||||||
struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
|
struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
|
||||||
.mode_tag = MESON_VENC_MODE_CVBS_PAL,
|
.mode_tag = MESON_VENC_MODE_CVBS_PAL,
|
||||||
.hso_begin = 3,
|
.hso_begin = 3,
|
||||||
|
@ -242,6 +247,20 @@ void meson_venc_disable_vsync(struct meson_drm *priv)
|
||||||
|
|
||||||
void meson_venc_init(struct meson_drm *priv)
|
void meson_venc_init(struct meson_drm *priv)
|
||||||
{
|
{
|
||||||
|
/* Disable CVBS VDAC */
|
||||||
|
regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
|
||||||
|
regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
|
||||||
|
|
||||||
|
/* Power Down Dacs */
|
||||||
|
writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
|
||||||
|
|
||||||
|
/* Disable HDMI PHY */
|
||||||
|
regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
|
||||||
|
|
||||||
|
/* Disable HDMI */
|
||||||
|
writel_bits_relaxed(0x3, 0,
|
||||||
|
priv->io_base + _REG(VPU_HDMI_SETTING));
|
||||||
|
|
||||||
/* Disable all encoders */
|
/* Disable all encoders */
|
||||||
writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
|
writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
|
||||||
writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
|
writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
|
||||||
|
|
|
@ -167,7 +167,7 @@ static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
|
||||||
|
|
||||||
/* Disable CVBS VDAC */
|
/* Disable CVBS VDAC */
|
||||||
regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
|
regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
|
||||||
regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
|
regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
|
static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
|
||||||
|
|
|
@ -213,7 +213,14 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
|
||||||
void adreno_flush(struct msm_gpu *gpu)
|
void adreno_flush(struct msm_gpu *gpu)
|
||||||
{
|
{
|
||||||
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
|
||||||
uint32_t wptr = get_wptr(gpu->rb);
|
uint32_t wptr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mask wptr value that we calculate to fit in the HW range. This is
|
||||||
|
* to account for the possibility that the last command fit exactly into
|
||||||
|
* the ringbuffer and rb->next hasn't wrapped to zero yet
|
||||||
|
*/
|
||||||
|
wptr = get_wptr(gpu->rb) & ((gpu->rb->size / 4) - 1);
|
||||||
|
|
||||||
/* ensure writes to ringbuffer have hit system memory: */
|
/* ensure writes to ringbuffer have hit system memory: */
|
||||||
mb();
|
mb();
|
||||||
|
|
|
@ -106,7 +106,8 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) {
|
if ((submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) ||
|
||||||
|
!(submit_bo.flags & MSM_SUBMIT_BO_FLAGS)) {
|
||||||
DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
|
DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -290,7 +291,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
|
||||||
{
|
{
|
||||||
uint32_t i, last_offset = 0;
|
uint32_t i, last_offset = 0;
|
||||||
uint32_t *ptr;
|
uint32_t *ptr;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
if (offset % 4) {
|
if (offset % 4) {
|
||||||
DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
|
DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
|
||||||
|
@ -318,12 +319,13 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
|
||||||
|
|
||||||
ret = copy_from_user(&submit_reloc, userptr, sizeof(submit_reloc));
|
ret = copy_from_user(&submit_reloc, userptr, sizeof(submit_reloc));
|
||||||
if (ret)
|
if (ret)
|
||||||
return -EFAULT;
|
goto out;
|
||||||
|
|
||||||
if (submit_reloc.submit_offset % 4) {
|
if (submit_reloc.submit_offset % 4) {
|
||||||
DRM_ERROR("non-aligned reloc offset: %u\n",
|
DRM_ERROR("non-aligned reloc offset: %u\n",
|
||||||
submit_reloc.submit_offset);
|
submit_reloc.submit_offset);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* offset in dwords: */
|
/* offset in dwords: */
|
||||||
|
@ -332,12 +334,13 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
|
||||||
if ((off >= (obj->base.size / 4)) ||
|
if ((off >= (obj->base.size / 4)) ||
|
||||||
(off < last_offset)) {
|
(off < last_offset)) {
|
||||||
DRM_ERROR("invalid offset %u at reloc %u\n", off, i);
|
DRM_ERROR("invalid offset %u at reloc %u\n", off, i);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, &valid);
|
ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, &valid);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
continue;
|
continue;
|
||||||
|
@ -354,9 +357,10 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
|
||||||
last_offset = off;
|
last_offset = off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
msm_gem_put_vaddr_locked(&obj->base);
|
msm_gem_put_vaddr_locked(&obj->base);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void submit_cleanup(struct msm_gem_submit *submit)
|
static void submit_cleanup(struct msm_gem_submit *submit)
|
||||||
|
|
|
@ -23,7 +23,8 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size)
|
||||||
struct msm_ringbuffer *ring;
|
struct msm_ringbuffer *ring;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
size = ALIGN(size, 4); /* size should be dword aligned */
|
if (WARN_ON(!is_power_of_2(size)))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
|
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
|
||||||
if (!ring) {
|
if (!ring) {
|
||||||
|
|
|
@ -50,7 +50,6 @@ MODULE_FIRMWARE("radeon/tahiti_ce.bin");
|
||||||
MODULE_FIRMWARE("radeon/tahiti_mc.bin");
|
MODULE_FIRMWARE("radeon/tahiti_mc.bin");
|
||||||
MODULE_FIRMWARE("radeon/tahiti_rlc.bin");
|
MODULE_FIRMWARE("radeon/tahiti_rlc.bin");
|
||||||
MODULE_FIRMWARE("radeon/tahiti_smc.bin");
|
MODULE_FIRMWARE("radeon/tahiti_smc.bin");
|
||||||
MODULE_FIRMWARE("radeon/tahiti_k_smc.bin");
|
|
||||||
|
|
||||||
MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
|
MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
|
||||||
MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
|
MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
|
||||||
|
@ -1657,9 +1656,6 @@ static int si_init_microcode(struct radeon_device *rdev)
|
||||||
switch (rdev->family) {
|
switch (rdev->family) {
|
||||||
case CHIP_TAHITI:
|
case CHIP_TAHITI:
|
||||||
chip_name = "TAHITI";
|
chip_name = "TAHITI";
|
||||||
/* XXX: figure out which Tahitis need the new ucode */
|
|
||||||
if (0)
|
|
||||||
new_smc = true;
|
|
||||||
new_chip_name = "tahiti";
|
new_chip_name = "tahiti";
|
||||||
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
||||||
me_req_size = SI_PM4_UCODE_SIZE * 4;
|
me_req_size = SI_PM4_UCODE_SIZE * 4;
|
||||||
|
@ -1671,12 +1667,9 @@ static int si_init_microcode(struct radeon_device *rdev)
|
||||||
break;
|
break;
|
||||||
case CHIP_PITCAIRN:
|
case CHIP_PITCAIRN:
|
||||||
chip_name = "PITCAIRN";
|
chip_name = "PITCAIRN";
|
||||||
if ((rdev->pdev->revision == 0x81) ||
|
if ((rdev->pdev->revision == 0x81) &&
|
||||||
(rdev->pdev->device == 0x6810) ||
|
((rdev->pdev->device == 0x6810) ||
|
||||||
(rdev->pdev->device == 0x6811) ||
|
(rdev->pdev->device == 0x6811)))
|
||||||
(rdev->pdev->device == 0x6816) ||
|
|
||||||
(rdev->pdev->device == 0x6817) ||
|
|
||||||
(rdev->pdev->device == 0x6806))
|
|
||||||
new_smc = true;
|
new_smc = true;
|
||||||
new_chip_name = "pitcairn";
|
new_chip_name = "pitcairn";
|
||||||
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
||||||
|
@ -1689,15 +1682,15 @@ static int si_init_microcode(struct radeon_device *rdev)
|
||||||
break;
|
break;
|
||||||
case CHIP_VERDE:
|
case CHIP_VERDE:
|
||||||
chip_name = "VERDE";
|
chip_name = "VERDE";
|
||||||
if ((rdev->pdev->revision == 0x81) ||
|
if (((rdev->pdev->device == 0x6820) &&
|
||||||
(rdev->pdev->revision == 0x83) ||
|
((rdev->pdev->revision == 0x81) ||
|
||||||
(rdev->pdev->revision == 0x87) ||
|
(rdev->pdev->revision == 0x83))) ||
|
||||||
(rdev->pdev->device == 0x6820) ||
|
((rdev->pdev->device == 0x6821) &&
|
||||||
(rdev->pdev->device == 0x6821) ||
|
((rdev->pdev->revision == 0x83) ||
|
||||||
(rdev->pdev->device == 0x6822) ||
|
(rdev->pdev->revision == 0x87))) ||
|
||||||
(rdev->pdev->device == 0x6823) ||
|
((rdev->pdev->revision == 0x87) &&
|
||||||
(rdev->pdev->device == 0x682A) ||
|
((rdev->pdev->device == 0x6823) ||
|
||||||
(rdev->pdev->device == 0x682B))
|
(rdev->pdev->device == 0x682b))))
|
||||||
new_smc = true;
|
new_smc = true;
|
||||||
new_chip_name = "verde";
|
new_chip_name = "verde";
|
||||||
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
||||||
|
@ -1710,13 +1703,13 @@ static int si_init_microcode(struct radeon_device *rdev)
|
||||||
break;
|
break;
|
||||||
case CHIP_OLAND:
|
case CHIP_OLAND:
|
||||||
chip_name = "OLAND";
|
chip_name = "OLAND";
|
||||||
if ((rdev->pdev->revision == 0xC7) ||
|
if (((rdev->pdev->revision == 0x81) &&
|
||||||
(rdev->pdev->revision == 0x80) ||
|
((rdev->pdev->device == 0x6600) ||
|
||||||
(rdev->pdev->revision == 0x81) ||
|
(rdev->pdev->device == 0x6604) ||
|
||||||
(rdev->pdev->revision == 0x83) ||
|
(rdev->pdev->device == 0x6605) ||
|
||||||
(rdev->pdev->revision == 0x87) ||
|
(rdev->pdev->device == 0x6610))) ||
|
||||||
(rdev->pdev->device == 0x6604) ||
|
((rdev->pdev->revision == 0x83) &&
|
||||||
(rdev->pdev->device == 0x6605))
|
(rdev->pdev->device == 0x6610)))
|
||||||
new_smc = true;
|
new_smc = true;
|
||||||
new_chip_name = "oland";
|
new_chip_name = "oland";
|
||||||
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
||||||
|
@ -1728,12 +1721,15 @@ static int si_init_microcode(struct radeon_device *rdev)
|
||||||
break;
|
break;
|
||||||
case CHIP_HAINAN:
|
case CHIP_HAINAN:
|
||||||
chip_name = "HAINAN";
|
chip_name = "HAINAN";
|
||||||
if ((rdev->pdev->revision == 0x81) ||
|
if (((rdev->pdev->revision == 0x81) &&
|
||||||
(rdev->pdev->revision == 0x83) ||
|
(rdev->pdev->device == 0x6660)) ||
|
||||||
(rdev->pdev->revision == 0xC3) ||
|
((rdev->pdev->revision == 0x83) &&
|
||||||
(rdev->pdev->device == 0x6664) ||
|
((rdev->pdev->device == 0x6660) ||
|
||||||
(rdev->pdev->device == 0x6665) ||
|
(rdev->pdev->device == 0x6663) ||
|
||||||
(rdev->pdev->device == 0x6667))
|
(rdev->pdev->device == 0x6665) ||
|
||||||
|
(rdev->pdev->device == 0x6667))) ||
|
||||||
|
((rdev->pdev->revision == 0xc3) &&
|
||||||
|
(rdev->pdev->device == 0x6665)))
|
||||||
new_smc = true;
|
new_smc = true;
|
||||||
new_chip_name = "hainan";
|
new_chip_name = "hainan";
|
||||||
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
|
||||||
|
|
|
@ -3008,19 +3008,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
||||||
(rdev->pdev->device == 0x6817) ||
|
(rdev->pdev->device == 0x6817) ||
|
||||||
(rdev->pdev->device == 0x6806))
|
(rdev->pdev->device == 0x6806))
|
||||||
max_mclk = 120000;
|
max_mclk = 120000;
|
||||||
} else if (rdev->family == CHIP_VERDE) {
|
|
||||||
if ((rdev->pdev->revision == 0x81) ||
|
|
||||||
(rdev->pdev->revision == 0x83) ||
|
|
||||||
(rdev->pdev->revision == 0x87) ||
|
|
||||||
(rdev->pdev->device == 0x6820) ||
|
|
||||||
(rdev->pdev->device == 0x6821) ||
|
|
||||||
(rdev->pdev->device == 0x6822) ||
|
|
||||||
(rdev->pdev->device == 0x6823) ||
|
|
||||||
(rdev->pdev->device == 0x682A) ||
|
|
||||||
(rdev->pdev->device == 0x682B)) {
|
|
||||||
max_sclk = 75000;
|
|
||||||
max_mclk = 80000;
|
|
||||||
}
|
|
||||||
} else if (rdev->family == CHIP_OLAND) {
|
} else if (rdev->family == CHIP_OLAND) {
|
||||||
if ((rdev->pdev->revision == 0xC7) ||
|
if ((rdev->pdev->revision == 0xC7) ||
|
||||||
(rdev->pdev->revision == 0x80) ||
|
(rdev->pdev->revision == 0x80) ||
|
||||||
|
|
|
@ -856,7 +856,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
|
||||||
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
|
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
|
||||||
struct drm_device *dev = crtc->dev;
|
struct drm_device *dev = crtc->dev;
|
||||||
struct tilcdc_drm_private *priv = dev->dev_private;
|
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||||
uint32_t stat;
|
uint32_t stat, reg;
|
||||||
|
|
||||||
stat = tilcdc_read_irqstatus(dev);
|
stat = tilcdc_read_irqstatus(dev);
|
||||||
tilcdc_clear_irqstatus(dev, stat);
|
tilcdc_clear_irqstatus(dev, stat);
|
||||||
|
@ -921,17 +921,26 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
|
||||||
dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost",
|
dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost",
|
||||||
__func__, stat);
|
__func__, stat);
|
||||||
tilcdc_crtc->frame_intact = false;
|
tilcdc_crtc->frame_intact = false;
|
||||||
if (tilcdc_crtc->sync_lost_count++ >
|
if (priv->rev == 1) {
|
||||||
SYNC_LOST_COUNT_LIMIT) {
|
reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG);
|
||||||
dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, recovering", __func__, stat);
|
if (reg & LCDC_RASTER_ENABLE) {
|
||||||
queue_work(system_wq, &tilcdc_crtc->recover_work);
|
|
||||||
if (priv->rev == 1)
|
|
||||||
tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
|
tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
|
||||||
LCDC_V1_SYNC_LOST_INT_ENA);
|
LCDC_RASTER_ENABLE);
|
||||||
else
|
tilcdc_set(dev, LCDC_RASTER_CTRL_REG,
|
||||||
|
LCDC_RASTER_ENABLE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tilcdc_crtc->sync_lost_count++ >
|
||||||
|
SYNC_LOST_COUNT_LIMIT) {
|
||||||
|
dev_err(dev->dev,
|
||||||
|
"%s(0x%08x): Sync lost flood detected, recovering",
|
||||||
|
__func__, stat);
|
||||||
|
queue_work(system_wq,
|
||||||
|
&tilcdc_crtc->recover_work);
|
||||||
tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
|
tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
|
||||||
LCDC_SYNC_LOST);
|
LCDC_SYNC_LOST);
|
||||||
tilcdc_crtc->sync_lost_count = 0;
|
tilcdc_crtc->sync_lost_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2496,6 +2496,7 @@ static const struct hid_device_id hid_ignore_list[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
|
||||||
#if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB)
|
#if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB)
|
||||||
|
|
|
@ -39,6 +39,9 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
|
if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
|
||||||
return rdesc;
|
return rdesc;
|
||||||
|
|
||||||
|
if (*rsize < 4)
|
||||||
|
return rdesc;
|
||||||
|
|
||||||
for (i = 0; i < *rsize - 4; i++)
|
for (i = 0; i < *rsize - 4; i++)
|
||||||
if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
|
if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
|
||||||
rdesc[i] = 0x19;
|
rdesc[i] = 0x19;
|
||||||
|
|
|
@ -816,6 +816,9 @@
|
||||||
#define USB_VENDOR_ID_PETALYNX 0x18b1
|
#define USB_VENDOR_ID_PETALYNX 0x18b1
|
||||||
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
|
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
|
||||||
|
|
||||||
|
#define USB_VENDOR_ID_PETZL 0x2122
|
||||||
|
#define USB_DEVICE_ID_PETZL_HEADLAMP 0x1234
|
||||||
|
|
||||||
#define USB_VENDOR_ID_PHILIPS 0x0471
|
#define USB_VENDOR_ID_PHILIPS 0x0471
|
||||||
#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
|
#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
|
||||||
|
|
||||||
|
|
|
@ -426,6 +426,15 @@ static int i2c_hid_hwreset(struct i2c_client *client)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The HID over I2C specification states that if a DEVICE needs time
|
||||||
|
* after the PWR_ON request, it should utilise CLOCK stretching.
|
||||||
|
* However, it has been observered that the Windows driver provides a
|
||||||
|
* 1ms sleep between the PWR_ON and RESET requests and that some devices
|
||||||
|
* rely on this.
|
||||||
|
*/
|
||||||
|
usleep_range(1000, 5000);
|
||||||
|
|
||||||
i2c_hid_dbg(ihid, "resetting...\n");
|
i2c_hid_dbg(ihid, "resetting...\n");
|
||||||
|
|
||||||
ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
|
ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue