mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-7.1-rc3). Conflicts: net/ipv4/igmp.c726fa7da2d("ipv4: igmp: get rid of IGMPV3_{QQIC,MRC} and simplify calculation")c6bebaa744("ipv4: igmp: annotate data-races in igmp_heard_query()") https://lore.kernel.org/a7365e4873340f7a5e30411207de3bf9@kernel.org Adjacent changes: net/psp/psp_main.c30cb24f97d("psp: strip variable-length PSP header in psp_dev_rcv()")c2b22277ad("psp: validate IPv4 header fields in psp_dev_rcv()") net/sched/sch_fq_codel.cf83e07b292("net/sched: sch_fq_codel: annotate data-races from fq_codel_dump_class_stats()")3f3aa77ff1("net/sched: add qstats_cpu_drop_inc() helper") net/wireless/pmsr.c0f3c0a1973("wifi: nl80211: fix NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST usage")410aa47fd9("wifi: cfg80211: allow suppressing FTM result reporting for PD requests") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
6a4c4656b0
6
.mailmap
6
.mailmap
|
|
@ -19,6 +19,7 @@ Abhinav Kumar <quic_abhinavk@quicinc.com> <abhinavk@codeaurora.org>
|
|||
Ahmad Masri <quic_amasri@quicinc.com> <amasri@codeaurora.org>
|
||||
Adam Oldham <oldhamca@gmail.com>
|
||||
Adam Radford <aradford@gmail.com>
|
||||
Aditya Garg <gargaditya08@proton.me> <gargaditya08@live.com>
|
||||
Adriana Reus <adi.reus@gmail.com> <adriana.reus@intel.com>
|
||||
Adrian Bunk <bunk@stusta.de>
|
||||
Ajay Kaher <ajay.kaher@broadcom.com> <akaher@vmware.com>
|
||||
|
|
@ -207,6 +208,7 @@ Claudiu Beznea <claudiu.beznea@tuxon.dev> <claudiu.beznea@microchip.com>
|
|||
Colin Ian King <colin.i.king@gmail.com> <colin.king@canonical.com>
|
||||
Corey Minyard <minyard@acm.org>
|
||||
Damian Hobson-Garcia <dhobsong@igel.co.jp>
|
||||
Dan Carpenter <error27@gmail.com> <dan.carpenter@linaro.org>
|
||||
Dan Carpenter <error27@gmail.com> <dan.carpenter@oracle.com>
|
||||
Dan Williams <djbw@kernel.org> <dan.j.williams@intel.com>
|
||||
Daniel Borkmann <daniel@iogearbox.net> <danborkmann@googlemail.com>
|
||||
|
|
@ -495,6 +497,7 @@ Leon Romanovsky <leon@kernel.org> <leon@leon.nu>
|
|||
Leon Romanovsky <leon@kernel.org> <leonro@mellanox.com>
|
||||
Leon Romanovsky <leon@kernel.org> <leonro@nvidia.com>
|
||||
Leo Yan <leo.yan@linux.dev> <leo.yan@linaro.org>
|
||||
Liam R. Howlett <liam@infradead.org> <Liam.Howlett@oracle.com>
|
||||
Liam Mark <quic_lmark@quicinc.com> <lmark@codeaurora.org>
|
||||
Linas Vepstas <linas@austin.ibm.com>
|
||||
Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
|
||||
|
|
@ -505,6 +508,8 @@ Linus Walleij <linusw@kernel.org> <linus.walleij@stericsson.com>
|
|||
Linus Walleij <linusw@kernel.org> <linus.walleij@linaro.org>
|
||||
Linus Walleij <linusw@kernel.org> <triad@df.lth.se>
|
||||
<linux-hardening@vger.kernel.org> <kernel-hardening@lists.openwall.com>
|
||||
Li Wang <li.wang@linux.dev> <liwang@redhat.com>
|
||||
Li Wang <li.wang@linux.dev> <wangli.ahau@gmail.com>
|
||||
Li Yang <leoyang.li@nxp.com> <leoli@freescale.com>
|
||||
Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
|
||||
Lior David <quic_liord@quicinc.com> <liord@codeaurora.org>
|
||||
|
|
@ -687,6 +692,7 @@ Punit Agrawal <punitagrawal@gmail.com> <punit.agrawal@arm.com>
|
|||
Puranjay Mohan <puranjay@kernel.org> <puranjay12@gmail.com>
|
||||
Qais Yousef <qyousef@layalina.io> <qais.yousef@imgtec.com>
|
||||
Qais Yousef <qyousef@layalina.io> <qais.yousef@arm.com>
|
||||
Qi Zheng <qi.zheng@linux.dev> <zhengqi.arch@bytedance.com>
|
||||
Quentin Monnet <qmo@kernel.org> <quentin.monnet@netronome.com>
|
||||
Quentin Monnet <qmo@kernel.org> <quentin@isovalent.com>
|
||||
Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
|
||||
|
|
|
|||
|
|
@ -47,21 +47,19 @@ Please note that implementation details can be changed.
|
|||
Called when swp_entry's refcnt goes down to 0. A charge against swap
|
||||
disappears.
|
||||
|
||||
3. charge-commit-cancel
|
||||
3. charge-commit
|
||||
=======================
|
||||
|
||||
Memcg pages are charged in two steps:
|
||||
|
||||
- mem_cgroup_try_charge()
|
||||
- mem_cgroup_commit_charge() or mem_cgroup_cancel_charge()
|
||||
- commit_charge()
|
||||
|
||||
At try_charge(), there are no flags to say "this page is charged".
|
||||
at this point, usage += PAGE_SIZE.
|
||||
|
||||
At commit(), the page is associated with the memcg.
|
||||
|
||||
At cancel(), simply usage -= PAGE_SIZE.
|
||||
|
||||
Under below explanation, we assume CONFIG_SWAP=y.
|
||||
|
||||
4. Anonymous
|
||||
|
|
|
|||
42
MAINTAINERS
42
MAINTAINERS
|
|
@ -7077,6 +7077,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/debugobjec
|
|||
F: include/linux/debugobjects.h
|
||||
F: lib/debugobjects.c
|
||||
|
||||
DEC LANCE NETWORK DRIVER
|
||||
M: "Maciej W. Rozycki" <macro@orcam.me.uk>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/amd/declance.c
|
||||
|
||||
DECSTATION PLATFORM SUPPORT
|
||||
M: "Maciej W. Rozycki" <macro@orcam.me.uk>
|
||||
L: linux-mips@vger.kernel.org
|
||||
|
|
@ -7873,7 +7879,7 @@ F: drivers/gpu/drm/sun4i/sun8i*
|
|||
|
||||
DRM DRIVER FOR APPLE TOUCH BARS
|
||||
M: Aun-Ali Zaidi <admin@kodeit.net>
|
||||
M: Aditya Garg <gargaditya08@live.com>
|
||||
M: Aditya Garg <gargaditya08@proton.me>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
|
|
@ -13860,7 +13866,6 @@ M: Pratyush Yadav <pratyush@kernel.org>
|
|||
R: Dave Young <ruirui.yang@linux.dev>
|
||||
L: kexec@lists.infradead.org
|
||||
S: Maintained
|
||||
W: http://lse.sourceforge.net/kdump/
|
||||
F: Documentation/admin-guide/kdump/
|
||||
F: fs/proc/vmcore.c
|
||||
F: include/linux/crash_core.h
|
||||
|
|
@ -15252,7 +15257,7 @@ M: Andrea Cervesato <andrea.cervesato@suse.com>
|
|||
M: Cyril Hrubis <chrubis@suse.cz>
|
||||
M: Jan Stancek <jstancek@redhat.com>
|
||||
M: Petr Vorel <pvorel@suse.cz>
|
||||
M: Li Wang <liwang@redhat.com>
|
||||
M: Li Wang <li.wang@linux.dev>
|
||||
M: Yang Xu <xuyang2018.jy@fujitsu.com>
|
||||
M: Xiao Yang <yangx.jy@fujitsu.com>
|
||||
L: ltp@lists.linux.it (subscribers-only)
|
||||
|
|
@ -15399,7 +15404,7 @@ F: include/net/netns/mctp.h
|
|||
F: net/mctp/
|
||||
|
||||
MAPLE TREE
|
||||
M: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
M: Liam R. Howlett <liam@infradead.org>
|
||||
R: Alice Ryhl <aliceryhl@google.com>
|
||||
R: Andrew Ballance <andrewjballance@gmail.com>
|
||||
L: maple-tree@lists.infradead.org
|
||||
|
|
@ -16759,7 +16764,7 @@ MEMORY MANAGEMENT - CORE
|
|||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
R: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
R: Vlastimil Babka <vbabka@kernel.org>
|
||||
R: Mike Rapoport <rppt@kernel.org>
|
||||
R: Suren Baghdasaryan <surenb@google.com>
|
||||
|
|
@ -16805,7 +16810,7 @@ F: mm/sparse.c
|
|||
F: mm/util.c
|
||||
F: mm/vmpressure.c
|
||||
F: mm/vmstat.c
|
||||
N: include/linux/page[-_]*
|
||||
N: include\/linux\/page[-_][a-zA-Z]*
|
||||
|
||||
MEMORY MANAGEMENT - EXECMEM
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
|
|
@ -16895,7 +16900,7 @@ MEMORY MANAGEMENT - MISC
|
|||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
R: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
R: Vlastimil Babka <vbabka@kernel.org>
|
||||
R: Mike Rapoport <rppt@kernel.org>
|
||||
R: Suren Baghdasaryan <surenb@google.com>
|
||||
|
|
@ -16962,6 +16967,7 @@ S: Maintained
|
|||
F: include/linux/compaction.h
|
||||
F: include/linux/gfp.h
|
||||
F: include/linux/page-isolation.h
|
||||
F: include/linux/pageblock-flags.h
|
||||
F: mm/compaction.c
|
||||
F: mm/debug_page_alloc.c
|
||||
F: mm/debug_page_ref.c
|
||||
|
|
@ -16983,7 +16989,7 @@ M: Andrew Morton <akpm@linux-foundation.org>
|
|||
M: Johannes Weiner <hannes@cmpxchg.org>
|
||||
R: David Hildenbrand <david@kernel.org>
|
||||
R: Michal Hocko <mhocko@kernel.org>
|
||||
R: Qi Zheng <zhengqi.arch@bytedance.com>
|
||||
R: Qi Zheng <qi.zheng@linux.dev>
|
||||
R: Shakeel Butt <shakeel.butt@linux.dev>
|
||||
R: Lorenzo Stoakes <ljs@kernel.org>
|
||||
L: linux-mm@kvack.org
|
||||
|
|
@ -16996,7 +17002,7 @@ M: Andrew Morton <akpm@linux-foundation.org>
|
|||
M: David Hildenbrand <david@kernel.org>
|
||||
M: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Rik van Riel <riel@surriel.com>
|
||||
R: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
R: Vlastimil Babka <vbabka@kernel.org>
|
||||
R: Harry Yoo <harry@kernel.org>
|
||||
R: Jann Horn <jannh@google.com>
|
||||
|
|
@ -17043,7 +17049,7 @@ M: David Hildenbrand <david@kernel.org>
|
|||
M: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Zi Yan <ziy@nvidia.com>
|
||||
R: Baolin Wang <baolin.wang@linux.alibaba.com>
|
||||
R: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
R: Nico Pache <npache@redhat.com>
|
||||
R: Ryan Roberts <ryan.roberts@arm.com>
|
||||
R: Dev Jain <dev.jain@arm.com>
|
||||
|
|
@ -17081,7 +17087,7 @@ F: tools/testing/selftests/mm/uffd-*.[ch]
|
|||
MEMORY MANAGEMENT - RUST
|
||||
M: Alice Ryhl <aliceryhl@google.com>
|
||||
R: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
L: linux-mm@kvack.org
|
||||
L: rust-for-linux@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
@ -17095,7 +17101,7 @@ F: rust/kernel/page.rs
|
|||
|
||||
MEMORY MAPPING
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
M: Liam R. Howlett <liam@infradead.org>
|
||||
M: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Vlastimil Babka <vbabka@kernel.org>
|
||||
R: Jann Horn <jannh@google.com>
|
||||
|
|
@ -17127,7 +17133,7 @@ F: tools/testing/vma/
|
|||
MEMORY MAPPING - LOCKING
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: Suren Baghdasaryan <surenb@google.com>
|
||||
M: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
M: Liam R. Howlett <liam@infradead.org>
|
||||
M: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Vlastimil Babka <vbabka@kernel.org>
|
||||
R: Shakeel Butt <shakeel.butt@linux.dev>
|
||||
|
|
@ -17142,7 +17148,7 @@ F: mm/mmap_lock.c
|
|||
|
||||
MEMORY MAPPING - MADVISE (MEMORY ADVICE)
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
M: Liam R. Howlett <liam@infradead.org>
|
||||
M: Lorenzo Stoakes <ljs@kernel.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
R: Vlastimil Babka <vbabka@kernel.org>
|
||||
|
|
@ -23403,7 +23409,7 @@ RUST [ALLOC]
|
|||
M: Danilo Krummrich <dakr@kernel.org>
|
||||
R: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Vlastimil Babka <vbabka@kernel.org>
|
||||
R: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
R: Uladzislau Rezki <urezki@gmail.com>
|
||||
L: rust-for-linux@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
@ -23555,7 +23561,7 @@ F: drivers/s390/net/
|
|||
|
||||
S390 PCI SUBSYSTEM
|
||||
M: Niklas Schnelle <schnelle@linux.ibm.com>
|
||||
M: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
|
||||
M: Gerd Bayer <gbayer@linux.ibm.com>
|
||||
L: linux-s390@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/arch/s390/pci.rst
|
||||
|
|
@ -24348,7 +24354,7 @@ F: include/media/i2c/rj54n1cb0c.h
|
|||
SHRINKER
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: Dave Chinner <david@fromorbit.com>
|
||||
R: Qi Zheng <zhengqi.arch@bytedance.com>
|
||||
R: Qi Zheng <qi.zheng@linux.dev>
|
||||
R: Roman Gushchin <roman.gushchin@linux.dev>
|
||||
R: Muchun Song <muchun.song@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
|
|
@ -24650,6 +24656,7 @@ S: Maintained
|
|||
F: fs/smb/client/smbdirect.*
|
||||
F: fs/smb/smbdirect/
|
||||
F: fs/smb/server/transport_rdma.*
|
||||
F: include/linux/smbdirect.h
|
||||
|
||||
SMC91x ETHERNET DRIVER
|
||||
M: Nicolas Pitre <nico@fluxnic.net>
|
||||
|
|
@ -24798,6 +24805,7 @@ SOFTWARE RAID (Multiple Disks) SUPPORT
|
|||
M: Song Liu <song@kernel.org>
|
||||
M: Yu Kuai <yukuai@fnnas.com>
|
||||
R: Li Nan <linan122@huawei.com>
|
||||
R: Xiao Ni <xiao@kernel.org>
|
||||
L: linux-raid@vger.kernel.org
|
||||
S: Supported
|
||||
Q: https://patchwork.kernel.org/project/linux-raid/list/
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 7
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc1
|
||||
EXTRAVERSION = -rc2
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ static __always_inline void __pmr_local_irq_enable(void)
|
|||
barrier();
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_enable(void)
|
||||
static __always_inline void arch_local_irq_enable(void)
|
||||
{
|
||||
if (system_uses_irq_prio_masking()) {
|
||||
__pmr_local_irq_enable();
|
||||
|
|
@ -68,7 +68,7 @@ static __always_inline void __pmr_local_irq_disable(void)
|
|||
barrier();
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_disable(void)
|
||||
static __always_inline void arch_local_irq_disable(void)
|
||||
{
|
||||
if (system_uses_irq_prio_masking()) {
|
||||
__pmr_local_irq_disable();
|
||||
|
|
@ -90,7 +90,7 @@ static __always_inline unsigned long __pmr_local_save_flags(void)
|
|||
/*
|
||||
* Save the current interrupt enable state.
|
||||
*/
|
||||
static inline unsigned long arch_local_save_flags(void)
|
||||
static __always_inline unsigned long arch_local_save_flags(void)
|
||||
{
|
||||
if (system_uses_irq_prio_masking()) {
|
||||
return __pmr_local_save_flags();
|
||||
|
|
@ -109,7 +109,7 @@ static __always_inline bool __pmr_irqs_disabled_flags(unsigned long flags)
|
|||
return flags != GIC_PRIO_IRQON;
|
||||
}
|
||||
|
||||
static inline bool arch_irqs_disabled_flags(unsigned long flags)
|
||||
static __always_inline bool arch_irqs_disabled_flags(unsigned long flags)
|
||||
{
|
||||
if (system_uses_irq_prio_masking()) {
|
||||
return __pmr_irqs_disabled_flags(flags);
|
||||
|
|
@ -128,7 +128,7 @@ static __always_inline bool __pmr_irqs_disabled(void)
|
|||
return __pmr_irqs_disabled_flags(__pmr_local_save_flags());
|
||||
}
|
||||
|
||||
static inline bool arch_irqs_disabled(void)
|
||||
static __always_inline bool arch_irqs_disabled(void)
|
||||
{
|
||||
if (system_uses_irq_prio_masking()) {
|
||||
return __pmr_irqs_disabled();
|
||||
|
|
@ -160,7 +160,7 @@ static __always_inline unsigned long __pmr_local_irq_save(void)
|
|||
return flags;
|
||||
}
|
||||
|
||||
static inline unsigned long arch_local_irq_save(void)
|
||||
static __always_inline unsigned long arch_local_irq_save(void)
|
||||
{
|
||||
if (system_uses_irq_prio_masking()) {
|
||||
return __pmr_local_irq_save();
|
||||
|
|
@ -187,7 +187,7 @@ static __always_inline void __pmr_local_irq_restore(unsigned long flags)
|
|||
/*
|
||||
* restore saved IRQ state
|
||||
*/
|
||||
static inline void arch_local_irq_restore(unsigned long flags)
|
||||
static __always_inline void arch_local_irq_restore(unsigned long flags)
|
||||
{
|
||||
if (system_uses_irq_prio_masking()) {
|
||||
__pmr_local_irq_restore(flags);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,12 @@
|
|||
#define KERNEL_SEGMENT_COUNT 5
|
||||
|
||||
#if SWAPPER_BLOCK_SIZE > SEGMENT_ALIGN
|
||||
#define EARLY_SEGMENT_EXTRA_PAGES (KERNEL_SEGMENT_COUNT + 1)
|
||||
/*
|
||||
* KERNEL_SEGMENT_COUNT counts the permanent kernel VMAs. The early mapping
|
||||
* has one additional split, [_text, _stext). Reserve one more page for the
|
||||
* SWAPPER_BLOCK_SIZE-unaligned boundaries.
|
||||
*/
|
||||
#define EARLY_SEGMENT_EXTRA_PAGES (KERNEL_SEGMENT_COUNT + 2)
|
||||
/*
|
||||
* The initial ID map consists of the kernel image, mapped as two separate
|
||||
* segments, and may appear misaligned wrt the swapper block size. This means
|
||||
|
|
|
|||
|
|
@ -196,9 +196,9 @@ static int scs_handle_fde_frame(const struct eh_frame *frame,
|
|||
loc += *opcode++ * code_alignment_factor;
|
||||
loc += (*opcode++ << 8) * code_alignment_factor;
|
||||
loc += (*opcode++ << 16) * code_alignment_factor;
|
||||
loc += (*opcode++ << 24) * code_alignment_factor;
|
||||
loc += ((u64)*opcode++ << 24) * code_alignment_factor;
|
||||
size -= 4;
|
||||
break;
|
||||
break;
|
||||
|
||||
case DW_CFA_def_cfa:
|
||||
case DW_CFA_offset_extended:
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ struct rt_sigframe_user_layout {
|
|||
unsigned long end_offset;
|
||||
};
|
||||
|
||||
#define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16)
|
||||
#define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16)
|
||||
|
||||
/*
|
||||
* Holds any EL0-controlled state that influences unprivileged memory accesses.
|
||||
* This includes both accesses done in userspace and uaccess done in the kernel.
|
||||
|
|
@ -74,13 +77,35 @@ struct rt_sigframe_user_layout {
|
|||
* This state needs to be carefully managed to ensure that it doesn't cause
|
||||
* uaccess to fail when setting up the signal frame, and the signal handler
|
||||
* itself also expects a well-defined state when entered.
|
||||
*
|
||||
* The struct should be zero-initialised. Its members should only be accessed
|
||||
* via the accessors below. __valid_fields tracks which of the fields are valid
|
||||
* (have been set to some value).
|
||||
*/
|
||||
struct user_access_state {
|
||||
u64 por_el0;
|
||||
unsigned int __valid_fields;
|
||||
u64 __por_el0;
|
||||
};
|
||||
|
||||
#define TERMINATOR_SIZE round_up(sizeof(struct _aarch64_ctx), 16)
|
||||
#define EXTRA_CONTEXT_SIZE round_up(sizeof(struct extra_context), 16)
|
||||
#define UA_STATE_HAS_POR_EL0 BIT(0)
|
||||
|
||||
static void set_ua_state_por_el0(struct user_access_state *ua_state,
|
||||
u64 por_el0)
|
||||
{
|
||||
ua_state->__por_el0 = por_el0;
|
||||
ua_state->__valid_fields |= UA_STATE_HAS_POR_EL0;
|
||||
}
|
||||
|
||||
static int get_ua_state_por_el0(const struct user_access_state *ua_state,
|
||||
u64 *por_el0)
|
||||
{
|
||||
if (ua_state->__valid_fields & UA_STATE_HAS_POR_EL0) {
|
||||
*por_el0 = ua_state->__por_el0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the user access state into ua_state and reset it to disable any
|
||||
|
|
@ -94,7 +119,7 @@ static void save_reset_user_access_state(struct user_access_state *ua_state)
|
|||
for (int pkey = 0; pkey < arch_max_pkey(); pkey++)
|
||||
por_enable_all |= POR_ELx_PERM_PREP(pkey, POE_RWX);
|
||||
|
||||
ua_state->por_el0 = read_sysreg_s(SYS_POR_EL0);
|
||||
set_ua_state_por_el0(ua_state, read_sysreg_s(SYS_POR_EL0));
|
||||
write_sysreg_s(por_enable_all, SYS_POR_EL0);
|
||||
/*
|
||||
* No ISB required as we can tolerate spurious Overlay faults -
|
||||
|
|
@ -122,8 +147,10 @@ static void set_handler_user_access_state(void)
|
|||
*/
|
||||
static void restore_user_access_state(const struct user_access_state *ua_state)
|
||||
{
|
||||
if (system_supports_poe())
|
||||
write_sysreg_s(ua_state->por_el0, SYS_POR_EL0);
|
||||
u64 por_el0;
|
||||
|
||||
if (get_ua_state_por_el0(ua_state, &por_el0) == 0)
|
||||
write_sysreg_s(por_el0, SYS_POR_EL0);
|
||||
}
|
||||
|
||||
static void init_user_layout(struct rt_sigframe_user_layout *user)
|
||||
|
|
@ -333,11 +360,16 @@ static int restore_fpmr_context(struct user_ctxs *user)
|
|||
static int preserve_poe_context(struct poe_context __user *ctx,
|
||||
const struct user_access_state *ua_state)
|
||||
{
|
||||
int err = 0;
|
||||
int err;
|
||||
u64 por_el0;
|
||||
|
||||
err = get_ua_state_por_el0(ua_state, &por_el0);
|
||||
if (WARN_ON_ONCE(err))
|
||||
return err;
|
||||
|
||||
__put_user_error(POE_MAGIC, &ctx->head.magic, err);
|
||||
__put_user_error(sizeof(*ctx), &ctx->head.size, err);
|
||||
__put_user_error(ua_state->por_el0, &ctx->por_el0, err);
|
||||
__put_user_error(por_el0, &ctx->por_el0, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -353,7 +385,7 @@ static int restore_poe_context(struct user_ctxs *user,
|
|||
|
||||
__get_user_error(por_el0, &(user->poe->por_el0), err);
|
||||
if (!err)
|
||||
ua_state->por_el0 = por_el0;
|
||||
set_ua_state_por_el0(ua_state, por_el0);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1095,7 +1127,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
|
|||
{
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
struct rt_sigframe __user *frame;
|
||||
struct user_access_state ua_state;
|
||||
struct user_access_state ua_state = {};
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
|
@ -1507,7 +1539,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
|
|||
{
|
||||
struct rt_sigframe_user_layout user;
|
||||
struct rt_sigframe __user *frame;
|
||||
struct user_access_state ua_state;
|
||||
struct user_access_state ua_state = {};
|
||||
int err = 0;
|
||||
|
||||
fpsimd_save_and_flush_current_state();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ obj-y += mm/
|
|||
obj-y += net/
|
||||
obj-y += vdso/
|
||||
|
||||
obj-$(CONFIG_KVM) += kvm/
|
||||
obj-$(subst m,y,$(CONFIG_KVM)) += kvm/
|
||||
|
||||
# for cleaning
|
||||
subdir- += boot
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ menu "Kernel type and options"
|
|||
|
||||
choice
|
||||
prompt "Kernel type"
|
||||
default 64BIT # Keep existing behavior
|
||||
|
||||
config 32BIT
|
||||
bool "32-bit kernel"
|
||||
|
|
|
|||
|
|
@ -55,9 +55,11 @@ endif
|
|||
ifdef CONFIG_32BIT
|
||||
tool-archpref = $(32bit-tool-archpref)
|
||||
UTS_MACHINE := loongarch32
|
||||
cflags-y += $(call cc-option,-m32)
|
||||
else
|
||||
tool-archpref = $(64bit-tool-archpref)
|
||||
UTS_MACHINE := loongarch64
|
||||
cflags-y += $(call cc-option,-m64)
|
||||
endif
|
||||
|
||||
ifneq ($(SUBARCH),$(ARCH))
|
||||
|
|
|
|||
|
|
@ -20,3 +20,23 @@ asmlinkage void noinstr __no_stack_protector ret_from_kernel_thread(struct task_
|
|||
struct pt_regs *regs,
|
||||
int (*fn)(void *),
|
||||
void *fn_arg);
|
||||
|
||||
struct kvm_run;
|
||||
struct kvm_vcpu;
|
||||
struct loongarch_fpu;
|
||||
|
||||
void kvm_exc_entry(void);
|
||||
int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu);
|
||||
|
||||
void kvm_save_fpu(struct loongarch_fpu *fpu);
|
||||
void kvm_restore_fpu(struct loongarch_fpu *fpu);
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
void kvm_save_lsx(struct loongarch_fpu *fpu);
|
||||
void kvm_restore_lsx(struct loongarch_fpu *fpu);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
void kvm_save_lasx(struct loongarch_fpu *fpu);
|
||||
void kvm_restore_lasx(struct loongarch_fpu *fpu);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ struct kvm_context {
|
|||
struct kvm_world_switch {
|
||||
int (*exc_entry)(void);
|
||||
int (*enter_guest)(struct kvm_run *run, struct kvm_vcpu *vcpu);
|
||||
unsigned long page_order;
|
||||
};
|
||||
|
||||
#define MAX_PGTABLE_LEVELS 4
|
||||
|
|
@ -359,8 +358,6 @@ void kvm_exc_entry(void);
|
|||
int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu);
|
||||
|
||||
extern unsigned long vpid_mask;
|
||||
extern const unsigned long kvm_exception_size;
|
||||
extern const unsigned long kvm_enter_guest_size;
|
||||
extern struct kvm_world_switch *kvm_loongarch_ops;
|
||||
|
||||
#define SW_GCSR (1 << 0)
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
9, 10, 11, 12, 13, 14, 15, 16, \
|
||||
17, 18, 19, 20, 21, 22, 23, 24, \
|
||||
25, 26, 27, 28, 29, 30, 31; \
|
||||
.cfi_offset \num, SC_REGS + \num * SZREG; \
|
||||
.cfi_offset \num, SC_REGS + \num * 8; \
|
||||
.endr; \
|
||||
\
|
||||
nop; \
|
||||
|
|
|
|||
|
|
@ -85,12 +85,6 @@ static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
|
|||
return count;
|
||||
}
|
||||
|
||||
static inline bool loongarch_vdso_hres_capable(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#define __arch_vdso_hres_capable loongarch_vdso_hres_capable
|
||||
|
||||
#endif /* CONFIG_GENERIC_GETTIMEOFDAY */
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@ include $(srctree)/virt/kvm/Makefile.kvm
|
|||
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
||||
|
||||
obj-y += switch.o
|
||||
|
||||
kvm-y += exit.o
|
||||
kvm-y += interrupt.o
|
||||
kvm-y += main.o
|
||||
kvm-y += mmu.o
|
||||
kvm-y += switch.o
|
||||
kvm-y += timer.o
|
||||
kvm-y += tlb.o
|
||||
kvm-y += vcpu.o
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst)
|
|||
run->mmio.len = 8;
|
||||
break;
|
||||
default:
|
||||
ret = EMULATE_FAIL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -28,23 +28,29 @@ static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
|
|||
static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
|
||||
{
|
||||
unsigned int irq = 0;
|
||||
unsigned long old, new;
|
||||
|
||||
clear_bit(priority, &vcpu->arch.irq_pending);
|
||||
if (priority < EXCCODE_INT_NUM)
|
||||
irq = priority_to_irq[priority];
|
||||
|
||||
if (kvm_guest_has_msgint(&vcpu->arch) && (priority == INT_AVEC)) {
|
||||
dmsintc_inject_irq(vcpu);
|
||||
set_gcsr_estat(irq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (priority) {
|
||||
case INT_AVEC:
|
||||
if (!kvm_guest_has_msgint(&vcpu->arch))
|
||||
break;
|
||||
dmsintc_inject_irq(vcpu);
|
||||
fallthrough;
|
||||
case INT_TI:
|
||||
case INT_IPI:
|
||||
case INT_SWI0:
|
||||
case INT_SWI1:
|
||||
old = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
|
||||
set_gcsr_estat(irq);
|
||||
new = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
|
||||
|
||||
/* Inject TI if TVAL inverted */
|
||||
if (new > old)
|
||||
set_gcsr_estat(CPU_TIMER);
|
||||
break;
|
||||
|
||||
case INT_HWI0 ... INT_HWI7:
|
||||
|
|
@ -61,22 +67,28 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
|
|||
static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
|
||||
{
|
||||
unsigned int irq = 0;
|
||||
unsigned long old, new;
|
||||
|
||||
clear_bit(priority, &vcpu->arch.irq_clear);
|
||||
if (priority < EXCCODE_INT_NUM)
|
||||
irq = priority_to_irq[priority];
|
||||
|
||||
if (kvm_guest_has_msgint(&vcpu->arch) && (priority == INT_AVEC)) {
|
||||
clear_gcsr_estat(irq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (priority) {
|
||||
case INT_AVEC:
|
||||
if (!kvm_guest_has_msgint(&vcpu->arch))
|
||||
break;
|
||||
fallthrough;
|
||||
case INT_TI:
|
||||
case INT_IPI:
|
||||
case INT_SWI0:
|
||||
case INT_SWI1:
|
||||
old = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
|
||||
clear_gcsr_estat(irq);
|
||||
new = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
|
||||
|
||||
/* Inject TI if TVAL inverted */
|
||||
if (new > old)
|
||||
set_gcsr_estat(CPU_TIMER);
|
||||
break;
|
||||
|
||||
case INT_HWI0 ... INT_HWI7:
|
||||
|
|
|
|||
|
|
@ -348,8 +348,7 @@ void kvm_arch_disable_virtualization_cpu(void)
|
|||
|
||||
static int kvm_loongarch_env_init(void)
|
||||
{
|
||||
int cpu, order, ret;
|
||||
void *addr;
|
||||
int cpu, ret;
|
||||
struct kvm_context *context;
|
||||
|
||||
vmcs = alloc_percpu(struct kvm_context);
|
||||
|
|
@ -365,30 +364,8 @@ static int kvm_loongarch_env_init(void)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* PGD register is shared between root kernel and kvm hypervisor.
|
||||
* So world switch entry should be in DMW area rather than TLB area
|
||||
* to avoid page fault reenter.
|
||||
*
|
||||
* In future if hardware pagetable walking is supported, we won't
|
||||
* need to copy world switch code to DMW area.
|
||||
*/
|
||||
order = get_order(kvm_exception_size + kvm_enter_guest_size);
|
||||
addr = (void *)__get_free_pages(GFP_KERNEL, order);
|
||||
if (!addr) {
|
||||
free_percpu(vmcs);
|
||||
vmcs = NULL;
|
||||
kfree(kvm_loongarch_ops);
|
||||
kvm_loongarch_ops = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(addr, kvm_exc_entry, kvm_exception_size);
|
||||
memcpy(addr + kvm_exception_size, kvm_enter_guest, kvm_enter_guest_size);
|
||||
flush_icache_range((unsigned long)addr, (unsigned long)addr + kvm_exception_size + kvm_enter_guest_size);
|
||||
kvm_loongarch_ops->exc_entry = addr;
|
||||
kvm_loongarch_ops->enter_guest = addr + kvm_exception_size;
|
||||
kvm_loongarch_ops->page_order = order;
|
||||
kvm_loongarch_ops->exc_entry = (void *)kvm_exc_entry;
|
||||
kvm_loongarch_ops->enter_guest = (void *)kvm_enter_guest;
|
||||
|
||||
vpid_mask = read_csr_gstat();
|
||||
vpid_mask = (vpid_mask & CSR_GSTAT_GIDBIT) >> CSR_GSTAT_GIDBIT_SHIFT;
|
||||
|
|
@ -428,16 +405,10 @@ static int kvm_loongarch_env_init(void)
|
|||
|
||||
static void kvm_loongarch_env_exit(void)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
if (vmcs)
|
||||
free_percpu(vmcs);
|
||||
|
||||
if (kvm_loongarch_ops) {
|
||||
if (kvm_loongarch_ops->exc_entry) {
|
||||
addr = (unsigned long)kvm_loongarch_ops->exc_entry;
|
||||
free_pages(addr, kvm_loongarch_ops->page_order);
|
||||
}
|
||||
kfree(kvm_loongarch_ops);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ static int kvm_flush_pte(kvm_pte_t *pte, phys_addr_t addr, kvm_ptw_ctx *ctx)
|
|||
else
|
||||
kvm->stat.pages--;
|
||||
|
||||
*pte = ctx->invalid_entry;
|
||||
kvm_set_pte(pte, ctx->invalid_entry);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@
|
|||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/kvm_types.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm/loongarch.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/unwind_hints.h>
|
||||
|
||||
|
|
@ -100,11 +102,16 @@
|
|||
* - is still in guest mode, such as pgd table/vmid registers etc,
|
||||
* - will fix with hw page walk enabled in future
|
||||
* load kvm_vcpu from reserved CSR KVM_VCPU_KS, and save a2 to KVM_TEMP_KS
|
||||
*
|
||||
* PGD register is shared between root kernel and kvm hypervisor.
|
||||
* So world switch entry should be in DMW area rather than TLB area
|
||||
* to avoid page fault re-enter.
|
||||
*/
|
||||
.text
|
||||
.p2align PAGE_SHIFT
|
||||
.cfi_sections .debug_frame
|
||||
SYM_CODE_START(kvm_exc_entry)
|
||||
UNWIND_HINT_UNDEFINED
|
||||
UNWIND_HINT_END_OF_STACK
|
||||
csrwr a2, KVM_TEMP_KS
|
||||
csrrd a2, KVM_VCPU_KS
|
||||
addi.d a2, a2, KVM_VCPU_ARCH
|
||||
|
|
@ -190,8 +197,8 @@ ret_to_host:
|
|||
kvm_restore_host_gpr a2
|
||||
jr ra
|
||||
|
||||
SYM_INNER_LABEL(kvm_exc_entry_end, SYM_L_LOCAL)
|
||||
SYM_CODE_END(kvm_exc_entry)
|
||||
EXPORT_SYMBOL_FOR_KVM(kvm_exc_entry)
|
||||
|
||||
/*
|
||||
* int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu)
|
||||
|
|
@ -215,8 +222,8 @@ SYM_FUNC_START(kvm_enter_guest)
|
|||
/* Save kvm_vcpu to kscratch */
|
||||
csrwr a1, KVM_VCPU_KS
|
||||
kvm_switch_to_guest
|
||||
SYM_INNER_LABEL(kvm_enter_guest_end, SYM_L_LOCAL)
|
||||
SYM_FUNC_END(kvm_enter_guest)
|
||||
EXPORT_SYMBOL_FOR_KVM(kvm_enter_guest)
|
||||
|
||||
SYM_FUNC_START(kvm_save_fpu)
|
||||
fpu_save_csr a0 t1
|
||||
|
|
@ -224,6 +231,7 @@ SYM_FUNC_START(kvm_save_fpu)
|
|||
fpu_save_cc a0 t1 t2
|
||||
jr ra
|
||||
SYM_FUNC_END(kvm_save_fpu)
|
||||
EXPORT_SYMBOL_FOR_KVM(kvm_save_fpu)
|
||||
|
||||
SYM_FUNC_START(kvm_restore_fpu)
|
||||
fpu_restore_double a0 t1
|
||||
|
|
@ -231,6 +239,7 @@ SYM_FUNC_START(kvm_restore_fpu)
|
|||
fpu_restore_cc a0 t1 t2
|
||||
jr ra
|
||||
SYM_FUNC_END(kvm_restore_fpu)
|
||||
EXPORT_SYMBOL_FOR_KVM(kvm_restore_fpu)
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LSX
|
||||
SYM_FUNC_START(kvm_save_lsx)
|
||||
|
|
@ -239,6 +248,7 @@ SYM_FUNC_START(kvm_save_lsx)
|
|||
lsx_save_data a0 t1
|
||||
jr ra
|
||||
SYM_FUNC_END(kvm_save_lsx)
|
||||
EXPORT_SYMBOL_FOR_KVM(kvm_save_lsx)
|
||||
|
||||
SYM_FUNC_START(kvm_restore_lsx)
|
||||
lsx_restore_data a0 t1
|
||||
|
|
@ -246,6 +256,7 @@ SYM_FUNC_START(kvm_restore_lsx)
|
|||
fpu_restore_csr a0 t1 t2
|
||||
jr ra
|
||||
SYM_FUNC_END(kvm_restore_lsx)
|
||||
EXPORT_SYMBOL_FOR_KVM(kvm_restore_lsx)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LASX
|
||||
|
|
@ -255,6 +266,7 @@ SYM_FUNC_START(kvm_save_lasx)
|
|||
lasx_save_data a0 t1
|
||||
jr ra
|
||||
SYM_FUNC_END(kvm_save_lasx)
|
||||
EXPORT_SYMBOL_FOR_KVM(kvm_save_lasx)
|
||||
|
||||
SYM_FUNC_START(kvm_restore_lasx)
|
||||
lasx_restore_data a0 t1
|
||||
|
|
@ -262,10 +274,8 @@ SYM_FUNC_START(kvm_restore_lasx)
|
|||
fpu_restore_csr a0 t1 t2
|
||||
jr ra
|
||||
SYM_FUNC_END(kvm_restore_lasx)
|
||||
EXPORT_SYMBOL_FOR_KVM(kvm_restore_lasx)
|
||||
#endif
|
||||
.section ".rodata"
|
||||
SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry)
|
||||
SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest)
|
||||
|
||||
#ifdef CONFIG_CPU_HAS_LBT
|
||||
STACK_FRAME_NON_STANDARD kvm_restore_fpu
|
||||
|
|
|
|||
|
|
@ -96,15 +96,21 @@ void kvm_restore_timer(struct kvm_vcpu *vcpu)
|
|||
* and set CSR TVAL with -1
|
||||
*/
|
||||
write_gcsr_timertick(0);
|
||||
__delay(2); /* Wait cycles until timer interrupt injected */
|
||||
|
||||
/*
|
||||
* Writing CSR_TINTCLR_TI to LOONGARCH_CSR_TINTCLR will clear
|
||||
* timer interrupt, and CSR TVAL keeps unchanged with -1, it
|
||||
* avoids spurious timer interrupt
|
||||
*/
|
||||
if (!(estat & CPU_TIMER))
|
||||
if (!(estat & CPU_TIMER)) {
|
||||
__delay(2); /* Wait cycles until timer interrupt injected */
|
||||
|
||||
/* Write TVAL with max value if no TI shot */
|
||||
estat = kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT);
|
||||
if (!(estat & CPU_TIMER))
|
||||
write_gcsr_timertick(CSR_TCFG_VAL);
|
||||
gcsr_write(CSR_TINTCLR_TI, LOONGARCH_CSR_TINTCLR);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|||
r = 1;
|
||||
break;
|
||||
case KVM_CAP_NR_VCPUS:
|
||||
r = num_online_cpus();
|
||||
r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS);
|
||||
break;
|
||||
case KVM_CAP_MAX_VCPUS:
|
||||
r = KVM_MAX_VCPUS;
|
||||
|
|
|
|||
|
|
@ -61,11 +61,16 @@ static void acpi_release_root_info(struct acpi_pci_root_info *ci)
|
|||
static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci)
|
||||
{
|
||||
int status;
|
||||
unsigned long long pci_h = 0;
|
||||
struct resource_entry *entry, *tmp;
|
||||
struct acpi_device *device = ci->bridge;
|
||||
|
||||
status = acpi_pci_probe_root_resources(ci);
|
||||
if (status > 0) {
|
||||
acpi_evaluate_integer(device->handle, "PCIH", NULL, &pci_h);
|
||||
if (pci_h)
|
||||
return status;
|
||||
|
||||
resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
|
||||
if (entry->res->flags & IORESOURCE_MEM) {
|
||||
entry->offset = ci->root->mcfg_addr & GENMASK_ULL(63, 40);
|
||||
|
|
|
|||
|
|
@ -132,6 +132,9 @@ static void loongson_gpu_fixup_dma_hang(struct pci_dev *pdev, bool on)
|
|||
crtc_reg = regbase;
|
||||
crtc_offset = 0x400;
|
||||
break;
|
||||
default:
|
||||
iounmap(regbase);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < CRTC_NUM_MAX; i++, crtc_reg += crtc_offset) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ obj-vdso-$(CONFIG_GENERIC_GETTIMEOFDAY) += vgettimeofday.o
|
|||
ccflags-vdso := \
|
||||
$(filter -I%,$(KBUILD_CFLAGS)) \
|
||||
$(filter -E%,$(KBUILD_CFLAGS)) \
|
||||
$(filter -m32,$(KBUILD_CFLAGS)) \
|
||||
$(filter -m64,$(KBUILD_CFLAGS)) \
|
||||
$(filter -march=%,$(KBUILD_CFLAGS)) \
|
||||
$(filter -m%-float,$(KBUILD_CFLAGS)) \
|
||||
$(CLANG_FLAGS) \
|
||||
|
|
|
|||
|
|
@ -174,15 +174,21 @@ ifeq ($(KBUILD_EXTMOD),)
|
|||
# this hack.
|
||||
prepare: vdso_prepare
|
||||
vdso_prepare: prepare0
|
||||
$(if $(CONFIG_64BIT),$(Q)$(MAKE) \
|
||||
$(build)=arch/parisc/kernel/vdso64 include/generated/vdso64-offsets.h)
|
||||
$(if $(CONFIG_PA11)$(CONFIG_COMPAT),$(Q)$(MAKE) \
|
||||
ifdef CONFIG_64BIT
|
||||
$(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso64 include/generated/vdso64-offsets.h
|
||||
$(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
|
||||
$(build)=arch/parisc/kernel/vdso32 include/generated/vdso32-offsets.h)
|
||||
else
|
||||
$(Q)$(MAKE) $(build)=arch/parisc/kernel/vdso32 include/generated/vdso32-offsets.h
|
||||
endif
|
||||
endif
|
||||
|
||||
vdso-install-$(CONFIG_PA11) += arch/parisc/kernel/vdso32/vdso32.so
|
||||
ifdef CONFIG_64BIT
|
||||
vdso-install-y += arch/parisc/kernel/vdso64/vdso64.so
|
||||
vdso-install-$(CONFIG_COMPAT) += arch/parisc/kernel/vdso32/vdso32.so
|
||||
vdso-install-$(CONFIG_64BIT) += arch/parisc/kernel/vdso64/vdso64.so
|
||||
else
|
||||
vdso-install-y += arch/parisc/kernel/vdso32/vdso32.so
|
||||
endif
|
||||
|
||||
install: KBUILD_IMAGE := vmlinux
|
||||
zinstall: KBUILD_IMAGE := vmlinuz
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
#ifdef CONFIG_64BIT
|
||||
#include <generated/vdso64-offsets.h>
|
||||
#define VDSO64_SYMBOL(tsk, name) ((tsk)->mm->context.vdso_base + (vdso64_offset_##name))
|
||||
#endif
|
||||
#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT)
|
||||
#include <generated/vdso32-offsets.h>
|
||||
#endif
|
||||
|
||||
#define VDSO64_SYMBOL(tsk, name) ((tsk)->mm->context.vdso_base + (vdso64_offset_##name))
|
||||
#define VDSO32_SYMBOL(tsk, name) ((tsk)->mm->context.vdso_base + (vdso32_offset_##name))
|
||||
#else
|
||||
#define VDSO32_SYMBOL(tsk, name) 0UL
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
|
|||
|
||||
# vdso
|
||||
obj-y += vdso.o
|
||||
obj-$(CONFIG_64BIT) += vdso64/
|
||||
obj-$(CONFIG_PA11) += vdso32/
|
||||
ifdef CONFIG_64BIT
|
||||
obj-y += vdso64/
|
||||
obj-$(CONFIG_COMPAT) += vdso32/
|
||||
else
|
||||
obj-y += vdso32/
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -41,9 +41,7 @@
|
|||
const struct dma_map_ops *hppa_dma_ops __ro_after_init;
|
||||
EXPORT_SYMBOL(hppa_dma_ops);
|
||||
|
||||
static struct device root = {
|
||||
.init_name = "parisc",
|
||||
};
|
||||
static struct device *root;
|
||||
|
||||
static inline int check_dev(struct device *dev)
|
||||
{
|
||||
|
|
@ -89,7 +87,7 @@ static int for_each_padev(int (*fn)(struct device *, void *), void * data)
|
|||
.obj = data,
|
||||
.fn = fn,
|
||||
};
|
||||
return device_for_each_child(&root, &recurse_data, descend_children);
|
||||
return device_for_each_child(root, &recurse_data, descend_children);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -290,7 +288,7 @@ const struct parisc_device *
|
|||
find_pa_parent_type(const struct parisc_device *padev, int type)
|
||||
{
|
||||
const struct device *dev = &padev->dev;
|
||||
while (dev != &root) {
|
||||
while (dev != root) {
|
||||
struct parisc_device *candidate = to_parisc_device(dev);
|
||||
if (candidate->id.hw_type == type)
|
||||
return candidate;
|
||||
|
|
@ -319,7 +317,7 @@ static void get_node_path(struct device *dev, struct hardware_path *path)
|
|||
dev = dev->parent;
|
||||
}
|
||||
|
||||
while (dev != &root) {
|
||||
while (dev != root) {
|
||||
if (dev_is_pci(dev)) {
|
||||
unsigned int devfn = to_pci_dev(dev)->devfn;
|
||||
path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn)<< 5);
|
||||
|
|
@ -482,7 +480,7 @@ static struct parisc_device * __init alloc_tree_node(
|
|||
static struct parisc_device *create_parisc_device(struct hardware_path *modpath)
|
||||
{
|
||||
int i;
|
||||
struct device *parent = &root;
|
||||
struct device *parent = root;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (modpath->bc[i] == -1)
|
||||
continue;
|
||||
|
|
@ -755,7 +753,7 @@ parse_tree_node(struct device *parent, int index, struct hardware_path *modpath)
|
|||
struct device *hwpath_to_device(struct hardware_path *modpath)
|
||||
{
|
||||
int i;
|
||||
struct device *parent = &root;
|
||||
struct device *parent = root;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (modpath->bc[i] == -1)
|
||||
continue;
|
||||
|
|
@ -880,7 +878,7 @@ void __init walk_central_bus(void)
|
|||
{
|
||||
walk_native_bus(CENTRAL_BUS_ADDR,
|
||||
CENTRAL_BUS_ADDR + (MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET),
|
||||
&root);
|
||||
root);
|
||||
}
|
||||
|
||||
static __init void print_parisc_device(struct parisc_device *dev)
|
||||
|
|
@ -907,9 +905,10 @@ void __init init_parisc_bus(void)
|
|||
{
|
||||
if (bus_register(&parisc_bus_type))
|
||||
panic("Could not register PA-RISC bus type\n");
|
||||
if (device_register(&root))
|
||||
|
||||
root = root_device_register("parisc");
|
||||
if (IS_ERR(root))
|
||||
panic("Could not register PA-RISC root device\n");
|
||||
get_device(&root);
|
||||
}
|
||||
|
||||
static __init void qemu_header(void)
|
||||
|
|
|
|||
|
|
@ -1414,6 +1414,9 @@ static inline char *debug_get_user_string(const char __user *user_buf,
|
|||
{
|
||||
char *buffer;
|
||||
|
||||
if (!user_len)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
buffer = memdup_user_nul(user_buf, user_len);
|
||||
if (IS_ERR(buffer))
|
||||
return buffer;
|
||||
|
|
@ -1584,6 +1587,11 @@ static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
|
|||
char input_buf[1];
|
||||
int rc = user_len;
|
||||
|
||||
if (!user_len) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (user_len > 0x10000)
|
||||
user_len = 0x10000;
|
||||
if (*offset != 0) {
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ void do_secure_storage_access(struct pt_regs *regs)
|
|||
panic("Unexpected PGM 0x3d with TEID bit 61=0");
|
||||
}
|
||||
if (is_kernel_fault(regs)) {
|
||||
folio = phys_to_folio(addr);
|
||||
folio = virt_to_folio((void *)addr);
|
||||
if (unlikely(!folio_try_get(folio)))
|
||||
return;
|
||||
rc = uv_convert_from_secure(folio_to_phys(folio));
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
/*
|
||||
* This is set up by the setup-routine at boot-time
|
||||
*/
|
||||
extern unsigned char *boot_params_page;
|
||||
extern unsigned char boot_params_page[];
|
||||
#define PARAM boot_params_page
|
||||
|
||||
#define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000))
|
||||
|
|
|
|||
|
|
@ -137,7 +137,8 @@ extern void __init efi_dump_pagetable(void);
|
|||
extern void __init efi_apply_memmap_quirks(void);
|
||||
extern int __init efi_reuse_config(u64 tables, int nr_tables);
|
||||
extern void efi_delete_dummy_variable(void);
|
||||
extern void efi_crash_gracefully_on_page_fault(unsigned long phys_addr);
|
||||
extern void efi_crash_gracefully_on_page_fault(unsigned long phys_addr,
|
||||
const struct pt_regs *regs);
|
||||
extern void efi_unmap_boot_services(void);
|
||||
|
||||
void arch_efi_call_virt_setup(void);
|
||||
|
|
|
|||
|
|
@ -2040,7 +2040,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
|||
* flush). Translate the address here so the memory can be uniformly
|
||||
* read with kvm_read_guest().
|
||||
*/
|
||||
if (!hc->fast && is_guest_mode(vcpu)) {
|
||||
if (!hc->fast && mmu_is_nested(vcpu)) {
|
||||
hc->ingpa = translate_nested_gpa(vcpu, hc->ingpa, 0, NULL);
|
||||
if (unlikely(hc->ingpa == INVALID_GPA))
|
||||
return HV_STATUS_INVALID_HYPERCALL_INPUT;
|
||||
|
|
|
|||
|
|
@ -667,13 +667,15 @@ bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr)
|
|||
u32 *__pir = (void *)pir_vals;
|
||||
u32 i, vec;
|
||||
u32 irr_val, prev_irr_val;
|
||||
int max_updated_irr;
|
||||
int max_new_irr;
|
||||
|
||||
max_updated_irr = -1;
|
||||
*max_irr = -1;
|
||||
|
||||
if (!pi_harvest_pir(pir, pir_vals))
|
||||
if (!pi_harvest_pir(pir, pir_vals)) {
|
||||
*max_irr = apic_find_highest_vector(regs + APIC_IRR);
|
||||
return false;
|
||||
}
|
||||
|
||||
max_new_irr = -1;
|
||||
*max_irr = -1;
|
||||
|
||||
for (i = vec = 0; i <= 7; i++, vec += 32) {
|
||||
u32 *p_irr = (u32 *)(regs + APIC_IRR + i * 0x10);
|
||||
|
|
@ -688,25 +690,25 @@ bool __kvm_apic_update_irr(unsigned long *pir, void *regs, int *max_irr)
|
|||
!try_cmpxchg(p_irr, &prev_irr_val, irr_val));
|
||||
|
||||
if (prev_irr_val != irr_val)
|
||||
max_updated_irr = __fls(irr_val ^ prev_irr_val) + vec;
|
||||
max_new_irr = __fls(irr_val ^ prev_irr_val) + vec;
|
||||
}
|
||||
if (irr_val)
|
||||
*max_irr = __fls(irr_val) + vec;
|
||||
}
|
||||
|
||||
return ((max_updated_irr != -1) &&
|
||||
(max_updated_irr == *max_irr));
|
||||
return max_new_irr != -1 && max_new_irr == *max_irr;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_KVM_INTERNAL(__kvm_apic_update_irr);
|
||||
|
||||
bool kvm_apic_update_irr(struct kvm_vcpu *vcpu, unsigned long *pir, int *max_irr)
|
||||
{
|
||||
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||
bool irr_updated = __kvm_apic_update_irr(pir, apic->regs, max_irr);
|
||||
bool max_irr_is_from_pir;
|
||||
|
||||
if (unlikely(!apic->apicv_active && irr_updated))
|
||||
max_irr_is_from_pir = __kvm_apic_update_irr(pir, apic->regs, max_irr);
|
||||
if (unlikely(!apic->apicv_active && max_irr_is_from_pir))
|
||||
apic->irr_pending = true;
|
||||
return irr_updated;
|
||||
return max_irr_is_from_pir;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_apic_update_irr);
|
||||
|
||||
|
|
|
|||
|
|
@ -182,6 +182,8 @@ static struct kmem_cache *pte_list_desc_cache;
|
|||
struct kmem_cache *mmu_page_header_cache;
|
||||
|
||||
static void mmu_spte_set(u64 *sptep, u64 spte);
|
||||
static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,
|
||||
u64 *spte, struct list_head *invalid_list);
|
||||
|
||||
struct kvm_mmu_role_regs {
|
||||
const unsigned long cr0;
|
||||
|
|
@ -1287,19 +1289,6 @@ static void drop_spte(struct kvm *kvm, u64 *sptep)
|
|||
rmap_remove(kvm, sptep);
|
||||
}
|
||||
|
||||
static void drop_large_spte(struct kvm *kvm, u64 *sptep, bool flush)
|
||||
{
|
||||
struct kvm_mmu_page *sp;
|
||||
|
||||
sp = sptep_to_sp(sptep);
|
||||
WARN_ON_ONCE(sp->role.level == PG_LEVEL_4K);
|
||||
|
||||
drop_spte(kvm, sptep);
|
||||
|
||||
if (flush)
|
||||
kvm_flush_remote_tlbs_sptep(kvm, sptep);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write-protect on the specified @sptep, @pt_protect indicates whether
|
||||
* spte write-protection is caused by protecting shadow page table.
|
||||
|
|
@ -2466,7 +2455,8 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu,
|
|||
{
|
||||
union kvm_mmu_page_role role;
|
||||
|
||||
if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep))
|
||||
if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep) &&
|
||||
spte_to_child_sp(*sptep) && spte_to_child_sp(*sptep)->gfn == gfn)
|
||||
return ERR_PTR(-EEXIST);
|
||||
|
||||
role = kvm_mmu_child_role(sptep, direct, access);
|
||||
|
|
@ -2544,13 +2534,16 @@ static void __link_shadow_page(struct kvm *kvm,
|
|||
|
||||
BUILD_BUG_ON(VMX_EPT_WRITABLE_MASK != PT_WRITABLE_MASK);
|
||||
|
||||
/*
|
||||
* If an SPTE is present already, it must be a leaf and therefore
|
||||
* a large one. Drop it, and flush the TLB if needed, before
|
||||
* installing sp.
|
||||
*/
|
||||
if (is_shadow_present_pte(*sptep))
|
||||
drop_large_spte(kvm, sptep, flush);
|
||||
if (is_shadow_present_pte(*sptep)) {
|
||||
struct kvm_mmu_page *parent_sp;
|
||||
LIST_HEAD(invalid_list);
|
||||
|
||||
parent_sp = sptep_to_sp(sptep);
|
||||
WARN_ON_ONCE(parent_sp->role.level == PG_LEVEL_4K);
|
||||
|
||||
mmu_page_zap_pte(kvm, parent_sp, sptep, &invalid_list);
|
||||
kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, true);
|
||||
}
|
||||
|
||||
spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp));
|
||||
|
||||
|
|
|
|||
|
|
@ -7029,8 +7029,8 @@ static void vmx_set_rvi(int vector)
|
|||
int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vt *vt = to_vt(vcpu);
|
||||
bool max_irr_is_from_pir;
|
||||
int max_irr;
|
||||
bool got_posted_interrupt;
|
||||
|
||||
if (KVM_BUG_ON(!enable_apicv, vcpu->kvm))
|
||||
return -EIO;
|
||||
|
|
@ -7042,17 +7042,22 @@ int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
|
|||
* But on x86 this is just a compiler barrier anyway.
|
||||
*/
|
||||
smp_mb__after_atomic();
|
||||
got_posted_interrupt =
|
||||
kvm_apic_update_irr(vcpu, vt->pi_desc.pir, &max_irr);
|
||||
max_irr_is_from_pir = kvm_apic_update_irr(vcpu, vt->pi_desc.pir,
|
||||
&max_irr);
|
||||
} else {
|
||||
max_irr = kvm_lapic_find_highest_irr(vcpu);
|
||||
got_posted_interrupt = false;
|
||||
max_irr_is_from_pir = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Newly recognized interrupts are injected via either virtual interrupt
|
||||
* delivery (RVI) or KVM_REQ_EVENT. Virtual interrupt delivery is
|
||||
* disabled in two cases:
|
||||
* If APICv is enabled and L2 is not active, then update the Requesting
|
||||
* Virtual Interrupt (RVI) portion of vmcs01.GUEST_INTR_STATUS with the
|
||||
* highest priority IRR to deliver the IRQ via Virtual Interrupt
|
||||
* Delivery. Note, this is required even if the highest priority IRQ
|
||||
* was already pending in the IRR, as RVI isn't updated in lockstep with
|
||||
* the IRR (unlike apic->irr_pending).
|
||||
*
|
||||
* For the cases where Virtual Interrupt Delivery can't be used:
|
||||
*
|
||||
* 1) If L2 is running and the vCPU has a new pending interrupt. If L1
|
||||
* wants to exit on interrupts, KVM_REQ_EVENT is needed to synthesize a
|
||||
|
|
@ -7063,10 +7068,29 @@ int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu)
|
|||
* 2) If APICv is disabled for this vCPU, assigned devices may still
|
||||
* attempt to post interrupts. The posted interrupt vector will cause
|
||||
* a VM-Exit and the subsequent entry will call sync_pir_to_irr.
|
||||
*
|
||||
* In both cases, set KVM_REQ_EVENT if and only if the highest priority
|
||||
* pending IRQ came from the PIR, as setting KVM_REQ_EVENT if any IRQ
|
||||
* is pending may put the vCPU into an infinite loop, e.g. if the IRQ
|
||||
* is blocked, then it will stay pending until an IRQ window is opened.
|
||||
*
|
||||
* Note! It's possible that one or more IRQs were moved from the PIR
|
||||
* to the IRR _without_ max_irr_is_from_pir being true! I.e. if there
|
||||
* was a higher priority IRQ already pending in the IRR. Not setting
|
||||
* KVM_REQ_EVENT in this case is intentional and safe. If APICv is
|
||||
* inactive, or L2 is running with exit-on-interrupt off (in vmcs12),
|
||||
* i.e. without nested virtual interrupt delivery, then there's no need
|
||||
* to request an IRQ window as the lower priority IRQ only needs to be
|
||||
* delivered when the higher priority IRQ is dismissed from the ISR,
|
||||
* i.e. on the next EOI, and EOIs are always intercepted if APICv is
|
||||
* disabled or if L2 is running without nested VID. If L2 is running
|
||||
* exit-on-interrupt on (in vmcs12), then the higher priority IRQ will
|
||||
* trigger a nested VM-Exit, at which point KVM will re-evaluate L1's
|
||||
* pending IRQs.
|
||||
*/
|
||||
if (!is_guest_mode(vcpu) && kvm_vcpu_apicv_active(vcpu))
|
||||
vmx_set_rvi(max_irr);
|
||||
else if (got_posted_interrupt)
|
||||
else if (max_irr_is_from_pir)
|
||||
kvm_make_request(KVM_REQ_EVENT, vcpu);
|
||||
|
||||
return max_irr;
|
||||
|
|
|
|||
|
|
@ -686,7 +686,7 @@ page_fault_oops(struct pt_regs *regs, unsigned long error_code,
|
|||
* avoid hanging the system.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_EFI))
|
||||
efi_crash_gracefully_on_page_fault(address);
|
||||
efi_crash_gracefully_on_page_fault(address, regs);
|
||||
|
||||
/* Only not-present faults should be handled by KFENCE. */
|
||||
if (!(error_code & X86_PF_PROT) &&
|
||||
|
|
|
|||
|
|
@ -761,7 +761,8 @@ int efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff,
|
|||
* @return: Returns, if the page fault is not handled. This function
|
||||
* will never return if the page fault is handled successfully.
|
||||
*/
|
||||
void efi_crash_gracefully_on_page_fault(unsigned long phys_addr)
|
||||
void efi_crash_gracefully_on_page_fault(unsigned long phys_addr,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_X86_64))
|
||||
return;
|
||||
|
|
@ -770,7 +771,7 @@ void efi_crash_gracefully_on_page_fault(unsigned long phys_addr)
|
|||
* If we get an interrupt/NMI while processing an EFI runtime service
|
||||
* then this is a regular OOPS, not an EFI failure.
|
||||
*/
|
||||
if (in_interrupt())
|
||||
if (!in_task())
|
||||
return;
|
||||
|
||||
/*
|
||||
|
|
@ -810,6 +811,14 @@ void efi_crash_gracefully_on_page_fault(unsigned long phys_addr)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The API does not permit entering a kernel mode FPU section with
|
||||
* interrupts enabled and leaving it with interrupts disabled. So
|
||||
* re-enable interrupts now if they were enabled when the page fault
|
||||
* occurred.
|
||||
*/
|
||||
local_irq_restore(regs->flags);
|
||||
|
||||
/*
|
||||
* Before calling EFI Runtime Service, the kernel has switched the
|
||||
* calling process to efi_mm. Hence, switch back to task_mm.
|
||||
|
|
|
|||
|
|
@ -390,6 +390,11 @@ static int crypto_authenc_esn_create(struct crypto_template *tmpl,
|
|||
auth = crypto_spawn_ahash_alg(&ctx->auth);
|
||||
auth_base = &auth->base;
|
||||
|
||||
if (auth->digestsize > 0 && auth->digestsize < 4) {
|
||||
err = -EINVAL;
|
||||
goto err_free_inst;
|
||||
}
|
||||
|
||||
err = crypto_grab_skcipher(&ctx->enc, aead_crypto_instance(inst),
|
||||
crypto_attr_alg_name(tb[2]), 0, mask);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -605,15 +605,12 @@ static umode_t acpi_tad_attr_is_visible(struct kobject *kobj,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct attribute_group acpi_tad_attr_group = {
|
||||
static const struct attribute_group acpi_tad_group = {
|
||||
.attrs = acpi_tad_attrs,
|
||||
.is_visible = acpi_tad_attr_is_visible,
|
||||
};
|
||||
|
||||
static const struct attribute_group *acpi_tad_attr_groups[] = {
|
||||
&acpi_tad_attr_group,
|
||||
NULL,
|
||||
};
|
||||
__ATTRIBUTE_GROUPS(acpi_tad);
|
||||
|
||||
#ifdef CONFIG_RTC_CLASS
|
||||
/* RTC class device interface */
|
||||
|
|
@ -683,9 +680,8 @@ static int acpi_tad_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
|
|||
|
||||
acpi_tad_rt_to_tm(&rt, &tm_now);
|
||||
|
||||
value = ktime_divns(ktime_sub(rtc_tm_to_ktime(t->time),
|
||||
rtc_tm_to_ktime(tm_now)), NSEC_PER_SEC);
|
||||
if (value <= 0 || value > U32_MAX)
|
||||
value = rtc_tm_to_time64(&t->time) - rtc_tm_to_time64(&tm_now);
|
||||
if (value <= 0 || value >= U32_MAX)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -748,8 +744,7 @@ static int acpi_tad_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
|
|||
|
||||
if (retval != ACPI_TAD_WAKE_DISABLED) {
|
||||
t->enabled = 1;
|
||||
t->time = rtc_ktime_to_tm(ktime_add_ns(rtc_tm_to_ktime(tm_now),
|
||||
(u64)retval * NSEC_PER_SEC));
|
||||
rtc_time64_to_tm(rtc_tm_to_time64(&tm_now) + retval, &t->time);
|
||||
} else {
|
||||
t->enabled = 0;
|
||||
t->time = tm_now;
|
||||
|
|
@ -795,9 +790,9 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id)
|
|||
return acpi_tad_wake_set(dev, "_STV", timer_id, ACPI_TAD_WAKE_DISABLED);
|
||||
}
|
||||
|
||||
static void acpi_tad_remove(struct platform_device *pdev)
|
||||
static void acpi_tad_remove(void *data)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device *dev = data;
|
||||
struct acpi_tad_driver_data *dd = dev_get_drvdata(dev);
|
||||
|
||||
device_init_wakeup(dev, false);
|
||||
|
|
@ -824,6 +819,7 @@ static int acpi_tad_probe(struct platform_device *pdev)
|
|||
struct acpi_tad_driver_data *dd;
|
||||
acpi_status status;
|
||||
unsigned long long caps;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Initialization failure messages are mostly about firmware issues, so
|
||||
|
|
@ -863,13 +859,21 @@ static int acpi_tad_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/*
|
||||
* The platform bus type layer tells the ACPI PM domain powers up the
|
||||
* device, so set the runtime PM status of it to "active".
|
||||
* The platform bus type probe callback tells the ACPI PM domain to
|
||||
* power up the device, so set the runtime PM status of it to "active".
|
||||
*/
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_suspend(dev);
|
||||
|
||||
/*
|
||||
* acpi_tad_remove() needs to run after unregistering the RTC class
|
||||
* device to avoid racing with the latter's callbacks.
|
||||
*/
|
||||
ret = devm_add_action_or_reset(&pdev->dev, acpi_tad_remove, &pdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (caps & ACPI_TAD_RT)
|
||||
acpi_tad_register_rtc(dev, caps);
|
||||
|
||||
|
|
@ -885,10 +889,9 @@ static struct platform_driver acpi_tad_driver = {
|
|||
.driver = {
|
||||
.name = "acpi-tad",
|
||||
.acpi_match_table = acpi_tad_ids,
|
||||
.dev_groups = acpi_tad_attr_groups,
|
||||
.dev_groups = acpi_tad_groups,
|
||||
},
|
||||
.probe = acpi_tad_probe,
|
||||
.remove = acpi_tad_remove,
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, acpi_tad_ids);
|
||||
|
||||
|
|
|
|||
|
|
@ -401,8 +401,18 @@ static struct acpi_generic_address *einj_get_trigger_parameter_region(
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool is_memory_injection(u32 type, u32 flags)
|
||||
{
|
||||
if (flags & SETWA_FLAGS_EINJV2)
|
||||
return !!(type & ACPI_EINJV2_MEMORY);
|
||||
if (type & ACPI5_VENDOR_BIT)
|
||||
return !!(vendor_flags & SETWA_FLAGS_MEM);
|
||||
return !!(type & MEM_ERROR_MASK) || !!(flags & SETWA_FLAGS_MEM);
|
||||
}
|
||||
|
||||
/* Execute instructions in trigger error action table */
|
||||
static int __einj_error_trigger(u64 trigger_paddr, u32 type,
|
||||
static int __einj_error_trigger(u64 trigger_paddr, u32 type, u32 flags,
|
||||
u64 param1, u64 param2)
|
||||
{
|
||||
struct acpi_einj_trigger trigger_tab;
|
||||
|
|
@ -480,7 +490,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
|
|||
* This will cause resource conflict with regular memory. So
|
||||
* remove it from trigger table resources.
|
||||
*/
|
||||
if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) {
|
||||
if ((param_extension || acpi5) && is_memory_injection(type, flags)) {
|
||||
struct apei_resources addr_resources;
|
||||
|
||||
apei_resources_init(&addr_resources);
|
||||
|
|
@ -660,7 +670,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
|
|||
return rc;
|
||||
trigger_paddr = apei_exec_ctx_get_output(&ctx);
|
||||
if (notrigger == 0) {
|
||||
rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
|
||||
rc = __einj_error_trigger(trigger_paddr, type, flags, param1, param2);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -718,28 +728,6 @@ int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3,
|
|||
SETWA_FLAGS_PCIE_SBDF | SETWA_FLAGS_EINJV2)))
|
||||
return -EINVAL;
|
||||
|
||||
/* check if type is a valid EINJv2 error type */
|
||||
if (is_v2) {
|
||||
if (!(type & available_error_type_v2))
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* We need extra sanity checks for memory errors.
|
||||
* Other types leap directly to injection.
|
||||
*/
|
||||
|
||||
/* ensure param1/param2 existed */
|
||||
if (!(param_extension || acpi5))
|
||||
goto inject;
|
||||
|
||||
/* ensure injection is memory related */
|
||||
if (type & ACPI5_VENDOR_BIT) {
|
||||
if (vendor_flags != SETWA_FLAGS_MEM)
|
||||
goto inject;
|
||||
} else if (!(type & MEM_ERROR_MASK) && !(flags & SETWA_FLAGS_MEM)) {
|
||||
goto inject;
|
||||
}
|
||||
|
||||
/*
|
||||
* Injections targeting a CXL 1.0/1.1 port have to be injected
|
||||
* via the einj_cxl_rch_error_inject() path as that does the proper
|
||||
|
|
@ -748,6 +736,23 @@ int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3,
|
|||
if (einj_is_cxl_error_type(type) && (flags & SETWA_FLAGS_MEM))
|
||||
return -EINVAL;
|
||||
|
||||
/* check if type is a valid EINJv2 error type */
|
||||
if (is_v2) {
|
||||
if (!(type & available_error_type_v2))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* ensure param1/param2 existed */
|
||||
if (!(param_extension || acpi5))
|
||||
goto inject;
|
||||
|
||||
/*
|
||||
* We need extra sanity checks for memory errors.
|
||||
* Other types leap directly to injection.
|
||||
*/
|
||||
if (!is_memory_injection(type, flags))
|
||||
goto inject;
|
||||
|
||||
/*
|
||||
* Disallow crazy address masks that give BIOS leeway to pick
|
||||
* injection address almost anywhere. Insist on page or
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
static int psci_acpi_cpu_init_idle(unsigned int cpu)
|
||||
{
|
||||
int i, count;
|
||||
int i;
|
||||
struct acpi_lpi_state *lpi;
|
||||
struct acpi_processor *pr = per_cpu(processors, cpu);
|
||||
|
||||
|
|
@ -30,14 +30,10 @@ static int psci_acpi_cpu_init_idle(unsigned int cpu)
|
|||
if (!psci_ops.cpu_suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
count = pr->power.count - 1;
|
||||
if (count <= 0)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
for (i = 1; i < pr->power.count; i++) {
|
||||
u32 state;
|
||||
|
||||
lpi = &pr->power.lpi_states[i + 1];
|
||||
lpi = &pr->power.lpi_states[i];
|
||||
/*
|
||||
* Only bits[31:0] represent a PSCI power_state while
|
||||
* bits[63:32] must be 0x0 as per ARM ACPI FFH Specification
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd)
|
|||
end:
|
||||
if (cmd == CMD_WRITE) {
|
||||
if (unlikely(ret)) {
|
||||
for_each_online_cpu(i) {
|
||||
for_each_possible_cpu(i) {
|
||||
struct cpc_desc *desc = per_cpu(cpc_desc_ptr, i);
|
||||
|
||||
if (!desc)
|
||||
|
|
@ -524,13 +524,13 @@ int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data)
|
|||
else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
|
||||
cpu_data->shared_type = CPUFREQ_SHARED_TYPE_ANY;
|
||||
|
||||
for_each_online_cpu(i) {
|
||||
for_each_possible_cpu(i) {
|
||||
if (i == cpu)
|
||||
continue;
|
||||
|
||||
match_cpc_ptr = per_cpu(cpc_desc_ptr, i);
|
||||
if (!match_cpc_ptr)
|
||||
goto err_fault;
|
||||
continue;
|
||||
|
||||
match_pdomain = &(match_cpc_ptr->domain_info);
|
||||
if (match_pdomain->domain != pdomain->domain)
|
||||
|
|
|
|||
|
|
@ -916,6 +916,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "82K8"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_native,
|
||||
/* HP OMEN Gaming Laptop 16-n0xxx */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16-n0xxx"),
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* x86 android tablets which directly control the backlight through
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va
|
|||
ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size);
|
||||
if (ret == -ENODATA) {
|
||||
if (!deferrable)
|
||||
dev_warn(dev, "Defer on undeferable control: %x\n", reg);
|
||||
dev_warn(dev, "Defer on undeferrable control: %x\n", reg);
|
||||
|
||||
ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx);
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -289,6 +289,9 @@ static inline void btintel_pcie_dump_debug_registers(struct hci_dev *hdev)
|
|||
skb_put_data(skb, buf, strlen(buf));
|
||||
data->boot_stage_cache = reg;
|
||||
|
||||
if (reg & BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_WARNING)
|
||||
bt_dev_warn(hdev, "Controller device warning (boot_stage: 0x%8.8x)", reg);
|
||||
|
||||
reg = btintel_pcie_rd_reg32(data, BTINTEL_PCIE_CSR_IPC_STATUS_REG);
|
||||
snprintf(buf, sizeof(buf), "ipc status: 0x%8.8x", reg);
|
||||
skb_put_data(skb, buf, strlen(buf));
|
||||
|
|
@ -880,8 +883,11 @@ static inline bool btintel_pcie_in_lockdown(struct btintel_pcie_data *data)
|
|||
|
||||
static inline bool btintel_pcie_in_error(struct btintel_pcie_data *data)
|
||||
{
|
||||
return (data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_ERR) ||
|
||||
(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ABORT_HANDLER);
|
||||
if (data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_WARNING)
|
||||
bt_dev_warn(data->hdev, "Controller device warning (boot_stage: 0x%8.8x)",
|
||||
data->boot_stage_cache);
|
||||
|
||||
return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_ABORT_HANDLER;
|
||||
}
|
||||
|
||||
static void btintel_pcie_msix_gp1_handler(struct btintel_pcie_data *data)
|
||||
|
|
@ -914,7 +920,8 @@ static void btintel_pcie_msix_gp0_handler(struct btintel_pcie_data *data)
|
|||
data->img_resp_cache = reg;
|
||||
|
||||
if (btintel_pcie_in_error(data)) {
|
||||
bt_dev_err(data->hdev, "Controller in error state");
|
||||
bt_dev_err(data->hdev, "Controller in error state (boot_stage: 0x%8.8x)",
|
||||
data->boot_stage_cache);
|
||||
btintel_pcie_dump_debug_registers(data->hdev);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_OPFW (BIT(2))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_ROM_LOCKDOWN (BIT(10))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_IML_LOCKDOWN (BIT(11))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_ERR (BIT(12))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_WARNING (BIT(12))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_ABORT_HANDLER (BIT(13))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_HALTED (BIT(14))
|
||||
#define BTINTEL_PCIE_CSR_BOOT_STAGE_MAC_ACCESS_ON (BIT(16))
|
||||
|
|
|
|||
|
|
@ -695,8 +695,13 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
|
|||
if (data->evt_skb == NULL)
|
||||
goto err_free_wc;
|
||||
|
||||
/* Parse and handle the return WMT event */
|
||||
wmt_evt = (struct btmtk_hci_wmt_evt *)data->evt_skb->data;
|
||||
wmt_evt = skb_pull_data(data->evt_skb, sizeof(*wmt_evt));
|
||||
if (!wmt_evt) {
|
||||
bt_dev_err(hdev, "WMT event too short (%u bytes)",
|
||||
data->evt_skb->len);
|
||||
err = -EINVAL;
|
||||
goto err_free_skb;
|
||||
}
|
||||
if (wmt_evt->whdr.op != hdr->op) {
|
||||
bt_dev_err(hdev, "Wrong op received %d expected %d",
|
||||
wmt_evt->whdr.op, hdr->op);
|
||||
|
|
@ -712,6 +717,12 @@ static int btmtk_usb_hci_wmt_sync(struct hci_dev *hdev,
|
|||
status = BTMTK_WMT_PATCH_DONE;
|
||||
break;
|
||||
case BTMTK_WMT_FUNC_CTRL:
|
||||
if (!skb_pull_data(data->evt_skb,
|
||||
sizeof(wmt_evt_funcc->status))) {
|
||||
err = -EINVAL;
|
||||
goto err_free_skb;
|
||||
}
|
||||
|
||||
wmt_evt_funcc = (struct btmtk_hci_wmt_evt_funcc *)wmt_evt;
|
||||
if (be16_to_cpu(wmt_evt_funcc->status) == 0x404)
|
||||
status = BTMTK_WMT_ON_DONE;
|
||||
|
|
|
|||
|
|
@ -191,6 +191,9 @@ static int ath_recv(struct hci_uart *hu, const void *data, int count)
|
|||
{
|
||||
struct ath_struct *ath = hu->priv;
|
||||
|
||||
if (!ath)
|
||||
return -ENODEV;
|
||||
|
||||
ath->rx_skb = h4_recv_buf(hu, ath->rx_skb, data, count,
|
||||
ath_recv_pkts, ARRAY_SIZE(ath_recv_pkts));
|
||||
if (IS_ERR(ath->rx_skb)) {
|
||||
|
|
|
|||
|
|
@ -585,6 +585,9 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count)
|
|||
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return -EUNATCH;
|
||||
|
||||
if (!bcsp)
|
||||
return -ENODEV;
|
||||
|
||||
BT_DBG("hu %p count %d rx_state %d rx_count %ld",
|
||||
hu, count, bcsp->rx_state, bcsp->rx_count);
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,9 @@ static int h4_recv(struct hci_uart *hu, const void *data, int count)
|
|||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
|
||||
if (!h4)
|
||||
return -ENODEV;
|
||||
|
||||
h4->rx_skb = h4_recv_buf(hu, h4->rx_skb, data, count,
|
||||
h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts));
|
||||
if (IS_ERR(h4->rx_skb)) {
|
||||
|
|
|
|||
|
|
@ -587,6 +587,9 @@ static int h5_recv(struct hci_uart *hu, const void *data, int count)
|
|||
struct h5 *h5 = hu->priv;
|
||||
const unsigned char *ptr = data;
|
||||
|
||||
if (!h5)
|
||||
return -ENODEV;
|
||||
|
||||
BT_DBG("%s pending %zu count %d", hu->hdev->name, h5->rx_pending,
|
||||
count);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#define VERSION "0.1"
|
||||
#define VIRTBT_RX_BUF_SIZE 1000
|
||||
|
||||
enum {
|
||||
VIRTBT_VQ_TX,
|
||||
|
|
@ -33,11 +34,11 @@ static int virtbt_add_inbuf(struct virtio_bluetooth *vbt)
|
|||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
skb = alloc_skb(1000, GFP_KERNEL);
|
||||
skb = alloc_skb(VIRTBT_RX_BUF_SIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
sg_init_one(sg, skb->data, 1000);
|
||||
sg_init_one(sg, skb->data, VIRTBT_RX_BUF_SIZE);
|
||||
|
||||
err = virtqueue_add_inbuf(vq, sg, 1, skb, GFP_KERNEL);
|
||||
if (err < 0) {
|
||||
|
|
@ -197,6 +198,7 @@ static int virtbt_shutdown_generic(struct hci_dev *hdev)
|
|||
|
||||
static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb)
|
||||
{
|
||||
size_t min_hdr;
|
||||
__u8 pkt_type;
|
||||
|
||||
pkt_type = *((__u8 *) skb->data);
|
||||
|
|
@ -204,16 +206,32 @@ static void virtbt_rx_handle(struct virtio_bluetooth *vbt, struct sk_buff *skb)
|
|||
|
||||
switch (pkt_type) {
|
||||
case HCI_EVENT_PKT:
|
||||
min_hdr = sizeof(struct hci_event_hdr);
|
||||
break;
|
||||
case HCI_ACLDATA_PKT:
|
||||
min_hdr = sizeof(struct hci_acl_hdr);
|
||||
break;
|
||||
case HCI_SCODATA_PKT:
|
||||
min_hdr = sizeof(struct hci_sco_hdr);
|
||||
break;
|
||||
case HCI_ISODATA_PKT:
|
||||
hci_skb_pkt_type(skb) = pkt_type;
|
||||
hci_recv_frame(vbt->hdev, skb);
|
||||
min_hdr = sizeof(struct hci_iso_hdr);
|
||||
break;
|
||||
default:
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
if (skb->len < min_hdr) {
|
||||
bt_dev_err_ratelimited(vbt->hdev,
|
||||
"rx pkt_type 0x%02x payload %u < hdr %zu\n",
|
||||
pkt_type, skb->len, min_hdr);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
hci_skb_pkt_type(skb) = pkt_type;
|
||||
hci_recv_frame(vbt->hdev, skb);
|
||||
}
|
||||
|
||||
static void virtbt_rx_work(struct work_struct *work)
|
||||
|
|
@ -227,8 +245,15 @@ static void virtbt_rx_work(struct work_struct *work)
|
|||
if (!skb)
|
||||
return;
|
||||
|
||||
skb_put(skb, len);
|
||||
virtbt_rx_handle(vbt, skb);
|
||||
if (!len || len > VIRTBT_RX_BUF_SIZE) {
|
||||
bt_dev_err_ratelimited(vbt->hdev,
|
||||
"rx reply len %u outside [1, %u]\n",
|
||||
len, VIRTBT_RX_BUF_SIZE);
|
||||
kfree_skb(skb);
|
||||
} else {
|
||||
skb_put(skb, len);
|
||||
virtbt_rx_handle(vbt, skb);
|
||||
}
|
||||
|
||||
if (virtbt_add_inbuf(vbt) < 0)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -631,6 +631,16 @@ int register_cdrom(struct gendisk *disk, struct cdrom_device_info *cdi)
|
|||
|
||||
WARN_ON(!cdo->generic_packet);
|
||||
|
||||
/*
|
||||
* Propagate the drive's write support to the block layer so BLKROGET
|
||||
* reflects actual write capability. Drivers that use GET CONFIGURATION
|
||||
* features (CDC_MRW_W, CDC_RAM) must have called
|
||||
* cdrom_probe_write_features() before register_cdrom() so the mask is
|
||||
* complete here.
|
||||
*/
|
||||
set_disk_ro(disk, !CDROM_CAN(CDC_DVD_RAM | CDC_MRW_W | CDC_RAM |
|
||||
CDC_CD_RW));
|
||||
|
||||
cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
|
||||
mutex_lock(&cdrom_mutex);
|
||||
list_add(&cdi->list, &cdrom_list);
|
||||
|
|
@ -742,6 +752,44 @@ static int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe write-related MMC features via GET CONFIGURATION and update
|
||||
* cdi->mask accordingly. Drivers that populate cdi->mask from the MODE SENSE
|
||||
* capabilities page (e.g. sr) should call this after those MODE SENSE bits
|
||||
* have been set but before register_cdrom(), so that the full set of
|
||||
* write-capability bits is known by the time register_cdrom() decides on the
|
||||
* initial read-only state of the disk.
|
||||
*/
|
||||
void cdrom_probe_write_features(struct cdrom_device_info *cdi)
|
||||
{
|
||||
int mrw, mrw_write, ram_write;
|
||||
|
||||
mrw = 0;
|
||||
if (!cdrom_is_mrw(cdi, &mrw_write))
|
||||
mrw = 1;
|
||||
|
||||
if (CDROM_CAN(CDC_MO_DRIVE))
|
||||
ram_write = 1;
|
||||
else
|
||||
(void) cdrom_is_random_writable(cdi, &ram_write);
|
||||
|
||||
if (mrw)
|
||||
cdi->mask &= ~CDC_MRW;
|
||||
else
|
||||
cdi->mask |= CDC_MRW;
|
||||
|
||||
if (mrw_write)
|
||||
cdi->mask &= ~CDC_MRW_W;
|
||||
else
|
||||
cdi->mask |= CDC_MRW_W;
|
||||
|
||||
if (ram_write)
|
||||
cdi->mask &= ~CDC_RAM;
|
||||
else
|
||||
cdi->mask |= CDC_RAM;
|
||||
}
|
||||
EXPORT_SYMBOL(cdrom_probe_write_features);
|
||||
|
||||
static int cdrom_media_erasable(struct cdrom_device_info *cdi)
|
||||
{
|
||||
disc_information di;
|
||||
|
|
@ -894,33 +942,8 @@ static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
|
|||
*/
|
||||
static int cdrom_open_write(struct cdrom_device_info *cdi)
|
||||
{
|
||||
int mrw, mrw_write, ram_write;
|
||||
int ret = 1;
|
||||
|
||||
mrw = 0;
|
||||
if (!cdrom_is_mrw(cdi, &mrw_write))
|
||||
mrw = 1;
|
||||
|
||||
if (CDROM_CAN(CDC_MO_DRIVE))
|
||||
ram_write = 1;
|
||||
else
|
||||
(void) cdrom_is_random_writable(cdi, &ram_write);
|
||||
|
||||
if (mrw)
|
||||
cdi->mask &= ~CDC_MRW;
|
||||
else
|
||||
cdi->mask |= CDC_MRW;
|
||||
|
||||
if (mrw_write)
|
||||
cdi->mask &= ~CDC_MRW_W;
|
||||
else
|
||||
cdi->mask |= CDC_MRW_W;
|
||||
|
||||
if (ram_write)
|
||||
cdi->mask &= ~CDC_RAM;
|
||||
else
|
||||
cdi->mask |= CDC_RAM;
|
||||
|
||||
if (CDROM_CAN(CDC_MRW_W))
|
||||
ret = cdrom_mrw_open_write(cdi);
|
||||
else if (CDROM_CAN(CDC_DVD_RAM))
|
||||
|
|
|
|||
|
|
@ -168,6 +168,10 @@ struct smi_info {
|
|||
OEM2_DATA_AVAIL)
|
||||
unsigned char msg_flags;
|
||||
|
||||
/* When requesting events and messages, don't do it forever. */
|
||||
unsigned int num_requests_in_a_row;
|
||||
bool last_was_flag_fetch;
|
||||
|
||||
/* Does the BMC have an event buffer? */
|
||||
bool has_event_buffer;
|
||||
|
||||
|
|
@ -410,7 +414,10 @@ static void start_getting_msg_queue(struct smi_info *smi_info)
|
|||
|
||||
start_new_msg(smi_info, smi_info->curr_msg->data,
|
||||
smi_info->curr_msg->data_size);
|
||||
smi_info->si_state = SI_GETTING_MESSAGES;
|
||||
if (smi_info->si_state != SI_GETTING_MESSAGES) {
|
||||
smi_info->num_requests_in_a_row = 0;
|
||||
smi_info->si_state = SI_GETTING_MESSAGES;
|
||||
}
|
||||
}
|
||||
|
||||
static void start_getting_events(struct smi_info *smi_info)
|
||||
|
|
@ -421,7 +428,10 @@ static void start_getting_events(struct smi_info *smi_info)
|
|||
|
||||
start_new_msg(smi_info, smi_info->curr_msg->data,
|
||||
smi_info->curr_msg->data_size);
|
||||
smi_info->si_state = SI_GETTING_EVENTS;
|
||||
if (smi_info->si_state != SI_GETTING_EVENTS) {
|
||||
smi_info->num_requests_in_a_row = 0;
|
||||
smi_info->si_state = SI_GETTING_EVENTS;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -487,15 +497,19 @@ static void handle_flags(struct smi_info *smi_info)
|
|||
} else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) {
|
||||
/* Messages available. */
|
||||
smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
|
||||
if (!smi_info->curr_msg)
|
||||
if (!smi_info->curr_msg) {
|
||||
smi_info->si_state = SI_NORMAL;
|
||||
return;
|
||||
}
|
||||
|
||||
start_getting_msg_queue(smi_info);
|
||||
} else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) {
|
||||
/* Events available. */
|
||||
smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
|
||||
if (!smi_info->curr_msg)
|
||||
if (!smi_info->curr_msg) {
|
||||
smi_info->si_state = SI_NORMAL;
|
||||
return;
|
||||
}
|
||||
|
||||
start_getting_events(smi_info);
|
||||
} else if (smi_info->msg_flags & OEM_DATA_AVAIL &&
|
||||
|
|
@ -595,6 +609,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
|
|||
smi_info->si_state = SI_NORMAL;
|
||||
} else {
|
||||
smi_info->msg_flags = msg[3];
|
||||
smi_info->last_was_flag_fetch = true;
|
||||
handle_flags(smi_info);
|
||||
}
|
||||
break;
|
||||
|
|
@ -630,7 +645,13 @@ static void handle_transaction_done(struct smi_info *smi_info)
|
|||
*/
|
||||
msg = smi_info->curr_msg;
|
||||
smi_info->curr_msg = NULL;
|
||||
if (msg->rsp[2] != 0) {
|
||||
/*
|
||||
* It appears some BMCs, with no event data, return no
|
||||
* data in the message and not a 0x80 error as the
|
||||
* spec says they should. Shut down processing if
|
||||
* the data is not the right length.
|
||||
*/
|
||||
if (msg->rsp[2] != 0 || msg->rsp_size != 19) {
|
||||
/* Error getting event, probably done. */
|
||||
msg->done(msg);
|
||||
|
||||
|
|
@ -640,6 +661,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
|
|||
} else {
|
||||
smi_inc_stat(smi_info, events);
|
||||
|
||||
smi_info->num_requests_in_a_row++;
|
||||
if (smi_info->num_requests_in_a_row > 10)
|
||||
/* Stop if we do this too many times. */
|
||||
smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
|
||||
|
||||
/*
|
||||
* Do this before we deliver the message
|
||||
* because delivering the message releases the
|
||||
|
|
@ -678,6 +704,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
|
|||
} else {
|
||||
smi_inc_stat(smi_info, incoming_messages);
|
||||
|
||||
smi_info->num_requests_in_a_row++;
|
||||
if (smi_info->num_requests_in_a_row > 10)
|
||||
/* Stop if we do this too many times. */
|
||||
smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
|
||||
|
||||
/*
|
||||
* Do this before we deliver the message
|
||||
* because delivering the message releases the
|
||||
|
|
@ -819,6 +850,26 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are currently idle, or if the last thing that was
|
||||
* done was a flag fetch and there is a message pending, try
|
||||
* to start the next message.
|
||||
*
|
||||
* We do the waiting message check to avoid a stuck flag
|
||||
* completely wedging the driver. Let a message through
|
||||
* in between flag operations if that happens.
|
||||
*/
|
||||
if (si_sm_result == SI_SM_IDLE ||
|
||||
(si_sm_result == SI_SM_ATTN && smi_info->waiting_msg &&
|
||||
smi_info->last_was_flag_fetch)) {
|
||||
smi_info->last_was_flag_fetch = false;
|
||||
smi_inc_stat(smi_info, idles);
|
||||
|
||||
si_sm_result = start_next_msg(smi_info);
|
||||
if (si_sm_result != SI_SM_IDLE)
|
||||
goto restart;
|
||||
}
|
||||
|
||||
/*
|
||||
* We prefer handling attn over new messages. But don't do
|
||||
* this if there is not yet an upper layer to handle anything.
|
||||
|
|
@ -846,15 +897,6 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
|
|||
}
|
||||
}
|
||||
|
||||
/* If we are currently idle, try to start the next message. */
|
||||
if (si_sm_result == SI_SM_IDLE) {
|
||||
smi_inc_stat(smi_info, idles);
|
||||
|
||||
si_sm_result = start_next_msg(smi_info);
|
||||
if (si_sm_result != SI_SM_IDLE)
|
||||
goto restart;
|
||||
}
|
||||
|
||||
if ((si_sm_result == SI_SM_IDLE)
|
||||
&& (atomic_read(&smi_info->req_events))) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -225,6 +225,9 @@ struct ssif_info {
|
|||
bool has_event_buffer;
|
||||
bool supports_alert;
|
||||
|
||||
/* When requesting events and messages, don't do it forever. */
|
||||
unsigned int num_requests_in_a_row;
|
||||
|
||||
/*
|
||||
* Used to tell what we should do with alerts. If we are
|
||||
* waiting on a response, read the data immediately.
|
||||
|
|
@ -413,7 +416,10 @@ static void start_event_fetch(struct ssif_info *ssif_info, unsigned long *flags)
|
|||
}
|
||||
|
||||
ssif_info->curr_msg = msg;
|
||||
ssif_info->ssif_state = SSIF_GETTING_EVENTS;
|
||||
if (ssif_info->ssif_state != SSIF_GETTING_EVENTS) {
|
||||
ssif_info->num_requests_in_a_row = 0;
|
||||
ssif_info->ssif_state = SSIF_GETTING_EVENTS;
|
||||
}
|
||||
ipmi_ssif_unlock_cond(ssif_info, flags);
|
||||
|
||||
msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
|
||||
|
|
@ -436,7 +442,10 @@ static void start_recv_msg_fetch(struct ssif_info *ssif_info,
|
|||
}
|
||||
|
||||
ssif_info->curr_msg = msg;
|
||||
ssif_info->ssif_state = SSIF_GETTING_MESSAGES;
|
||||
if (ssif_info->ssif_state != SSIF_GETTING_MESSAGES) {
|
||||
ssif_info->num_requests_in_a_row = 0;
|
||||
ssif_info->ssif_state = SSIF_GETTING_MESSAGES;
|
||||
}
|
||||
ipmi_ssif_unlock_cond(ssif_info, flags);
|
||||
|
||||
msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
|
||||
|
|
@ -843,6 +852,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
|
|||
ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
|
||||
handle_flags(ssif_info, flags);
|
||||
} else {
|
||||
ssif_info->num_requests_in_a_row++;
|
||||
if (ssif_info->num_requests_in_a_row > 10)
|
||||
/* Stop if we do this too many times. */
|
||||
ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
|
||||
|
||||
handle_flags(ssif_info, flags);
|
||||
ssif_inc_stat(ssif_info, events);
|
||||
deliver_recv_msg(ssif_info, msg);
|
||||
|
|
@ -876,6 +890,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
|
|||
ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
|
||||
handle_flags(ssif_info, flags);
|
||||
} else {
|
||||
ssif_info->num_requests_in_a_row++;
|
||||
if (ssif_info->num_requests_in_a_row > 10)
|
||||
/* Stop if we do this too many times. */
|
||||
ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
|
||||
|
||||
ssif_inc_stat(ssif_info, incoming_messages);
|
||||
handle_flags(ssif_info, flags);
|
||||
deliver_recv_msg(ssif_info, msg);
|
||||
|
|
@ -1886,6 +1905,7 @@ static int ssif_probe(struct i2c_client *client)
|
|||
"kssif%4.4x", thread_num);
|
||||
if (IS_ERR(ssif_info->thread)) {
|
||||
rv = PTR_ERR(ssif_info->thread);
|
||||
ssif_info->thread = NULL;
|
||||
dev_notice(&ssif_info->client->dev,
|
||||
"Could not start kernel thread: error %d\n",
|
||||
rv);
|
||||
|
|
|
|||
|
|
@ -60,8 +60,10 @@ static int efi_pstore_open(struct pstore_info *psi)
|
|||
return err;
|
||||
|
||||
psi->data = kzalloc(record_size, GFP_KERNEL);
|
||||
if (!psi->data)
|
||||
if (!psi->data) {
|
||||
efivar_unlock();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
|
|||
lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
|
||||
file.o mem.o random.o randomalloc.o pci.o \
|
||||
skip_spaces.o lib-cmdline.o lib-ctype.o \
|
||||
alignedmem.o relocate.o printk.o vsprintf.o
|
||||
alignedmem.o printk.o vsprintf.o
|
||||
|
||||
# include the stub's libfdt dependencies from lib/ when needed
|
||||
libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \
|
||||
|
|
|
|||
|
|
@ -1104,13 +1104,6 @@ efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
|
|||
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long min);
|
||||
|
||||
efi_status_t efi_relocate_kernel(unsigned long *image_addr,
|
||||
unsigned long image_size,
|
||||
unsigned long alloc_size,
|
||||
unsigned long preferred_addr,
|
||||
unsigned long alignment,
|
||||
unsigned long min_addr);
|
||||
|
||||
efi_status_t efi_parse_options(char const *cmdline);
|
||||
|
||||
void efi_parse_option_graphics(char *option);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,86 @@ extern int kernel_asize;
|
|||
extern int kernel_fsize;
|
||||
extern int kernel_entry;
|
||||
|
||||
/**
|
||||
* efi_relocate_kernel() - copy memory area
|
||||
* @image_addr: pointer to address of memory area to copy
|
||||
* @image_size: size of memory area to copy
|
||||
* @alloc_size: minimum size of memory to allocate, must be greater or
|
||||
* equal to image_size
|
||||
* @preferred_addr: preferred target address
|
||||
* @alignment: minimum alignment of the allocated memory area. It
|
||||
* should be a power of two.
|
||||
* @min_addr: minimum target address
|
||||
*
|
||||
* Copy a memory area to a newly allocated memory area aligned according
|
||||
* to @alignment but at least EFI_ALLOC_ALIGN. If the preferred address
|
||||
* is not available, the allocated address will not be below @min_addr.
|
||||
* On exit, @image_addr is updated to the target copy address that was used.
|
||||
*
|
||||
* This function is used to copy the Linux kernel verbatim. It does not apply
|
||||
* any relocation changes.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
static
|
||||
efi_status_t efi_relocate_kernel(unsigned long *image_addr,
|
||||
unsigned long image_size,
|
||||
unsigned long alloc_size,
|
||||
unsigned long preferred_addr,
|
||||
unsigned long alignment,
|
||||
unsigned long min_addr)
|
||||
{
|
||||
unsigned long cur_image_addr;
|
||||
unsigned long new_addr = 0;
|
||||
efi_status_t status;
|
||||
unsigned long nr_pages;
|
||||
efi_physical_addr_t efi_addr = preferred_addr;
|
||||
|
||||
if (!image_addr || !image_size || !alloc_size)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
if (alloc_size < image_size)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
cur_image_addr = *image_addr;
|
||||
|
||||
/*
|
||||
* The EFI firmware loader could have placed the kernel image
|
||||
* anywhere in memory, but the kernel has restrictions on the
|
||||
* max physical address it can run at. Some architectures
|
||||
* also have a preferred address, so first try to relocate
|
||||
* to the preferred address. If that fails, allocate as low
|
||||
* as possible while respecting the required alignment.
|
||||
*/
|
||||
nr_pages = round_up(alloc_size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
|
||||
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
|
||||
EFI_LOADER_DATA, nr_pages, &efi_addr);
|
||||
new_addr = efi_addr;
|
||||
/*
|
||||
* If preferred address allocation failed allocate as low as
|
||||
* possible.
|
||||
*/
|
||||
if (status != EFI_SUCCESS) {
|
||||
status = efi_low_alloc_above(alloc_size, alignment, &new_addr,
|
||||
min_addr);
|
||||
}
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate usable memory for kernel.\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* We know source/dest won't overlap since both memory ranges
|
||||
* have been allocated by UEFI, so we can safely use memcpy.
|
||||
*/
|
||||
memcpy((void *)new_addr, (void *)cur_image_addr, image_size);
|
||||
efi_cache_sync_image(new_addr, image_size);
|
||||
|
||||
/* Return the new address of the relocated image. */
|
||||
*image_addr = new_addr;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
efi_status_t handle_kernel_image(unsigned long *image_addr,
|
||||
unsigned long *image_size,
|
||||
unsigned long *reserve_addr,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ efi_status_t check_platform_features(void)
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
void efi_cache_sync_image(unsigned long image_base, unsigned long alloc_size)
|
||||
{
|
||||
asm volatile ("ibar 0" ::: "memory");
|
||||
}
|
||||
|
||||
struct exit_boot_struct {
|
||||
efi_memory_desc_t *runtime_map;
|
||||
int runtime_entry_count;
|
||||
|
|
|
|||
|
|
@ -124,3 +124,85 @@ void efi_free(unsigned long size, unsigned long addr)
|
|||
nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
|
||||
efi_bs_call(free_pages, addr, nr_pages);
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_low_alloc_above() - allocate pages at or above given address
|
||||
* @size: size of the memory area to allocate
|
||||
* @align: minimum alignment of the allocated memory area. It should
|
||||
* a power of two.
|
||||
* @addr: on exit the address of the allocated memory
|
||||
* @min: minimum address to used for the memory allocation
|
||||
*
|
||||
* Allocate at the lowest possible address that is not below @min as
|
||||
* EFI_LOADER_DATA. The allocated pages are aligned according to @align but at
|
||||
* least EFI_ALLOC_ALIGN. The first allocated page will not below the address
|
||||
* given by @min.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long min)
|
||||
{
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
unsigned long nr_pages;
|
||||
int i;
|
||||
|
||||
status = efi_get_memory_map(&map, false);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Enforce minimum alignment that EFI or Linux requires when
|
||||
* requesting a specific address. We are doing page-based (or
|
||||
* larger) allocations, and both the address and size must meet
|
||||
* alignment constraints.
|
||||
*/
|
||||
if (align < EFI_ALLOC_ALIGN)
|
||||
align = EFI_ALLOC_ALIGN;
|
||||
|
||||
size = round_up(size, EFI_ALLOC_ALIGN);
|
||||
nr_pages = size / EFI_PAGE_SIZE;
|
||||
for (i = 0; i < map->map_size / map->desc_size; i++) {
|
||||
efi_memory_desc_t *desc;
|
||||
unsigned long m = (unsigned long)map->map;
|
||||
u64 start, end;
|
||||
|
||||
desc = efi_memdesc_ptr(m, map->desc_size, i);
|
||||
|
||||
if (desc->type != EFI_CONVENTIONAL_MEMORY)
|
||||
continue;
|
||||
|
||||
if (desc->attribute & EFI_MEMORY_HOT_PLUGGABLE)
|
||||
continue;
|
||||
|
||||
if (efi_soft_reserve_enabled() &&
|
||||
(desc->attribute & EFI_MEMORY_SP))
|
||||
continue;
|
||||
|
||||
if (desc->num_pages < nr_pages)
|
||||
continue;
|
||||
|
||||
start = desc->phys_addr;
|
||||
end = start + desc->num_pages * EFI_PAGE_SIZE;
|
||||
|
||||
if (start < min)
|
||||
start = min;
|
||||
|
||||
start = round_up(start, align);
|
||||
if ((start + size) > end)
|
||||
continue;
|
||||
|
||||
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
|
||||
EFI_LOADER_DATA, nr_pages, &start);
|
||||
if (status == EFI_SUCCESS) {
|
||||
*addr = start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == map->map_size / map->desc_size)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,166 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
/**
|
||||
* efi_low_alloc_above() - allocate pages at or above given address
|
||||
* @size: size of the memory area to allocate
|
||||
* @align: minimum alignment of the allocated memory area. It should
|
||||
* a power of two.
|
||||
* @addr: on exit the address of the allocated memory
|
||||
* @min: minimum address to used for the memory allocation
|
||||
*
|
||||
* Allocate at the lowest possible address that is not below @min as
|
||||
* EFI_LOADER_DATA. The allocated pages are aligned according to @align but at
|
||||
* least EFI_ALLOC_ALIGN. The first allocated page will not below the address
|
||||
* given by @min.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long min)
|
||||
{
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
unsigned long nr_pages;
|
||||
int i;
|
||||
|
||||
status = efi_get_memory_map(&map, false);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Enforce minimum alignment that EFI or Linux requires when
|
||||
* requesting a specific address. We are doing page-based (or
|
||||
* larger) allocations, and both the address and size must meet
|
||||
* alignment constraints.
|
||||
*/
|
||||
if (align < EFI_ALLOC_ALIGN)
|
||||
align = EFI_ALLOC_ALIGN;
|
||||
|
||||
size = round_up(size, EFI_ALLOC_ALIGN);
|
||||
nr_pages = size / EFI_PAGE_SIZE;
|
||||
for (i = 0; i < map->map_size / map->desc_size; i++) {
|
||||
efi_memory_desc_t *desc;
|
||||
unsigned long m = (unsigned long)map->map;
|
||||
u64 start, end;
|
||||
|
||||
desc = efi_memdesc_ptr(m, map->desc_size, i);
|
||||
|
||||
if (desc->type != EFI_CONVENTIONAL_MEMORY)
|
||||
continue;
|
||||
|
||||
if (desc->attribute & EFI_MEMORY_HOT_PLUGGABLE)
|
||||
continue;
|
||||
|
||||
if (efi_soft_reserve_enabled() &&
|
||||
(desc->attribute & EFI_MEMORY_SP))
|
||||
continue;
|
||||
|
||||
if (desc->num_pages < nr_pages)
|
||||
continue;
|
||||
|
||||
start = desc->phys_addr;
|
||||
end = start + desc->num_pages * EFI_PAGE_SIZE;
|
||||
|
||||
if (start < min)
|
||||
start = min;
|
||||
|
||||
start = round_up(start, align);
|
||||
if ((start + size) > end)
|
||||
continue;
|
||||
|
||||
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
|
||||
EFI_LOADER_DATA, nr_pages, &start);
|
||||
if (status == EFI_SUCCESS) {
|
||||
*addr = start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == map->map_size / map->desc_size)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* efi_relocate_kernel() - copy memory area
|
||||
* @image_addr: pointer to address of memory area to copy
|
||||
* @image_size: size of memory area to copy
|
||||
* @alloc_size: minimum size of memory to allocate, must be greater or
|
||||
* equal to image_size
|
||||
* @preferred_addr: preferred target address
|
||||
* @alignment: minimum alignment of the allocated memory area. It
|
||||
* should be a power of two.
|
||||
* @min_addr: minimum target address
|
||||
*
|
||||
* Copy a memory area to a newly allocated memory area aligned according
|
||||
* to @alignment but at least EFI_ALLOC_ALIGN. If the preferred address
|
||||
* is not available, the allocated address will not be below @min_addr.
|
||||
* On exit, @image_addr is updated to the target copy address that was used.
|
||||
*
|
||||
* This function is used to copy the Linux kernel verbatim. It does not apply
|
||||
* any relocation changes.
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
efi_status_t efi_relocate_kernel(unsigned long *image_addr,
|
||||
unsigned long image_size,
|
||||
unsigned long alloc_size,
|
||||
unsigned long preferred_addr,
|
||||
unsigned long alignment,
|
||||
unsigned long min_addr)
|
||||
{
|
||||
unsigned long cur_image_addr;
|
||||
unsigned long new_addr = 0;
|
||||
efi_status_t status;
|
||||
unsigned long nr_pages;
|
||||
efi_physical_addr_t efi_addr = preferred_addr;
|
||||
|
||||
if (!image_addr || !image_size || !alloc_size)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
if (alloc_size < image_size)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
cur_image_addr = *image_addr;
|
||||
|
||||
/*
|
||||
* The EFI firmware loader could have placed the kernel image
|
||||
* anywhere in memory, but the kernel has restrictions on the
|
||||
* max physical address it can run at. Some architectures
|
||||
* also have a preferred address, so first try to relocate
|
||||
* to the preferred address. If that fails, allocate as low
|
||||
* as possible while respecting the required alignment.
|
||||
*/
|
||||
nr_pages = round_up(alloc_size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
|
||||
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
|
||||
EFI_LOADER_DATA, nr_pages, &efi_addr);
|
||||
new_addr = efi_addr;
|
||||
/*
|
||||
* If preferred address allocation failed allocate as low as
|
||||
* possible.
|
||||
*/
|
||||
if (status != EFI_SUCCESS) {
|
||||
status = efi_low_alloc_above(alloc_size, alignment, &new_addr,
|
||||
min_addr);
|
||||
}
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate usable memory for kernel.\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* We know source/dest won't overlap since both memory ranges
|
||||
* have been allocated by UEFI, so we can safely use memcpy.
|
||||
*/
|
||||
memcpy((void *)new_addr, (void *)cur_image_addr, image_size);
|
||||
|
||||
/* Return the new address of the relocated image. */
|
||||
*image_addr = new_addr;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
@ -2839,8 +2839,12 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)
|
|||
* that checks whether the PSP is running. A solution for those issues
|
||||
* in the APU is to trigger a GPU reset, but this should be done during
|
||||
* the unload phase to avoid adding boot latency and screen flicker.
|
||||
* GFX V11 has GC block as default off IP. Every time AMDGPU driver sends
|
||||
* a request to PMFW to unload MP1, PMFW will put GC in reset and power down
|
||||
* the voltage. Hence, skipping reset for APUs with GFX V11 or later.
|
||||
*/
|
||||
if ((adev->flags & AMD_IS_APU) && !adev->gmc.is_app_apu) {
|
||||
if ((adev->flags & AMD_IS_APU) && !adev->gmc.is_app_apu &&
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0) < IP_VERSION(11, 0, 0)) {
|
||||
r = amdgpu_asic_reset(adev);
|
||||
if (r)
|
||||
dev_err(adev->dev, "asic reset on %s failed\n", __func__);
|
||||
|
|
|
|||
|
|
@ -3090,10 +3090,8 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
|
|||
case IP_VERSION(11, 5, 1):
|
||||
case IP_VERSION(11, 5, 2):
|
||||
case IP_VERSION(11, 5, 3):
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_0;
|
||||
break;
|
||||
case IP_VERSION(11, 5, 4):
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_4;
|
||||
adev->family = AMDGPU_FAMILY_GC_11_5_0;
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
|
|
|
|||
|
|
@ -3158,8 +3158,10 @@ static int __init amdgpu_init(void)
|
|||
amdgpu_register_atpx_handler();
|
||||
amdgpu_acpi_detect();
|
||||
|
||||
/* Ignore KFD init failures. Normal when CONFIG_HSA_AMD is not set. */
|
||||
amdgpu_amdkfd_init();
|
||||
/* Ignore KFD init failures when CONFIG_HSA_AMD is not set. */
|
||||
r = amdgpu_amdkfd_init();
|
||||
if (r && r != -ENOENT)
|
||||
goto error_fence;
|
||||
|
||||
if (amdgpu_pp_feature_mask & PP_OVERDRIVE_MASK) {
|
||||
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
|
||||
|
|
|
|||
|
|
@ -314,7 +314,10 @@ void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc,
|
|||
mc->gart_start = max_mc_address - mc->gart_size + 1;
|
||||
break;
|
||||
case AMDGPU_GART_PLACEMENT_LOW:
|
||||
mc->gart_start = 0;
|
||||
if (size_bf >= mc->gart_size)
|
||||
mc->gart_start = 0;
|
||||
else
|
||||
mc->gart_start = ALIGN(mc->fb_end, four_gb);
|
||||
break;
|
||||
case AMDGPU_GART_PLACEMENT_BEST_FIT:
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -873,68 +873,59 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|||
? -EFAULT : 0;
|
||||
}
|
||||
case AMDGPU_INFO_READ_MMR_REG: {
|
||||
int ret = 0;
|
||||
unsigned int n, alloc_size;
|
||||
uint32_t *regs;
|
||||
unsigned int se_num = (info->read_mmr_reg.instance >>
|
||||
AMDGPU_INFO_MMR_SE_INDEX_SHIFT) &
|
||||
AMDGPU_INFO_MMR_SE_INDEX_MASK;
|
||||
unsigned int sh_num = (info->read_mmr_reg.instance >>
|
||||
AMDGPU_INFO_MMR_SH_INDEX_SHIFT) &
|
||||
AMDGPU_INFO_MMR_SH_INDEX_MASK;
|
||||
|
||||
if (!down_read_trylock(&adev->reset_domain->sem))
|
||||
return -ENOENT;
|
||||
unsigned int alloc_size;
|
||||
uint32_t *regs;
|
||||
int ret;
|
||||
|
||||
/* set full masks if the userspace set all bits
|
||||
* in the bitfields
|
||||
*/
|
||||
if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK) {
|
||||
if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK)
|
||||
se_num = 0xffffffff;
|
||||
} else if (se_num >= AMDGPU_GFX_MAX_SE) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
else if (se_num >= AMDGPU_GFX_MAX_SE)
|
||||
return -EINVAL;
|
||||
|
||||
if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK) {
|
||||
if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK)
|
||||
sh_num = 0xffffffff;
|
||||
} else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE)
|
||||
return -EINVAL;
|
||||
|
||||
if (info->read_mmr_reg.count > 128) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (info->read_mmr_reg.count > 128)
|
||||
return -EINVAL;
|
||||
|
||||
regs = kmalloc_array(info->read_mmr_reg.count, sizeof(*regs), GFP_KERNEL);
|
||||
if (!regs) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
regs = kmalloc_array(info->read_mmr_reg.count, sizeof(*regs),
|
||||
GFP_KERNEL);
|
||||
if (!regs)
|
||||
return -ENOMEM;
|
||||
|
||||
down_read(&adev->reset_domain->sem);
|
||||
alloc_size = info->read_mmr_reg.count * sizeof(*regs);
|
||||
|
||||
amdgpu_gfx_off_ctrl(adev, false);
|
||||
ret = 0;
|
||||
for (i = 0; i < info->read_mmr_reg.count; i++) {
|
||||
if (amdgpu_asic_read_register(adev, se_num, sh_num,
|
||||
info->read_mmr_reg.dword_offset + i,
|
||||
®s[i])) {
|
||||
DRM_DEBUG_KMS("unallowed offset %#x\n",
|
||||
info->read_mmr_reg.dword_offset + i);
|
||||
kfree(regs);
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
amdgpu_gfx_off_ctrl(adev, true);
|
||||
n = copy_to_user(out, regs, min(size, alloc_size));
|
||||
kfree(regs);
|
||||
ret = (n ? -EFAULT : 0);
|
||||
out:
|
||||
up_read(&adev->reset_domain->sem);
|
||||
|
||||
if (!ret) {
|
||||
ret = copy_to_user(out, regs, min(size, alloc_size))
|
||||
? -EFAULT : 0;
|
||||
}
|
||||
kfree(regs);
|
||||
return ret;
|
||||
}
|
||||
case AMDGPU_INFO_DEV_INFO: {
|
||||
|
|
|
|||
|
|
@ -1950,7 +1950,7 @@ void amdgpu_ras_check_bad_page_status(struct amdgpu_device *adev)
|
|||
if (!control || amdgpu_bad_page_threshold == 0)
|
||||
return;
|
||||
|
||||
if (control->ras_num_bad_pages >= ras->bad_page_cnt_threshold) {
|
||||
if (control->ras_num_bad_pages > ras->bad_page_cnt_threshold) {
|
||||
if (amdgpu_dpm_send_rma_reason(adev))
|
||||
dev_warn(adev->dev, "Unable to send out-of-band RMA CPER");
|
||||
else
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev,
|
|||
unsigned int type,
|
||||
uint64_t size_in_page)
|
||||
{
|
||||
if (!size_in_page)
|
||||
return 0;
|
||||
|
||||
return ttm_range_man_init(&adev->mman.bdev, type,
|
||||
false, size_in_page);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,6 +205,19 @@ void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue)
|
|||
msecs_to_jiffies(timeout_ms));
|
||||
}
|
||||
|
||||
void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell)
|
||||
{
|
||||
struct xarray *xa = &adev->userq_doorbell_xa;
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(xa, flags);
|
||||
queue = xa_load(xa, doorbell);
|
||||
if (queue)
|
||||
amdgpu_userq_fence_driver_process(queue->fence_drv);
|
||||
xa_unlock_irqrestore(xa, flags);
|
||||
}
|
||||
|
||||
static void amdgpu_userq_init_hang_detect_work(struct amdgpu_usermode_queue *queue)
|
||||
{
|
||||
INIT_DELAYED_WORK(&queue->hang_detect_work, amdgpu_userq_hang_detect_work);
|
||||
|
|
@ -643,12 +656,6 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
|
|||
#endif
|
||||
amdgpu_userq_detect_and_reset_queues(uq_mgr);
|
||||
r = amdgpu_userq_unmap_helper(queue);
|
||||
/*TODO: It requires a reset for userq hw unmap error*/
|
||||
if (r) {
|
||||
drm_warn(adev_to_drm(uq_mgr->adev), "trying to destroy a HW mapping userq\n");
|
||||
queue->state = AMDGPU_USERQ_STATE_HUNG;
|
||||
}
|
||||
|
||||
atomic_dec(&uq_mgr->userq_count[queue->queue_type]);
|
||||
amdgpu_userq_cleanup(queue);
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
|
|
@ -1187,7 +1194,7 @@ amdgpu_userq_vm_validate(struct amdgpu_userq_mgr *uq_mgr)
|
|||
bo = range->bo;
|
||||
ret = amdgpu_ttm_tt_get_user_pages(bo, range);
|
||||
if (ret)
|
||||
goto unlock_all;
|
||||
goto free_ranges;
|
||||
}
|
||||
|
||||
invalidated = true;
|
||||
|
|
@ -1214,6 +1221,7 @@ amdgpu_userq_vm_validate(struct amdgpu_userq_mgr *uq_mgr)
|
|||
|
||||
unlock_all:
|
||||
drm_exec_fini(&exec);
|
||||
free_ranges:
|
||||
xa_for_each(&xa, tmp_key, range) {
|
||||
if (!range)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ void amdgpu_userq_reset_work(struct work_struct *work);
|
|||
void amdgpu_userq_pre_reset(struct amdgpu_device *adev);
|
||||
int amdgpu_userq_post_reset(struct amdgpu_device *adev, bool vram_lost);
|
||||
void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue);
|
||||
void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell);
|
||||
|
||||
int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
|
||||
struct amdgpu_usermode_queue *queue,
|
||||
|
|
|
|||
|
|
@ -3023,11 +3023,22 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
|||
|
||||
is_compute_context = vm->is_compute_context;
|
||||
|
||||
if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
|
||||
node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
|
||||
if (is_compute_context) {
|
||||
/* Unreserve root since svm_range_restore_pages might try to reserve it. */
|
||||
/* TODO: rework svm_range_restore_pages so that this isn't necessary. */
|
||||
amdgpu_bo_unreserve(root);
|
||||
|
||||
if (!svm_range_restore_pages(adev, pasid, vmid,
|
||||
node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
|
||||
amdgpu_bo_unref(&root);
|
||||
return true;
|
||||
}
|
||||
amdgpu_bo_unref(&root);
|
||||
return true;
|
||||
|
||||
/* Re-acquire the VM lock, could be that the VM was freed in between. */
|
||||
vm = amdgpu_vm_lock_by_pasid(adev, &root, pasid);
|
||||
if (!vm)
|
||||
return false;
|
||||
}
|
||||
|
||||
addr /= AMDGPU_GPU_PAGE_SIZE;
|
||||
|
|
|
|||
|
|
@ -6523,15 +6523,7 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
|
|||
DRM_DEBUG("IH: CP EOP\n");
|
||||
|
||||
if (adev->enable_mes && doorbell_offset) {
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
struct xarray *xa = &adev->userq_doorbell_xa;
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(xa, flags);
|
||||
queue = xa_load(xa, doorbell_offset);
|
||||
if (queue)
|
||||
amdgpu_userq_fence_driver_process(queue->fence_drv);
|
||||
xa_unlock_irqrestore(xa, flags);
|
||||
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
|
||||
} else {
|
||||
me_id = (entry->ring_id & 0x0c) >> 2;
|
||||
pipe_id = (entry->ring_id & 0x03) >> 0;
|
||||
|
|
|
|||
|
|
@ -4854,15 +4854,7 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
|
|||
DRM_DEBUG("IH: CP EOP\n");
|
||||
|
||||
if (adev->enable_mes && doorbell_offset) {
|
||||
struct xarray *xa = &adev->userq_doorbell_xa;
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(xa, flags);
|
||||
queue = xa_load(xa, doorbell_offset);
|
||||
if (queue)
|
||||
amdgpu_userq_fence_driver_process(queue->fence_drv);
|
||||
xa_unlock_irqrestore(xa, flags);
|
||||
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
|
||||
} else {
|
||||
me_id = (entry->ring_id & 0x0c) >> 2;
|
||||
pipe_id = (entry->ring_id & 0x03) >> 0;
|
||||
|
|
|
|||
|
|
@ -3643,16 +3643,7 @@ static int gfx_v12_1_eop_irq(struct amdgpu_device *adev,
|
|||
DRM_DEBUG("IH: CP EOP\n");
|
||||
|
||||
if (adev->enable_mes && doorbell_offset) {
|
||||
struct xarray *xa = &adev->userq_doorbell_xa;
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
unsigned long flags;
|
||||
|
||||
xa_lock_irqsave(xa, flags);
|
||||
queue = xa_load(xa, doorbell_offset);
|
||||
if (queue)
|
||||
amdgpu_userq_fence_driver_process(queue->fence_drv);
|
||||
|
||||
xa_unlock_irqrestore(xa, flags);
|
||||
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
|
||||
} else {
|
||||
me_id = (entry->ring_id & 0x0c) >> 2;
|
||||
pipe_id = (entry->ring_id & 0x03) >> 0;
|
||||
|
|
|
|||
|
|
@ -1571,6 +1571,71 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev)
|
|||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfx_v6_0_setup_tcc() - setup which TCCs are used
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Verify whether the current GPU has any TCCs disabled,
|
||||
* which can happen when the GPU is harvested and some
|
||||
* memory channels are disabled, reducing the memory bus width.
|
||||
* For example, on the Radeon HD 7870 XT (Tahiti LE).
|
||||
*
|
||||
* If some TCCs are disabled, we need to make sure that
|
||||
* the disabled TCCs are not used, and the remaining TCCs
|
||||
* are used optimally.
|
||||
*
|
||||
* TCP_CHAN_STEER_LO/HI control which TCC is used by TCP channels.
|
||||
* TCP_ADDR_CONFIG.NUM_TCC_BANKS controls how many channels are used.
|
||||
*
|
||||
* For optimal performance:
|
||||
* - Rely on the CHAN_STEER from the golden registers table,
|
||||
* only skip disabled TCCs but keep the mapping order.
|
||||
* - Limit NUM_TCC_BANKS to number of active TCCs to avoid thrashing,
|
||||
* which performs better than using the same TCC twice.
|
||||
*/
|
||||
static void gfx_v6_0_setup_tcc(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 i, tcc, tcp_addr_config, num_active_tcc = 0;
|
||||
u64 chan_steer, patched_chan_steer = 0;
|
||||
const u32 num_max_tcc = adev->gfx.config.max_texture_channel_caches;
|
||||
const u32 dis_tcc_mask =
|
||||
amdgpu_gfx_create_bitmask(num_max_tcc) &
|
||||
(REG_GET_FIELD(RREG32(mmCGTS_TCC_DISABLE),
|
||||
CGTS_TCC_DISABLE, TCC_DISABLE) |
|
||||
REG_GET_FIELD(RREG32(mmCGTS_USER_TCC_DISABLE),
|
||||
CGTS_USER_TCC_DISABLE, TCC_DISABLE));
|
||||
|
||||
/* When no TCC is disabled, the golden registers table already has optimal TCC setup */
|
||||
if (!dis_tcc_mask)
|
||||
return;
|
||||
|
||||
/* Each 4-bit nibble contains the index of a TCC used by all TCPs */
|
||||
chan_steer = RREG32(mmTCP_CHAN_STEER_LO) | ((u64)RREG32(mmTCP_CHAN_STEER_HI) << 32ull);
|
||||
|
||||
/* Patch the TCP to TCC mapping to skip disabled TCCs */
|
||||
for (i = 0; i < num_max_tcc; ++i) {
|
||||
tcc = (chan_steer >> (u64)(4 * i)) & 0xf;
|
||||
|
||||
if (!((1 << tcc) & dis_tcc_mask)) {
|
||||
/* Copy enabled TCC indices to the patched register value. */
|
||||
patched_chan_steer |= (u64)tcc << (u64)(4 * num_active_tcc);
|
||||
++num_active_tcc;
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON(num_active_tcc != num_max_tcc - hweight32(dis_tcc_mask));
|
||||
|
||||
/* Patch number of TCCs used by TCPs */
|
||||
tcp_addr_config = REG_SET_FIELD(RREG32(mmTCP_ADDR_CONFIG),
|
||||
TCP_ADDR_CONFIG, NUM_TCC_BANKS,
|
||||
num_active_tcc - 1);
|
||||
|
||||
WREG32(mmTCP_ADDR_CONFIG, tcp_addr_config);
|
||||
WREG32(mmTCP_CHAN_STEER_HI, upper_32_bits(patched_chan_steer));
|
||||
WREG32(mmTCP_CHAN_STEER_LO, lower_32_bits(patched_chan_steer));
|
||||
}
|
||||
|
||||
static void gfx_v6_0_config_init(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->gfx.config.double_offchip_lds_buf = 0;
|
||||
|
|
@ -1729,6 +1794,7 @@ static void gfx_v6_0_constants_init(struct amdgpu_device *adev)
|
|||
gfx_v6_0_tiling_mode_table_init(adev);
|
||||
|
||||
gfx_v6_0_setup_rb(adev);
|
||||
gfx_v6_0_setup_tcc(adev);
|
||||
|
||||
gfx_v6_0_setup_spi(adev);
|
||||
|
||||
|
|
|
|||
|
|
@ -802,6 +802,7 @@ static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v2_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v2_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v2_0_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -693,6 +693,7 @@ static const struct amd_ip_funcs jpeg_v2_6_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v2_5_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v2_5_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v2_5_dec_ring_set_wptr,
|
||||
|
|
@ -724,6 +725,7 @@ static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v2_6_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v2_5_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v2_5_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v2_5_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -594,6 +594,7 @@ static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v3_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v3_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v3_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v3_0_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -759,6 +759,7 @@ static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v4_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v4_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v4_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v4_0_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -1219,6 +1219,7 @@ static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v4_0_3_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v4_0_3_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v4_0_3_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v4_0_3_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -804,6 +804,7 @@ static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v4_0_5_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v4_0_5_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v4_0_5_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v4_0_5_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -680,6 +680,7 @@ static const struct amd_ip_funcs jpeg_v5_0_0_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v5_0_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v5_0_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v5_0_0_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -884,6 +884,7 @@ static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v5_0_1_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v5_0_1_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v5_0_1_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v5_0_1_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -703,6 +703,7 @@ static const struct amd_ip_funcs jpeg_v5_0_2_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v5_0_2_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v5_0_2_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v5_0_2_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v5_0_2_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -661,6 +661,7 @@ static const struct amd_ip_funcs jpeg_v5_3_0_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs jpeg_v5_3_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_JPEG,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = jpeg_v5_3_0_dec_ring_get_rptr,
|
||||
.get_wptr = jpeg_v5_3_0_dec_ring_get_wptr,
|
||||
.set_wptr = jpeg_v5_3_0_dec_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -1662,17 +1662,8 @@ static int sdma_v6_0_process_fence_irq(struct amdgpu_device *adev,
|
|||
u32 doorbell_offset = entry->src_data[0];
|
||||
|
||||
if (adev->enable_mes && doorbell_offset) {
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
struct xarray *xa = &adev->userq_doorbell_xa;
|
||||
unsigned long flags;
|
||||
|
||||
doorbell_offset >>= SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
|
||||
|
||||
xa_lock_irqsave(xa, flags);
|
||||
queue = xa_load(xa, doorbell_offset);
|
||||
if (queue)
|
||||
amdgpu_userq_fence_driver_process(queue->fence_drv);
|
||||
xa_unlock_irqrestore(xa, flags);
|
||||
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1594,17 +1594,8 @@ static int sdma_v7_0_process_fence_irq(struct amdgpu_device *adev,
|
|||
u32 doorbell_offset = entry->src_data[0];
|
||||
|
||||
if (adev->enable_mes && doorbell_offset) {
|
||||
struct xarray *xa = &adev->userq_doorbell_xa;
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
unsigned long flags;
|
||||
|
||||
doorbell_offset >>= SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
|
||||
|
||||
xa_lock_irqsave(xa, flags);
|
||||
queue = xa_load(xa, doorbell_offset);
|
||||
if (queue)
|
||||
amdgpu_userq_fence_driver_process(queue->fence_drv);
|
||||
xa_unlock_irqrestore(xa, flags);
|
||||
amdgpu_userq_process_fence_irq(adev, doorbell_offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -242,6 +242,10 @@ static void uvd_v3_1_mc_resume(struct amdgpu_device *adev)
|
|||
uint64_t addr;
|
||||
uint32_t size;
|
||||
|
||||
/* When the keyselect is already set, don't perturb it. */
|
||||
if (RREG32(mmUVD_FW_START))
|
||||
return;
|
||||
|
||||
/* program the VCPU memory controller bits 0-27 */
|
||||
addr = (adev->uvd.inst->gpu_addr + AMDGPU_UVD_FIRMWARE_OFFSET) >> 3;
|
||||
size = AMDGPU_UVD_FIRMWARE_SIZE(adev) >> 3;
|
||||
|
|
@ -284,6 +288,12 @@ static int uvd_v3_1_fw_validate(struct amdgpu_device *adev)
|
|||
int i;
|
||||
uint32_t keysel = adev->uvd.keyselect;
|
||||
|
||||
if (RREG32(mmUVD_FW_START) & UVD_FW_STATUS__PASS_MASK) {
|
||||
dev_dbg(adev->dev, "UVD keyselect already set: 0x%x (on CPU: 0x%x)\n",
|
||||
RREG32(mmUVD_FW_START), adev->uvd.keyselect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
WREG32(mmUVD_FW_START, keysel);
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
|
|
|
|||
|
|
@ -2113,6 +2113,7 @@ static const struct amd_ip_funcs vcn_v2_0_ip_funcs = {
|
|||
static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_DEC,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.secure_submission_supported = true,
|
||||
.get_rptr = vcn_v2_0_dec_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_0_dec_ring_get_wptr,
|
||||
|
|
@ -2145,6 +2146,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v2_0_enc_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_0_enc_ring_get_wptr,
|
||||
.set_wptr = vcn_v2_0_enc_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -1778,6 +1778,7 @@ static void vcn_v2_5_dec_ring_set_wptr(struct amdgpu_ring *ring)
|
|||
static const struct amdgpu_ring_funcs vcn_v2_5_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_DEC,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.secure_submission_supported = true,
|
||||
.get_rptr = vcn_v2_5_dec_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_5_dec_ring_get_wptr,
|
||||
|
|
@ -1879,6 +1880,7 @@ static const struct amdgpu_ring_funcs vcn_v2_5_enc_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v2_5_enc_ring_get_rptr,
|
||||
.get_wptr = vcn_v2_5_enc_ring_get_wptr,
|
||||
.set_wptr = vcn_v2_5_enc_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -1856,6 +1856,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_dec_sw_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_DEC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_DEC_SW_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.secure_submission_supported = true,
|
||||
.get_rptr = vcn_v3_0_dec_ring_get_rptr,
|
||||
.get_wptr = vcn_v3_0_dec_ring_get_wptr,
|
||||
|
|
@ -1972,6 +1973,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
|||
|
||||
for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
|
||||
uint32_t offset, size, *create;
|
||||
uint64_t buf_end;
|
||||
|
||||
if (msg[0] != RDECODE_MESSAGE_CREATE)
|
||||
continue;
|
||||
|
|
@ -1979,7 +1981,8 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
|||
offset = msg[1];
|
||||
size = msg[2];
|
||||
|
||||
if (size < 4 || offset + size > end - addr) {
|
||||
if (size < 4 || check_add_overflow(offset, size, &buf_end) ||
|
||||
buf_end > end - addr) {
|
||||
DRM_ERROR("VCN message buffer exceeds BO bounds!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
|
|
@ -2036,6 +2039,7 @@ static int vcn_v3_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
|
|||
static const struct amdgpu_ring_funcs vcn_v3_0_dec_ring_vm_funcs = {
|
||||
.type = AMDGPU_RING_TYPE_VCN_DEC,
|
||||
.align_mask = 0xf,
|
||||
.no_user_fence = true,
|
||||
.secure_submission_supported = true,
|
||||
.get_rptr = vcn_v3_0_dec_ring_get_rptr,
|
||||
.get_wptr = vcn_v3_0_dec_ring_get_wptr,
|
||||
|
|
@ -2138,6 +2142,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_enc_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v3_0_enc_ring_get_rptr,
|
||||
.get_wptr = vcn_v3_0_enc_ring_get_wptr,
|
||||
.set_wptr = vcn_v3_0_enc_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -1889,6 +1889,7 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
|||
|
||||
for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
|
||||
uint32_t offset, size, *create;
|
||||
uint64_t buf_end;
|
||||
|
||||
if (msg[0] != RDECODE_MESSAGE_CREATE)
|
||||
continue;
|
||||
|
|
@ -1896,7 +1897,8 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job,
|
|||
offset = msg[1];
|
||||
size = msg[2];
|
||||
|
||||
if (size < 4 || offset + size > end - addr) {
|
||||
if (size < 4 || check_add_overflow(offset, size, &buf_end) ||
|
||||
buf_end > end - addr) {
|
||||
DRM_ERROR("VCN message buffer exceeds BO bounds!\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
|
|
@ -1994,6 +1996,7 @@ static struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.extra_bytes = sizeof(struct amdgpu_vcn_rb_metadata),
|
||||
.get_rptr = vcn_v4_0_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v4_0_unified_ring_get_wptr,
|
||||
|
|
|
|||
|
|
@ -1775,6 +1775,7 @@ static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v4_0_3_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v4_0_3_unified_ring_get_wptr,
|
||||
.set_wptr = vcn_v4_0_3_unified_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -1483,6 +1483,7 @@ static struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v4_0_5_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v4_0_5_unified_ring_get_wptr,
|
||||
.set_wptr = vcn_v4_0_5_unified_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -1207,6 +1207,7 @@ static const struct amdgpu_ring_funcs vcn_v5_0_0_unified_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v5_0_0_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v5_0_0_unified_ring_get_wptr,
|
||||
.set_wptr = vcn_v5_0_0_unified_ring_set_wptr,
|
||||
|
|
|
|||
|
|
@ -1419,6 +1419,7 @@ static const struct amdgpu_ring_funcs vcn_v5_0_1_unified_ring_vm_funcs = {
|
|||
.type = AMDGPU_RING_TYPE_VCN_ENC,
|
||||
.align_mask = 0x3f,
|
||||
.nop = VCN_ENC_CMD_NO_OP,
|
||||
.no_user_fence = true,
|
||||
.get_rptr = vcn_v5_0_1_unified_ring_get_rptr,
|
||||
.get_wptr = vcn_v5_0_1_unified_ring_get_wptr,
|
||||
.set_wptr = vcn_v5_0_1_unified_ring_set_wptr,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user