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:
Greg Kroah-Hartman 2017-01-16 17:01:44 +01:00
commit 39461ffdfc
312 changed files with 2969 additions and 1721 deletions

View File

@ -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>

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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*

View File

@ -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
/* /*

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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 */

View File

@ -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",

View File

@ -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 */

View File

@ -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:

View File

@ -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

View File

@ -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!",

View File

@ -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 = {

View File

@ -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]);

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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));

View File

@ -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 *

View File

@ -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;
}; };

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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);

View File

@ -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:

View File

@ -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",

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -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))

View File

@ -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;
} }

View File

@ -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:

View File

@ -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();
} }

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
} }

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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.

View File

@ -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 */

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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);
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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}
}; };

View File

@ -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:

View File

@ -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;
} }

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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";

View File

@ -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))

View File

@ -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 */

View File

@ -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);

View File

@ -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,
}; };

View File

@ -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;

View File

@ -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);

View File

@ -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:

View File

@ -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;
}
} }
/* /*

View File

@ -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);

View File

@ -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));

View File

@ -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)

View File

@ -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();

View File

@ -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)

View File

@ -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) {

View File

@ -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;

View File

@ -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) ||

View File

@ -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;
}
} }
} }

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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