Merge v7.0-rc7 into drm-next

Thomas Zimmermann needs 2f42c1a616 ("drm/ast: dp501: Fix
initialization of SCU2C") for drm-misc-next.

Conflicts:
- drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c

Just between e927b36ae1 ("drm/amd/display: Fix NULL pointer
dereference in dcn401_init_hw()") and it's cherry-pick that confused
git.

- drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c

Deleted in 6b0a611628 ("drm/amd/pm: Unify version check in SMUv11")
but some cherry-picks confused git. Same for v12/v14.

Signed-off-by: Simona Vetter <simona.vetter@ffwll.ch>
This commit is contained in:
Simona Vetter
2026-04-07 12:27:36 +02:00
344 changed files with 5332 additions and 1775 deletions

View File

@@ -1,6 +1,7 @@
Alan Cox <alan@lxorguk.ukuu.org.uk>
Alan Cox <root@hraefn.swansea.linux.org.uk>
Alyssa Rosenzweig <alyssa@rosenzweig.io>
Askar Safin <safinaskar@gmail.com>
Christoph Hellwig <hch@lst.de>
Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Marc Gonzalez <marc.w.gonzalez@free.fr>

View File

@@ -66,7 +66,7 @@ then:
required:
- refresh-rate-hz
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@@ -301,6 +301,7 @@ properties:
maxItems: 4
dependencies:
pd-disable: [typec-power-opmode]
sink-vdos-v1: [ sink-vdos ]
sink-vdos: [ sink-vdos-v1 ]

View File

@@ -37,7 +37,7 @@ properties:
const: 2
"#interrupt-cells":
const: 1
const: 2
ngpios:
description:
@@ -86,7 +86,7 @@ examples:
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <1>;
#interrupt-cells = <2>;
interrupts = <53>, <53>, <53>, <53>,
<53>, <53>, <53>, <53>,
<53>, <53>, <53>, <53>,

View File

@@ -5,8 +5,138 @@ Security bugs
Linux kernel developers take security very seriously. As such, we'd
like to know when a security bug is found so that it can be fixed and
disclosed as quickly as possible. Please report security bugs to the
Linux kernel security team.
disclosed as quickly as possible.
Preparing your report
---------------------
Like with any bug report, a security bug report requires a lot of analysis work
from the developers, so the more information you can share about the issue, the
better. Please review the procedure outlined in
Documentation/admin-guide/reporting-issues.rst if you are unclear about what
information is helpful. The following information are absolutely necessary in
**any** security bug report:
* **affected kernel version range**: with no version indication, your report
will not be processed. A significant part of reports are for bugs that
have already been fixed, so it is extremely important that vulnerabilities
are verified on recent versions (development tree or latest stable
version), at least by verifying that the code has not changed since the
version where it was detected.
* **description of the problem**: a detailed description of the problem, with
traces showing its manifestation, and why you consider that the observed
behavior as a problem in the kernel, is necessary.
* **reproducer**: developers will need to be able to reproduce the problem to
consider a fix as effective. This includes both a way to trigger the issue
and a way to confirm it happens. A reproducer with low complexity
dependencies will be needed (source code, shell script, sequence of
instructions, file-system image etc). Binary-only executables are not
accepted. Working exploits are extremely helpful and will not be released
without consent from the reporter, unless they are already public. By
definition if an issue cannot be reproduced, it is not exploitable, thus it
is not a security bug.
* **conditions**: if the bug depends on certain configuration options,
sysctls, permissions, timing, code modifications etc, these should be
indicated.
In addition, the following information are highly desirable:
* **suspected location of the bug**: the file names and functions where the
bug is suspected to be present are very important, at least to help forward
the report to the appropriate maintainers. When not possible (for example,
"system freezes each time I run this command"), the security team will help
identify the source of the bug.
* **a proposed fix**: bug reporters who have analyzed the cause of a bug in
the source code almost always have an accurate idea on how to fix it,
because they spent a long time studying it and its implications. Proposing
a tested fix will save maintainers a lot of time, even if the fix ends up
not being the right one, because it helps understand the bug. When
proposing a tested fix, please always format it in a way that can be
immediately merged (see Documentation/process/submitting-patches.rst).
This will save some back-and-forth exchanges if it is accepted, and you
will be credited for finding and fixing this issue. Note that in this case
only a ``Signed-off-by:`` tag is needed, without ``Reported-by:`` when the
reporter and author are the same.
* **mitigations**: very often during a bug analysis, some ways of mitigating
the issue appear. It is useful to share them, as they can be helpful to
keep end users protected during the time it takes them to apply the fix.
Identifying contacts
--------------------
The most effective way to report a security bug is to send it directly to the
affected subsystem's maintainers and Cc: the Linux kernel security team. Do
not send it to a public list at this stage, unless you have good reasons to
consider the issue as being public or trivial to discover (e.g. result of a
widely available automated vulnerability scanning tool that can be repeated by
anyone).
If you're sending a report for issues affecting multiple parts in the kernel,
even if they're fairly similar issues, please send individual messages (think
that maintainers will not all work on the issues at the same time). The only
exception is when an issue concerns closely related parts maintained by the
exact same subset of maintainers, and these parts are expected to be fixed all
at once by the same commit, then it may be acceptable to report them at once.
One difficulty for most first-time reporters is to figure the right list of
recipients to send a report to. In the Linux kernel, all official maintainers
are trusted, so the consequences of accidentally including the wrong maintainer
are essentially a bit more noise for that person, i.e. nothing dramatic. As
such, a suitable method to figure the list of maintainers (which kernel
security officers use) is to rely on the get_maintainer.pl script, tuned to
only report maintainers. This script, when passed a file name, will look for
its path in the MAINTAINERS file to figure a hierarchical list of relevant
maintainers. Calling it a first time with the finest level of filtering will
most of the time return a short list of this specific file's maintainers::
$ ./scripts/get_maintainer.pl --no-l --no-r --pattern-depth 1 \
drivers/example.c
Developer One <dev1@example.com> (maintainer:example driver)
Developer Two <dev2@example.org> (maintainer:example driver)
These two maintainers should then receive the message. If the command does not
return anything, it means the affected file is part of a wider subsystem, so we
should be less specific::
$ ./scripts/get_maintainer.pl --no-l --no-r drivers/example.c
Developer One <dev1@example.com> (maintainer:example subsystem)
Developer Two <dev2@example.org> (maintainer:example subsystem)
Developer Three <dev3@example.com> (maintainer:example subsystem [GENERAL])
Developer Four <dev4@example.org> (maintainer:example subsystem [GENERAL])
Here, picking the first, most specific ones, is sufficient. When the list is
long, it is possible to produce a comma-delimited e-mail address list on a
single line suitable for use in the To: field of a mailer like this::
$ ./scripts/get_maintainer.pl --no-tree --no-l --no-r --no-n --m \
--no-git-fallback --no-substatus --no-rolestats --no-multiline \
--pattern-depth 1 drivers/example.c
dev1@example.com, dev2@example.org
or this for the wider list::
$ ./scripts/get_maintainer.pl --no-tree --no-l --no-r --no-n --m \
--no-git-fallback --no-substatus --no-rolestats --no-multiline \
drivers/example.c
dev1@example.com, dev2@example.org, dev3@example.com, dev4@example.org
If at this point you're still facing difficulties spotting the right
maintainers, **and only in this case**, it's possible to send your report to
the Linux kernel security team only. Your message will be triaged, and you
will receive instructions about whom to contact, if needed. Your message may
equally be forwarded as-is to the relevant maintainers.
Sending the report
------------------
Reports are to be sent over e-mail exclusively. Please use a working e-mail
address, preferably the same that you want to appear in ``Reported-by`` tags
if any. If unsure, send your report to yourself first.
The security team and maintainers almost always require additional
information beyond what was initially provided in a report and rely on
@@ -18,20 +148,12 @@ run additional tests. Reports where the reporter does not respond promptly
or cannot effectively discuss their findings may be abandoned if the
communication does not quickly improve.
As it is with any bug, the more information provided the easier it
will be to diagnose and fix. Please review the procedure outlined in
'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what
information is helpful. Any exploit code is very helpful and will not
be released without consent from the reporter unless it has already been
made public.
The report must be sent to maintainers, with the security team in ``Cc:``.
The Linux kernel security team can be contacted by email at
<security@kernel.org>. This is a private list of security officers
who will help verify the bug report and develop and release a fix.
If you already have a fix, please include it with your report, as
that can speed up the process considerably. It is possible that the
security team will bring in extra help from area maintainers to
understand and fix the security vulnerability.
who will help verify the bug report and assist developers working on a fix.
It is possible that the security team will bring in extra help from area
maintainers to understand and fix the security vulnerability.
Please send **plain text** emails without attachments where possible.
It is much harder to have a context-quoted discussion about a complex
@@ -42,7 +164,9 @@ reproduction steps, and follow it with a proposed fix, all in plain text.
Markdown, HTML and RST formatted reports are particularly frowned upon since
they're quite hard to read for humans and encourage to use dedicated viewers,
sometimes online, which by definition is not acceptable for a confidential
security report.
security report. Note that some mailers tend to mangle formatting of plain
text by default, please consult Documentation/process/email-clients.rst for
more info.
Disclosure and embargoed information
------------------------------------

View File

@@ -2,7 +2,7 @@
VERSION = 7
PATCHLEVEL = 0
SUBLEVEL = 0
EXTRAVERSION = -rc6
EXTRAVERSION = -rc7
NAME = Baby Opossum Posse
# *DOCUMENTATION*

View File

@@ -252,6 +252,7 @@ config ARM64
select HAVE_RSEQ
select HAVE_RUST if RUSTC_SUPPORTS_ARM64
select HAVE_STACKPROTECTOR
select HAVE_STATIC_CALL if CFI
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES

View File

@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_STATIC_CALL_H
#define _ASM_STATIC_CALL_H
#define __ARCH_DEFINE_STATIC_CALL_TRAMP(name, target) \
asm(" .pushsection .static_call.text, \"ax\" \n" \
" .align 4 \n" \
" .globl " name " \n" \
name ": \n" \
" hint 34 /* BTI C */ \n" \
" adrp x16, 1f \n" \
" ldr x16, [x16, :lo12:1f] \n" \
" br x16 \n" \
" .type " name ", %function \n" \
" .size " name ", . - " name " \n" \
" .popsection \n" \
" .pushsection .rodata, \"a\" \n" \
" .align 3 \n" \
"1: .quad " target " \n" \
" .popsection \n")
#define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func) \
__ARCH_DEFINE_STATIC_CALL_TRAMP(STATIC_CALL_TRAMP_STR(name), #func)
#define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) \
ARCH_DEFINE_STATIC_CALL_TRAMP(name, __static_call_return0)
#define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name) \
ARCH_DEFINE_STATIC_CALL_TRAMP(name, __static_call_return0)
#endif /* _ASM_STATIC_CALL_H */

View File

@@ -46,6 +46,7 @@ obj-$(CONFIG_MODULES) += module.o module-plts.o
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
obj-$(CONFIG_HARDLOCKUP_DETECTOR_PERF) += watchdog_hld.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_HAVE_STATIC_CALL) += static_call.o
obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_EFI) += efi.o efi-rt-wrapper.o

View File

@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/static_call.h>
#include <linux/memory.h>
#include <asm/text-patching.h>
void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
{
u64 literal;
int ret;
if (!func)
func = __static_call_return0;
/* decode the instructions to discover the literal address */
literal = ALIGN_DOWN((u64)tramp + 4, SZ_4K) +
aarch64_insn_adrp_get_offset(le32_to_cpup(tramp + 4)) +
8 * aarch64_insn_decode_immediate(AARCH64_INSN_IMM_12,
le32_to_cpup(tramp + 8));
ret = aarch64_insn_write_literal_u64((void *)literal, (u64)func);
WARN_ON_ONCE(ret);
}
EXPORT_SYMBOL_GPL(arch_static_call_transform);

View File

@@ -191,6 +191,7 @@ SECTIONS
LOCK_TEXT
KPROBES_TEXT
HYPERVISOR_TEXT
STATIC_CALL_TEXT
*(.gnu.warning)
}

View File

@@ -484,7 +484,6 @@
# endif
# ifndef cpu_vmbits
# define cpu_vmbits cpu_data[0].vmbits
# define __NEED_VMBITS_PROBE
# endif
#endif

View File

@@ -80,9 +80,7 @@ struct cpuinfo_mips {
int srsets; /* Shadow register sets */
int package;/* physical package number */
unsigned int globalnumber;
#ifdef CONFIG_64BIT
int vmbits; /* Virtual memory size in bits */
#endif
void *data; /* Additional data */
unsigned int watch_reg_count; /* Number that exist */
unsigned int watch_reg_use_cnt; /* Usable by ptrace */

View File

@@ -1871,6 +1871,8 @@ do { \
#define read_c0_entryhi() __read_ulong_c0_register($10, 0)
#define write_c0_entryhi(val) __write_ulong_c0_register($10, 0, val)
#define read_c0_entryhi_64() __read_64bit_c0_register($10, 0)
#define write_c0_entryhi_64(val) __write_64bit_c0_register($10, 0, val)
#define read_c0_guestctl1() __read_32bit_c0_register($10, 4)
#define write_c0_guestctl1(val) __write_32bit_c0_register($10, 4, val)

View File

@@ -210,11 +210,14 @@ static inline void set_elf_base_platform(const char *plat)
static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
{
#ifdef __NEED_VMBITS_PROBE
write_c0_entryhi(0x3fffffffffffe000ULL);
back_to_back_c0_hazard();
c->vmbits = fls64(read_c0_entryhi() & 0x3fffffffffffe000ULL);
#endif
int vmbits = 31;
if (cpu_has_64bits) {
write_c0_entryhi_64(0x3fffffffffffe000ULL);
back_to_back_c0_hazard();
vmbits = fls64(read_c0_entryhi_64() & 0x3fffffffffffe000ULL);
}
c->vmbits = vmbits;
}
static void set_isa(struct cpuinfo_mips *c, unsigned int isa)

View File

@@ -137,6 +137,8 @@ void cpu_probe(void)
else
cpu_set_nofpu_opts(c);
c->vmbits = 31;
reserve_exception_space(0, 0x400);
}

View File

@@ -4,12 +4,12 @@
#include "libgcc.h"
/*
* GCC 7 & older can suboptimally generate __multi3 calls for mips64r6, so for
* GCC 9 & older can suboptimally generate __multi3 calls for mips64r6, so for
* that specific case only we implement that intrinsic here.
*
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
*/
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 8)
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 10)
/* multiply 64-bit values, low 64-bits returned */
static inline long long notrace dmulu(long long a, long long b)
@@ -51,4 +51,4 @@ ti_type notrace __multi3(ti_type a, ti_type b)
}
EXPORT_SYMBOL(__multi3);
#endif /* 64BIT && CPU_MIPSR6 && GCC7 */
#endif /* 64BIT && CPU_MIPSR6 && GCC9 */

View File

@@ -17,7 +17,9 @@
#include <linux/dma-map-ops.h>
#include <linux/export.h>
#include <linux/libfdt.h>
#include <linux/minmax.h>
#include <linux/pci_ids.h>
#include <linux/serial_core.h>
#include <linux/string_choices.h>
#include <asm/bootinfo.h>
#include <loongson.h>
@@ -106,9 +108,23 @@ static void __init lefi_fixup_fdt(struct system_loongson *system)
is_loongson64g = (read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64G;
for (i = 0; i < system->nr_uarts; i++) {
for (i = 0; i < min(system->nr_uarts, MAX_UARTS); i++) {
uartdev = &system->uarts[i];
/*
* Some firmware does not set nr_uarts properly and passes empty
* items. Ignore them silently.
*/
if (uartdev->uart_base == 0)
continue;
/* Our DT only works with UPIO_MEM. */
if (uartdev->iotype != UPIO_MEM) {
pr_warn("Ignore UART 0x%llx with iotype %u passed by firmware\n",
uartdev->uart_base, uartdev->iotype);
continue;
}
ret = lefi_fixup_fdt_serial(fdt_buf, uartdev->uart_base,
uartdev->uartclk);
/*

View File

@@ -207,7 +207,8 @@ void cpu_cache_init(void)
{
if (IS_ENABLED(CONFIG_CPU_R3000) && cpu_has_3k_cache)
r3k_cache_init();
if (IS_ENABLED(CONFIG_CPU_R4K_CACHE_TLB) && cpu_has_4k_cache)
if ((IS_ENABLED(CONFIG_CPU_R4K_CACHE_TLB) ||
IS_ENABLED(CONFIG_CPU_SB1)) && cpu_has_4k_cache)
r4k_cache_init();
if (IS_ENABLED(CONFIG_CPU_CAVIUM_OCTEON) && cpu_has_octeon_cache)

View File

@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/memblock.h>
#include <linux/minmax.h>
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/export.h>
@@ -24,6 +25,7 @@
#include <asm/hazards.h>
#include <asm/mmu_context.h>
#include <asm/tlb.h>
#include <asm/tlbdebug.h>
#include <asm/tlbex.h>
#include <asm/tlbmisc.h>
#include <asm/setup.h>
@@ -511,12 +513,229 @@ static int __init set_ntlb(char *str)
__setup("ntlb=", set_ntlb);
/* Comparison function for EntryHi VPN fields. */
static int r4k_vpn_cmp(const void *a, const void *b)
/* The start bit position of VPN2 and Mask in EntryHi/PageMask registers. */
#define VPN2_SHIFT 13
/* Read full EntryHi even with CONFIG_32BIT. */
static inline unsigned long long read_c0_entryhi_native(void)
{
long v = *(unsigned long *)a - *(unsigned long *)b;
int s = sizeof(long) > sizeof(int) ? sizeof(long) * 8 - 1: 0;
return s ? (v != 0) | v >> s : v;
return cpu_has_64bits ? read_c0_entryhi_64() : read_c0_entryhi();
}
/* Write full EntryHi even with CONFIG_32BIT. */
static inline void write_c0_entryhi_native(unsigned long long v)
{
if (cpu_has_64bits)
write_c0_entryhi_64(v);
else
write_c0_entryhi(v);
}
/* TLB entry state for uniquification. */
struct tlbent {
unsigned long long wired:1;
unsigned long long global:1;
unsigned long long asid:10;
unsigned long long vpn:51;
unsigned long long pagesz:5;
unsigned long long index:14;
};
/*
* Comparison function for TLB entry sorting. Place wired entries first,
* then global entries, then order by the increasing VPN/ASID and the
* decreasing page size. This lets us avoid clashes with wired entries
* easily and get entries for larger pages out of the way first.
*
* We could group bits so as to reduce the number of comparisons, but this
* is seldom executed and not performance-critical, so prefer legibility.
*/
static int r4k_entry_cmp(const void *a, const void *b)
{
struct tlbent ea = *(struct tlbent *)a, eb = *(struct tlbent *)b;
if (ea.wired > eb.wired)
return -1;
else if (ea.wired < eb.wired)
return 1;
else if (ea.global > eb.global)
return -1;
else if (ea.global < eb.global)
return 1;
else if (ea.vpn < eb.vpn)
return -1;
else if (ea.vpn > eb.vpn)
return 1;
else if (ea.asid < eb.asid)
return -1;
else if (ea.asid > eb.asid)
return 1;
else if (ea.pagesz > eb.pagesz)
return -1;
else if (ea.pagesz < eb.pagesz)
return 1;
else
return 0;
}
/*
* Fetch all the TLB entries. Mask individual VPN values retrieved with
* the corresponding page mask and ignoring any 1KiB extension as we'll
* be using 4KiB pages for uniquification.
*/
static void __ref r4k_tlb_uniquify_read(struct tlbent *tlb_vpns, int tlbsize)
{
int start = num_wired_entries();
unsigned long long vpn_mask;
bool global;
int i;
vpn_mask = GENMASK(current_cpu_data.vmbits - 1, VPN2_SHIFT);
vpn_mask |= cpu_has_64bits ? 3ULL << 62 : 1 << 31;
for (i = 0; i < tlbsize; i++) {
unsigned long long entryhi, vpn, mask, asid;
unsigned int pagesz;
write_c0_index(i);
mtc0_tlbr_hazard();
tlb_read();
tlb_read_hazard();
global = !!(read_c0_entrylo0() & ENTRYLO_G);
entryhi = read_c0_entryhi_native();
mask = read_c0_pagemask();
asid = entryhi & cpu_asid_mask(&current_cpu_data);
vpn = (entryhi & vpn_mask & ~mask) >> VPN2_SHIFT;
pagesz = ilog2((mask >> VPN2_SHIFT) + 1);
tlb_vpns[i].global = global;
tlb_vpns[i].asid = global ? 0 : asid;
tlb_vpns[i].vpn = vpn;
tlb_vpns[i].pagesz = pagesz;
tlb_vpns[i].wired = i < start;
tlb_vpns[i].index = i;
}
}
/*
* Write unique values to all but the wired TLB entries each, using
* the 4KiB page size. This size might not be supported with R6, but
* EHINV is mandatory for R6, so we won't ever be called in that case.
*
* A sorted table is supplied with any wired entries at the beginning,
* followed by any global entries, and then finally regular entries.
* We start at the VPN and ASID values of zero and only assign user
* addresses, therefore guaranteeing no clash with addresses produced
* by UNIQUE_ENTRYHI. We avoid any VPN values used by wired or global
* entries, by increasing the VPN value beyond the span of such entry.
*
* When a VPN/ASID clash is found with a regular entry we increment the
* ASID instead until no VPN/ASID clash has been found or the ASID space
* has been exhausted, in which case we increase the VPN value beyond
* the span of the largest clashing entry.
*
* We do not need to be concerned about FTLB or MMID configurations as
* those are required to implement the EHINV feature.
*/
static void __ref r4k_tlb_uniquify_write(struct tlbent *tlb_vpns, int tlbsize)
{
unsigned long long asid, vpn, vpn_size, pagesz;
int widx, gidx, idx, sidx, lidx, i;
vpn_size = 1ULL << (current_cpu_data.vmbits - VPN2_SHIFT);
pagesz = ilog2((PM_4K >> VPN2_SHIFT) + 1);
write_c0_pagemask(PM_4K);
write_c0_entrylo0(0);
write_c0_entrylo1(0);
asid = 0;
vpn = 0;
widx = 0;
gidx = 0;
for (sidx = 0; sidx < tlbsize && tlb_vpns[sidx].wired; sidx++)
;
for (lidx = sidx; lidx < tlbsize && tlb_vpns[lidx].global; lidx++)
;
idx = gidx = sidx + 1;
for (i = sidx; i < tlbsize; i++) {
unsigned long long entryhi, vpn_pagesz = 0;
while (1) {
if (WARN_ON(vpn >= vpn_size)) {
dump_tlb_all();
/* Pray local_flush_tlb_all() will cope. */
return;
}
/* VPN must be below the next wired entry. */
if (widx < sidx && vpn >= tlb_vpns[widx].vpn) {
vpn = max(vpn,
(tlb_vpns[widx].vpn +
(1ULL << tlb_vpns[widx].pagesz)));
asid = 0;
widx++;
continue;
}
/* VPN must be below the next global entry. */
if (gidx < lidx && vpn >= tlb_vpns[gidx].vpn) {
vpn = max(vpn,
(tlb_vpns[gidx].vpn +
(1ULL << tlb_vpns[gidx].pagesz)));
asid = 0;
gidx++;
continue;
}
/* Try to find a free ASID so as to conserve VPNs. */
if (idx < tlbsize && vpn == tlb_vpns[idx].vpn &&
asid == tlb_vpns[idx].asid) {
unsigned long long idx_pagesz;
idx_pagesz = tlb_vpns[idx].pagesz;
vpn_pagesz = max(vpn_pagesz, idx_pagesz);
do
idx++;
while (idx < tlbsize &&
vpn == tlb_vpns[idx].vpn &&
asid == tlb_vpns[idx].asid);
asid++;
if (asid > cpu_asid_mask(&current_cpu_data)) {
vpn += vpn_pagesz;
asid = 0;
vpn_pagesz = 0;
}
continue;
}
/* VPN mustn't be above the next regular entry. */
if (idx < tlbsize && vpn > tlb_vpns[idx].vpn) {
vpn = max(vpn,
(tlb_vpns[idx].vpn +
(1ULL << tlb_vpns[idx].pagesz)));
asid = 0;
idx++;
continue;
}
break;
}
entryhi = (vpn << VPN2_SHIFT) | asid;
write_c0_entryhi_native(entryhi);
write_c0_index(tlb_vpns[i].index);
mtc0_tlbw_hazard();
tlb_write_indexed();
tlb_vpns[i].asid = asid;
tlb_vpns[i].vpn = vpn;
tlb_vpns[i].pagesz = pagesz;
asid++;
if (asid > cpu_asid_mask(&current_cpu_data)) {
vpn += 1ULL << pagesz;
asid = 0;
}
}
}
/*
@@ -527,70 +746,25 @@ static void __ref r4k_tlb_uniquify(void)
{
int tlbsize = current_cpu_data.tlbsize;
bool use_slab = slab_is_available();
int start = num_wired_entries();
phys_addr_t tlb_vpn_size;
unsigned long *tlb_vpns;
unsigned long vpn_mask;
int cnt, ent, idx, i;
vpn_mask = GENMASK(cpu_vmbits - 1, 13);
vpn_mask |= IS_ENABLED(CONFIG_64BIT) ? 3ULL << 62 : 1 << 31;
struct tlbent *tlb_vpns;
tlb_vpn_size = tlbsize * sizeof(*tlb_vpns);
tlb_vpns = (use_slab ?
kmalloc(tlb_vpn_size, GFP_KERNEL) :
kmalloc(tlb_vpn_size, GFP_ATOMIC) :
memblock_alloc_raw(tlb_vpn_size, sizeof(*tlb_vpns)));
if (WARN_ON(!tlb_vpns))
return; /* Pray local_flush_tlb_all() is good enough. */
htw_stop();
for (i = start, cnt = 0; i < tlbsize; i++, cnt++) {
unsigned long vpn;
r4k_tlb_uniquify_read(tlb_vpns, tlbsize);
write_c0_index(i);
mtc0_tlbr_hazard();
tlb_read();
tlb_read_hazard();
vpn = read_c0_entryhi();
vpn &= vpn_mask & PAGE_MASK;
tlb_vpns[cnt] = vpn;
sort(tlb_vpns, tlbsize, sizeof(*tlb_vpns), r4k_entry_cmp, NULL);
/* Prevent any large pages from overlapping regular ones. */
write_c0_pagemask(read_c0_pagemask() & PM_DEFAULT_MASK);
mtc0_tlbw_hazard();
tlb_write_indexed();
tlbw_use_hazard();
}
sort(tlb_vpns, cnt, sizeof(tlb_vpns[0]), r4k_vpn_cmp, NULL);
r4k_tlb_uniquify_write(tlb_vpns, tlbsize);
write_c0_pagemask(PM_DEFAULT_MASK);
write_c0_entrylo0(0);
write_c0_entrylo1(0);
idx = 0;
ent = tlbsize;
for (i = start; i < tlbsize; i++)
while (1) {
unsigned long entryhi, vpn;
entryhi = UNIQUE_ENTRYHI(ent);
vpn = entryhi & vpn_mask & PAGE_MASK;
if (idx >= cnt || vpn < tlb_vpns[idx]) {
write_c0_entryhi(entryhi);
write_c0_index(i);
mtc0_tlbw_hazard();
tlb_write_indexed();
ent++;
break;
} else if (vpn == tlb_vpns[idx]) {
ent++;
} else {
idx++;
}
}
tlbw_use_hazard();
htw_start();
@@ -640,7 +814,8 @@ static void r4k_tlb_configure(void)
temp_tlb_entry = current_cpu_data.tlbsize - 1;
/* From this point on the ARC firmware is dead. */
r4k_tlb_uniquify();
if (!cpu_has_tlbinv)
r4k_tlb_uniquify();
local_flush_tlb_all();
/* Did I tell you that ARC SUCKS? */

View File

@@ -21,16 +21,16 @@ static const char *clk_cpu(int *idx)
{
switch (ralink_soc) {
case RT2880_SOC:
*idx = 0;
*idx = 1;
return "ralink,rt2880-sysc";
case RT3883_SOC:
*idx = 0;
*idx = 1;
return "ralink,rt3883-sysc";
case RT305X_SOC_RT3050:
*idx = 0;
*idx = 1;
return "ralink,rt3050-sysc";
case RT305X_SOC_RT3052:
*idx = 0;
*idx = 1;
return "ralink,rt3052-sysc";
case RT305X_SOC_RT3350:
*idx = 1;

View File

@@ -67,7 +67,7 @@ bool arch_dma_unmap_sg_direct(struct device *dev, struct scatterlist *sg,
}
bool arch_dma_alloc_direct(struct device *dev)
{
if (dev->dma_ops_bypass)
if (dev->dma_ops_bypass && dev->bus_dma_limit)
return true;
return false;
@@ -75,7 +75,7 @@ bool arch_dma_alloc_direct(struct device *dev)
bool arch_dma_free_direct(struct device *dev, dma_addr_t dma_handle)
{
if (!dev->dma_ops_bypass)
if (!dev->dma_ops_bypass || !dev->bus_dma_limit)
return false;
return is_direct_handle(dev, dma_handle);

View File

@@ -2,6 +2,10 @@
#ifndef _ASM_RISCV_RUNTIME_CONST_H
#define _ASM_RISCV_RUNTIME_CONST_H
#ifdef MODULE
#error "Cannot use runtime-const infrastructure from modules"
#endif
#include <asm/asm.h>
#include <asm/alternative.h>
#include <asm/cacheflush.h>

View File

@@ -9,6 +9,7 @@
#ifndef __ASSEMBLER__
#include <linux/types.h>
#include <linux/const.h>
#define PTRACE_GETFDPIC 33
@@ -138,12 +139,12 @@ struct __sc_riscv_cfi_state {
#define PTRACE_CFI_SS_LOCK_BIT 4
#define PTRACE_CFI_SS_PTR_BIT 5
#define PTRACE_CFI_LP_EN_STATE BIT(PTRACE_CFI_LP_EN_BIT)
#define PTRACE_CFI_LP_LOCK_STATE BIT(PTRACE_CFI_LP_LOCK_BIT)
#define PTRACE_CFI_ELP_STATE BIT(PTRACE_CFI_ELP_BIT)
#define PTRACE_CFI_SS_EN_STATE BIT(PTRACE_CFI_SS_EN_BIT)
#define PTRACE_CFI_SS_LOCK_STATE BIT(PTRACE_CFI_SS_LOCK_BIT)
#define PTRACE_CFI_SS_PTR_STATE BIT(PTRACE_CFI_SS_PTR_BIT)
#define PTRACE_CFI_LP_EN_STATE _BITUL(PTRACE_CFI_LP_EN_BIT)
#define PTRACE_CFI_LP_LOCK_STATE _BITUL(PTRACE_CFI_LP_LOCK_BIT)
#define PTRACE_CFI_ELP_STATE _BITUL(PTRACE_CFI_ELP_BIT)
#define PTRACE_CFI_SS_EN_STATE _BITUL(PTRACE_CFI_SS_EN_BIT)
#define PTRACE_CFI_SS_LOCK_STATE _BITUL(PTRACE_CFI_SS_LOCK_BIT)
#define PTRACE_CFI_SS_PTR_STATE _BITUL(PTRACE_CFI_SS_PTR_BIT)
#define PRACE_CFI_STATE_INVALID_MASK ~(PTRACE_CFI_LP_EN_STATE | \
PTRACE_CFI_LP_LOCK_STATE | \

View File

@@ -175,7 +175,7 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
{DBG_REG_T1, GDB_SIZEOF_REG, offsetof(struct pt_regs, t1)},
{DBG_REG_T2, GDB_SIZEOF_REG, offsetof(struct pt_regs, t2)},
{DBG_REG_FP, GDB_SIZEOF_REG, offsetof(struct pt_regs, s0)},
{DBG_REG_S1, GDB_SIZEOF_REG, offsetof(struct pt_regs, a1)},
{DBG_REG_S1, GDB_SIZEOF_REG, offsetof(struct pt_regs, s1)},
{DBG_REG_A0, GDB_SIZEOF_REG, offsetof(struct pt_regs, a0)},
{DBG_REG_A1, GDB_SIZEOF_REG, offsetof(struct pt_regs, a1)},
{DBG_REG_A2, GDB_SIZEOF_REG, offsetof(struct pt_regs, a2)},
@@ -244,8 +244,9 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
gdb_regs[DBG_REG_S6_OFF] = task->thread.s[6];
gdb_regs[DBG_REG_S7_OFF] = task->thread.s[7];
gdb_regs[DBG_REG_S8_OFF] = task->thread.s[8];
gdb_regs[DBG_REG_S9_OFF] = task->thread.s[10];
gdb_regs[DBG_REG_S10_OFF] = task->thread.s[11];
gdb_regs[DBG_REG_S9_OFF] = task->thread.s[9];
gdb_regs[DBG_REG_S10_OFF] = task->thread.s[10];
gdb_regs[DBG_REG_S11_OFF] = task->thread.s[11];
gdb_regs[DBG_REG_EPC_OFF] = task->thread.ra;
}

View File

@@ -42,19 +42,20 @@ static inline bool is_kernel_exittext(uintptr_t addr)
static __always_inline void *patch_map(void *addr, const unsigned int fixmap)
{
uintptr_t uintaddr = (uintptr_t) addr;
struct page *page;
phys_addr_t phys;
if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr))
page = phys_to_page(__pa_symbol(addr));
else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
page = vmalloc_to_page(addr);
else
if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr)) {
phys = __pa_symbol(addr);
} else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) {
struct page *page = vmalloc_to_page(addr);
BUG_ON(!page);
phys = page_to_phys(page) + offset_in_page(addr);
} else {
return addr;
}
BUG_ON(!page);
return (void *)set_fixmap_offset(fixmap, page_to_phys(page) +
offset_in_page(addr));
return (void *)set_fixmap_offset(fixmap, phys);
}
static void patch_unmap(int fixmap)

View File

@@ -347,8 +347,10 @@ long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg)
if (arg & PR_TAGGED_ADDR_ENABLE && (tagged_addr_disabled || !pmlen))
return -EINVAL;
if (!(arg & PR_TAGGED_ADDR_ENABLE))
if (!(arg & PR_TAGGED_ADDR_ENABLE)) {
pmlen = PMLEN_0;
pmm = ENVCFG_PMM_PMLEN_0;
}
if (mmap_write_lock_killable(mm))
return -EINTR;

View File

@@ -1168,6 +1168,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
static void hw_perf_event_update(struct perf_event *event, int flush_all)
{
unsigned long long event_overflow, sampl_overflow, num_sdb;
struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf);
struct hw_perf_event *hwc = &event->hw;
union hws_trailer_header prev, new;
struct hws_trailer_entry *te;
@@ -1247,8 +1248,11 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
* are dropped.
* Slightly increase the interval to avoid hitting this limit.
*/
if (event_overflow)
if (event_overflow) {
SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10);
if (SAMPL_RATE(hwc) > cpuhw->qsi.max_sampl_rate)
SAMPL_RATE(hwc) = cpuhw->qsi.max_sampl_rate;
}
}
static inline unsigned long aux_sdb_index(struct aux_buffer *aux,

View File

@@ -4855,8 +4855,10 @@ static int intel_pmu_hw_config(struct perf_event *event)
intel_pmu_set_acr_caused_constr(leader, idx++, cause_mask);
if (leader->nr_siblings) {
for_each_sibling_event(sibling, leader)
intel_pmu_set_acr_caused_constr(sibling, idx++, cause_mask);
for_each_sibling_event(sibling, leader) {
if (is_x86_event(sibling))
intel_pmu_set_acr_caused_constr(sibling, idx++, cause_mask);
}
}
if (leader != event)

View File

@@ -44,6 +44,20 @@ KCOV_INSTRUMENT_unwind_orc.o := n
KCOV_INSTRUMENT_unwind_frame.o := n
KCOV_INSTRUMENT_unwind_guess.o := n
# Disable KCOV to prevent crashes during kexec: load_segments() invalidates
# the GS base, which KCOV relies on for per-CPU data.
#
# As KCOV and KEXEC compatibility should be preserved (e.g. syzkaller is
# using it to collect crash dumps during kernel fuzzing), disabling
# KCOV for KEXEC kernels is not an option. Selectively disabling KCOV
# instrumentation for individual affected functions can be fragile, while
# adding more checks to KCOV would slow it down.
#
# As a compromise solution, disable KCOV instrumentation for the whole
# source code file. If its coverage is ever needed, other approaches
# should be considered.
KCOV_INSTRUMENT_machine_kexec_64.o := n
CFLAGS_head32.o := -fno-stack-protector
CFLAGS_head64.o := -fno-stack-protector
CFLAGS_irq.o := -I $(src)/../include/asm/trace

View File

@@ -4,6 +4,8 @@ KCOV_INSTRUMENT_tlb.o := n
KCOV_INSTRUMENT_mem_encrypt.o := n
KCOV_INSTRUMENT_mem_encrypt_amd.o := n
KCOV_INSTRUMENT_pgprot.o := n
# See the "Disable KCOV" comment in arch/x86/kernel/Makefile.
KCOV_INSTRUMENT_physaddr.o := n
KASAN_SANITIZE_mem_encrypt.o := n
KASAN_SANITIZE_mem_encrypt_amd.o := n

View File

@@ -28,8 +28,10 @@ static const struct software_node geode_gpio_keys_node = {
.properties = geode_gpio_keys_props,
};
static struct property_entry geode_restart_key_props[] = {
{ /* Placeholder for GPIO property */ },
static struct software_node_ref_args geode_restart_gpio_ref;
static const struct property_entry geode_restart_key_props[] = {
PROPERTY_ENTRY_REF_ARRAY_LEN("gpios", &geode_restart_gpio_ref, 1),
PROPERTY_ENTRY_U32("linux,code", KEY_RESTART),
PROPERTY_ENTRY_STRING("label", "Reset button"),
PROPERTY_ENTRY_U32("debounce-interval", 100),
@@ -64,8 +66,7 @@ int __init geode_create_restart_key(unsigned int pin)
struct platform_device *pd;
int err;
geode_restart_key_props[0] = PROPERTY_ENTRY_GPIO("gpios",
&geode_gpiochip_node,
geode_restart_gpio_ref = SOFTWARE_NODE_REFERENCE(&geode_gpiochip_node,
pin, GPIO_ACTIVE_LOW);
err = software_node_register_node_group(geode_gpio_keys_swnodes);
@@ -99,6 +100,7 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
const struct software_node *group[MAX_LEDS + 2] = { 0 };
struct software_node *swnodes;
struct property_entry *props;
struct software_node_ref_args *gpio_refs;
struct platform_device_info led_info = {
.name = "leds-gpio",
.id = PLATFORM_DEVID_NONE,
@@ -127,6 +129,12 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
goto err_free_swnodes;
}
gpio_refs = kzalloc_objs(*gpio_refs, n_leds);
if (!gpio_refs) {
err = -ENOMEM;
goto err_free_props;
}
group[0] = &geode_gpio_leds_node;
for (i = 0; i < n_leds; i++) {
node_name = kasprintf(GFP_KERNEL, "%s:%d", label, i);
@@ -135,9 +143,11 @@ int __init geode_create_leds(const char *label, const struct geode_led *leds,
goto err_free_names;
}
gpio_refs[i] = SOFTWARE_NODE_REFERENCE(&geode_gpiochip_node,
leds[i].pin,
GPIO_ACTIVE_LOW);
props[i * 3 + 0] =
PROPERTY_ENTRY_GPIO("gpios", &geode_gpiochip_node,
leds[i].pin, GPIO_ACTIVE_LOW);
PROPERTY_ENTRY_REF_ARRAY_LEN("gpios", &gpio_refs[i], 1);
props[i * 3 + 1] =
PROPERTY_ENTRY_STRING("linux,default-trigger",
leds[i].default_on ?
@@ -171,6 +181,8 @@ err_unregister_group:
err_free_names:
while (--i >= 0)
kfree(swnodes[i].name);
kfree(gpio_refs);
err_free_props:
kfree(props);
err_free_swnodes:
kfree(swnodes);

View File

@@ -623,8 +623,10 @@ static int af_alg_alloc_tsgl(struct sock *sk)
sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
sgl->cur = 0;
if (sg)
if (sg) {
sg_unmark_end(sg + MAX_SGL_ENTS - 1);
sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
}
list_add_tail(&sgl->list, &ctx->tsgl_list);
}
@@ -635,15 +637,13 @@ static int af_alg_alloc_tsgl(struct sock *sk)
/**
* af_alg_count_tsgl - Count number of TX SG entries
*
* The counting starts from the beginning of the SGL to @bytes. If
* an @offset is provided, the counting of the SG entries starts at the @offset.
* The counting starts from the beginning of the SGL to @bytes.
*
* @sk: socket of connection to user space
* @bytes: Count the number of SG entries holding given number of bytes.
* @offset: Start the counting of SG entries from the given offset.
* Return: Number of TX SG entries found given the constraints
*/
unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset)
unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes)
{
const struct alg_sock *ask = alg_sk(sk);
const struct af_alg_ctx *ctx = ask->private;
@@ -658,25 +658,11 @@ unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset)
const struct scatterlist *sg = sgl->sg;
for (i = 0; i < sgl->cur; i++) {
size_t bytes_count;
/* Skip offset */
if (offset >= sg[i].length) {
offset -= sg[i].length;
bytes -= sg[i].length;
continue;
}
bytes_count = sg[i].length - offset;
offset = 0;
sgl_count++;
/* If we have seen requested number of bytes, stop */
if (bytes_count >= bytes)
if (sg[i].length >= bytes)
return sgl_count;
bytes -= bytes_count;
bytes -= sg[i].length;
}
}
@@ -688,19 +674,14 @@ EXPORT_SYMBOL_GPL(af_alg_count_tsgl);
* af_alg_pull_tsgl - Release the specified buffers from TX SGL
*
* If @dst is non-null, reassign the pages to @dst. The caller must release
* the pages. If @dst_offset is given only reassign the pages to @dst starting
* at the @dst_offset (byte). The caller must ensure that @dst is large
* enough (e.g. by using af_alg_count_tsgl with the same offset).
* the pages.
*
* @sk: socket of connection to user space
* @used: Number of bytes to pull from TX SGL
* @dst: If non-NULL, buffer is reassigned to dst SGL instead of releasing. The
* caller must release the buffers in dst.
* @dst_offset: Reassign the TX SGL from given offset. All buffers before
* reaching the offset is released.
*/
void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
size_t dst_offset)
void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst)
{
struct alg_sock *ask = alg_sk(sk);
struct af_alg_ctx *ctx = ask->private;
@@ -725,18 +706,10 @@ void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
* SG entries in dst.
*/
if (dst) {
if (dst_offset >= plen) {
/* discard page before offset */
dst_offset -= plen;
} else {
/* reassign page to dst after offset */
get_page(page);
sg_set_page(dst + j, page,
plen - dst_offset,
sg[i].offset + dst_offset);
dst_offset = 0;
j++;
}
/* reassign page to dst after offset */
get_page(page);
sg_set_page(dst + j, page, plen, sg[i].offset);
j++;
}
sg[i].length -= plen;

View File

@@ -26,7 +26,6 @@
#include <crypto/internal/aead.h>
#include <crypto/scatterwalk.h>
#include <crypto/if_alg.h>
#include <crypto/skcipher.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/kernel.h>
@@ -72,9 +71,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
struct alg_sock *pask = alg_sk(psk);
struct af_alg_ctx *ctx = ask->private;
struct crypto_aead *tfm = pask->private;
unsigned int i, as = crypto_aead_authsize(tfm);
unsigned int as = crypto_aead_authsize(tfm);
struct af_alg_async_req *areq;
struct af_alg_tsgl *tsgl, *tmp;
struct scatterlist *rsgl_src, *tsgl_src = NULL;
int err = 0;
size_t used = 0; /* [in] TX bufs to be en/decrypted */
@@ -154,23 +152,24 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
outlen -= less;
}
/*
* Create a per request TX SGL for this request which tracks the
* SG entries from the global TX SGL.
*/
processed = used + ctx->aead_assoclen;
list_for_each_entry_safe(tsgl, tmp, &ctx->tsgl_list, list) {
for (i = 0; i < tsgl->cur; i++) {
struct scatterlist *process_sg = tsgl->sg + i;
if (!(process_sg->length) || !sg_page(process_sg))
continue;
tsgl_src = process_sg;
break;
}
if (tsgl_src)
break;
}
if (processed && !tsgl_src) {
err = -EFAULT;
areq->tsgl_entries = af_alg_count_tsgl(sk, processed);
if (!areq->tsgl_entries)
areq->tsgl_entries = 1;
areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
areq->tsgl_entries),
GFP_KERNEL);
if (!areq->tsgl) {
err = -ENOMEM;
goto free;
}
sg_init_table(areq->tsgl, areq->tsgl_entries);
af_alg_pull_tsgl(sk, processed, areq->tsgl);
tsgl_src = areq->tsgl;
/*
* Copy of AAD from source to destination
@@ -179,76 +178,15 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
* when user space uses an in-place cipher operation, the kernel
* will copy the data as it does not see whether such in-place operation
* is initiated.
*
* To ensure efficiency, the following implementation ensure that the
* ciphers are invoked to perform a crypto operation in-place. This
* is achieved by memory management specified as follows.
*/
/* Use the RX SGL as source (and destination) for crypto op. */
rsgl_src = areq->first_rsgl.sgl.sgt.sgl;
if (ctx->enc) {
/*
* Encryption operation - The in-place cipher operation is
* achieved by the following operation:
*
* TX SGL: AAD || PT
* | |
* | copy |
* v v
* RX SGL: AAD || PT || Tag
*/
memcpy_sglist(areq->first_rsgl.sgl.sgt.sgl, tsgl_src,
processed);
af_alg_pull_tsgl(sk, processed, NULL, 0);
} else {
/*
* Decryption operation - To achieve an in-place cipher
* operation, the following SGL structure is used:
*
* TX SGL: AAD || CT || Tag
* | | ^
* | copy | | Create SGL link.
* v v |
* RX SGL: AAD || CT ----+
*/
/* Copy AAD || CT to RX SGL buffer for in-place operation. */
memcpy_sglist(areq->first_rsgl.sgl.sgt.sgl, tsgl_src, outlen);
/* Create TX SGL for tag and chain it to RX SGL. */
areq->tsgl_entries = af_alg_count_tsgl(sk, processed,
processed - as);
if (!areq->tsgl_entries)
areq->tsgl_entries = 1;
areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
areq->tsgl_entries),
GFP_KERNEL);
if (!areq->tsgl) {
err = -ENOMEM;
goto free;
}
sg_init_table(areq->tsgl, areq->tsgl_entries);
/* Release TX SGL, except for tag data and reassign tag data. */
af_alg_pull_tsgl(sk, processed, areq->tsgl, processed - as);
/* chain the areq TX SGL holding the tag with RX SGL */
if (usedpages) {
/* RX SGL present */
struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl;
struct scatterlist *sg = sgl_prev->sgt.sgl;
sg_unmark_end(sg + sgl_prev->sgt.nents - 1);
sg_chain(sg, sgl_prev->sgt.nents + 1, areq->tsgl);
} else
/* no RX SGL present (e.g. authentication only) */
rsgl_src = areq->tsgl;
}
memcpy_sglist(rsgl_src, tsgl_src, ctx->aead_assoclen);
/* Initialize the crypto operation */
aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src,
aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv);
aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
@@ -450,7 +388,7 @@ static void aead_sock_destruct(struct sock *sk)
struct crypto_aead *tfm = pask->private;
unsigned int ivlen = crypto_aead_ivsize(tfm);
af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
af_alg_pull_tsgl(sk, ctx->used, NULL);
sock_kzfree_s(sk, ctx->iv, ivlen);
sock_kfree_s(sk, ctx, ctx->len);
af_alg_release_parent(sk);

View File

@@ -138,7 +138,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
* Create a per request TX SGL for this request which tracks the
* SG entries from the global TX SGL.
*/
areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
areq->tsgl_entries = af_alg_count_tsgl(sk, len);
if (!areq->tsgl_entries)
areq->tsgl_entries = 1;
areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
@@ -149,7 +149,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
goto free;
}
sg_init_table(areq->tsgl, areq->tsgl_entries);
af_alg_pull_tsgl(sk, len, areq->tsgl, 0);
af_alg_pull_tsgl(sk, len, areq->tsgl);
/* Initialize the crypto operation */
skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm);
@@ -363,7 +363,7 @@ static void skcipher_sock_destruct(struct sock *sk)
struct alg_sock *pask = alg_sk(psk);
struct crypto_skcipher *tfm = pask->private;
af_alg_pull_tsgl(sk, ctx->used, NULL, 0);
af_alg_pull_tsgl(sk, ctx->used, NULL);
sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
if (ctx->state)
sock_kzfree_s(sk, ctx->state, crypto_skcipher_statesize(tfm));

View File

@@ -207,6 +207,7 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
u8 *ohash = areq_ctx->tail;
unsigned int cryptlen = req->cryptlen - authsize;
unsigned int assoclen = req->assoclen;
struct scatterlist *src = req->src;
struct scatterlist *dst = req->dst;
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
u32 tmp[2];
@@ -214,23 +215,27 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
if (!authsize)
goto decrypt;
/* Move high-order bits of sequence number back. */
scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
if (src == dst) {
/* Move high-order bits of sequence number back. */
scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
scatterwalk_map_and_copy(tmp, dst, 0, 8, 1);
} else
memcpy_sglist(dst, src, assoclen);
if (crypto_memneq(ihash, ohash, authsize))
return -EBADMSG;
decrypt:
sg_init_table(areq_ctx->dst, 2);
if (src != dst)
src = scatterwalk_ffwd(areq_ctx->src, src, assoclen);
dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
skcipher_request_set_tfm(skreq, ctx->enc);
skcipher_request_set_callback(skreq, flags,
req->base.complete, req->base.data);
skcipher_request_set_crypt(skreq, dst, dst, cryptlen, req->iv);
skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv);
return crypto_skcipher_decrypt(skreq);
}
@@ -255,6 +260,7 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
unsigned int assoclen = req->assoclen;
unsigned int cryptlen = req->cryptlen;
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
struct scatterlist *src = req->src;
struct scatterlist *dst = req->dst;
u32 tmp[2];
int err;
@@ -262,24 +268,28 @@ static int crypto_authenc_esn_decrypt(struct aead_request *req)
if (assoclen < 8)
return -EINVAL;
cryptlen -= authsize;
if (req->src != dst)
memcpy_sglist(dst, req->src, assoclen + cryptlen);
scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
authsize, 0);
if (!authsize)
goto tail;
/* Move high-order bits of sequence number to the end. */
scatterwalk_map_and_copy(tmp, dst, 0, 8, 0);
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
cryptlen -= authsize;
scatterwalk_map_and_copy(ihash, req->src, assoclen + cryptlen,
authsize, 0);
sg_init_table(areq_ctx->dst, 2);
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
/* Move high-order bits of sequence number to the end. */
scatterwalk_map_and_copy(tmp, src, 0, 8, 0);
if (src == dst) {
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
} else {
scatterwalk_map_and_copy(tmp, dst, 0, 4, 1);
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen - 4, 4, 1);
src = scatterwalk_ffwd(areq_ctx->src, src, 8);
dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
memcpy_sglist(dst, src, assoclen + cryptlen - 8);
dst = req->dst;
}
ahash_request_set_tfm(ahreq, auth);
ahash_request_set_crypt(ahreq, dst, ohash, assoclen + cryptlen);

View File

@@ -164,18 +164,21 @@ static int deflate_decompress_one(struct acomp_req *req,
do {
unsigned int dcur;
unsigned long avail_in;
dcur = acomp_walk_next_dst(&walk);
if (!dcur) {
out_of_space = true;
break;
}
stream->avail_out = dcur;
stream->next_out = walk.dst.virt.addr;
avail_in = stream->avail_in;
ret = zlib_inflate(stream, Z_NO_FLUSH);
if (!dcur && avail_in == stream->avail_in) {
out_of_space = true;
break;
}
dcur -= stream->avail_out;
acomp_walk_done_dst(&walk, dcur);
} while (ret == Z_OK && stream->avail_in);

View File

@@ -914,7 +914,7 @@ static int decode_deactivate(struct qaic_device *qdev, void *trans, u32 *msg_len
*/
return -ENODEV;
if (status) {
if (usr && status) {
/*
* Releasing resources failed on the device side, which puts
* us in a bind since they may still be in use, so enable the
@@ -1109,6 +1109,9 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u
mutex_lock(&qdev->cntl_mutex);
if (!list_empty(&elem.list))
list_del(&elem.list);
/* resp_worker() processed the response but the wait was interrupted */
else if (ret == -ERESTARTSYS)
ret = 0;
if (!ret && !elem.buf)
ret = -ETIMEDOUT;
else if (ret > 0 && !elem.buf)
@@ -1419,9 +1422,49 @@ static void resp_worker(struct work_struct *work)
}
mutex_unlock(&qdev->cntl_mutex);
if (!found)
if (!found) {
/*
* The user might have gone away at this point without waiting
* for QAIC_TRANS_DEACTIVATE_FROM_DEV transaction coming from
* the device. If this is not handled correctly, the host will
* not know that the DBC[n] has been freed on the device.
* Due to this failure in synchronization between the device and
* the host, if another user requests to activate a network, and
* the device assigns DBC[n] again, save_dbc_buf() will hang,
* waiting for dbc[n]->in_use to be set to false, which will not
* happen unless the qaic_dev_reset_clean_local_state() gets
* called by resetting the device (or re-inserting the module).
*
* As a solution, we look for QAIC_TRANS_DEACTIVATE_FROM_DEV
* transactions in the message before disposing of it, then
* handle releasing the DBC resources.
*
* Since the user has gone away, if the device could not
* deactivate the network (status != 0), there is no way to
* enable and reassign the DBC to the user. We can put trust in
* the device that it will release all the active DBCs in
* response to the QAIC_TRANS_TERMINATE_TO_DEV transaction,
* otherwise, the user can issue an soc_reset to the device.
*/
u32 msg_count = le32_to_cpu(msg->hdr.count);
u32 msg_len = le32_to_cpu(msg->hdr.len);
u32 len = 0;
int j;
for (j = 0; j < msg_count && len < msg_len; ++j) {
struct wire_trans_hdr *trans_hdr;
trans_hdr = (struct wire_trans_hdr *)(msg->data + len);
if (le32_to_cpu(trans_hdr->type) == QAIC_TRANS_DEACTIVATE_FROM_DEV) {
if (decode_deactivate(qdev, trans_hdr, &len, NULL))
len += le32_to_cpu(trans_hdr->len);
} else {
len += le32_to_cpu(trans_hdr->len);
}
}
/* request must have timed out, drop packet */
kfree(msg);
}
kfree(resp);
}

View File

@@ -263,6 +263,13 @@ static int rimt_iommu_xlate(struct device *dev, struct acpi_rimt_node *node, u32
if (!rimt_fwnode)
return -EPROBE_DEFER;
/*
* EPROBE_DEFER ensures IOMMU is probed before the devices that
* depend on them. During shutdown, however, the IOMMU may be removed
* first, leading to issues. To avoid this, a device link is added
* which enforces the correct removal order.
*/
device_link_add(dev, rimt_fwnode->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
return acpi_iommu_fwspec_init(dev, deviceid, rimt_fwnode);
}

View File

@@ -13,6 +13,8 @@
//
// The shrinker will use trylock methods because it locks them in a different order.
use crate::AssertSync;
use core::{
marker::PhantomPinned,
mem::{size_of, size_of_val, MaybeUninit},
@@ -143,14 +145,14 @@ pub(crate) struct ShrinkablePageRange {
}
// We do not define any ops. For now, used only to check identity of vmas.
static BINDER_VM_OPS: bindings::vm_operations_struct = pin_init::zeroed();
static BINDER_VM_OPS: AssertSync<bindings::vm_operations_struct> = AssertSync(pin_init::zeroed());
// To ensure that we do not accidentally install pages into or zap pages from the wrong vma, we
// check its vm_ops and private data before using it.
fn check_vma(vma: &virt::VmaRef, owner: *const ShrinkablePageRange) -> Option<&virt::VmaMixedMap> {
// SAFETY: Just reading the vm_ops pointer of any active vma is safe.
let vm_ops = unsafe { (*vma.as_ptr()).vm_ops };
if !ptr::eq(vm_ops, &BINDER_VM_OPS) {
if !ptr::eq(vm_ops, &BINDER_VM_OPS.0) {
return None;
}
@@ -342,7 +344,7 @@ impl ShrinkablePageRange {
// SAFETY: We own the vma, and we don't use any methods on VmaNew that rely on
// `vm_ops`.
unsafe { (*vma.as_ptr()).vm_ops = &BINDER_VM_OPS };
unsafe { (*vma.as_ptr()).vm_ops = &BINDER_VM_OPS.0 };
Ok(num_pages)
}

View File

@@ -306,7 +306,7 @@ impl kernel::Module for BinderModule {
/// Makes the inner type Sync.
#[repr(transparent)]
pub struct AssertSync<T>(T);
// SAFETY: Used only to insert `file_operations` into a global, which is safe.
// SAFETY: Used only to insert C bindings types into globals, which is safe.
unsafe impl<T> Sync for AssertSync<T> {}
/// File operations that rust_binderfs.c can use.

View File

@@ -99,8 +99,13 @@ static int lcd2s_print(struct charlcd *lcd, int c)
{
struct lcd2s_data *lcd2s = lcd->drvdata;
u8 buf[2] = { LCD2S_CMD_WRITE, c };
int ret;
lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
ret = lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
if (ret < 0)
return ret;
if (ret != sizeof(buf))
return -EIO;
return 0;
}
@@ -108,9 +113,13 @@ static int lcd2s_gotoxy(struct charlcd *lcd, unsigned int x, unsigned int y)
{
struct lcd2s_data *lcd2s = lcd->drvdata;
u8 buf[3] = { LCD2S_CMD_CUR_POS, y + 1, x + 1 };
int ret;
lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
ret = lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
if (ret < 0)
return ret;
if (ret != sizeof(buf))
return -EIO;
return 0;
}

View File

@@ -365,7 +365,7 @@ static DEFINE_IDA(linedisp_id);
static void linedisp_release(struct device *dev)
{
struct linedisp *linedisp = to_linedisp(dev);
struct linedisp *linedisp = container_of(dev, struct linedisp, dev);
kfree(linedisp->map);
kfree(linedisp->message);

View File

@@ -109,9 +109,6 @@ static int h4_recv(struct hci_uart *hu, const void *data, int count)
{
struct h4_struct *h4 = hu->priv;
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
return -EUNATCH;
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)) {

View File

@@ -793,13 +793,15 @@ static void do_become_nonbusy(struct comedi_device *dev,
__comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING |
COMEDI_SRF_BUSY);
spin_unlock_irqrestore(&s->spin_lock, flags);
if (comedi_is_runflags_busy(runflags)) {
if (async) {
/*
* "Run active" counter was set to 1 when setting up the
* command. Decrement it and wait for it to become 0.
*/
comedi_put_is_subdevice_running(s);
wait_for_completion(&async->run_complete);
if (comedi_is_runflags_busy(runflags)) {
comedi_put_is_subdevice_running(s);
wait_for_completion(&async->run_complete);
}
comedi_buf_reset(s);
async->inttrig = NULL;
kfree(async->cmd.chanlist);

View File

@@ -1063,6 +1063,14 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
ret = -EIO;
goto out;
}
if (IS_ENABLED(CONFIG_LOCKDEP)) {
/*
* dev->spinlock is for private use by the attached low-level
* driver. Reinitialize it to stop lock-dependency tracking
* between attachments to different low-level drivers.
*/
spin_lock_init(&dev->spinlock);
}
dev->driver = driv;
dev->board_name = dev->board_ptr ? *(const char **)dev->board_ptr
: dev->driver->driver_name;

View File

@@ -175,6 +175,18 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
? current_range_type : voltage_range_type;
}
/*
* Check if hardware is present before attempting any I/O operations.
* Reading 0xff from status register typically indicates no hardware
* on the bus (floating bus reads as all 1s).
*/
if (inb(dev->iobase + DT2815_STATUS) == 0xff) {
dev_err(dev->class_dev,
"No hardware detected at I/O base 0x%lx\n",
dev->iobase);
return -ENODEV;
}
/* Init the 2815 */
outb(0x00, dev->iobase + DT2815_STATUS);
for (i = 0; i < 100; i++) {

View File

@@ -315,6 +315,18 @@ static int me4000_xilinx_download(struct comedi_device *dev,
unsigned int val;
unsigned int i;
/* Get data stream length from header. */
if (size >= 4) {
file_length = (((unsigned int)data[0] & 0xff) << 24) +
(((unsigned int)data[1] & 0xff) << 16) +
(((unsigned int)data[2] & 0xff) << 8) +
((unsigned int)data[3] & 0xff);
}
if (size < 16 || file_length > size - 16) {
dev_err(dev->class_dev, "Firmware length inconsistency\n");
return -EINVAL;
}
if (!xilinx_iobase)
return -ENODEV;
@@ -346,10 +358,6 @@ static int me4000_xilinx_download(struct comedi_device *dev,
outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
/* Download Xilinx firmware */
file_length = (((unsigned int)data[0] & 0xff) << 24) +
(((unsigned int)data[1] & 0xff) << 16) +
(((unsigned int)data[2] & 0xff) << 8) +
((unsigned int)data[3] & 0xff);
usleep_range(10, 1000);
for (i = 0; i < file_length; i++) {

View File

@@ -344,6 +344,25 @@ static int me2600_xilinx_download(struct comedi_device *dev,
unsigned int file_length;
unsigned int i;
/*
* Format of the firmware
* Build longs from the byte-wise coded header
* Byte 1-3: length of the array
* Byte 4-7: version
* Byte 8-11: date
* Byte 12-15: reserved
*/
if (size >= 4) {
file_length = (((unsigned int)data[0] & 0xff) << 24) +
(((unsigned int)data[1] & 0xff) << 16) +
(((unsigned int)data[2] & 0xff) << 8) +
((unsigned int)data[3] & 0xff);
}
if (size < 16 || file_length > size - 16) {
dev_err(dev->class_dev, "Firmware length inconsistency\n");
return -EINVAL;
}
/* disable irq's on PLX */
writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR);
@@ -357,22 +376,6 @@ static int me2600_xilinx_download(struct comedi_device *dev,
writeb(0x00, dev->mmio + 0x0);
sleep(1);
/*
* Format of the firmware
* Build longs from the byte-wise coded header
* Byte 1-3: length of the array
* Byte 4-7: version
* Byte 8-11: date
* Byte 12-15: reserved
*/
if (size < 16)
return -EINVAL;
file_length = (((unsigned int)data[0] & 0xff) << 24) +
(((unsigned int)data[1] & 0xff) << 16) +
(((unsigned int)data[2] & 0xff) << 8) +
((unsigned int)data[3] & 0xff);
/*
* Loop for writing firmware byte by byte to xilinx
* Firmware data start at offset 16

View File

@@ -698,7 +698,8 @@ static int atmio16d_attach(struct comedi_device *dev,
static void atmio16d_detach(struct comedi_device *dev)
{
reset_atmio16d(dev);
if (dev->private)
reset_atmio16d(dev);
comedi_legacy_detach(dev);
}

View File

@@ -107,9 +107,9 @@ static bool rz_mtu3_is_counter_invalid(struct counter_device *counter, int id)
struct rz_mtu3_cnt *const priv = counter_priv(counter);
unsigned long tmdr;
pm_runtime_get_sync(priv->ch->dev);
pm_runtime_get_sync(counter->parent);
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
pm_runtime_put(priv->ch->dev);
pm_runtime_put(counter->parent);
if (id == RZ_MTU3_32_BIT_CH && test_bit(RZ_MTU3_TMDR3_LWA, &tmdr))
return false;
@@ -165,12 +165,12 @@ static int rz_mtu3_count_read(struct counter_device *counter,
if (ret)
return ret;
pm_runtime_get_sync(ch->dev);
pm_runtime_get_sync(counter->parent);
if (count->id == RZ_MTU3_32_BIT_CH)
*val = rz_mtu3_32bit_ch_read(ch, RZ_MTU3_TCNTLW);
else
*val = rz_mtu3_16bit_ch_read(ch, RZ_MTU3_TCNT);
pm_runtime_put(ch->dev);
pm_runtime_put(counter->parent);
mutex_unlock(&priv->lock);
return 0;
@@ -187,26 +187,26 @@ static int rz_mtu3_count_write(struct counter_device *counter,
if (ret)
return ret;
pm_runtime_get_sync(ch->dev);
pm_runtime_get_sync(counter->parent);
if (count->id == RZ_MTU3_32_BIT_CH)
rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TCNTLW, val);
else
rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TCNT, val);
pm_runtime_put(ch->dev);
pm_runtime_put(counter->parent);
mutex_unlock(&priv->lock);
return 0;
}
static int rz_mtu3_count_function_read_helper(struct rz_mtu3_channel *const ch,
struct rz_mtu3_cnt *const priv,
struct counter_device *const counter,
enum counter_function *function)
{
u8 timer_mode;
pm_runtime_get_sync(ch->dev);
pm_runtime_get_sync(counter->parent);
timer_mode = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TMDR1);
pm_runtime_put(ch->dev);
pm_runtime_put(counter->parent);
switch (timer_mode & RZ_MTU3_TMDR1_PH_CNT_MODE_MASK) {
case RZ_MTU3_TMDR1_PH_CNT_MODE_1:
@@ -240,7 +240,7 @@ static int rz_mtu3_count_function_read(struct counter_device *counter,
if (ret)
return ret;
ret = rz_mtu3_count_function_read_helper(ch, priv, function);
ret = rz_mtu3_count_function_read_helper(ch, counter, function);
mutex_unlock(&priv->lock);
return ret;
@@ -279,9 +279,9 @@ static int rz_mtu3_count_function_write(struct counter_device *counter,
return -EINVAL;
}
pm_runtime_get_sync(ch->dev);
pm_runtime_get_sync(counter->parent);
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TMDR1, timer_mode);
pm_runtime_put(ch->dev);
pm_runtime_put(counter->parent);
mutex_unlock(&priv->lock);
return 0;
@@ -300,9 +300,9 @@ static int rz_mtu3_count_direction_read(struct counter_device *counter,
if (ret)
return ret;
pm_runtime_get_sync(ch->dev);
pm_runtime_get_sync(counter->parent);
tsr = rz_mtu3_8bit_ch_read(ch, RZ_MTU3_TSR);
pm_runtime_put(ch->dev);
pm_runtime_put(counter->parent);
*direction = (tsr & RZ_MTU3_TSR_TCFD) ?
COUNTER_COUNT_DIRECTION_FORWARD : COUNTER_COUNT_DIRECTION_BACKWARD;
@@ -377,14 +377,14 @@ static int rz_mtu3_count_ceiling_write(struct counter_device *counter,
return -EINVAL;
}
pm_runtime_get_sync(ch->dev);
pm_runtime_get_sync(counter->parent);
if (count->id == RZ_MTU3_32_BIT_CH)
rz_mtu3_32bit_ch_write(ch, RZ_MTU3_TGRALW, ceiling);
else
rz_mtu3_16bit_ch_write(ch, RZ_MTU3_TGRA, ceiling);
rz_mtu3_8bit_ch_write(ch, RZ_MTU3_TCR, RZ_MTU3_TCR_CCLR_TGRA);
pm_runtime_put(ch->dev);
pm_runtime_put(counter->parent);
mutex_unlock(&priv->lock);
return 0;
@@ -495,25 +495,28 @@ static int rz_mtu3_count_enable_read(struct counter_device *counter,
static int rz_mtu3_count_enable_write(struct counter_device *counter,
struct counter_count *count, u8 enable)
{
struct rz_mtu3_channel *const ch = rz_mtu3_get_ch(counter, count->id);
struct rz_mtu3_cnt *const priv = counter_priv(counter);
int ret = 0;
mutex_lock(&priv->lock);
if (priv->count_is_enabled[count->id] == enable)
goto exit;
if (enable) {
mutex_lock(&priv->lock);
pm_runtime_get_sync(ch->dev);
pm_runtime_get_sync(counter->parent);
ret = rz_mtu3_initialize_counter(counter, count->id);
if (ret == 0)
priv->count_is_enabled[count->id] = true;
mutex_unlock(&priv->lock);
} else {
mutex_lock(&priv->lock);
rz_mtu3_terminate_counter(counter, count->id);
priv->count_is_enabled[count->id] = false;
pm_runtime_put(ch->dev);
mutex_unlock(&priv->lock);
pm_runtime_put(counter->parent);
}
exit:
mutex_unlock(&priv->lock);
return ret;
}
@@ -540,9 +543,9 @@ static int rz_mtu3_cascade_counts_enable_get(struct counter_device *counter,
if (ret)
return ret;
pm_runtime_get_sync(priv->ch->dev);
pm_runtime_get_sync(counter->parent);
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
pm_runtime_put(priv->ch->dev);
pm_runtime_put(counter->parent);
*cascade_enable = test_bit(RZ_MTU3_TMDR3_LWA, &tmdr);
mutex_unlock(&priv->lock);
@@ -559,10 +562,10 @@ static int rz_mtu3_cascade_counts_enable_set(struct counter_device *counter,
if (ret)
return ret;
pm_runtime_get_sync(priv->ch->dev);
pm_runtime_get_sync(counter->parent);
rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
RZ_MTU3_TMDR3_LWA, cascade_enable);
pm_runtime_put(priv->ch->dev);
pm_runtime_put(counter->parent);
mutex_unlock(&priv->lock);
return 0;
@@ -579,9 +582,9 @@ static int rz_mtu3_ext_input_phase_clock_select_get(struct counter_device *count
if (ret)
return ret;
pm_runtime_get_sync(priv->ch->dev);
pm_runtime_get_sync(counter->parent);
tmdr = rz_mtu3_shared_reg_read(priv->ch, RZ_MTU3_TMDR3);
pm_runtime_put(priv->ch->dev);
pm_runtime_put(counter->parent);
*ext_input_phase_clock_select = test_bit(RZ_MTU3_TMDR3_PHCKSEL, &tmdr);
mutex_unlock(&priv->lock);
@@ -598,11 +601,11 @@ static int rz_mtu3_ext_input_phase_clock_select_set(struct counter_device *count
if (ret)
return ret;
pm_runtime_get_sync(priv->ch->dev);
pm_runtime_get_sync(counter->parent);
rz_mtu3_shared_reg_update_bit(priv->ch, RZ_MTU3_TMDR3,
RZ_MTU3_TMDR3_PHCKSEL,
ext_input_phase_clock_select);
pm_runtime_put(priv->ch->dev);
pm_runtime_put(counter->parent);
mutex_unlock(&priv->lock);
return 0;
@@ -640,7 +643,7 @@ static int rz_mtu3_action_read(struct counter_device *counter,
if (ret)
return ret;
ret = rz_mtu3_count_function_read_helper(ch, priv, &function);
ret = rz_mtu3_count_function_read_helper(ch, counter, &function);
if (ret) {
mutex_unlock(&priv->lock);
return ret;

View File

@@ -468,13 +468,13 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
/* Failure, so roll back. */
pr_err("initialization failed (dbs_data kobject init error %d)\n", ret);
kobject_put(&dbs_data->attr_set.kobj);
policy->governor_data = NULL;
if (!have_governor_per_policy())
gov->gdbs_data = NULL;
gov->exit(dbs_data);
kobject_put(&dbs_data->attr_set.kobj);
goto free_policy_dbs_info;
free_dbs_data:
kfree(dbs_data);

View File

@@ -3326,9 +3326,10 @@ static int ahash_setkey(struct crypto_ahash *ahash, const u8 *key,
if (aligned_len < keylen)
return -EOVERFLOW;
hashed_key = kmemdup(key, aligned_len, GFP_KERNEL);
hashed_key = kmalloc(aligned_len, GFP_KERNEL);
if (!hashed_key)
return -ENOMEM;
memcpy(hashed_key, key, keylen);
ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
if (ret)
goto bad_free_key;

View File

@@ -441,9 +441,10 @@ static int ahash_setkey(struct crypto_ahash *ahash,
if (aligned_len < keylen)
return -EOVERFLOW;
hashed_key = kmemdup(key, keylen, GFP_KERNEL);
hashed_key = kmalloc(aligned_len, GFP_KERNEL);
if (!hashed_key)
return -ENOMEM;
memcpy(hashed_key, key, keylen);
ret = hash_digest_key(ctx, &keylen, hashed_key, digestsize);
if (ret)
goto bad_free_key;

View File

@@ -529,7 +529,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
.cra_name = "cbc(aes)",
.cra_driver_name = "cbc-aes-tegra",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_aes_ctx),
.cra_alignmask = 0xf,
@@ -550,7 +550,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
.cra_name = "ecb(aes)",
.cra_driver_name = "ecb-aes-tegra",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_aes_ctx),
.cra_alignmask = 0xf,
@@ -572,7 +572,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
.cra_name = "ctr(aes)",
.cra_driver_name = "ctr-aes-tegra",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_ASYNC,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = 1,
.cra_ctxsize = sizeof(struct tegra_aes_ctx),
.cra_alignmask = 0xf,
@@ -594,6 +594,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
.cra_name = "xts(aes)",
.cra_driver_name = "xts-aes-tegra",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_aes_ctx),
.cra_alignmask = (__alignof__(u64) - 1),
@@ -1922,6 +1923,7 @@ static struct tegra_se_alg tegra_aead_algs[] = {
.cra_name = "gcm(aes)",
.cra_driver_name = "gcm-aes-tegra",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = 1,
.cra_ctxsize = sizeof(struct tegra_aead_ctx),
.cra_alignmask = 0xf,
@@ -1944,6 +1946,7 @@ static struct tegra_se_alg tegra_aead_algs[] = {
.cra_name = "ccm(aes)",
.cra_driver_name = "ccm-aes-tegra",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = 1,
.cra_ctxsize = sizeof(struct tegra_aead_ctx),
.cra_alignmask = 0xf,
@@ -1971,7 +1974,7 @@ static struct tegra_se_alg tegra_cmac_algs[] = {
.cra_name = "cmac(aes)",
.cra_driver_name = "tegra-se-cmac",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_cmac_ctx),
.cra_alignmask = 0,

View File

@@ -761,7 +761,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha1",
.cra_driver_name = "tegra-se-sha1",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -786,7 +786,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha224",
.cra_driver_name = "tegra-se-sha224",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -811,7 +811,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha256",
.cra_driver_name = "tegra-se-sha256",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -836,7 +836,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha384",
.cra_driver_name = "tegra-se-sha384",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -861,7 +861,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha512",
.cra_driver_name = "tegra-se-sha512",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -886,7 +886,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha3-224",
.cra_driver_name = "tegra-se-sha3-224",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA3_224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -911,7 +911,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha3-256",
.cra_driver_name = "tegra-se-sha3-256",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA3_256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -936,7 +936,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha3-384",
.cra_driver_name = "tegra-se-sha3-384",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA3_384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -961,7 +961,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "sha3-512",
.cra_driver_name = "tegra-se-sha3-512",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA3_512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -988,7 +988,8 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "hmac(sha224)",
.cra_driver_name = "tegra-se-hmac-sha224",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -1015,7 +1016,8 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "hmac(sha256)",
.cra_driver_name = "tegra-se-hmac-sha256",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -1042,7 +1044,8 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "hmac(sha384)",
.cra_driver_name = "tegra-se-hmac-sha384",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,
@@ -1069,7 +1072,8 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_name = "hmac(sha512)",
.cra_driver_name = "tegra-se-hmac-sha512",
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK,
.cra_flags = CRYPTO_ALG_ASYNC |
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tegra_sha_ctx),
.cra_alignmask = 0,

View File

@@ -122,6 +122,7 @@ config GPIB_FLUKE
depends on OF
select GPIB_COMMON
select GPIB_NEC7210
depends on HAS_IOMEM
help
GPIB driver for Fluke based cda devices.

View File

@@ -888,10 +888,6 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo
if (read_cmd.completed_transfer_count > read_cmd.requested_transfer_count)
return -EINVAL;
desc = handle_to_descriptor(file_priv, read_cmd.handle);
if (!desc)
return -EINVAL;
if (WARN_ON_ONCE(sizeof(userbuf) > sizeof(read_cmd.buffer_ptr)))
return -EFAULT;
@@ -904,6 +900,17 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo
if (!access_ok(userbuf, remain))
return -EFAULT;
/* Lock descriptors to prevent concurrent close from freeing descriptor */
if (mutex_lock_interruptible(&file_priv->descriptors_mutex))
return -ERESTARTSYS;
desc = handle_to_descriptor(file_priv, read_cmd.handle);
if (!desc) {
mutex_unlock(&file_priv->descriptors_mutex);
return -EINVAL;
}
atomic_inc(&desc->descriptor_busy);
mutex_unlock(&file_priv->descriptors_mutex);
atomic_set(&desc->io_in_progress, 1);
/* Read buffer loads till we fill the user supplied buffer */
@@ -937,6 +944,7 @@ static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo
retval = copy_to_user((void __user *)arg, &read_cmd, sizeof(read_cmd));
atomic_set(&desc->io_in_progress, 0);
atomic_dec(&desc->descriptor_busy);
wake_up_interruptible(&board->wait);
if (retval)
@@ -964,10 +972,6 @@ static int command_ioctl(struct gpib_file_private *file_priv,
if (cmd.completed_transfer_count > cmd.requested_transfer_count)
return -EINVAL;
desc = handle_to_descriptor(file_priv, cmd.handle);
if (!desc)
return -EINVAL;
userbuf = (u8 __user *)(unsigned long)cmd.buffer_ptr;
userbuf += cmd.completed_transfer_count;
@@ -980,6 +984,17 @@ static int command_ioctl(struct gpib_file_private *file_priv,
if (!access_ok(userbuf, remain))
return -EFAULT;
/* Lock descriptors to prevent concurrent close from freeing descriptor */
if (mutex_lock_interruptible(&file_priv->descriptors_mutex))
return -ERESTARTSYS;
desc = handle_to_descriptor(file_priv, cmd.handle);
if (!desc) {
mutex_unlock(&file_priv->descriptors_mutex);
return -EINVAL;
}
atomic_inc(&desc->descriptor_busy);
mutex_unlock(&file_priv->descriptors_mutex);
/*
* Write buffer loads till we empty the user supplied buffer.
* Call drivers at least once, even if remain is zero, in
@@ -1003,6 +1018,7 @@ static int command_ioctl(struct gpib_file_private *file_priv,
userbuf += bytes_written;
if (retval < 0) {
atomic_set(&desc->io_in_progress, 0);
atomic_dec(&desc->descriptor_busy);
wake_up_interruptible(&board->wait);
break;
@@ -1022,6 +1038,7 @@ static int command_ioctl(struct gpib_file_private *file_priv,
*/
if (!no_clear_io_in_prog || fault)
atomic_set(&desc->io_in_progress, 0);
atomic_dec(&desc->descriptor_busy);
wake_up_interruptible(&board->wait);
if (fault)
@@ -1047,10 +1064,6 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b
if (write_cmd.completed_transfer_count > write_cmd.requested_transfer_count)
return -EINVAL;
desc = handle_to_descriptor(file_priv, write_cmd.handle);
if (!desc)
return -EINVAL;
userbuf = (u8 __user *)(unsigned long)write_cmd.buffer_ptr;
userbuf += write_cmd.completed_transfer_count;
@@ -1060,6 +1073,17 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b
if (!access_ok(userbuf, remain))
return -EFAULT;
/* Lock descriptors to prevent concurrent close from freeing descriptor */
if (mutex_lock_interruptible(&file_priv->descriptors_mutex))
return -ERESTARTSYS;
desc = handle_to_descriptor(file_priv, write_cmd.handle);
if (!desc) {
mutex_unlock(&file_priv->descriptors_mutex);
return -EINVAL;
}
atomic_inc(&desc->descriptor_busy);
mutex_unlock(&file_priv->descriptors_mutex);
atomic_set(&desc->io_in_progress, 1);
/* Write buffer loads till we empty the user supplied buffer */
@@ -1094,6 +1118,7 @@ static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *b
fault = copy_to_user((void __user *)arg, &write_cmd, sizeof(write_cmd));
atomic_set(&desc->io_in_progress, 0);
atomic_dec(&desc->descriptor_busy);
wake_up_interruptible(&board->wait);
if (fault)
@@ -1276,6 +1301,9 @@ static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigne
{
struct gpib_close_dev_ioctl cmd;
struct gpib_file_private *file_priv = filep->private_data;
struct gpib_descriptor *desc;
unsigned int pad;
int sad;
int retval;
retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd));
@@ -1284,19 +1312,27 @@ static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigne
if (cmd.handle >= GPIB_MAX_NUM_DESCRIPTORS)
return -EINVAL;
if (!file_priv->descriptors[cmd.handle])
mutex_lock(&file_priv->descriptors_mutex);
desc = file_priv->descriptors[cmd.handle];
if (!desc) {
mutex_unlock(&file_priv->descriptors_mutex);
return -EINVAL;
retval = decrement_open_device_count(board, &board->device_list,
file_priv->descriptors[cmd.handle]->pad,
file_priv->descriptors[cmd.handle]->sad);
if (retval < 0)
return retval;
kfree(file_priv->descriptors[cmd.handle]);
}
if (atomic_read(&desc->descriptor_busy)) {
mutex_unlock(&file_priv->descriptors_mutex);
return -EBUSY;
}
/* Remove from table while holding lock to prevent new IO from starting */
file_priv->descriptors[cmd.handle] = NULL;
pad = desc->pad;
sad = desc->sad;
mutex_unlock(&file_priv->descriptors_mutex);
return 0;
retval = decrement_open_device_count(board, &board->device_list, pad, sad);
kfree(desc);
return retval;
}
static int serial_poll_ioctl(struct gpib_board *board, unsigned long arg)
@@ -1331,12 +1367,25 @@ static int wait_ioctl(struct gpib_file_private *file_priv, struct gpib_board *bo
if (retval)
return -EFAULT;
/*
* Lock descriptors to prevent concurrent close from freeing
* descriptor. ibwait() releases big_gpib_mutex when wait_mask
* is non-zero, so desc must be pinned with descriptor_busy.
*/
mutex_lock(&file_priv->descriptors_mutex);
desc = handle_to_descriptor(file_priv, wait_cmd.handle);
if (!desc)
if (!desc) {
mutex_unlock(&file_priv->descriptors_mutex);
return -EINVAL;
}
atomic_inc(&desc->descriptor_busy);
mutex_unlock(&file_priv->descriptors_mutex);
retval = ibwait(board, wait_cmd.wait_mask, wait_cmd.clear_mask,
wait_cmd.set_mask, &wait_cmd.ibsta, wait_cmd.usec_timeout, desc);
atomic_dec(&desc->descriptor_busy);
if (retval < 0)
return retval;
@@ -2035,6 +2084,7 @@ void init_gpib_descriptor(struct gpib_descriptor *desc)
desc->is_board = 0;
desc->autopoll_enabled = 0;
atomic_set(&desc->io_in_progress, 0);
atomic_set(&desc->descriptor_busy, 0);
}
int gpib_register_driver(struct gpib_interface *interface, struct module *provider_module)

View File

@@ -364,6 +364,14 @@ struct gpib_descriptor {
unsigned int pad; /* primary gpib address */
int sad; /* secondary gpib address (negative means disabled) */
atomic_t io_in_progress;
/*
* Kernel-only reference count to prevent descriptor from being
* freed while IO handlers hold a pointer to it. Incremented
* before each IO operation, decremented when done. Unlike
* io_in_progress, this cannot be modified from userspace via
* general_ibstatus().
*/
atomic_t descriptor_busy;
unsigned is_board : 1;
unsigned autopoll_enabled : 1;
};

View File

@@ -406,7 +406,7 @@ static int usb_gpib_attach(struct gpib_board *board, const struct gpib_board_con
for (j = 0 ; j < MAX_DEV ; j++) {
if ((assigned_usb_minors & 1 << j) == 0)
continue;
udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j]));
udev = interface_to_usbdev(lpvo_usb_interfaces[j]);
device_path = kobject_get_path(&udev->dev.kobj, GFP_KERNEL);
match = gpib_match_device_path(&lpvo_usb_interfaces[j]->dev,
config->device_path);
@@ -421,7 +421,7 @@ static int usb_gpib_attach(struct gpib_board *board, const struct gpib_board_con
for (j = 0 ; j < MAX_DEV ; j++) {
if ((assigned_usb_minors & 1 << j) == 0)
continue;
udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j]));
udev = interface_to_usbdev(lpvo_usb_interfaces[j]);
DIA_LOG(1, "dev. %d: bus %d -> %d dev: %d -> %d\n", j,
udev->bus->busnum, config->pci_bus, udev->devnum, config->pci_slot);
if (config->pci_bus == udev->bus->busnum &&

View File

@@ -584,12 +584,13 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
unsigned long config;
bool ret = false;
int i, type;
bool is_imx8qm = of_device_is_compatible(port->dev->of_node, "fsl,imx8qm-gpio");
static const u32 pad_type_map[] = {
IMX_SCU_WAKEUP_OFF, /* 0 */
IMX_SCU_WAKEUP_RISE_EDGE, /* IRQ_TYPE_EDGE_RISING */
IMX_SCU_WAKEUP_FALL_EDGE, /* IRQ_TYPE_EDGE_FALLING */
IMX_SCU_WAKEUP_FALL_EDGE, /* IRQ_TYPE_EDGE_BOTH */
IMX_SCU_WAKEUP_RISE_EDGE, /* IRQ_TYPE_EDGE_BOTH */
IMX_SCU_WAKEUP_HIGH_LVL, /* IRQ_TYPE_LEVEL_HIGH */
IMX_SCU_WAKEUP_OFF, /* 5 */
IMX_SCU_WAKEUP_OFF, /* 6 */
@@ -604,6 +605,13 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
config = pad_type_map[type];
else
config = IMX_SCU_WAKEUP_OFF;
if (is_imx8qm && config == IMX_SCU_WAKEUP_FALL_EDGE) {
dev_warn_once(port->dev,
"No falling-edge support for wakeup on i.MX8QM\n");
config = IMX_SCU_WAKEUP_OFF;
}
ret |= mxc_gpio_generic_config(port, i, config);
}
}

View File

@@ -60,8 +60,8 @@ static int qixis_cpld_gpio_probe(struct platform_device *pdev)
return PTR_ERR(reg);
regmap = devm_regmap_init_mmio(&pdev->dev, reg, &regmap_config_8r_8v);
if (!regmap)
return -ENODEV;
if (IS_ERR(regmap))
return PTR_ERR(regmap);
/* In this case, the offset of our register is 0 inside the
* regmap area that we just created.

View File

@@ -443,8 +443,8 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer,
}
#endif /* CONFIG_RESET_GPIO */
int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
unsigned long lflags)
int gpio_shared_add_proxy_lookup(struct device *consumer, struct fwnode_handle *fwnode,
const char *con_id, unsigned long lflags)
{
const char *dev_id = dev_name(consumer);
struct gpiod_lookup_table *lookup;
@@ -458,7 +458,7 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
if (!ref->fwnode && device_is_compatible(consumer, "reset-gpio")) {
if (!gpio_shared_dev_is_reset_gpio(consumer, entry, ref))
continue;
} else if (!device_match_fwnode(consumer, ref->fwnode)) {
} else if (fwnode != ref->fwnode) {
continue;
}
@@ -506,8 +506,9 @@ static void gpio_shared_remove_adev(struct auxiliary_device *adev)
auxiliary_device_uninit(adev);
}
int gpio_device_setup_shared(struct gpio_device *gdev)
int gpiochip_setup_shared(struct gpio_chip *gc)
{
struct gpio_device *gdev = gc->gpiodev;
struct gpio_shared_entry *entry;
struct gpio_shared_ref *ref;
struct gpio_desc *desc;
@@ -538,20 +539,42 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
if (list_count_nodes(&entry->refs) <= 1)
continue;
desc = &gdev->descs[entry->offset];
scoped_guard(mutex, &entry->lock) {
#if IS_ENABLED(CONFIG_OF)
if (is_of_node(entry->fwnode) && gc->of_xlate) {
/*
* This is the earliest that we can tranlate the
* devicetree offset to the chip offset.
*/
struct of_phandle_args gpiospec = { };
__set_bit(GPIOD_FLAG_SHARED, &desc->flags);
/*
* Shared GPIOs are not requested via the normal path. Make
* them inaccessible to anyone even before we register the
* chip.
*/
ret = gpiod_request_commit(desc, "shared");
if (ret)
return ret;
gpiospec.np = to_of_node(entry->fwnode);
gpiospec.args_count = 2;
gpiospec.args[0] = entry->offset;
pr_debug("GPIO %u owned by %s is shared by multiple consumers\n",
entry->offset, gpio_device_get_label(gdev));
ret = gc->of_xlate(gc, &gpiospec, NULL);
if (ret < 0)
return ret;
entry->offset = ret;
}
#endif /* CONFIG_OF */
desc = &gdev->descs[entry->offset];
__set_bit(GPIOD_FLAG_SHARED, &desc->flags);
/*
* Shared GPIOs are not requested via the normal path. Make
* them inaccessible to anyone even before we register the
* chip.
*/
ret = gpiod_request_commit(desc, "shared");
if (ret)
return ret;
pr_debug("GPIO %u owned by %s is shared by multiple consumers\n",
entry->offset, gpio_device_get_label(gdev));
}
list_for_each_entry(ref, &entry->refs, list) {
pr_debug("Setting up a shared GPIO entry for %s (con_id: '%s')\n",
@@ -575,6 +598,8 @@ void gpio_device_teardown_shared(struct gpio_device *gdev)
struct gpio_shared_ref *ref;
list_for_each_entry(entry, &gpio_shared_list, list) {
guard(mutex)(&entry->lock);
if (!device_match_fwnode(&gdev->dev, entry->fwnode))
continue;

View File

@@ -11,17 +11,19 @@
struct gpio_device;
struct gpio_desc;
struct device;
struct fwnode_handle;
#if IS_ENABLED(CONFIG_GPIO_SHARED)
int gpio_device_setup_shared(struct gpio_device *gdev);
int gpiochip_setup_shared(struct gpio_chip *gc);
void gpio_device_teardown_shared(struct gpio_device *gdev);
int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
unsigned long lflags);
int gpio_shared_add_proxy_lookup(struct device *consumer,
struct fwnode_handle *fwnode,
const char *con_id, unsigned long lflags);
#else
static inline int gpio_device_setup_shared(struct gpio_device *gdev)
static inline int gpiochip_setup_shared(struct gpio_chip *gc)
{
return 0;
}
@@ -29,6 +31,7 @@ static inline int gpio_device_setup_shared(struct gpio_device *gdev)
static inline void gpio_device_teardown_shared(struct gpio_device *gdev) { }
static inline int gpio_shared_add_proxy_lookup(struct device *consumer,
struct fwnode_handle *fwnode,
const char *con_id,
unsigned long lflags)
{

View File

@@ -892,13 +892,15 @@ static const struct device_type gpio_dev_type = {
#define gcdev_unregister(gdev) device_del(&(gdev)->dev)
#endif
/*
* An initial reference count has been held in gpiochip_add_data_with_key().
* The caller should drop the reference via gpio_device_put() on errors.
*/
static int gpiochip_setup_dev(struct gpio_device *gdev)
{
struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev);
int ret;
device_initialize(&gdev->dev);
/*
* If fwnode doesn't belong to another device, it's safe to clear its
* initialized flag.
@@ -964,9 +966,11 @@ static void gpiochip_setup_devs(void)
list_for_each_entry_srcu(gdev, &gpio_devices, list,
srcu_read_lock_held(&gpio_devices_srcu)) {
ret = gpiochip_setup_dev(gdev);
if (ret)
if (ret) {
gpio_device_put(gdev);
dev_err(&gdev->dev,
"Failed to initialize gpio device (%d)\n", ret);
}
}
}
@@ -1047,33 +1051,65 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
int base = 0;
int ret;
/*
* First: allocate and populate the internal stat container, and
* set up the struct device.
*/
gdev = kzalloc(sizeof(*gdev), GFP_KERNEL);
if (!gdev)
return -ENOMEM;
gdev->dev.type = &gpio_dev_type;
gdev->dev.bus = &gpio_bus_type;
gdev->dev.parent = gc->parent;
rcu_assign_pointer(gdev->chip, gc);
gc->gpiodev = gdev;
gpiochip_set_data(gc, data);
device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc));
ret = ida_alloc(&gpio_ida, GFP_KERNEL);
if (ret < 0)
goto err_free_gdev;
gdev->id = ret;
ret = dev_set_name(&gdev->dev, GPIOCHIP_NAME "%d", gdev->id);
ret = init_srcu_struct(&gdev->srcu);
if (ret)
goto err_free_ida;
rcu_assign_pointer(gdev->chip, gc);
ret = init_srcu_struct(&gdev->desc_srcu);
if (ret)
goto err_cleanup_gdev_srcu;
ret = dev_set_name(&gdev->dev, GPIOCHIP_NAME "%d", gdev->id);
if (ret)
goto err_cleanup_desc_srcu;
device_initialize(&gdev->dev);
/*
* After this point any allocated resources to `gdev` will be
* free():ed by gpiodev_release(). If you add new resources
* then make sure they get free():ed there.
*/
gdev->dev.type = &gpio_dev_type;
gdev->dev.bus = &gpio_bus_type;
gdev->dev.parent = gc->parent;
device_set_node(&gdev->dev, gpiochip_choose_fwnode(gc));
ret = gpiochip_get_ngpios(gc, &gdev->dev);
if (ret)
goto err_put_device;
gdev->ngpio = gc->ngpio;
gdev->descs = kcalloc(gc->ngpio, sizeof(*gdev->descs), GFP_KERNEL);
if (!gdev->descs) {
ret = -ENOMEM;
goto err_put_device;
}
gdev->label = kstrdup_const(gc->label ?: "unknown", GFP_KERNEL);
if (!gdev->label) {
ret = -ENOMEM;
goto err_put_device;
}
gdev->can_sleep = gc->can_sleep;
rwlock_init(&gdev->line_state_lock);
RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
#ifdef CONFIG_PINCTRL
INIT_LIST_HEAD(&gdev->pin_ranges);
#endif
if (gc->parent && gc->parent->driver)
gdev->owner = gc->parent->driver->owner;
else if (gc->owner)
@@ -1082,37 +1118,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
else
gdev->owner = THIS_MODULE;
ret = gpiochip_get_ngpios(gc, &gdev->dev);
if (ret)
goto err_free_dev_name;
gdev->descs = kcalloc(gc->ngpio, sizeof(*gdev->descs), GFP_KERNEL);
if (!gdev->descs) {
ret = -ENOMEM;
goto err_free_dev_name;
}
gdev->label = kstrdup_const(gc->label ?: "unknown", GFP_KERNEL);
if (!gdev->label) {
ret = -ENOMEM;
goto err_free_descs;
}
gdev->ngpio = gc->ngpio;
gdev->can_sleep = gc->can_sleep;
rwlock_init(&gdev->line_state_lock);
RAW_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
ret = init_srcu_struct(&gdev->srcu);
if (ret)
goto err_free_label;
ret = init_srcu_struct(&gdev->desc_srcu);
if (ret)
goto err_cleanup_gdev_srcu;
scoped_guard(mutex, &gpio_devices_lock) {
/*
* TODO: this allocates a Linux GPIO number base in the global
@@ -1127,7 +1132,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (base < 0) {
ret = base;
base = 0;
goto err_cleanup_desc_srcu;
goto err_put_device;
}
/*
@@ -1147,14 +1152,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
ret = gpiodev_add_to_list_unlocked(gdev);
if (ret) {
gpiochip_err(gc, "GPIO integer space overlap, cannot add chip\n");
goto err_cleanup_desc_srcu;
goto err_put_device;
}
}
#ifdef CONFIG_PINCTRL
INIT_LIST_HEAD(&gdev->pin_ranges);
#endif
if (gc->names)
gpiochip_set_desc_names(gc);
@@ -1210,7 +1211,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (ret)
goto err_remove_irqchip_mask;
ret = gpio_device_setup_shared(gdev);
ret = gpiochip_setup_shared(gc);
if (ret)
goto err_remove_irqchip;
@@ -1248,25 +1249,19 @@ err_remove_from_list:
scoped_guard(mutex, &gpio_devices_lock)
list_del_rcu(&gdev->list);
synchronize_srcu(&gpio_devices_srcu);
if (gdev->dev.release) {
/* release() has been registered by gpiochip_setup_dev() */
gpio_device_put(gdev);
goto err_print_message;
}
err_put_device:
gpio_device_put(gdev);
goto err_print_message;
err_cleanup_desc_srcu:
cleanup_srcu_struct(&gdev->desc_srcu);
err_cleanup_gdev_srcu:
cleanup_srcu_struct(&gdev->srcu);
err_free_label:
kfree_const(gdev->label);
err_free_descs:
kfree(gdev->descs);
err_free_dev_name:
kfree(dev_name(&gdev->dev));
err_free_ida:
ida_free(&gpio_ida, gdev->id);
err_free_gdev:
kfree(gdev);
err_print_message:
/* failures here can mean systems won't boot... */
if (ret != -EPROBE_DEFER) {
@@ -2465,8 +2460,10 @@ int gpiod_request_commit(struct gpio_desc *desc, const char *label)
return -EBUSY;
offset = gpiod_hwgpio(desc);
if (!gpiochip_line_is_valid(guard.gc, offset))
return -EINVAL;
if (!gpiochip_line_is_valid(guard.gc, offset)) {
ret = -EINVAL;
goto out_clear_bit;
}
/* NOTE: gpio_request() can be called in early boot,
* before IRQs are enabled, for non-sleeping (SOC) GPIOs.
@@ -4717,8 +4714,8 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
* lookup table for the proxy device as previously
* we only knew the consumer's fwnode.
*/
ret = gpio_shared_add_proxy_lookup(consumer, con_id,
lookupflags);
ret = gpio_shared_add_proxy_lookup(consumer, fwnode,
con_id, lookupflags);
if (ret)
return ERR_PTR(ret);

View File

@@ -368,8 +368,8 @@ void dcn401_init_hw(struct dc *dc)
dc->res_pool->funcs->update_bw_bounding_box &&
dc->clk_mgr && dc->clk_mgr->bw_params) {
/* update bounding box if FAMS2 disabled, or if dchub clk has changed */
if (dc->clk_mgr)
dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
dc->res_pool->funcs->update_bw_bounding_box(dc,
dc->clk_mgr->bw_params);
}
}
}

View File

@@ -71,6 +71,7 @@
#include "dce/dce_dmcu.h"
#include "dce/dce_aux.h"
#include "dce/dce_i2c.h"
#include "dio/dcn10/dcn10_dio.h"
#ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
#define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f
@@ -444,6 +445,33 @@ static const struct dcn_hubbub_mask hubbub_mask = {
HUBBUB_MASK_SH_LIST_DCN10(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static struct dio *dcn10_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static int map_transmitter_id_to_phy_instance(
enum transmitter transmitter)
{
@@ -918,6 +946,11 @@ static void dcn10_resource_destruct(struct dcn10_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.opps[i] != NULL)
pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
@@ -1663,6 +1696,14 @@ static bool dcn10_resource_construct(
goto fail;
}
/* DIO */
pool->base.dio = dcn10_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto fail;
}
if (!resource_construct(num_virtual_links, dc, &pool->base,
&res_create_funcs))
goto fail;

View File

@@ -82,6 +82,7 @@
#include "dce/dce_dmcu.h"
#include "dce/dce_aux.h"
#include "dce/dce_i2c.h"
#include "dio/dcn10/dcn10_dio.h"
#include "vm_helper.h"
#include "link_enc_cfg.h"
@@ -550,6 +551,33 @@ static const struct dcn_hubbub_mask hubbub_mask = {
HUBBUB_MASK_SH_LIST_DCN20(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static struct dio *dcn20_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
#define vmid_regs(id)\
[id] = {\
DCN20_VMID_REG_LIST(id)\
@@ -1105,6 +1133,12 @@ static void dcn20_resource_destruct(struct dcn20_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn20_dpp_destroy(&pool->base.dpps[i]);
@@ -2709,6 +2743,14 @@ static bool dcn20_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn20_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
pool->base.dscs[i] = dcn20_dsc_create(ctx, i);
if (pool->base.dscs[i] == NULL) {

View File

@@ -56,6 +56,7 @@
#include "dce/dce_aux.h"
#include "dce/dce_i2c.h"
#include "dcn10/dcn10_resource.h"
#include "dio/dcn10/dcn10_dio.h"
#include "cyan_skillfish_ip_offset.h"
@@ -755,6 +756,33 @@ static struct hubbub *dcn201_hubbub_create(struct dc_context *ctx)
return &hubbub->base;
}
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static struct dio *dcn201_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct timing_generator *dcn201_timing_generator_create(
struct dc_context *ctx,
uint32_t instance)
@@ -930,6 +958,11 @@ static void dcn201_resource_destruct(struct dcn201_resource_pool *pool)
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn201_dpp_destroy(&pool->base.dpps[i]);
@@ -1277,6 +1310,14 @@ static bool dcn201_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn201_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
if (!resource_construct(num_virtual_links, dc, &pool->base,
&res_create_funcs))
goto create_fail;

View File

@@ -84,6 +84,7 @@
#include "dce/dce_dmcu.h"
#include "dce/dce_aux.h"
#include "dce/dce_i2c.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dcn21_resource.h"
#include "vm_helper.h"
#include "dcn20/dcn20_vmid.h"
@@ -329,6 +330,25 @@ static const struct dcn_hubbub_mask hubbub_mask = {
HUBBUB_MASK_SH_LIST_DCN21(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
static const struct dcn_dio_shift dio_shift = { 0 };
static const struct dcn_dio_mask dio_mask = { 0 };
static struct dio *dcn21_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
#define vmid_regs(id)\
[id] = {\
@@ -677,6 +697,12 @@ static void dcn21_resource_destruct(struct dcn21_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn20_dpp_destroy(&pool->base.dpps[i]);
@@ -1662,6 +1688,14 @@ static bool dcn21_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn21_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
pool->base.dscs[i] = dcn21_dsc_create(ctx, i);
if (pool->base.dscs[i] == NULL) {

View File

@@ -60,6 +60,7 @@
#include "dml/display_mode_vba.h"
#include "dcn30/dcn30_dccg.h"
#include "dcn10/dcn10_resource.h"
#include "dio/dcn10/dcn10_dio.h"
#include "link_service.h"
#include "dce/dce_panel_cntl.h"
@@ -886,6 +887,33 @@ static struct hubbub *dcn30_hubbub_create(struct dc_context *ctx)
return &hubbub3->base;
}
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static struct dio *dcn30_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct timing_generator *dcn30_timing_generator_create(
struct dc_context *ctx,
uint32_t instance)
@@ -1096,6 +1124,12 @@ static void dcn30_resource_destruct(struct dcn30_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn30_dpp_destroy(&pool->base.dpps[i]);
@@ -2468,6 +2502,14 @@ static bool dcn30_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn30_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn30_hubp_create(ctx, i);

View File

@@ -59,6 +59,7 @@
#include "dml/display_mode_vba.h"
#include "dcn301/dcn301_dccg.h"
#include "dcn10/dcn10_resource.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dcn30/dcn30_dio_stream_encoder.h"
#include "dcn301/dcn301_dio_link_encoder.h"
#include "dcn301/dcn301_panel_cntl.h"
@@ -843,6 +844,33 @@ static struct hubbub *dcn301_hubbub_create(struct dc_context *ctx)
return &hubbub3->base;
}
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static struct dio *dcn301_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct timing_generator *dcn301_timing_generator_create(
struct dc_context *ctx, uint32_t instance)
{
@@ -1067,6 +1095,12 @@ static void dcn301_destruct(struct dcn301_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn301_dpp_destroy(&pool->base.dpps[i]);
@@ -1584,6 +1618,14 @@ static bool dcn301_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn301_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
j = 0;
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {

View File

@@ -46,6 +46,7 @@
#include "dml/dcn30/dcn30_fpu.h"
#include "dcn10/dcn10_resource.h"
#include "dio/dcn10/dcn10_dio.h"
#include "link_service.h"
@@ -253,6 +254,33 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static struct dio *dcn302_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn302_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1023,6 +1051,11 @@ static void dcn302_resource_destruct(struct resource_pool *pool)
pool->hubbub = NULL;
}
if (pool->dio != NULL) {
kfree(TO_DCN10_DIO(pool->dio));
pool->dio = NULL;
}
for (i = 0; i < pool->pipe_count; i++) {
if (pool->dpps[i] != NULL) {
kfree(TO_DCN20_DPP(pool->dpps[i]));
@@ -1374,6 +1407,14 @@ static bool dcn302_resource_construct(
goto create_fail;
}
/* DIO */
pool->dio = dcn302_dio_create(ctx);
if (pool->dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->pipe_count; i++) {
pool->hubps[i] = dcn302_hubp_create(ctx, i);

View File

@@ -46,6 +46,7 @@
#include "dml/dcn30/dcn30_fpu.h"
#include "dcn10/dcn10_resource.h"
#include "dio/dcn10/dcn10_dio.h"
#include "link_service.h"
@@ -249,6 +250,33 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static struct dio *dcn303_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn303_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -967,6 +995,11 @@ static void dcn303_resource_destruct(struct resource_pool *pool)
pool->hubbub = NULL;
}
if (pool->dio != NULL) {
kfree(TO_DCN10_DIO(pool->dio));
pool->dio = NULL;
}
for (i = 0; i < pool->pipe_count; i++) {
if (pool->dpps[i] != NULL) {
kfree(TO_DCN20_DPP(pool->dpps[i]));
@@ -1306,6 +1339,14 @@ static bool dcn303_resource_construct(
goto create_fail;
}
/* DIO */
pool->dio = dcn303_dio_create(ctx);
if (pool->dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->pipe_count; i++) {
pool->hubps[i] = dcn303_hubp_create(ctx, i);

View File

@@ -64,6 +64,7 @@
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
@@ -810,6 +811,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn31 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -1021,6 +1037,18 @@ static struct mpc *dcn31_mpc_create(
return &mpc30->base;
}
static struct dio *dcn31_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1397,6 +1425,10 @@ static void dcn31_resource_destruct(struct dcn31_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn31_dpp_destroy(&pool->base.dpps[i]);
@@ -2065,6 +2097,14 @@ static bool dcn31_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn31_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);

View File

@@ -66,6 +66,7 @@
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
@@ -822,6 +823,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn314 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -1079,6 +1095,18 @@ static struct mpc *dcn31_mpc_create(
return &mpc30->base;
}
static struct dio *dcn314_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1456,6 +1484,10 @@ static void dcn314_resource_destruct(struct dcn314_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn31_dpp_destroy(&pool->base.dpps[i]);
@@ -1992,6 +2024,14 @@ static bool dcn314_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn314_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);

View File

@@ -63,6 +63,7 @@
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
@@ -809,6 +810,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn31 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -1020,6 +1036,18 @@ static struct mpc *dcn31_mpc_create(
return &mpc30->base;
}
static struct dio *dcn315_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1398,6 +1426,10 @@ static void dcn315_resource_destruct(struct dcn315_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn31_dpp_destroy(&pool->base.dpps[i]);
@@ -2015,6 +2047,14 @@ static bool dcn315_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn315_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);

View File

@@ -63,6 +63,7 @@
#include "dce/dce_audio.h"
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
@@ -804,6 +805,21 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static const struct dcn_dio_registers dio_regs = {
DIO_REG_LIST_DCN10()
};
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn31 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -1013,6 +1029,18 @@ static struct mpc *dcn31_mpc_create(
return &mpc30->base;
}
static struct dio *dcn316_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn31_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1393,6 +1421,10 @@ static void dcn316_resource_destruct(struct dcn316_resource_pool *pool)
kfree(pool->base.hubbub);
pool->base.hubbub = NULL;
}
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
for (i = 0; i < pool->base.pipe_count; i++) {
if (pool->base.dpps[i] != NULL)
dcn31_dpp_destroy(&pool->base.dpps[i]);
@@ -1891,6 +1923,14 @@ static bool dcn316_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn316_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn31_hubp_create(ctx, i);

View File

@@ -66,6 +66,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dml/display_mode_vba.h"
#include "dcn32/dcn32_dccg.h"
#include "dcn10/dcn10_resource.h"
@@ -643,6 +644,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static struct dcn_dio_registers dio_regs;
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn32 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -833,6 +847,22 @@ static struct clock_source *dcn32_clock_source_create(
return NULL;
}
static struct dio *dcn32_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
#undef REG_STRUCT
#define REG_STRUCT dio_regs
DIO_REG_LIST_DCN10();
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn32_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1494,6 +1524,11 @@ static void dcn32_resource_destruct(struct dcn32_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
if (pool->base.oem_device != NULL) {
struct dc *dc = pool->base.oem_device->ctx->dc;
@@ -2374,6 +2409,14 @@ static bool dcn32_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn32_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs, TGs, ABMs */
for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {

View File

@@ -69,6 +69,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dml/display_mode_vba.h"
#include "dcn32/dcn32_dccg.h"
#include "dcn10/dcn10_resource.h"
@@ -639,6 +640,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static struct dcn_dio_registers dio_regs;
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn321 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -827,6 +841,22 @@ static struct clock_source *dcn321_clock_source_create(
return NULL;
}
static struct dio *dcn321_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
#undef REG_STRUCT
#define REG_STRUCT dio_regs
DIO_REG_LIST_DCN10();
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn321_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1474,6 +1504,11 @@ static void dcn321_resource_destruct(struct dcn321_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
if (pool->base.oem_device != NULL) {
struct dc *dc = pool->base.oem_device->ctx->dc;
@@ -1873,6 +1908,14 @@ static bool dcn321_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn321_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs, TGs, ABMs */
for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {

View File

@@ -71,6 +71,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
#include "dcn35/dcn35_dccg.h"
@@ -664,6 +665,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static struct dcn_dio_registers dio_regs;
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn35 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -973,6 +987,22 @@ static struct mpc *dcn35_mpc_create(
return &mpc30->base;
}
static struct dio *dcn35_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
#undef REG_STRUCT
#define REG_STRUCT dio_regs
DIO_REG_LIST_DCN10();
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1563,6 +1593,11 @@ static void dcn35_resource_destruct(struct dcn35_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
}
static struct hubp *dcn35_hubp_create(
@@ -2045,6 +2080,14 @@ static bool dcn35_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn35_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);

View File

@@ -50,6 +50,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
#include "dcn35/dcn35_dccg.h"
@@ -644,6 +645,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static struct dcn_dio_registers dio_regs;
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn351 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -953,6 +967,22 @@ static struct mpc *dcn35_mpc_create(
return &mpc30->base;
}
static struct dio *dcn351_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
#undef REG_STRUCT
#define REG_STRUCT dio_regs
DIO_REG_LIST_DCN10();
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1543,6 +1573,11 @@ static void dcn351_resource_destruct(struct dcn351_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
}
static struct hubp *dcn35_hubp_create(
@@ -2017,6 +2052,14 @@ static bool dcn351_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn351_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);

View File

@@ -50,6 +50,7 @@
#include "dce/dce_hwseq.h"
#include "clk_mgr.h"
#include "dio/virtual/virtual_stream_encoder.h"
#include "dio/dcn10/dcn10_dio.h"
#include "dce110/dce110_resource.h"
#include "dml/display_mode_vba.h"
#include "dcn35/dcn35_dccg.h"
@@ -651,6 +652,19 @@ static const struct dcn20_vmid_mask vmid_masks = {
DCN20_VMID_MASK_SH_LIST(_MASK)
};
static struct dcn_dio_registers dio_regs;
#define DIO_MASK_SH_LIST(mask_sh)\
HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh)
static const struct dcn_dio_shift dio_shift = {
DIO_MASK_SH_LIST(__SHIFT)
};
static const struct dcn_dio_mask dio_mask = {
DIO_MASK_SH_LIST(_MASK)
};
static const struct resource_caps res_cap_dcn36 = {
.num_timing_generator = 4,
.num_opp = 4,
@@ -960,6 +974,22 @@ static struct mpc *dcn35_mpc_create(
return &mpc30->base;
}
static struct dio *dcn36_dio_create(struct dc_context *ctx)
{
struct dcn10_dio *dio10 = kzalloc_obj(struct dcn10_dio);
if (!dio10)
return NULL;
#undef REG_STRUCT
#define REG_STRUCT dio_regs
DIO_REG_LIST_DCN10();
dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask);
return &dio10->base;
}
static struct hubbub *dcn35_hubbub_create(struct dc_context *ctx)
{
int i;
@@ -1550,6 +1580,11 @@ static void dcn36_resource_destruct(struct dcn36_resource_pool *pool)
if (pool->base.dccg != NULL)
dcn_dccg_destroy(&pool->base.dccg);
if (pool->base.dio != NULL) {
kfree(TO_DCN10_DIO(pool->base.dio));
pool->base.dio = NULL;
}
}
static struct hubp *dcn35_hubp_create(
@@ -2015,6 +2050,14 @@ static bool dcn36_resource_construct(
goto create_fail;
}
/* DIO */
pool->base.dio = dcn36_dio_create(ctx);
if (pool->base.dio == NULL) {
BREAK_TO_DEBUGGER();
dm_error("DC: failed to create dio!\n");
goto create_fail;
}
/* HUBPs, DPPs, OPPs and TGs */
for (i = 0; i < pool->base.pipe_count; i++) {
pool->base.hubps[i] = dcn35_hubp_create(ctx, i);

View File

@@ -436,7 +436,7 @@ static void ast_init_analog(struct ast_device *ast)
/* Finally, clear bits [17:16] of SCU2c */
data = ast_read32(ast, 0x1202c);
data &= 0xfffcffff;
ast_write32(ast, 0, data);
ast_write32(ast, 0x1202c, data);
/* Disable DVO */
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xcf, 0x00);

View File

@@ -1603,11 +1603,17 @@ EXPORT_SYMBOL(devm_drm_put_bridge);
static void drm_bridge_debugfs_show_bridge(struct drm_printer *p,
struct drm_bridge *bridge,
unsigned int idx,
bool lingering)
bool lingering,
bool scoped)
{
unsigned int refcount = kref_read(&bridge->refcount);
if (scoped)
refcount--;
drm_printf(p, "bridge[%u]: %ps\n", idx, bridge->funcs);
drm_printf(p, "\trefcount: %u%s\n", kref_read(&bridge->refcount),
drm_printf(p, "\trefcount: %u%s\n", refcount,
lingering ? " [lingering]" : "");
drm_printf(p, "\ttype: [%d] %s\n",
@@ -1641,10 +1647,10 @@ static int allbridges_show(struct seq_file *m, void *data)
mutex_lock(&bridge_lock);
list_for_each_entry(bridge, &bridge_list, list)
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false);
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, false);
list_for_each_entry(bridge, &bridge_lingering_list, list)
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, true);
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, true, false);
mutex_unlock(&bridge_lock);
@@ -1659,7 +1665,7 @@ static int encoder_bridges_show(struct seq_file *m, void *data)
unsigned int idx = 0;
drm_for_each_bridge_in_chain_scoped(encoder, bridge)
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false);
drm_bridge_debugfs_show_bridge(&p, bridge, idx++, false, true);
return 0;
}

View File

@@ -233,7 +233,6 @@ static void drm_events_release(struct drm_file *file_priv)
void drm_file_free(struct drm_file *file)
{
struct drm_device *dev;
int idx;
if (!file)
return;
@@ -250,11 +249,9 @@ void drm_file_free(struct drm_file *file)
drm_events_release(file);
if (drm_core_check_feature(dev, DRIVER_MODESET) &&
drm_dev_enter(dev, &idx)) {
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
drm_fb_release(file);
drm_property_destroy_user_blobs(dev, file);
drm_dev_exit(idx);
}
if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))

View File

@@ -28,6 +28,7 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
#include <linux/nospec.h>
#include <linux/ratelimit.h>
#include <linux/export.h>
@@ -374,6 +375,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (nr >= ARRAY_SIZE(drm_compat_ioctls))
return drm_ioctl(filp, cmd, arg);
nr = array_index_nospec(nr, ARRAY_SIZE(drm_compat_ioctls));
fn = drm_compat_ioctls[nr].fn;
if (!fn)
return drm_ioctl(filp, cmd, arg);

View File

@@ -589,13 +589,10 @@ void drm_mode_config_cleanup(struct drm_device *dev)
*/
WARN_ON(!list_empty(&dev->mode_config.fb_list));
list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) {
struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
drm_framebuffer_print_info(&p, 1, fb);
}
list_del_init(&fb->filp_head);
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
drm_framebuffer_print_info(&p, 1, fb);
drm_framebuffer_free(&fb->base.refcount);
}

View File

@@ -136,7 +136,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
intel_dp->DP |= DP_SYNC_VS_HIGH;
intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
if (pipe_config->enhanced_framing)
intel_dp->DP |= DP_ENHANCED_FRAMING;
intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);

View File

@@ -2972,6 +2972,53 @@ static int intel_cdclk_update_crtc_min_cdclk(struct intel_atomic_state *state,
return 0;
}
static int intel_cdclk_update_crtc_min_voltage_level(struct intel_atomic_state *state,
struct intel_crtc *crtc,
u8 old_min_voltage_level,
u8 new_min_voltage_level,
bool *need_cdclk_calc)
{
struct intel_display *display = to_intel_display(state);
struct intel_cdclk_state *cdclk_state;
bool allow_voltage_level_decrease = intel_any_crtc_needs_modeset(state);
int ret;
if (new_min_voltage_level == old_min_voltage_level)
return 0;
if (!allow_voltage_level_decrease &&
new_min_voltage_level < old_min_voltage_level)
return 0;
cdclk_state = intel_atomic_get_cdclk_state(state);
if (IS_ERR(cdclk_state))
return PTR_ERR(cdclk_state);
old_min_voltage_level = cdclk_state->min_voltage_level[crtc->pipe];
if (new_min_voltage_level == old_min_voltage_level)
return 0;
if (!allow_voltage_level_decrease &&
new_min_voltage_level < old_min_voltage_level)
return 0;
cdclk_state->min_voltage_level[crtc->pipe] = new_min_voltage_level;
ret = intel_atomic_lock_global_state(&cdclk_state->base);
if (ret)
return ret;
*need_cdclk_calc = true;
drm_dbg_kms(display->drm,
"[CRTC:%d:%s] min voltage level: %d -> %d\n",
crtc->base.base.id, crtc->base.name,
old_min_voltage_level, new_min_voltage_level);
return 0;
}
int intel_cdclk_update_dbuf_bw_min_cdclk(struct intel_atomic_state *state,
int old_min_cdclk, int new_min_cdclk,
bool *need_cdclk_calc)
@@ -3387,6 +3434,13 @@ static int intel_crtcs_calc_min_cdclk(struct intel_atomic_state *state,
need_cdclk_calc);
if (ret)
return ret;
ret = intel_cdclk_update_crtc_min_voltage_level(state, crtc,
old_crtc_state->min_voltage_level,
new_crtc_state->min_voltage_level,
need_cdclk_calc);
if (ret)
return ret;
}
return 0;

View File

@@ -898,6 +898,8 @@ static struct i915_vma *eb_lookup_vma(struct i915_execbuffer *eb, u32 handle)
vma = radix_tree_lookup(&eb->gem_context->handles_vma, handle);
if (likely(vma && vma->vm == vm))
vma = i915_vma_tryget(vma);
else
vma = NULL;
rcu_read_unlock();
if (likely(vma))
return vma;

View File

@@ -157,7 +157,6 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
struct drm_sysfb_device *sysfb;
struct drm_device *dev;
struct resource *mem = NULL;
void __iomem *screen_base = NULL;
struct drm_plane *primary_plane;
struct drm_crtc *crtc;
struct drm_encoder *encoder;
@@ -244,21 +243,38 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv,
mem_flags = efidrm_get_mem_flags(dev, res->start, vsize);
if (mem_flags & EFI_MEMORY_WC)
screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem));
else if (mem_flags & EFI_MEMORY_UC)
screen_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
else if (mem_flags & EFI_MEMORY_WT)
screen_base = devm_memremap(&pdev->dev, mem->start, resource_size(mem),
MEMREMAP_WT);
else if (mem_flags & EFI_MEMORY_WB)
screen_base = devm_memremap(&pdev->dev, mem->start, resource_size(mem),
MEMREMAP_WB);
else
if (mem_flags & EFI_MEMORY_WC) {
void __iomem *screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
resource_size(mem));
if (!screen_base)
return ERR_PTR(-ENXIO);
iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
} else if (mem_flags & EFI_MEMORY_UC) {
void __iomem *screen_base = devm_ioremap(&pdev->dev, mem->start,
resource_size(mem));
if (!screen_base)
return ERR_PTR(-ENXIO);
iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
} else if (mem_flags & EFI_MEMORY_WT) {
void *screen_base = devm_memremap(&pdev->dev, mem->start,
resource_size(mem), MEMREMAP_WT);
if (IS_ERR(screen_base))
return ERR_CAST(screen_base);
iosys_map_set_vaddr(&sysfb->fb_addr, screen_base);
} else if (mem_flags & EFI_MEMORY_WB) {
void *screen_base = devm_memremap(&pdev->dev, mem->start,
resource_size(mem), MEMREMAP_WB);
if (IS_ERR(screen_base))
return ERR_CAST(screen_base);
iosys_map_set_vaddr(&sysfb->fb_addr, screen_base);
} else {
drm_err(dev, "invalid mem_flags: 0x%llx\n", mem_flags);
if (!screen_base)
return ERR_PTR(-ENOMEM);
iosys_map_set_vaddr_iomem(&sysfb->fb_addr, screen_base);
return ERR_PTR(-EINVAL);
}
/*
* Modesetting

View File

@@ -833,6 +833,14 @@ static void detect_preproduction_hw(struct xe_device *xe)
}
}
static void xe_device_wedged_fini(struct drm_device *drm, void *arg)
{
struct xe_device *xe = arg;
if (atomic_read(&xe->wedged.flag))
xe_pm_runtime_put(xe);
}
int xe_device_probe(struct xe_device *xe)
{
struct xe_tile *tile;
@@ -1009,6 +1017,10 @@ int xe_device_probe(struct xe_device *xe)
detect_preproduction_hw(xe);
err = drmm_add_action_or_reset(&xe->drm, xe_device_wedged_fini, xe);
if (err)
goto err_unregister_display;
return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe);
err_unregister_display:
@@ -1240,13 +1252,6 @@ u64 xe_device_uncanonicalize_addr(struct xe_device *xe, u64 address)
return address & GENMASK_ULL(xe->info.va_bits - 1, 0);
}
static void xe_device_wedged_fini(struct drm_device *drm, void *arg)
{
struct xe_device *xe = arg;
xe_pm_runtime_put(xe);
}
/**
* DOC: Xe Device Wedging
*
@@ -1324,15 +1329,9 @@ void xe_device_declare_wedged(struct xe_device *xe)
return;
}
xe_pm_runtime_get_noresume(xe);
if (drmm_add_action_or_reset(&xe->drm, xe_device_wedged_fini, xe)) {
drm_err(&xe->drm, "Failed to register xe_device_wedged_fini clean-up. Although device is wedged.\n");
return;
}
if (!atomic_xchg(&xe->wedged.flag, 1)) {
xe->needs_flr_on_fini = true;
xe_pm_runtime_get_noresume(xe);
drm_err(&xe->drm,
"CRITICAL: Xe has declared device %s as wedged.\n"
"IOCTLs and executions are blocked.\n"

View File

@@ -380,6 +380,18 @@ int xe_pxp_init(struct xe_device *xe)
return 0;
}
/*
* On PTL, older GSC FWs have a bug that can cause them to crash during
* PXP invalidation events, which leads to a complete loss of power
* management on the media GT. Therefore, we can't use PXP on FWs that
* have this bug, which was fixed in PTL GSC build 1396.
*/
if (xe->info.platform == XE_PANTHERLAKE &&
gt->uc.gsc.fw.versions.found[XE_UC_FW_VER_RELEASE].build < 1396) {
drm_info(&xe->drm, "PXP requires PTL GSC build 1396 or newer\n");
return 0;
}
pxp = drmm_kzalloc(&xe->drm, sizeof(struct xe_pxp), GFP_KERNEL);
if (!pxp) {
err = -ENOMEM;
@@ -512,7 +524,7 @@ static int __exec_queue_add(struct xe_pxp *pxp, struct xe_exec_queue *q)
static int pxp_start(struct xe_pxp *pxp, u8 type)
{
int ret = 0;
bool restart = false;
bool restart;
if (!xe_pxp_is_enabled(pxp))
return -ENODEV;
@@ -541,6 +553,8 @@ wait_for_idle:
msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS)))
return -ETIMEDOUT;
restart = false;
mutex_lock(&pxp->mutex);
/* If PXP is not already active, turn it on */
@@ -583,6 +597,7 @@ wait_for_idle:
drm_err(&pxp->xe->drm, "PXP termination failed before start\n");
mutex_lock(&pxp->mutex);
pxp->status = XE_PXP_ERROR;
complete_all(&pxp->termination);
goto out_unlock;
}
@@ -870,11 +885,6 @@ wait_for_activation:
pxp->key_instance++;
needs_queue_inval = true;
break;
default:
drm_err(&pxp->xe->drm, "unexpected state during PXP suspend: %u",
pxp->status);
ret = -EIO;
goto out;
}
/*
@@ -899,7 +909,6 @@ wait_for_activation:
pxp->last_suspend_key_instance = pxp->key_instance;
out:
return ret;
}

View File

@@ -931,7 +931,7 @@ int xe_svm_init(struct xe_vm *vm)
void xe_svm_close(struct xe_vm *vm)
{
xe_assert(vm->xe, xe_vm_is_closed(vm));
flush_work(&vm->svm.garbage_collector.work);
disable_work_sync(&vm->svm.garbage_collector.work);
xe_svm_put_pagemaps(vm);
drm_pagemap_release_owner(&vm->svm.peer);
}

View File

@@ -111,6 +111,8 @@ enum ec_sensors {
ec_sensor_temp_mb,
/* "T_Sensor" temperature sensor reading [℃] */
ec_sensor_temp_t_sensor,
/* like ec_sensor_temp_t_sensor, but at an alternate address [℃] */
ec_sensor_temp_t_sensor_alt1,
/* VRM temperature [℃] */
ec_sensor_temp_vrm,
/* VRM east (right) temperature [℃] */
@@ -160,6 +162,7 @@ enum ec_sensors {
#define SENSOR_TEMP_CPU_PACKAGE BIT(ec_sensor_temp_cpu_package)
#define SENSOR_TEMP_MB BIT(ec_sensor_temp_mb)
#define SENSOR_TEMP_T_SENSOR BIT(ec_sensor_temp_t_sensor)
#define SENSOR_TEMP_T_SENSOR_ALT1 BIT(ec_sensor_temp_t_sensor_alt1)
#define SENSOR_TEMP_VRM BIT(ec_sensor_temp_vrm)
#define SENSOR_TEMP_VRME BIT(ec_sensor_temp_vrme)
#define SENSOR_TEMP_VRMW BIT(ec_sensor_temp_vrmw)
@@ -279,6 +282,8 @@ static const struct ec_sensor_info sensors_family_amd_600[] = {
EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x33),
[ec_sensor_temp_t_sensor] =
EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x36),
[ec_sensor_temp_t_sensor_alt1] =
EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x37),
[ec_sensor_fan_cpu_opt] =
EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
[ec_sensor_temp_water_in] =
@@ -519,7 +524,7 @@ static const struct ec_board_info board_info_prime_x570_pro = {
static const struct ec_board_info board_info_prime_x670e_pro_wifi = {
.sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE |
SENSOR_TEMP_MB | SENSOR_TEMP_VRM |
SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT,
SENSOR_TEMP_T_SENSOR_ALT1 | SENSOR_FAN_CPU_OPT,
.mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
.family = family_amd_600_series,
};

View File

@@ -420,6 +420,12 @@ static ssize_t occ_show_freq_2(struct device *dev,
return sysfs_emit(buf, "%u\n", val);
}
static u64 occ_get_powr_avg(u64 accum, u32 samples)
{
return (samples == 0) ? 0 :
mul_u64_u32_div(accum, 1000000UL, samples);
}
static ssize_t occ_show_power_1(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -441,9 +447,8 @@ static ssize_t occ_show_power_1(struct device *dev,
val = get_unaligned_be16(&power->sensor_id);
break;
case 1:
val = get_unaligned_be32(&power->accumulator) /
get_unaligned_be32(&power->update_tag);
val *= 1000000ULL;
val = occ_get_powr_avg(get_unaligned_be32(&power->accumulator),
get_unaligned_be32(&power->update_tag));
break;
case 2:
val = (u64)get_unaligned_be32(&power->update_tag) *
@@ -459,12 +464,6 @@ static ssize_t occ_show_power_1(struct device *dev,
return sysfs_emit(buf, "%llu\n", val);
}
static u64 occ_get_powr_avg(u64 accum, u32 samples)
{
return (samples == 0) ? 0 :
mul_u64_u32_div(accum, 1000000UL, samples);
}
static ssize_t occ_show_power_2(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -725,7 +724,7 @@ static ssize_t occ_show_extended(struct device *dev,
switch (sattr->nr) {
case 0:
if (extn->flags & EXTN_FLAG_SENSOR_ID) {
rc = sysfs_emit(buf, "%u",
rc = sysfs_emit(buf, "%u\n",
get_unaligned_be32(&extn->sensor_id));
} else {
rc = sysfs_emit(buf, "%4phN\n", extn->name);

View File

@@ -173,3 +173,4 @@ module_i2c_driver(ltc4286_driver);
MODULE_AUTHOR("Delphine CC Chiu <Delphine_CC_Chiu@wiwynn.com>");
MODULE_DESCRIPTION("PMBUS driver for LTC4286 and compatibles");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("PMBUS");

View File

@@ -104,7 +104,10 @@ static int pxe1610_probe(struct i2c_client *client)
* By default this device doesn't boot to page 0, so set page 0
* to access all pmbus registers.
*/
i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
if (ret < 0)
return dev_err_probe(&client->dev, ret,
"Failed to set page 0\n");
/* Read Manufacturer id */
ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);

View File

@@ -103,10 +103,10 @@ static int tps53679_identify_chip(struct i2c_client *client,
}
ret = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, buf);
if (ret < 0)
return ret;
if (ret <= 0)
return ret < 0 ? ret : -EIO;
/* Adjust length if null terminator if present */
/* Adjust length if null terminator is present */
buf_len = (buf[ret - 1] != '\x00' ? ret : ret - 1);
id_len = strlen(id);
@@ -175,8 +175,8 @@ static int tps53676_identify(struct i2c_client *client,
ret = i2c_smbus_read_block_data(client, PMBUS_IC_DEVICE_ID, buf);
if (ret < 0)
return ret;
if (strncmp("TI\x53\x67\x60", buf, 5)) {
dev_err(&client->dev, "Unexpected device ID: %s\n", buf);
if (ret != 6 || memcmp(buf, "TI\x53\x67\x60\x00", 6)) {
dev_err(&client->dev, "Unexpected device ID: %*ph\n", ret, buf);
return -ENODEV;
}

Some files were not shown because too many files have changed in this diff Show More