Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Cross-merge networking fixes after downstream PR (net-7.0-rc6).

No conflicts, or adjacent changes.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-01-08 11:37:07 -08:00
commit 9ebcf66cd6
347 changed files with 4433 additions and 1586 deletions

View File

@ -587,6 +587,7 @@ Morten Welinder <terra@gnome.org>
Morten Welinder <welinder@anemone.rentec.com>
Morten Welinder <welinder@darter.rentec.com>
Morten Welinder <welinder@troll.com>
Muhammad Usama Anjum <usama.anjum@arm.com> <usama.anjum@collabora.com>
Mukesh Ojha <quic_mojha@quicinc.com> <mojha@codeaurora.org>
Muna Sinada <quic_msinada@quicinc.com> <msinada@codeaurora.org>
Murali Nalajala <quic_mnalajal@quicinc.com> <mnalajal@codeaurora.org>

View File

@ -149,11 +149,33 @@ For architectures that require cache flushing for DMA coherence
DMA_ATTR_MMIO will not perform any cache flushing. The address
provided must never be mapped cacheable into the CPU.
DMA_ATTR_CPU_CACHE_CLEAN
------------------------
DMA_ATTR_DEBUGGING_IGNORE_CACHELINES
------------------------------------
This attribute indicates the CPU will not dirty any cacheline overlapping this
DMA_FROM_DEVICE/DMA_BIDIRECTIONAL buffer while it is mapped. This allows
multiple small buffers to safely share a cacheline without risk of data
corruption, suppressing DMA debug warnings about overlapping mappings.
All mappings sharing a cacheline should have this attribute.
This attribute indicates that CPU cache lines may overlap for buffers mapped
with DMA_FROM_DEVICE or DMA_BIDIRECTIONAL.
Such overlap may occur when callers map multiple small buffers that reside
within the same cache line. In this case, callers must guarantee that the CPU
will not dirty these cache lines after the mappings are established. When this
condition is met, multiple buffers can safely share a cache line without risking
data corruption.
All mappings that share a cache line must set this attribute to suppress DMA
debug warnings about overlapping mappings.
DMA_ATTR_REQUIRE_COHERENT
-------------------------
DMA mapping requests with the DMA_ATTR_REQUIRE_COHERENT fail on any
system where SWIOTLB or cache management is required. This should only
be used to support uAPI designs that require continuous HW DMA
coherence with userspace processes, for example RDMA and DRM. At a
minimum the memory being mapped must be userspace memory from
pin_user_pages() or similar.
Drivers should consider using dma_mmap_pages() instead of this
interface when building their uAPIs, when possible.
It must never be used in an in-kernel driver that only works with
kernel memory.

View File

@ -19,9 +19,6 @@ description:
Flash sub nodes describe the memory range and optional per-flash
properties.
allOf:
- $ref: mtd.yaml#
properties:
compatible:
const: st,spear600-smi
@ -42,14 +39,29 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
description: Functional clock rate of the SMI controller in Hz.
st,smi-fast-mode:
type: boolean
description: Indicates that the attached flash supports fast read mode.
patternProperties:
"^flash@.*$":
$ref: /schemas/mtd/mtd.yaml#
properties:
reg:
maxItems: 1
st,smi-fast-mode:
type: boolean
description: Indicates that the attached flash supports fast read mode.
unevaluatedProperties: false
required:
- reg
required:
- compatible
- reg
- clock-rate
- "#address-cells"
- "#size-cells"
unevaluatedProperties: false
@ -64,7 +76,7 @@ examples:
interrupts = <12>;
clock-rate = <50000000>; /* 50 MHz */
flash@f8000000 {
flash@fc000000 {
reg = <0xfc000000 0x1000>;
st,smi-fast-mode;
};

View File

@ -168,7 +168,7 @@ properties:
offset from voltage set to regulator.
regulator-uv-protection-microvolt:
description: Set over under voltage protection limit. This is a limit where
description: Set under voltage protection limit. This is a limit where
hardware performs emergency shutdown. Zero can be passed to disable
protection and value '1' indicates that protection should be enabled but
limit setting can be omitted. Limit is given as microvolt offset from
@ -182,7 +182,7 @@ properties:
is given as microvolt offset from voltage set to regulator.
regulator-uv-warn-microvolt:
description: Set over under voltage warning limit. This is a limit where
description: Set under voltage warning limit. This is a limit where
hardware is assumed still to be functional but approaching limit where
it gets damaged. Recovery actions should be initiated. Zero can be passed
to disable detection and value '1' indicates that detection should

View File

@ -99,3 +99,51 @@ of the driver is decremented. All symlinks between the two are removed.
When a driver is removed, the list of devices that it supports is
iterated over, and the driver's remove callback is called for each
one. The device is removed from that list and the symlinks removed.
Driver Override
~~~~~~~~~~~~~~~
Userspace may override the standard matching by writing a driver name to
a device's ``driver_override`` sysfs attribute. When set, only a driver
whose name matches the override will be considered during binding. This
bypasses all bus-specific matching (OF, ACPI, ID tables, etc.).
The override may be cleared by writing an empty string, which returns
the device to standard matching rules. Writing to ``driver_override``
does not automatically unbind the device from its current driver or
make any attempt to load the specified driver.
Buses opt into this mechanism by setting the ``driver_override`` flag in
their ``struct bus_type``::
const struct bus_type example_bus_type = {
...
.driver_override = true,
};
When the flag is set, the driver core automatically creates the
``driver_override`` sysfs attribute for every device on that bus.
The bus's ``match()`` callback should check the override before performing
its own matching, using ``device_match_driver_override()``::
static int example_match(struct device *dev, const struct device_driver *drv)
{
int ret;
ret = device_match_driver_override(dev, drv);
if (ret >= 0)
return ret;
/* Fall through to bus-specific matching... */
}
``device_match_driver_override()`` returns > 0 if the override matches
the given driver, 0 if the override is set but does not match, or < 0 if
no override is set at all.
Additional helpers are available:
- ``device_set_driver_override()`` - set or clear the override from kernel code.
- ``device_has_driver_override()`` - check whether an override is set.

View File

@ -3986,7 +3986,7 @@ F: drivers/hwmon/asus-ec-sensors.c
ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
M: Corentin Chary <corentin.chary@gmail.com>
M: Luke D. Jones <luke@ljones.dev>
M: Denis Benato <benato.denis96@gmail.com>
M: Denis Benato <denis.benato@linux.dev>
L: platform-driver-x86@vger.kernel.org
S: Maintained
W: https://asus-linux.org/
@ -7998,7 +7998,9 @@ F: Documentation/devicetree/bindings/display/himax,hx8357.yaml
F: drivers/gpu/drm/tiny/hx8357d.c
DRM DRIVER FOR HYPERV SYNTHETIC VIDEO DEVICE
M: Deepak Rawat <drawat.floss@gmail.com>
M: Dexuan Cui <decui@microsoft.com>
M: Long Li <longli@microsoft.com>
M: Saurabh Sengar <ssengar@linux.microsoft.com>
L: linux-hyperv@vger.kernel.org
L: dri-devel@lists.freedesktop.org
S: Maintained
@ -24904,9 +24906,9 @@ F: drivers/clk/spear/
F: drivers/pinctrl/spear/
SPI NOR SUBSYSTEM
M: Tudor Ambarus <tudor.ambarus@linaro.org>
M: Pratyush Yadav <pratyush@kernel.org>
M: Michael Walle <mwalle@kernel.org>
R: Takahiro Kuwano <takahiro.kuwano@infineon.com>
L: linux-mtd@lists.infradead.org
S: Maintained
W: http://www.linux-mtd.infradead.org/

View File

@ -2,7 +2,7 @@
VERSION = 7
PATCHLEVEL = 0
SUBLEVEL = 0
EXTRAVERSION = -rc4
EXTRAVERSION = -rc5
NAME = Baby Opossum Posse
# *DOCUMENTATION*
@ -1654,7 +1654,7 @@ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
modules.builtin.ranges vmlinux.o.map vmlinux.unstripped \
compile_commands.json rust/test \
rust-project.json .vmlinux.objs .vmlinux.export.c \
.builtin-dtbs-list .builtin-dtb.S
.builtin-dtbs-list .builtin-dtbs.S
# Directories & files removed with 'make mrproper'
MRPROPER_FILES += include/config include/generated \

View File

@ -192,6 +192,14 @@ static int scs_handle_fde_frame(const struct eh_frame *frame,
size -= 2;
break;
case DW_CFA_advance_loc4:
loc += *opcode++ * code_alignment_factor;
loc += (*opcode++ << 8) * code_alignment_factor;
loc += (*opcode++ << 16) * code_alignment_factor;
loc += (*opcode++ << 24) * code_alignment_factor;
size -= 4;
break;
case DW_CFA_def_cfa:
case DW_CFA_offset_extended:
size = skip_xleb128(&opcode, size);

View File

@ -12,6 +12,7 @@
#include <asm/io.h>
#include <asm/mem_encrypt.h>
#include <asm/pgtable.h>
#include <asm/rsi.h>
static struct realm_config config;
@ -146,7 +147,7 @@ void __init arm64_rsi_init(void)
return;
if (WARN_ON(rsi_get_realm_config(&config)))
return;
prot_ns_shared = BIT(config.ipa_bits - 1);
prot_ns_shared = __phys_to_pte_val(BIT(config.ipa_bits - 1));
if (arm64_ioremap_prot_hook_register(realm_ioremap_hook))
return;

View File

@ -1753,7 +1753,7 @@ int __kvm_at_swap_desc(struct kvm *kvm, gpa_t ipa, u64 old, u64 new)
if (!writable)
return -EPERM;
ptep = (u64 __user *)hva + offset;
ptep = (void __user *)hva + offset;
if (cpus_have_final_cap(ARM64_HAS_LSE_ATOMICS))
r = __lse_swap_desc(ptep, old, new);
else

View File

@ -247,6 +247,20 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
kvm_vcpu_set_be(vcpu);
*vcpu_pc(vcpu) = target_pc;
/*
* We may come from a state where either a PC update was
* pending (SMC call resulting in PC being increpented to
* skip the SMC) or a pending exception. Make sure we get
* rid of all that, as this cannot be valid out of reset.
*
* Note that clearing the exception mask also clears PC
* updates, but that's an implementation detail, and we
* really want to make it explicit.
*/
vcpu_clear_flag(vcpu, PENDING_EXCEPTION);
vcpu_clear_flag(vcpu, EXCEPT_MASK);
vcpu_clear_flag(vcpu, INCREMENT_PC);
vcpu_set_reg(vcpu, 0, reset_state.r0);
}

View File

@ -953,7 +953,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
#else
"1: cmpb,<<,n %0,%2,1b\n"
#endif
" fic,m %3(%4,%0)\n"
" fdc,m %3(%4,%0)\n"
"2: sync\n"
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1")
: "+r" (start), "+r" (error)
@ -968,7 +968,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
#else
"1: cmpb,<<,n %0,%2,1b\n"
#endif
" fdc,m %3(%4,%0)\n"
" fic,m %3(%4,%0)\n"
"2: sync\n"
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1")
: "+r" (start), "+r" (error)

View File

@ -710,6 +710,9 @@ void kvm_arch_crypto_clear_masks(struct kvm *kvm);
void kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm,
unsigned long *aqm, unsigned long *adm);
#define SIE64_RETURN_NORMAL 0
#define SIE64_RETURN_MCCK 1
int __sie64a(phys_addr_t sie_block_phys, struct kvm_s390_sie_block *sie_block, u64 *rsa,
unsigned long gasce);

View File

@ -62,7 +62,7 @@ struct stack_frame {
struct {
unsigned long sie_control_block;
unsigned long sie_savearea;
unsigned long sie_reason;
unsigned long sie_return;
unsigned long sie_flags;
unsigned long sie_control_block_phys;
unsigned long sie_guest_asce;

View File

@ -63,7 +63,7 @@ int main(void)
OFFSET(__SF_EMPTY, stack_frame, empty[0]);
OFFSET(__SF_SIE_CONTROL, stack_frame, sie_control_block);
OFFSET(__SF_SIE_SAVEAREA, stack_frame, sie_savearea);
OFFSET(__SF_SIE_REASON, stack_frame, sie_reason);
OFFSET(__SF_SIE_RETURN, stack_frame, sie_return);
OFFSET(__SF_SIE_FLAGS, stack_frame, sie_flags);
OFFSET(__SF_SIE_CONTROL_PHYS, stack_frame, sie_control_block_phys);
OFFSET(__SF_SIE_GUEST_ASCE, stack_frame, sie_guest_asce);

View File

@ -200,7 +200,7 @@ SYM_FUNC_START(__sie64a)
stg %r3,__SF_SIE_CONTROL(%r15) # ...and virtual addresses
stg %r4,__SF_SIE_SAVEAREA(%r15) # save guest register save area
stg %r5,__SF_SIE_GUEST_ASCE(%r15) # save guest asce
xc __SF_SIE_REASON(8,%r15),__SF_SIE_REASON(%r15) # reason code = 0
xc __SF_SIE_RETURN(8,%r15),__SF_SIE_RETURN(%r15) # return code = 0
mvc __SF_SIE_FLAGS(8,%r15),__TI_flags(%r14) # copy thread flags
lmg %r0,%r13,0(%r4) # load guest gprs 0-13
mvi __TI_sie(%r14),1
@ -237,7 +237,7 @@ SYM_INNER_LABEL(sie_exit, SYM_L_GLOBAL)
xgr %r4,%r4
xgr %r5,%r5
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
lg %r2,__SF_SIE_REASON(%r15) # return exit reason code
lg %r2,__SF_SIE_RETURN(%r15) # return sie return code
BR_EX %r14
SYM_FUNC_END(__sie64a)
EXPORT_SYMBOL(__sie64a)

View File

@ -487,8 +487,8 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
mcck_dam_code = (mci.val & MCIC_SUBCLASS_MASK);
if (test_cpu_flag(CIF_MCCK_GUEST) &&
(mcck_dam_code & MCCK_CODE_NO_GUEST) != mcck_dam_code) {
/* Set exit reason code for host's later handling */
*((long *)(regs->gprs[15] + __SF_SIE_REASON)) = -EINTR;
/* Set sie return code for host's later handling */
((struct stack_frame *)regs->gprs[15])->sie_return = SIE64_RETURN_MCCK;
}
clear_cpu_flag(CIF_MCCK_GUEST);

View File

@ -1434,7 +1434,8 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union
if (rc)
return rc;
pgste = pgste_get_lock(ptep_h);
if (!pgste_get_trylock(ptep_h, &pgste))
return -EAGAIN;
newpte = _pte(f->pfn, f->writable, !p, 0);
newpte.s.d |= ptep->s.d;
newpte.s.sd |= ptep->s.sd;
@ -1444,7 +1445,8 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union
pgste_set_unlock(ptep_h, pgste);
newpte = _pte(f->pfn, 0, !p, 0);
pgste = pgste_get_lock(ptep);
if (!pgste_get_trylock(ptep, &pgste))
return -EAGAIN;
pgste = __dat_ptep_xchg(ptep, pgste, newpte, gpa_to_gfn(raddr), sg->asce, uses_skeys(sg));
pgste_set_unlock(ptep, pgste);

View File

@ -2724,6 +2724,9 @@ static unsigned long get_ind_bit(__u64 addr, unsigned long bit_nr, bool swap)
bit = bit_nr + (addr % PAGE_SIZE) * 8;
/* kvm_set_routing_entry() should never allow this to happen */
WARN_ON_ONCE(bit > (PAGE_SIZE * BITS_PER_BYTE - 1));
return swap ? (bit ^ (BITS_PER_LONG - 1)) : bit;
}
@ -2824,6 +2827,12 @@ void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
int rc;
mci.val = mcck_info->mcic;
/* log machine checks being reinjected on all debugs */
VCPU_EVENT(vcpu, 2, "guest machine check %lx", mci.val);
KVM_EVENT(2, "guest machine check %lx", mci.val);
pr_info("guest machine check pid %d: %lx", current->pid, mci.val);
if (mci.sr)
cr14 |= CR14_RECOVERY_SUBMASK;
if (mci.dg)
@ -2852,6 +2861,7 @@ int kvm_set_routing_entry(struct kvm *kvm,
struct kvm_kernel_irq_routing_entry *e,
const struct kvm_irq_routing_entry *ue)
{
const struct kvm_irq_routing_s390_adapter *adapter;
u64 uaddr_s, uaddr_i;
int idx;
@ -2862,6 +2872,14 @@ int kvm_set_routing_entry(struct kvm *kvm,
return -EINVAL;
e->set = set_adapter_int;
adapter = &ue->u.adapter;
if (adapter->summary_addr + (adapter->summary_offset / 8) >=
(adapter->summary_addr & PAGE_MASK) + PAGE_SIZE)
return -EINVAL;
if (adapter->ind_addr + (adapter->ind_offset / 8) >=
(adapter->ind_addr & PAGE_MASK) + PAGE_SIZE)
return -EINVAL;
idx = srcu_read_lock(&kvm->srcu);
uaddr_s = gpa_to_hva(kvm, ue->u.adapter.summary_addr);
uaddr_i = gpa_to_hva(kvm, ue->u.adapter.ind_addr);

View File

@ -4617,7 +4617,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu)
return 0;
}
static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
static int vcpu_post_run(struct kvm_vcpu *vcpu, int sie_return)
{
struct mcck_volatile_info *mcck_info;
struct sie_page *sie_page;
@ -4633,14 +4633,14 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
vcpu->run->s.regs.gprs[14] = vcpu->arch.sie_block->gg14;
vcpu->run->s.regs.gprs[15] = vcpu->arch.sie_block->gg15;
if (exit_reason == -EINTR) {
VCPU_EVENT(vcpu, 3, "%s", "machine check");
if (sie_return == SIE64_RETURN_MCCK) {
sie_page = container_of(vcpu->arch.sie_block,
struct sie_page, sie_block);
mcck_info = &sie_page->mcck_info;
kvm_s390_reinject_machine_check(vcpu, mcck_info);
return 0;
}
WARN_ON_ONCE(sie_return != SIE64_RETURN_NORMAL);
if (vcpu->arch.sie_block->icptcode > 0) {
rc = kvm_handle_sie_intercept(vcpu);
@ -4679,7 +4679,7 @@ int noinstr kvm_s390_enter_exit_sie(struct kvm_s390_sie_block *scb,
#define PSW_INT_MASK (PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_MCHECK)
static int __vcpu_run(struct kvm_vcpu *vcpu)
{
int rc, exit_reason;
int rc, sie_return;
struct sie_page *sie_page = (struct sie_page *)vcpu->arch.sie_block;
/*
@ -4719,9 +4719,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
guest_timing_enter_irqoff();
__disable_cpu_timer_accounting(vcpu);
exit_reason = kvm_s390_enter_exit_sie(vcpu->arch.sie_block,
vcpu->run->s.regs.gprs,
vcpu->arch.gmap->asce.val);
sie_return = kvm_s390_enter_exit_sie(vcpu->arch.sie_block,
vcpu->run->s.regs.gprs,
vcpu->arch.gmap->asce.val);
__enable_cpu_timer_accounting(vcpu);
guest_timing_exit_irqoff();
@ -4744,7 +4744,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
}
kvm_vcpu_srcu_read_lock(vcpu);
rc = vcpu_post_run(vcpu, exit_reason);
rc = vcpu_post_run(vcpu, sie_return);
if (rc || guestdbg_exit_pending(vcpu)) {
kvm_vcpu_srcu_read_unlock(vcpu);
break;

View File

@ -1122,6 +1122,7 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, struc
{
struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s;
struct kvm_s390_sie_block *scb_o = vsie_page->scb_o;
unsigned long sie_return = SIE64_RETURN_NORMAL;
int guest_bp_isolation;
int rc = 0;
@ -1163,7 +1164,7 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, struc
goto xfer_to_guest_mode_check;
}
guest_timing_enter_irqoff();
rc = kvm_s390_enter_exit_sie(scb_s, vcpu->run->s.regs.gprs, sg->asce.val);
sie_return = kvm_s390_enter_exit_sie(scb_s, vcpu->run->s.regs.gprs, sg->asce.val);
guest_timing_exit_irqoff();
local_irq_enable();
}
@ -1178,12 +1179,13 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, struc
kvm_vcpu_srcu_read_lock(vcpu);
if (rc == -EINTR) {
VCPU_EVENT(vcpu, 3, "%s", "machine check");
if (sie_return == SIE64_RETURN_MCCK) {
kvm_s390_reinject_machine_check(vcpu, &vsie_page->mcck_info);
return 0;
}
WARN_ON_ONCE(sie_return != SIE64_RETURN_NORMAL);
if (rc > 0)
rc = 0; /* we could still have an icpt */
else if (current->thread.gmap_int_code)

View File

@ -441,10 +441,17 @@ void do_secure_storage_access(struct pt_regs *regs)
folio = phys_to_folio(addr);
if (unlikely(!folio_try_get(folio)))
return;
rc = arch_make_folio_accessible(folio);
rc = uv_convert_from_secure(folio_to_phys(folio));
if (!rc)
clear_bit(PG_arch_1, &folio->flags.f);
folio_put(folio);
/*
* There are some valid fixup types for kernel
* accesses to donated secure memory. zeropad is one
* of them.
*/
if (rc)
BUG();
return handle_fault_error_nolock(regs, 0);
} else {
if (faulthandler_disabled())
return handle_fault_error_nolock(regs, 0);

View File

@ -26,10 +26,6 @@ static int platform_match(struct device *dev, struct device_driver *drv)
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
/* When driver_override is set, only bind to the matching driver */
if (pdev->driver_override)
return !strcmp(pdev->driver_override, drv->name);
/* Then try to match against the id table */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;

View File

@ -13,7 +13,7 @@
#include <linux/types.h>
#include <vdso/gettime.h>
#include "../../../../lib/vdso/gettimeofday.c"
#include "lib/vdso/gettimeofday.c"
int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
{

View File

@ -1372,14 +1372,17 @@ static void x86_pmu_enable(struct pmu *pmu)
else if (i < n_running)
continue;
if (hwc->state & PERF_HES_ARCH)
cpuc->events[hwc->idx] = event;
if (hwc->state & PERF_HES_ARCH) {
static_call(x86_pmu_set_period)(event);
continue;
}
/*
* if cpuc->enabled = 0, then no wrmsr as
* per x86_pmu_enable_event()
*/
cpuc->events[hwc->idx] = event;
x86_pmu_start(event, PERF_EF_RELOAD);
}
cpuc->n_added = 0;

View File

@ -4628,6 +4628,19 @@ static inline void intel_pmu_set_acr_caused_constr(struct perf_event *event,
event->hw.dyn_constraint &= hybrid(event->pmu, acr_cause_mask64);
}
static inline int intel_set_branch_counter_constr(struct perf_event *event,
int *num)
{
if (branch_sample_call_stack(event))
return -EINVAL;
if (branch_sample_counters(event)) {
(*num)++;
event->hw.dyn_constraint &= x86_pmu.lbr_counters;
}
return 0;
}
static int intel_pmu_hw_config(struct perf_event *event)
{
int ret = x86_pmu_hw_config(event);
@ -4698,21 +4711,19 @@ static int intel_pmu_hw_config(struct perf_event *event)
* group, which requires the extra space to store the counters.
*/
leader = event->group_leader;
if (branch_sample_call_stack(leader))
if (intel_set_branch_counter_constr(leader, &num))
return -EINVAL;
if (branch_sample_counters(leader)) {
num++;
leader->hw.dyn_constraint &= x86_pmu.lbr_counters;
}
leader->hw.flags |= PERF_X86_EVENT_BRANCH_COUNTERS;
for_each_sibling_event(sibling, leader) {
if (branch_sample_call_stack(sibling))
if (intel_set_branch_counter_constr(sibling, &num))
return -EINVAL;
}
/* event isn't installed as a sibling yet. */
if (event != leader) {
if (intel_set_branch_counter_constr(event, &num))
return -EINVAL;
if (branch_sample_counters(sibling)) {
num++;
sibling->hw.dyn_constraint &= x86_pmu.lbr_counters;
}
}
if (num > fls(x86_pmu.lbr_counters))

View File

@ -345,12 +345,12 @@ static u64 parse_omr_data_source(u8 dse)
if (omr.omr_remote)
val |= REM;
val |= omr.omr_hitm ? P(SNOOP, HITM) : P(SNOOP, HIT);
if (omr.omr_source == 0x2) {
u8 snoop = omr.omr_snoop | omr.omr_promoted;
u8 snoop = omr.omr_snoop | (omr.omr_promoted << 1);
if (snoop == 0x0)
if (omr.omr_hitm)
val |= P(SNOOP, HITM);
else if (snoop == 0x0)
val |= P(SNOOP, NA);
else if (snoop == 0x1)
val |= P(SNOOP, MISS);
@ -359,7 +359,10 @@ static u64 parse_omr_data_source(u8 dse)
else if (snoop == 0x3)
val |= P(SNOOP, NONE);
} else if (omr.omr_source > 0x2 && omr.omr_source < 0x7) {
val |= omr.omr_hitm ? P(SNOOP, HITM) : P(SNOOP, HIT);
val |= omr.omr_snoop ? P(SNOOPX, FWD) : 0;
} else {
val |= P(SNOOP, NONE);
}
return val;

View File

@ -107,14 +107,12 @@ static void __noreturn hv_panic_timeout_reboot(void)
cpu_relax();
}
/* This cannot be inlined as it needs stack */
static noinline __noclone void hv_crash_restore_tss(void)
static void hv_crash_restore_tss(void)
{
load_TR_desc();
}
/* This cannot be inlined as it needs stack */
static noinline void hv_crash_clear_kernpt(void)
static void hv_crash_clear_kernpt(void)
{
pgd_t *pgd;
p4d_t *p4d;
@ -125,50 +123,9 @@ static noinline void hv_crash_clear_kernpt(void)
native_p4d_clear(p4d);
}
/*
* This is the C entry point from the asm glue code after the disable hypercall.
* We enter here in IA32-e long mode, ie, full 64bit mode running on kernel
* page tables with our below 4G page identity mapped, but using a temporary
* GDT. ds/fs/gs/es are null. ss is not usable. bp is null. stack is not
* available. We restore kernel GDT, and rest of the context, and continue
* to kexec.
*/
static asmlinkage void __noreturn hv_crash_c_entry(void)
static void __noreturn hv_crash_handle(void)
{
struct hv_crash_ctxt *ctxt = &hv_crash_ctxt;
/* first thing, restore kernel gdt */
native_load_gdt(&ctxt->gdtr);
asm volatile("movw %%ax, %%ss" : : "a"(ctxt->ss));
asm volatile("movq %0, %%rsp" : : "m"(ctxt->rsp));
asm volatile("movw %%ax, %%ds" : : "a"(ctxt->ds));
asm volatile("movw %%ax, %%es" : : "a"(ctxt->es));
asm volatile("movw %%ax, %%fs" : : "a"(ctxt->fs));
asm volatile("movw %%ax, %%gs" : : "a"(ctxt->gs));
native_wrmsrq(MSR_IA32_CR_PAT, ctxt->pat);
asm volatile("movq %0, %%cr0" : : "r"(ctxt->cr0));
asm volatile("movq %0, %%cr8" : : "r"(ctxt->cr8));
asm volatile("movq %0, %%cr4" : : "r"(ctxt->cr4));
asm volatile("movq %0, %%cr2" : : "r"(ctxt->cr4));
native_load_idt(&ctxt->idtr);
native_wrmsrq(MSR_GS_BASE, ctxt->gsbase);
native_wrmsrq(MSR_EFER, ctxt->efer);
/* restore the original kernel CS now via far return */
asm volatile("movzwq %0, %%rax\n\t"
"pushq %%rax\n\t"
"pushq $1f\n\t"
"lretq\n\t"
"1:nop\n\t" : : "m"(ctxt->cs) : "rax");
/* We are in asmlinkage without stack frame, hence make C function
* calls which will buy stack frames.
*/
hv_crash_restore_tss();
hv_crash_clear_kernpt();
@ -177,7 +134,54 @@ static asmlinkage void __noreturn hv_crash_c_entry(void)
hv_panic_timeout_reboot();
}
/* Tell gcc we are using lretq long jump in the above function intentionally */
/*
* __naked functions do not permit function calls, not even to __always_inline
* functions that only contain asm() blocks themselves. So use a macro instead.
*/
#define hv_wrmsr(msr, val) \
asm volatile("wrmsr" :: "c"(msr), "a"((u32)val), "d"((u32)(val >> 32)) : "memory")
/*
* This is the C entry point from the asm glue code after the disable hypercall.
* We enter here in IA32-e long mode, ie, full 64bit mode running on kernel
* page tables with our below 4G page identity mapped, but using a temporary
* GDT. ds/fs/gs/es are null. ss is not usable. bp is null. stack is not
* available. We restore kernel GDT, and rest of the context, and continue
* to kexec.
*/
static void __naked hv_crash_c_entry(void)
{
/* first thing, restore kernel gdt */
asm volatile("lgdt %0" : : "m" (hv_crash_ctxt.gdtr));
asm volatile("movw %0, %%ss\n\t"
"movq %1, %%rsp"
:: "m"(hv_crash_ctxt.ss), "m"(hv_crash_ctxt.rsp));
asm volatile("movw %0, %%ds" : : "m"(hv_crash_ctxt.ds));
asm volatile("movw %0, %%es" : : "m"(hv_crash_ctxt.es));
asm volatile("movw %0, %%fs" : : "m"(hv_crash_ctxt.fs));
asm volatile("movw %0, %%gs" : : "m"(hv_crash_ctxt.gs));
hv_wrmsr(MSR_IA32_CR_PAT, hv_crash_ctxt.pat);
asm volatile("movq %0, %%cr0" : : "r"(hv_crash_ctxt.cr0));
asm volatile("movq %0, %%cr8" : : "r"(hv_crash_ctxt.cr8));
asm volatile("movq %0, %%cr4" : : "r"(hv_crash_ctxt.cr4));
asm volatile("movq %0, %%cr2" : : "r"(hv_crash_ctxt.cr2));
asm volatile("lidt %0" : : "m" (hv_crash_ctxt.idtr));
hv_wrmsr(MSR_GS_BASE, hv_crash_ctxt.gsbase);
hv_wrmsr(MSR_EFER, hv_crash_ctxt.efer);
/* restore the original kernel CS now via far return */
asm volatile("pushq %q0\n\t"
"pushq %q1\n\t"
"lretq"
:: "r"(hv_crash_ctxt.cs), "r"(hv_crash_handle));
}
/* Tell objtool we are using lretq long jump in the above function intentionally */
STACK_FRAME_NON_STANDARD(hv_crash_c_entry);
static void hv_mark_tss_not_busy(void)
@ -195,20 +199,20 @@ static void hv_hvcrash_ctxt_save(void)
{
struct hv_crash_ctxt *ctxt = &hv_crash_ctxt;
asm volatile("movq %%rsp,%0" : "=m"(ctxt->rsp));
ctxt->rsp = current_stack_pointer;
ctxt->cr0 = native_read_cr0();
ctxt->cr4 = native_read_cr4();
asm volatile("movq %%cr2, %0" : "=a"(ctxt->cr2));
asm volatile("movq %%cr8, %0" : "=a"(ctxt->cr8));
asm volatile("movq %%cr2, %0" : "=r"(ctxt->cr2));
asm volatile("movq %%cr8, %0" : "=r"(ctxt->cr8));
asm volatile("movl %%cs, %%eax" : "=a"(ctxt->cs));
asm volatile("movl %%ss, %%eax" : "=a"(ctxt->ss));
asm volatile("movl %%ds, %%eax" : "=a"(ctxt->ds));
asm volatile("movl %%es, %%eax" : "=a"(ctxt->es));
asm volatile("movl %%fs, %%eax" : "=a"(ctxt->fs));
asm volatile("movl %%gs, %%eax" : "=a"(ctxt->gs));
asm volatile("movw %%cs, %0" : "=m"(ctxt->cs));
asm volatile("movw %%ss, %0" : "=m"(ctxt->ss));
asm volatile("movw %%ds, %0" : "=m"(ctxt->ds));
asm volatile("movw %%es, %0" : "=m"(ctxt->es));
asm volatile("movw %%fs, %0" : "=m"(ctxt->fs));
asm volatile("movw %%gs, %0" : "=m"(ctxt->gs));
native_store_gdt(&ctxt->gdtr);
store_idt(&ctxt->idtr);

View File

@ -1708,8 +1708,22 @@ static void __init uv_system_init_hub(void)
struct uv_hub_info_s *new_hub;
/* Allocate & fill new per hub info list */
new_hub = (bid == 0) ? &uv_hub_info_node0
: kzalloc_node(bytes, GFP_KERNEL, uv_blade_to_node(bid));
if (bid == 0) {
new_hub = &uv_hub_info_node0;
} else {
int nid;
/*
* Deconfigured sockets are mapped to SOCK_EMPTY. Use
* NUMA_NO_NODE to allocate on a valid node.
*/
nid = uv_blade_to_node(bid);
if (nid == SOCK_EMPTY)
nid = NUMA_NO_NODE;
new_hub = kzalloc_node(bytes, GFP_KERNEL, nid);
}
if (WARN_ON_ONCE(!new_hub)) {
/* do not kfree() bid 0, which is statically allocated */
while (--bid > 0)

View File

@ -875,13 +875,18 @@ void amd_clear_bank(struct mce *m)
{
amd_reset_thr_limit(m->bank);
/* Clear MCA_DESTAT for all deferred errors even those logged in MCA_STATUS. */
if (m->status & MCI_STATUS_DEFERRED)
mce_wrmsrq(MSR_AMD64_SMCA_MCx_DESTAT(m->bank), 0);
if (mce_flags.smca) {
/*
* Clear MCA_DESTAT for all deferred errors even those
* logged in MCA_STATUS.
*/
if (m->status & MCI_STATUS_DEFERRED)
mce_wrmsrq(MSR_AMD64_SMCA_MCx_DESTAT(m->bank), 0);
/* Don't clear MCA_STATUS if MCA_DESTAT was used exclusively. */
if (m->kflags & MCE_CHECK_DFR_REGS)
return;
/* Don't clear MCA_STATUS if MCA_DESTAT was used exclusively. */
if (m->kflags & MCE_CHECK_DFR_REGS)
return;
}
mce_wrmsrq(mca_msr_reg(m->bank, MCA_STATUS), 0);
}

View File

@ -496,8 +496,9 @@ static void hv_reserve_irq_vectors(void)
test_and_set_bit(HYPERV_DBG_FASTFAIL_VECTOR, system_vectors))
BUG();
pr_info("Hyper-V: reserve vectors: %d %d %d\n", HYPERV_DBG_ASSERT_VECTOR,
HYPERV_DBG_SERVICE_VECTOR, HYPERV_DBG_FASTFAIL_VECTOR);
pr_info("Hyper-V: reserve vectors: 0x%x 0x%x 0x%x\n",
HYPERV_DBG_ASSERT_VECTOR, HYPERV_DBG_SERVICE_VECTOR,
HYPERV_DBG_FASTFAIL_VECTOR);
}
static void __init ms_hyperv_init_platform(void)

View File

@ -4188,6 +4188,9 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
{ "ST3320[68]13AS", "SD1[5-9]", ATA_QUIRK_NONCQ |
ATA_QUIRK_FIRMWARE_WARN },
/* ADATA devices with LPM issues. */
{ "ADATA SU680", NULL, ATA_QUIRK_NOLPM },
/* Seagate disks with LPM issues */
{ "ST1000DM010-2EP102", NULL, ATA_QUIRK_NOLPM },
{ "ST2000DM008-2FR102", NULL, ATA_QUIRK_NOLPM },

View File

@ -3600,7 +3600,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_device *dev,
if (cdb[2] != 1 && cdb[2] != 3) {
ata_dev_warn(dev, "invalid command format %d\n", cdb[2]);
ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
return 0;
}

View File

@ -504,6 +504,36 @@ int bus_for_each_drv(const struct bus_type *bus, struct device_driver *start,
}
EXPORT_SYMBOL_GPL(bus_for_each_drv);
static ssize_t driver_override_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
ret = __device_set_driver_override(dev, buf, count);
if (ret)
return ret;
return count;
}
static ssize_t driver_override_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
guard(spinlock)(&dev->driver_override.lock);
return sysfs_emit(buf, "%s\n", dev->driver_override.name);
}
static DEVICE_ATTR_RW(driver_override);
static struct attribute *driver_override_dev_attrs[] = {
&dev_attr_driver_override.attr,
NULL,
};
static const struct attribute_group driver_override_dev_group = {
.attrs = driver_override_dev_attrs,
};
/**
* bus_add_device - add device to bus
* @dev: device being added
@ -537,9 +567,15 @@ int bus_add_device(struct device *dev)
if (error)
goto out_put;
if (dev->bus->driver_override) {
error = device_add_group(dev, &driver_override_dev_group);
if (error)
goto out_groups;
}
error = sysfs_create_link(&sp->devices_kset->kobj, &dev->kobj, dev_name(dev));
if (error)
goto out_groups;
goto out_override;
error = sysfs_create_link(&dev->kobj, &sp->subsys.kobj, "subsystem");
if (error)
@ -550,6 +586,9 @@ int bus_add_device(struct device *dev)
out_subsys:
sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev));
out_override:
if (dev->bus->driver_override)
device_remove_group(dev, &driver_override_dev_group);
out_groups:
device_remove_groups(dev, sp->bus->dev_groups);
out_put:
@ -607,6 +646,8 @@ void bus_remove_device(struct device *dev)
sysfs_remove_link(&dev->kobj, "subsystem");
sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev));
if (dev->bus->driver_override)
device_remove_group(dev, &driver_override_dev_group);
device_remove_groups(dev, dev->bus->dev_groups);
if (klist_node_attached(&dev->p->knode_bus))
klist_del(&dev->p->knode_bus);

View File

@ -2556,6 +2556,7 @@ static void device_release(struct kobject *kobj)
devres_release_all(dev);
kfree(dev->dma_range_map);
kfree(dev->driver_override.name);
if (dev->release)
dev->release(dev);
@ -3159,6 +3160,7 @@ void device_initialize(struct device *dev)
kobject_init(&dev->kobj, &device_ktype);
INIT_LIST_HEAD(&dev->dma_pools);
mutex_init(&dev->mutex);
spin_lock_init(&dev->driver_override.lock);
lockdep_set_novalidate_class(&dev->mutex);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);

View File

@ -381,6 +381,66 @@ static void __exit deferred_probe_exit(void)
}
__exitcall(deferred_probe_exit);
int __device_set_driver_override(struct device *dev, const char *s, size_t len)
{
const char *new, *old;
char *cp;
if (!s)
return -EINVAL;
/*
* The stored value will be used in sysfs show callback (sysfs_emit()),
* which has a length limit of PAGE_SIZE and adds a trailing newline.
* Thus we can store one character less to avoid truncation during sysfs
* show.
*/
if (len >= (PAGE_SIZE - 1))
return -EINVAL;
/*
* Compute the real length of the string in case userspace sends us a
* bunch of \0 characters like python likes to do.
*/
len = strlen(s);
if (!len) {
/* Empty string passed - clear override */
spin_lock(&dev->driver_override.lock);
old = dev->driver_override.name;
dev->driver_override.name = NULL;
spin_unlock(&dev->driver_override.lock);
kfree(old);
return 0;
}
cp = strnchr(s, len, '\n');
if (cp)
len = cp - s;
new = kstrndup(s, len, GFP_KERNEL);
if (!new)
return -ENOMEM;
spin_lock(&dev->driver_override.lock);
old = dev->driver_override.name;
if (cp != s) {
dev->driver_override.name = new;
spin_unlock(&dev->driver_override.lock);
} else {
/* "\n" passed - clear override */
dev->driver_override.name = NULL;
spin_unlock(&dev->driver_override.lock);
kfree(new);
}
kfree(old);
return 0;
}
EXPORT_SYMBOL_GPL(__device_set_driver_override);
/**
* device_is_bound() - Check if device is bound to a driver
* @dev: device to check

View File

@ -603,7 +603,6 @@ static void platform_device_release(struct device *dev)
kfree(pa->pdev.dev.platform_data);
kfree(pa->pdev.mfd_cell);
kfree(pa->pdev.resource);
kfree(pa->pdev.driver_override);
kfree(pa);
}
@ -1306,38 +1305,9 @@ static ssize_t numa_node_show(struct device *dev,
}
static DEVICE_ATTR_RO(numa_node);
static ssize_t driver_override_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
ssize_t len;
device_lock(dev);
len = sysfs_emit(buf, "%s\n", pdev->driver_override);
device_unlock(dev);
return len;
}
static ssize_t driver_override_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct platform_device *pdev = to_platform_device(dev);
int ret;
ret = driver_set_override(dev, &pdev->driver_override, buf, count);
if (ret)
return ret;
return count;
}
static DEVICE_ATTR_RW(driver_override);
static struct attribute *platform_dev_attrs[] = {
&dev_attr_modalias.attr,
&dev_attr_numa_node.attr,
&dev_attr_driver_override.attr,
NULL,
};
@ -1377,10 +1347,12 @@ static int platform_match(struct device *dev, const struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
int ret;
/* When driver_override is set, only bind to the matching driver */
if (pdev->driver_override)
return !strcmp(pdev->driver_override, drv->name);
ret = device_match_driver_override(dev, drv);
if (ret >= 0)
return ret;
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
@ -1516,6 +1488,7 @@ static const struct dev_pm_ops platform_dev_pm_ops = {
const struct bus_type platform_bus_type = {
.name = "platform",
.dev_groups = platform_dev_groups,
.driver_override = true,
.match = platform_match,
.uevent = platform_uevent,
.probe = platform_probe,

View File

@ -917,9 +917,8 @@ static void zram_account_writeback_submit(struct zram *zram)
static int zram_writeback_complete(struct zram *zram, struct zram_wb_req *req)
{
u32 size, index = req->pps->index;
int err, prio;
bool huge;
u32 index = req->pps->index;
int err;
err = blk_status_to_errno(req->bio.bi_status);
if (err) {
@ -946,28 +945,13 @@ static int zram_writeback_complete(struct zram *zram, struct zram_wb_req *req)
goto out;
}
if (zram->compressed_wb) {
/*
* ZRAM_WB slots get freed, we need to preserve data required
* for read decompression.
*/
size = get_slot_size(zram, index);
prio = get_slot_comp_priority(zram, index);
huge = test_slot_flag(zram, index, ZRAM_HUGE);
}
slot_free(zram, index);
set_slot_flag(zram, index, ZRAM_WB);
clear_slot_flag(zram, index, ZRAM_IDLE);
if (test_slot_flag(zram, index, ZRAM_HUGE))
atomic64_dec(&zram->stats.huge_pages);
atomic64_sub(get_slot_size(zram, index), &zram->stats.compr_data_size);
zs_free(zram->mem_pool, get_slot_handle(zram, index));
set_slot_handle(zram, index, req->blk_idx);
if (zram->compressed_wb) {
if (huge)
set_slot_flag(zram, index, ZRAM_HUGE);
set_slot_size(zram, index, size);
set_slot_comp_priority(zram, index, prio);
}
atomic64_inc(&zram->stats.pages_stored);
set_slot_flag(zram, index, ZRAM_WB);
out:
slot_unlock(zram, index);
@ -2010,8 +1994,13 @@ static void slot_free(struct zram *zram, u32 index)
set_slot_comp_priority(zram, index, 0);
if (test_slot_flag(zram, index, ZRAM_HUGE)) {
/*
* Writeback completion decrements ->huge_pages but keeps
* ZRAM_HUGE flag for deferred decompression path.
*/
if (!test_slot_flag(zram, index, ZRAM_WB))
atomic64_dec(&zram->stats.huge_pages);
clear_slot_flag(zram, index, ZRAM_HUGE);
atomic64_dec(&zram->stats.huge_pages);
}
if (test_slot_flag(zram, index, ZRAM_WB)) {

View File

@ -251,11 +251,13 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)
bt_dev_err(hdev, "Hardware error 0x%2.2x", code);
hci_req_sync_lock(hdev);
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Reset after hardware error failed (%ld)",
PTR_ERR(skb));
return;
goto unlock;
}
kfree_skb(skb);
@ -263,18 +265,21 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)
if (IS_ERR(skb)) {
bt_dev_err(hdev, "Retrieving Intel exception info failed (%ld)",
PTR_ERR(skb));
return;
goto unlock;
}
if (skb->len != 13) {
bt_dev_err(hdev, "Exception info size mismatch");
kfree_skb(skb);
return;
goto unlock;
}
bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1));
kfree_skb(skb);
unlock:
hci_req_sync_unlock(hdev);
}
EXPORT_SYMBOL_GPL(btintel_hw_error);

View File

@ -2376,8 +2376,11 @@ static void btusb_work(struct work_struct *work)
if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_CVSD) {
if (hdev->voice_setting & 0x0020) {
static const int alts[3] = { 2, 4, 5 };
unsigned int sco_idx;
new_alts = alts[data->sco_num - 1];
sco_idx = min_t(unsigned int, data->sco_num - 1,
ARRAY_SIZE(alts) - 1);
new_alts = alts[sco_idx];
} else {
new_alts = data->sco_num;
}

View File

@ -541,6 +541,8 @@ static int download_firmware(struct ll_device *lldev)
if (err || !fw->data || !fw->size) {
bt_dev_err(lldev->hu.hdev, "request_firmware failed(errno %d) for %s",
err, bts_scr_name);
if (!err)
release_firmware(fw);
return -EINVAL;
}
ptr = (void *)fw->data;

View File

@ -36,7 +36,7 @@ static int simple_pm_bus_probe(struct platform_device *pdev)
* that's not listed in simple_pm_bus_of_match. We don't want to do any
* of the simple-pm-bus tasks for these devices, so return early.
*/
if (pdev->driver_override)
if (device_has_driver_override(&pdev->dev))
return 0;
match = of_match_device(dev->driver->of_match_table, dev);
@ -78,7 +78,7 @@ static void simple_pm_bus_remove(struct platform_device *pdev)
{
const void *data = of_device_get_match_data(&pdev->dev);
if (pdev->driver_override || data)
if (device_has_driver_override(&pdev->dev) || data)
return;
dev_dbg(&pdev->dev, "%s\n", __func__);

View File

@ -706,8 +706,7 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
if (ret)
goto put_device;
ret = driver_set_override(&pdev->dev, &pdev->driver_override,
"imx-scu-clk", strlen("imx-scu-clk"));
ret = device_set_driver_override(&pdev->dev, "imx-scu-clk");
if (ret)
goto put_device;

View File

@ -59,6 +59,7 @@ config CXL_ACPI
tristate "CXL ACPI: Platform Support"
depends on ACPI
depends on ACPI_NUMA
depends on CXL_PMEM || !CXL_PMEM
default CXL_BUS
select ACPI_TABLE_LIB
select ACPI_HMAT

View File

@ -94,7 +94,6 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
struct cxl_hdm *cxlhdm;
void __iomem *hdm;
u32 ctrl;
int i;
if (!info)
return false;
@ -113,22 +112,16 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
return false;
/*
* If any decoders are committed already, there should not be any
* emulated DVSEC decoders.
* If HDM decoders are globally enabled, do not fall back to DVSEC
* range emulation. Zeroed decoder registers after region teardown
* do not imply absence of HDM capability.
*
* Falling back to DVSEC here would treat the decoder as AUTO and
* may incorrectly latch default interleave settings.
*/
for (i = 0; i < cxlhdm->decoder_count; i++) {
ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i));
dev_dbg(&info->port->dev,
"decoder%d.%d: committed: %ld base: %#x_%.8x size: %#x_%.8x\n",
info->port->id, i,
FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl),
readl(hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(i)),
readl(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(i)),
readl(hdm + CXL_HDM_DECODER0_SIZE_HIGH_OFFSET(i)),
readl(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(i)));
if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl))
return false;
}
ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
if (ctrl & CXL_HDM_DECODER_ENABLE)
return false;
return true;
}

View File

@ -1301,7 +1301,7 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)
* Require an endpoint to be safe otherwise the driver can not
* be sure that the device is unmapped.
*/
if (endpoint && cxl_num_decoders_committed(endpoint) == 0)
if (cxlmd->dev.driver && cxl_num_decoders_committed(endpoint) == 0)
return __cxl_mem_sanitize(mds, cmd);
return -EBUSY;

View File

@ -552,10 +552,13 @@ static void cxl_port_release(struct device *dev)
xa_destroy(&port->dports);
xa_destroy(&port->regions);
ida_free(&cxl_port_ida, port->id);
if (is_cxl_root(port))
if (is_cxl_root(port)) {
kfree(to_cxl_root(port));
else
} else {
put_device(dev->parent);
kfree(port);
}
}
static ssize_t decoders_committed_show(struct device *dev,
@ -707,6 +710,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport_dev,
struct cxl_port *iter;
dev->parent = &parent_port->dev;
get_device(dev->parent);
port->depth = parent_port->depth + 1;
port->parent_dport = parent_dport;

View File

@ -3854,8 +3854,10 @@ static int __construct_region(struct cxl_region *cxlr,
}
rc = sysfs_update_group(&cxlr->dev.kobj, &cxl_region_group);
if (rc)
if (rc) {
kfree(res);
return rc;
}
rc = insert_resource(cxlrd->res, res);
if (rc) {

View File

@ -554,7 +554,7 @@ static __exit void cxl_pmem_exit(void)
MODULE_DESCRIPTION("CXL PMEM: Persistent Memory Support");
MODULE_LICENSE("GPL v2");
module_init(cxl_pmem_init);
subsys_initcall(cxl_pmem_init);
module_exit(cxl_pmem_exit);
MODULE_IMPORT_NS("CXL");
MODULE_ALIAS_CXL(CXL_DEVICE_NVDIMM_BRIDGE);

View File

@ -36,6 +36,7 @@
#define AMDGPU_BO_LIST_MAX_PRIORITY 32u
#define AMDGPU_BO_LIST_NUM_BUCKETS (AMDGPU_BO_LIST_MAX_PRIORITY + 1)
#define AMDGPU_BO_LIST_MAX_ENTRIES (128 * 1024)
static void amdgpu_bo_list_free_rcu(struct rcu_head *rcu)
{
@ -188,6 +189,9 @@ int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in,
const uint32_t bo_number = in->bo_number;
struct drm_amdgpu_bo_list_entry *info;
if (bo_number > AMDGPU_BO_LIST_MAX_ENTRIES)
return -EINVAL;
/* copy the handle array from userspace to a kernel buffer */
if (likely(info_size == bo_info_size)) {
info = vmemdup_array_user(uptr, bo_number, info_size);

View File

@ -1069,7 +1069,10 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params,
}
/* Prepare a TLB flush fence to be attached to PTs */
if (!params->unlocked) {
/* The check for need_tlb_fence should be dropped once we
* sort out the issues with KIQ/MES TLB invalidation timeouts.
*/
if (!params->unlocked && vm->need_tlb_fence) {
amdgpu_vm_tlb_fence_create(params->adev, vm, fence);
/* Makes sure no PD/PT is freed before the flush */
@ -2602,6 +2605,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
ttm_lru_bulk_move_init(&vm->lru_bulk_move);
vm->is_compute_context = false;
vm->need_tlb_fence = amdgpu_userq_enabled(&adev->ddev);
vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
AMDGPU_VM_USE_CPU_FOR_GFX);
@ -2739,6 +2743,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
dma_fence_put(vm->last_update);
vm->last_update = dma_fence_get_stub();
vm->is_compute_context = true;
vm->need_tlb_fence = true;
unreserve_bo:
amdgpu_bo_unreserve(vm->root.bo);

View File

@ -441,6 +441,8 @@ struct amdgpu_vm {
struct ttm_lru_bulk_move lru_bulk_move;
/* Flag to indicate if VM is used for compute */
bool is_compute_context;
/* Flag to indicate if VM needs a TLB fence (KFD or KGD) */
bool need_tlb_fence;
/* Memory partition number, -1 means any partition */
int8_t mem_id;

View File

@ -662,28 +662,35 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
} else {
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(9, 0, 0):
mmhub_cid = mmhub_client_ids_vega10[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega10) ?
mmhub_client_ids_vega10[cid][rw] : NULL;
break;
case IP_VERSION(9, 3, 0):
mmhub_cid = mmhub_client_ids_vega12[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega12) ?
mmhub_client_ids_vega12[cid][rw] : NULL;
break;
case IP_VERSION(9, 4, 0):
mmhub_cid = mmhub_client_ids_vega20[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega20) ?
mmhub_client_ids_vega20[cid][rw] : NULL;
break;
case IP_VERSION(9, 4, 1):
mmhub_cid = mmhub_client_ids_arcturus[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_arcturus) ?
mmhub_client_ids_arcturus[cid][rw] : NULL;
break;
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 0):
mmhub_cid = mmhub_client_ids_raven[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_raven) ?
mmhub_client_ids_raven[cid][rw] : NULL;
break;
case IP_VERSION(1, 5, 0):
case IP_VERSION(2, 4, 0):
mmhub_cid = mmhub_client_ids_renoir[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_renoir) ?
mmhub_client_ids_renoir[cid][rw] : NULL;
break;
case IP_VERSION(1, 8, 0):
case IP_VERSION(9, 4, 2):
mmhub_cid = mmhub_client_ids_aldebaran[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_aldebaran) ?
mmhub_client_ids_aldebaran[cid][rw] : NULL;
break;
default:
mmhub_cid = NULL;

View File

@ -129,7 +129,7 @@ static int isp_genpd_add_device(struct device *dev, void *data)
if (!pdev)
return -EINVAL;
if (!dev->type->name) {
if (!dev->type || !dev->type->name) {
drm_dbg(&adev->ddev, "Invalid device type to add\n");
goto exit;
}
@ -165,7 +165,7 @@ static int isp_genpd_remove_device(struct device *dev, void *data)
if (!pdev)
return -EINVAL;
if (!dev->type->name) {
if (!dev->type || !dev->type->name) {
drm_dbg(&adev->ddev, "Invalid device type to remove\n");
goto exit;
}

View File

@ -154,14 +154,17 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(2, 0, 0):
case IP_VERSION(2, 0, 2):
mmhub_cid = mmhub_client_ids_navi1x[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_navi1x) ?
mmhub_client_ids_navi1x[cid][rw] : NULL;
break;
case IP_VERSION(2, 1, 0):
case IP_VERSION(2, 1, 1):
mmhub_cid = mmhub_client_ids_sienna_cichlid[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_sienna_cichlid) ?
mmhub_client_ids_sienna_cichlid[cid][rw] : NULL;
break;
case IP_VERSION(2, 1, 2):
mmhub_cid = mmhub_client_ids_beige_goby[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_beige_goby) ?
mmhub_client_ids_beige_goby[cid][rw] : NULL;
break;
default:
mmhub_cid = NULL;

View File

@ -94,7 +94,8 @@ mmhub_v2_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
case IP_VERSION(2, 3, 0):
case IP_VERSION(2, 4, 0):
case IP_VERSION(2, 4, 1):
mmhub_cid = mmhub_client_ids_vangogh[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vangogh) ?
mmhub_client_ids_vangogh[cid][rw] : NULL;
break;
default:
mmhub_cid = NULL;

View File

@ -110,7 +110,8 @@ mmhub_v3_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 0, 1):
mmhub_cid = mmhub_client_ids_v3_0_0[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_0) ?
mmhub_client_ids_v3_0_0[cid][rw] : NULL;
break;
default:
mmhub_cid = NULL;

View File

@ -117,7 +117,8 @@ mmhub_v3_0_1_print_l2_protection_fault_status(struct amdgpu_device *adev,
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(3, 0, 1):
mmhub_cid = mmhub_client_ids_v3_0_1[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_1) ?
mmhub_client_ids_v3_0_1[cid][rw] : NULL;
break;
default:
mmhub_cid = NULL;

View File

@ -108,7 +108,8 @@ mmhub_v3_0_2_print_l2_protection_fault_status(struct amdgpu_device *adev,
"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
status);
mmhub_cid = mmhub_client_ids_v3_0_2[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_2) ?
mmhub_client_ids_v3_0_2[cid][rw] : NULL;
dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
mmhub_cid ? mmhub_cid : "unknown", cid);
dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",

View File

@ -102,7 +102,8 @@ mmhub_v4_1_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
status);
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(4, 1, 0):
mmhub_cid = mmhub_client_ids_v4_1_0[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v4_1_0) ?
mmhub_client_ids_v4_1_0[cid][rw] : NULL;
break;
default:
mmhub_cid = NULL;

View File

@ -688,7 +688,8 @@ mmhub_v4_2_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
status);
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(4, 2, 0):
mmhub_cid = mmhub_client_ids_v4_2_0[cid][rw];
mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v4_2_0) ?
mmhub_client_ids_v4_2_0[cid][rw] : NULL;
break;
default:
mmhub_cid = NULL;

View File

@ -2554,7 +2554,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
PSP_HEADER_BYTES_256;
fw_meta_info_params.fw_bss_data = region_params.bss_data_size ? adev->dm.dmub_fw->data +
fw_meta_info_params.fw_bss_data = fw_meta_info_params.bss_data_size ? adev->dm.dmub_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes) +
le32_to_cpu(hdr->inst_const_bytes) : NULL;
fw_meta_info_params.custom_psp_footer_size = 0;
@ -13119,7 +13119,7 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector,
u16 min_vfreq;
u16 max_vfreq;
if (edid == NULL || edid->extensions == 0)
if (!edid || !edid->extensions)
return;
/* Find DisplayID extension */
@ -13129,7 +13129,7 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector,
break;
}
if (edid_ext == NULL)
if (i == edid->extensions)
return;
while (j < EDID_LENGTH) {

View File

@ -37,19 +37,19 @@ const u64 amdgpu_dm_supported_degam_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) |
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
const u64 amdgpu_dm_supported_shaper_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF) |
BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
const u64 amdgpu_dm_supported_blnd_tfs =
BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) |
BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV);
BIT(DRM_COLOROP_1D_CURVE_GAMMA22);
#define MAX_COLOR_PIPELINE_OPS 10

View File

@ -255,6 +255,10 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
BREAK_TO_DEBUGGER();
return NULL;
}
if (ctx->dce_version == DCN_VERSION_2_01) {
dcn201_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base;
}
if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) {
dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base;
@ -267,10 +271,6 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base;
}
if (ctx->dce_version == DCN_VERSION_2_01) {
dcn201_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base;
}
dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
return &clk_mgr->base;
}

View File

@ -1785,7 +1785,10 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, enum dc_valid
dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
DC_FP_START();
dcn32_override_min_req_memclk(dc, context);
DC_FP_END();
dcn32_override_min_req_dcfclk(dc, context);
BW_VAL_TRACE_END_WATERMARKS();

View File

@ -3454,9 +3454,11 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
if (adev->asic_type == CHIP_HAINAN) {
if ((adev->pdev->revision == 0x81) ||
(adev->pdev->revision == 0xC3) ||
(adev->pdev->device == 0x6660) ||
(adev->pdev->device == 0x6664) ||
(adev->pdev->device == 0x6665) ||
(adev->pdev->device == 0x6667)) {
(adev->pdev->device == 0x6667) ||
(adev->pdev->device == 0x666F)) {
max_sclk = 75000;
}
if ((adev->pdev->revision == 0xC3) ||

View File

@ -848,7 +848,7 @@ static int dw_hdmi_qp_config_audio_infoframe(struct dw_hdmi_qp *hdmi,
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS0, &header_bytes, 1);
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS1, &buffer[3], 1);
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[4], 1);
regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[7], 1);
/* Enable ACR, AUDI, AMD */
dw_hdmi_qp_mod(hdmi,

View File

@ -233,6 +233,7 @@ 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;
@ -249,9 +250,11 @@ void drm_file_free(struct drm_file *file)
drm_events_release(file);
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
if (drm_core_check_feature(dev, DRIVER_MODESET) &&
drm_dev_enter(dev, &idx)) {
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

@ -577,10 +577,13 @@ 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) {
struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
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]");
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
drm_framebuffer_print_info(&p, 1, fb);
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
drm_framebuffer_print_info(&p, 1, fb);
}
list_del_init(&fb->filp_head);
drm_framebuffer_free(&fb->base.refcount);
}

View File

@ -65,18 +65,14 @@ static void drm_pagemap_cache_fini(void *arg)
drm_dbg(cache->shrinker->drm, "Destroying dpagemap cache.\n");
spin_lock(&cache->lock);
dpagemap = cache->dpagemap;
if (!dpagemap) {
spin_unlock(&cache->lock);
goto out;
}
cache->dpagemap = NULL;
if (dpagemap && !drm_pagemap_shrinker_cancel(dpagemap))
dpagemap = NULL;
spin_unlock(&cache->lock);
if (drm_pagemap_shrinker_cancel(dpagemap)) {
cache->dpagemap = NULL;
spin_unlock(&cache->lock);
if (dpagemap)
drm_pagemap_destroy(dpagemap, false);
}
out:
mutex_destroy(&cache->lookup_mutex);
kfree(cache);
}

View File

@ -806,7 +806,7 @@ void gen9_set_dc_state(struct intel_display *display, u32 state)
power_domains->dc_state, val & mask);
enable_dc6 = state & DC_STATE_EN_UPTO_DC6;
dc6_was_enabled = val & DC_STATE_EN_UPTO_DC6;
dc6_was_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6;
if (!dc6_was_enabled && enable_dc6)
intel_dmc_update_dc6_allowed_count(display, true);

View File

@ -1186,6 +1186,7 @@ struct intel_crtc_state {
u32 dc3co_exitline;
u16 su_y_granularity;
u8 active_non_psr_pipes;
u8 entry_setup_frames;
const char *no_psr_reason;
/*

View File

@ -1599,8 +1599,7 @@ static bool intel_dmc_get_dc6_allowed_count(struct intel_display *display, u32 *
return false;
mutex_lock(&power_domains->lock);
dc6_enabled = intel_de_read(display, DC_STATE_EN) &
DC_STATE_EN_UPTO_DC6;
dc6_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6;
if (dc6_enabled)
intel_dmc_update_dc6_allowed_count(display, false);

View File

@ -1717,7 +1717,7 @@ static bool _psr_compute_config(struct intel_dp *intel_dp,
entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, conn_state, adjusted_mode);
if (entry_setup_frames >= 0) {
intel_dp->psr.entry_setup_frames = entry_setup_frames;
crtc_state->entry_setup_frames = entry_setup_frames;
} else {
crtc_state->no_psr_reason = "PSR setup timing not met";
drm_dbg_kms(display->drm,
@ -1815,7 +1815,7 @@ static bool intel_psr_needs_wa_18037818876(struct intel_dp *intel_dp,
{
struct intel_display *display = to_intel_display(intel_dp);
return (DISPLAY_VER(display) == 20 && intel_dp->psr.entry_setup_frames > 0 &&
return (DISPLAY_VER(display) == 20 && crtc_state->entry_setup_frames > 0 &&
!crtc_state->has_sel_update);
}
@ -2189,6 +2189,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp,
intel_dp->psr.pkg_c_latency_used = crtc_state->pkg_c_latency_used;
intel_dp->psr.io_wake_lines = crtc_state->alpm_state.io_wake_lines;
intel_dp->psr.fast_wake_lines = crtc_state->alpm_state.fast_wake_lines;
intel_dp->psr.entry_setup_frames = crtc_state->entry_setup_frames;
if (!psr_interrupt_error_check(intel_dp))
return;
@ -3109,6 +3110,8 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state,
* - Display WA #1136: skl, bxt
*/
if (intel_crtc_needs_modeset(new_crtc_state) ||
new_crtc_state->update_m_n ||
new_crtc_state->update_lrr ||
!new_crtc_state->has_psr ||
!new_crtc_state->active_planes ||
new_crtc_state->has_sel_update != psr->sel_update_enabled ||

View File

@ -1967,7 +1967,8 @@ void intel_engines_reset_default_submission(struct intel_gt *gt)
if (engine->sanitize)
engine->sanitize(engine);
engine->set_default_submission(engine);
if (engine->set_default_submission)
engine->set_default_submission(engine);
}
}

View File

@ -225,29 +225,12 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data)
}
if (pvr_dev->has_safety_events) {
int err;
/*
* Ensure the GPU is powered on since some safety events (such
* as ECC faults) can happen outside of job submissions, which
* are otherwise the only time a power reference is held.
*/
err = pvr_power_get(pvr_dev);
if (err) {
drm_err_ratelimited(drm_dev,
"%s: could not take power reference (%d)\n",
__func__, err);
return ret;
}
while (pvr_device_safety_irq_pending(pvr_dev)) {
pvr_device_safety_irq_clear(pvr_dev);
pvr_device_handle_safety_events(pvr_dev);
ret = IRQ_HANDLED;
}
pvr_power_put(pvr_dev);
}
return ret;

View File

@ -90,11 +90,11 @@ pvr_power_request_pwr_off(struct pvr_device *pvr_dev)
}
static int
pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset)
pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset, bool rpm_suspend)
{
if (!hard_reset) {
int err;
int err;
if (!hard_reset) {
cancel_delayed_work_sync(&pvr_dev->watchdog.work);
err = pvr_power_request_idle(pvr_dev);
@ -106,29 +106,47 @@ pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset)
return err;
}
return pvr_fw_stop(pvr_dev);
if (rpm_suspend) {
/* This also waits for late processing of GPU or firmware IRQs in other cores */
disable_irq(pvr_dev->irq);
}
err = pvr_fw_stop(pvr_dev);
if (err && rpm_suspend)
enable_irq(pvr_dev->irq);
return err;
}
static int
pvr_power_fw_enable(struct pvr_device *pvr_dev)
pvr_power_fw_enable(struct pvr_device *pvr_dev, bool rpm_resume)
{
int err;
if (rpm_resume)
enable_irq(pvr_dev->irq);
err = pvr_fw_start(pvr_dev);
if (err)
return err;
goto out;
err = pvr_wait_for_fw_boot(pvr_dev);
if (err) {
drm_err(from_pvr_device(pvr_dev), "Firmware failed to boot\n");
pvr_fw_stop(pvr_dev);
return err;
goto out;
}
queue_delayed_work(pvr_dev->sched_wq, &pvr_dev->watchdog.work,
msecs_to_jiffies(WATCHDOG_TIME_MS));
return 0;
out:
if (rpm_resume)
disable_irq(pvr_dev->irq);
return err;
}
bool
@ -361,7 +379,7 @@ pvr_power_device_suspend(struct device *dev)
return -EIO;
if (pvr_dev->fw_dev.booted) {
err = pvr_power_fw_disable(pvr_dev, false);
err = pvr_power_fw_disable(pvr_dev, false, true);
if (err)
goto err_drm_dev_exit;
}
@ -391,7 +409,7 @@ pvr_power_device_resume(struct device *dev)
goto err_drm_dev_exit;
if (pvr_dev->fw_dev.booted) {
err = pvr_power_fw_enable(pvr_dev);
err = pvr_power_fw_enable(pvr_dev, true);
if (err)
goto err_power_off;
}
@ -510,7 +528,16 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
}
/* Disable IRQs for the duration of the reset. */
disable_irq(pvr_dev->irq);
if (hard_reset) {
disable_irq(pvr_dev->irq);
} else {
/*
* Soft reset is triggered as a response to a FW command to the Host and is
* processed from the threaded IRQ handler. This code cannot (nor needs to)
* wait for any IRQ processing to complete.
*/
disable_irq_nosync(pvr_dev->irq);
}
do {
if (hard_reset) {
@ -518,7 +545,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
queues_disabled = true;
}
err = pvr_power_fw_disable(pvr_dev, hard_reset);
err = pvr_power_fw_disable(pvr_dev, hard_reset, false);
if (!err) {
if (hard_reset) {
pvr_dev->fw_dev.booted = false;
@ -541,7 +568,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset)
pvr_fw_irq_clear(pvr_dev);
err = pvr_power_fw_enable(pvr_dev);
err = pvr_power_fw_enable(pvr_dev, false);
}
if (err && hard_reset)

View File

@ -2915,9 +2915,11 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
if (rdev->family == CHIP_HAINAN) {
if ((rdev->pdev->revision == 0x81) ||
(rdev->pdev->revision == 0xC3) ||
(rdev->pdev->device == 0x6660) ||
(rdev->pdev->device == 0x6664) ||
(rdev->pdev->device == 0x6665) ||
(rdev->pdev->device == 0x6667)) {
(rdev->pdev->device == 0x6667) ||
(rdev->pdev->device == 0x666F)) {
max_sclk = 75000;
}
if ((rdev->pdev->revision == 0xC3) ||

View File

@ -96,12 +96,17 @@ struct vmwgfx_hash_item {
struct vmw_res_func;
struct vmw_bo;
struct vmw_bo;
struct vmw_resource_dirty;
/**
* struct vmw-resource - base class for hardware resources
* struct vmw_resource - base class for hardware resources
*
* @kref: For refcounting.
* @dev_priv: Pointer to the device private for this resource. Immutable.
* @id: Device id. Protected by @dev_priv::resource_lock.
* @used_prio: Priority for this resource.
* @guest_memory_size: Guest memory buffer size. Immutable.
* @res_dirty: Resource contains data not yet in the guest memory buffer.
* Protected by resource reserved.
@ -117,18 +122,16 @@ struct vmw_res_func;
* pin-count greater than zero. It is not on the resource LRU lists and its
* guest memory buffer is pinned. Hence it can't be evicted.
* @func: Method vtable for this resource. Immutable.
* @mob_node; Node for the MOB guest memory rbtree. Protected by
* @mob_node: Node for the MOB guest memory rbtree. Protected by
* @guest_memory_bo reserved.
* @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock.
* @binding_head: List head for the context binding list. Protected by
* the @dev_priv::binding_mutex
* @dirty: resource's dirty tracker
* @res_free: The resource destructor.
* @hw_destroy: Callback to destroy the resource on the device, as part of
* resource destruction.
*/
struct vmw_bo;
struct vmw_bo;
struct vmw_resource_dirty;
struct vmw_resource {
struct kref kref;
struct vmw_private *dev_priv;
@ -196,8 +199,8 @@ struct vmw_surface_offset;
* @quality_level: Quality level.
* @autogen_filter: Filter for automatically generated mipmaps.
* @array_size: Number of array elements for a 1D/2D texture. For cubemap
texture number of faces * array_size. This should be 0 for pre
SM4 device.
* texture number of faces * array_size. This should be 0 for pre
* SM4 device.
* @buffer_byte_stride: Buffer byte stride.
* @num_sizes: Size of @sizes. For GB surface this should always be 1.
* @base_size: Surface dimension.
@ -265,18 +268,24 @@ struct vmw_fifo_state {
struct vmw_res_cache_entry {
uint32_t handle;
struct vmw_resource *res;
/* private: */
void *private;
/* public: */
unsigned short valid_handle;
unsigned short valid;
};
/**
* enum vmw_dma_map_mode - indicate how to perform TTM page dma mappings.
* @vmw_dma_alloc_coherent: Use TTM coherent pages
* @vmw_dma_map_populate: Unmap from DMA just after unpopulate
* @vmw_dma_map_bind: Unmap from DMA just before unbind
*/
enum vmw_dma_map_mode {
vmw_dma_alloc_coherent, /* Use TTM coherent pages */
vmw_dma_map_populate, /* Unmap from DMA just after unpopulate */
vmw_dma_map_bind, /* Unmap from DMA just before unbind */
vmw_dma_alloc_coherent,
vmw_dma_map_populate,
vmw_dma_map_bind,
/* private: */
vmw_dma_map_max
};
@ -284,8 +293,11 @@ enum vmw_dma_map_mode {
* struct vmw_sg_table - Scatter/gather table for binding, with additional
* device-specific information.
*
* @mode: which page mapping mode to use
* @pages: Array of page pointers to the pages.
* @addrs: DMA addresses to the pages if coherent pages are used.
* @sgt: Pointer to a struct sg_table with binding information
* @num_regions: Number of regions with device-address contiguous pages
* @num_pages: Number of @pages
*/
struct vmw_sg_table {
enum vmw_dma_map_mode mode;
@ -353,6 +365,7 @@ struct vmw_ctx_validation_info;
* than from user-space
* @fp: If @kernel is false, points to the file of the client. Otherwise
* NULL
* @filp: DRM state for this file
* @cmd_bounce: Command bounce buffer used for command validation before
* copying to fifo space
* @cmd_bounce_size: Current command bounce buffer size
@ -729,7 +742,7 @@ extern void vmw_svga_disable(struct vmw_private *dev_priv);
bool vmwgfx_supported(struct vmw_private *vmw);
/**
/*
* GMR utilities - vmwgfx_gmr.c
*/
@ -739,7 +752,7 @@ extern int vmw_gmr_bind(struct vmw_private *dev_priv,
int gmr_id);
extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id);
/**
/*
* User handles
*/
struct vmw_user_object {
@ -759,7 +772,7 @@ void *vmw_user_object_map_size(struct vmw_user_object *uo, size_t size);
void vmw_user_object_unmap(struct vmw_user_object *uo);
bool vmw_user_object_is_mapped(struct vmw_user_object *uo);
/**
/*
* Resource utilities - vmwgfx_resource.c
*/
struct vmw_user_resource_conv;
@ -819,7 +832,7 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res)
return !RB_EMPTY_NODE(&res->mob_node);
}
/**
/*
* GEM related functionality - vmwgfx_gem.c
*/
struct vmw_bo_params;
@ -833,7 +846,7 @@ extern int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);
extern void vmw_debugfs_gem_init(struct vmw_private *vdev);
/**
/*
* Misc Ioctl functionality - vmwgfx_ioctl.c
*/
@ -846,7 +859,7 @@ extern int vmw_present_ioctl(struct drm_device *dev, void *data,
extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
/**
/*
* Fifo utilities - vmwgfx_fifo.c
*/
@ -880,9 +893,11 @@ extern int vmw_cmd_flush(struct vmw_private *dev_priv,
/**
* vmw_fifo_caps - Returns the capabilities of the FIFO command
* vmw_fifo_caps - Get the capabilities of the FIFO command
* queue or 0 if fifo memory isn't present.
* @dev_priv: The device private context
*
* Returns: capabilities of the FIFO command or %0 if fifo memory not present
*/
static inline uint32_t vmw_fifo_caps(const struct vmw_private *dev_priv)
{
@ -893,9 +908,11 @@ static inline uint32_t vmw_fifo_caps(const struct vmw_private *dev_priv)
/**
* vmw_is_cursor_bypass3_enabled - Returns TRUE iff Cursor Bypass 3
* is enabled in the FIFO.
* vmw_is_cursor_bypass3_enabled - check Cursor Bypass 3 enabled setting
* in the FIFO.
* @dev_priv: The device private context
*
* Returns: %true iff Cursor Bypass 3 is enabled in the FIFO
*/
static inline bool
vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv)
@ -903,7 +920,7 @@ vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv)
return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0;
}
/**
/*
* TTM buffer object driver - vmwgfx_ttm_buffer.c
*/
@ -927,7 +944,7 @@ extern void vmw_piter_start(struct vmw_piter *viter,
*
* @viter: Pointer to the iterator to advance.
*
* Returns false if past the list of pages, true otherwise.
* Returns: false if past the list of pages, true otherwise.
*/
static inline bool vmw_piter_next(struct vmw_piter *viter)
{
@ -939,7 +956,7 @@ static inline bool vmw_piter_next(struct vmw_piter *viter)
*
* @viter: Pointer to the iterator
*
* Returns the DMA address of the page pointed to by @viter.
* Returns: the DMA address of the page pointed to by @viter.
*/
static inline dma_addr_t vmw_piter_dma_addr(struct vmw_piter *viter)
{
@ -951,14 +968,14 @@ static inline dma_addr_t vmw_piter_dma_addr(struct vmw_piter *viter)
*
* @viter: Pointer to the iterator
*
* Returns the DMA address of the page pointed to by @viter.
* Returns: the DMA address of the page pointed to by @viter.
*/
static inline struct page *vmw_piter_page(struct vmw_piter *viter)
{
return viter->pages[viter->i];
}
/**
/*
* Command submission - vmwgfx_execbuf.c
*/
@ -993,7 +1010,7 @@ extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
int32_t out_fence_fd);
bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd);
/**
/*
* IRQs and wating - vmwgfx_irq.c
*/
@ -1016,7 +1033,7 @@ bool vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag,
bool vmw_generic_waiter_remove(struct vmw_private *dev_priv,
u32 flag, int *waiter_count);
/**
/*
* Kernel modesetting - vmwgfx_kms.c
*/
@ -1048,7 +1065,7 @@ extern int vmw_resource_pin(struct vmw_resource *res, bool interruptible);
extern void vmw_resource_unpin(struct vmw_resource *res);
extern enum vmw_res_type vmw_res_type(const struct vmw_resource *res);
/**
/*
* Overlay control - vmwgfx_overlay.c
*/
@ -1063,20 +1080,20 @@ int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id);
int vmw_overlay_num_overlays(struct vmw_private *dev_priv);
int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv);
/**
/*
* GMR Id manager
*/
int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type);
void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type);
/**
/*
* System memory manager
*/
int vmw_sys_man_init(struct vmw_private *dev_priv);
void vmw_sys_man_fini(struct vmw_private *dev_priv);
/**
/*
* Prime - vmwgfx_prime.c
*/
@ -1292,7 +1309,7 @@ extern void vmw_cmdbuf_irqthread(struct vmw_cmdbuf_man *man);
* @line: The current line of the blit.
* @line_offset: Offset of the current line segment.
* @cpp: Bytes per pixel (granularity information).
* @memcpy: Which memcpy function to use.
* @do_cpy: Which memcpy function to use.
*/
struct vmw_diff_cpy {
struct drm_rect rect;
@ -1380,13 +1397,14 @@ vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf);
/**
* VMW_DEBUG_KMS - Debug output for kernel mode-setting
* @fmt: format string for the args
*
* This macro is for debugging vmwgfx mode-setting code.
*/
#define VMW_DEBUG_KMS(fmt, ...) \
DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
/**
/*
* Inline helper functions
*/
@ -1417,11 +1435,13 @@ static inline void vmw_fifo_resource_dec(struct vmw_private *dev_priv)
/**
* vmw_fifo_mem_read - Perform a MMIO read from the fifo memory
*
* @vmw: The device private structure
* @fifo_reg: The fifo register to read from
*
* This function is intended to be equivalent to ioread32() on
* memremap'd memory, but without byteswapping.
*
* Returns: the value read
*/
static inline u32 vmw_fifo_mem_read(struct vmw_private *vmw, uint32 fifo_reg)
{
@ -1431,8 +1451,9 @@ static inline u32 vmw_fifo_mem_read(struct vmw_private *vmw, uint32 fifo_reg)
/**
* vmw_fifo_mem_write - Perform a MMIO write to volatile memory
*
* @addr: The fifo register to write to
* @vmw: The device private structure
* @fifo_reg: The fifo register to write to
* @value: The value to write
*
* This function is intended to be equivalent to iowrite32 on
* memremap'd memory, but without byteswapping.

View File

@ -771,7 +771,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
ret = vmw_bo_dirty_add(bo);
if (!ret && surface && surface->res.func->dirty_alloc) {
surface->res.coherent = true;
ret = surface->res.func->dirty_alloc(&surface->res);
if (surface->res.dirty == NULL)
ret = surface->res.func->dirty_alloc(&surface->res);
}
ttm_bo_unreserve(&bo->tbo);
}

View File

@ -313,6 +313,8 @@ static void dev_fini_ggtt(void *arg)
{
struct xe_ggtt *ggtt = arg;
scoped_guard(mutex, &ggtt->lock)
ggtt->flags &= ~XE_GGTT_FLAGS_ONLINE;
drain_workqueue(ggtt->wq);
}
@ -377,6 +379,7 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)
if (err)
return err;
ggtt->flags |= XE_GGTT_FLAGS_ONLINE;
err = devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt);
if (err)
return err;
@ -410,13 +413,10 @@ static void xe_ggtt_initial_clear(struct xe_ggtt *ggtt)
static void ggtt_node_remove(struct xe_ggtt_node *node)
{
struct xe_ggtt *ggtt = node->ggtt;
struct xe_device *xe = tile_to_xe(ggtt->tile);
bool bound;
int idx;
bound = drm_dev_enter(&xe->drm, &idx);
mutex_lock(&ggtt->lock);
bound = ggtt->flags & XE_GGTT_FLAGS_ONLINE;
if (bound)
xe_ggtt_clear(ggtt, node->base.start, node->base.size);
drm_mm_remove_node(&node->base);
@ -429,8 +429,6 @@ static void ggtt_node_remove(struct xe_ggtt_node *node)
if (node->invalidate_on_remove)
xe_ggtt_invalidate(ggtt);
drm_dev_exit(idx);
free_node:
xe_ggtt_node_fini(node);
}

View File

@ -28,11 +28,14 @@ struct xe_ggtt {
/** @size: Total usable size of this GGTT */
u64 size;
#define XE_GGTT_FLAGS_64K BIT(0)
#define XE_GGTT_FLAGS_64K BIT(0)
#define XE_GGTT_FLAGS_ONLINE BIT(1)
/**
* @flags: Flags for this GGTT
* Acceptable flags:
* - %XE_GGTT_FLAGS_64K - if PTE size is 64K. Otherwise, regular is 4K.
* - %XE_GGTT_FLAGS_ONLINE - is GGTT online, protected by ggtt->lock
* after init
*/
unsigned int flags;
/** @scratch: Internal object allocation used as a scratch page */

View File

@ -12,6 +12,7 @@
#include "xe_gt_printk.h"
#include "xe_gt_sysfs.h"
#include "xe_mmio.h"
#include "xe_pm.h"
#include "xe_sriov.h"
static void __xe_gt_apply_ccs_mode(struct xe_gt *gt, u32 num_engines)
@ -150,6 +151,7 @@ ccs_mode_store(struct device *kdev, struct device_attribute *attr,
xe_gt_info(gt, "Setting compute mode to %d\n", num_engines);
gt->ccs_mode = num_engines;
xe_gt_record_user_engines(gt);
guard(xe_pm_runtime)(xe);
xe_gt_reset(gt);
}

View File

@ -1124,14 +1124,14 @@ static int guc_wait_ucode(struct xe_guc *guc)
struct xe_guc_pc *guc_pc = &gt->uc.guc.pc;
u32 before_freq, act_freq, cur_freq;
u32 status = 0, tries = 0;
int load_result, ret;
ktime_t before;
u64 delta_ms;
int ret;
before_freq = xe_guc_pc_get_act_freq(guc_pc);
before = ktime_get();
ret = poll_timeout_us(ret = guc_load_done(gt, &status, &tries), ret,
ret = poll_timeout_us(load_result = guc_load_done(gt, &status, &tries), load_result,
10 * USEC_PER_MSEC,
GUC_LOAD_TIMEOUT_SEC * USEC_PER_SEC, false);
@ -1139,7 +1139,7 @@ static int guc_wait_ucode(struct xe_guc *guc)
act_freq = xe_guc_pc_get_act_freq(guc_pc);
cur_freq = xe_guc_pc_get_cur_freq_fw(guc_pc);
if (ret) {
if (ret || load_result <= 0) {
xe_gt_err(gt, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz (req %dMHz)\n",
status, delta_ms, xe_guc_pc_get_act_freq(guc_pc),
xe_guc_pc_get_cur_freq_fw(guc_pc));
@ -1347,15 +1347,37 @@ int xe_guc_enable_communication(struct xe_guc *guc)
return 0;
}
int xe_guc_suspend(struct xe_guc *guc)
/**
* xe_guc_softreset() - Soft reset GuC
* @guc: The GuC object
*
* Send soft reset command to GuC through mmio send.
*
* Return: 0 if success, otherwise error code
*/
int xe_guc_softreset(struct xe_guc *guc)
{
struct xe_gt *gt = guc_to_gt(guc);
u32 action[] = {
XE_GUC_ACTION_CLIENT_SOFT_RESET,
};
int ret;
if (!xe_uc_fw_is_running(&guc->fw))
return 0;
ret = xe_guc_mmio_send(guc, action, ARRAY_SIZE(action));
if (ret)
return ret;
return 0;
}
int xe_guc_suspend(struct xe_guc *guc)
{
struct xe_gt *gt = guc_to_gt(guc);
int ret;
ret = xe_guc_softreset(guc);
if (ret) {
xe_gt_err(gt, "GuC suspend failed: %pe\n", ERR_PTR(ret));
return ret;

View File

@ -44,6 +44,7 @@ int xe_guc_opt_in_features_enable(struct xe_guc *guc);
void xe_guc_runtime_suspend(struct xe_guc *guc);
void xe_guc_runtime_resume(struct xe_guc *guc);
int xe_guc_suspend(struct xe_guc *guc);
int xe_guc_softreset(struct xe_guc *guc);
void xe_guc_notify(struct xe_guc *guc);
int xe_guc_auth_huc(struct xe_guc *guc, u32 rsa_addr);
int xe_guc_mmio_send(struct xe_guc *guc, const u32 *request, u32 len);

View File

@ -345,6 +345,7 @@ static void guc_action_disable_ct(void *arg)
{
struct xe_guc_ct *ct = arg;
xe_guc_ct_stop(ct);
guc_ct_change_state(ct, XE_GUC_CT_STATE_DISABLED);
}

View File

@ -48,6 +48,8 @@
#define XE_GUC_EXEC_QUEUE_CGP_CONTEXT_ERROR_LEN 6
static int guc_submit_reset_prepare(struct xe_guc *guc);
static struct xe_guc *
exec_queue_to_guc(struct xe_exec_queue *q)
{
@ -239,7 +241,7 @@ static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q)
EXEC_QUEUE_STATE_BANNED));
}
static void guc_submit_fini(struct drm_device *drm, void *arg)
static void guc_submit_sw_fini(struct drm_device *drm, void *arg)
{
struct xe_guc *guc = arg;
struct xe_device *xe = guc_to_xe(guc);
@ -257,6 +259,19 @@ static void guc_submit_fini(struct drm_device *drm, void *arg)
xa_destroy(&guc->submission_state.exec_queue_lookup);
}
static void guc_submit_fini(void *arg)
{
struct xe_guc *guc = arg;
/* Forcefully kill any remaining exec queues */
xe_guc_ct_stop(&guc->ct);
guc_submit_reset_prepare(guc);
xe_guc_softreset(guc);
xe_guc_submit_stop(guc);
xe_uc_fw_sanitize(&guc->fw);
xe_guc_submit_pause_abort(guc);
}
static void guc_submit_wedged_fini(void *arg)
{
struct xe_guc *guc = arg;
@ -326,7 +341,11 @@ int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids)
guc->submission_state.initialized = true;
return drmm_add_action_or_reset(&xe->drm, guc_submit_fini, guc);
err = drmm_add_action_or_reset(&xe->drm, guc_submit_sw_fini, guc);
if (err)
return err;
return devm_add_action_or_reset(xe->drm.dev, guc_submit_fini, guc);
}
/*
@ -1252,6 +1271,7 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
*/
void xe_guc_submit_wedge(struct xe_guc *guc)
{
struct xe_device *xe = guc_to_xe(guc);
struct xe_gt *gt = guc_to_gt(guc);
struct xe_exec_queue *q;
unsigned long index;
@ -1266,20 +1286,28 @@ void xe_guc_submit_wedge(struct xe_guc *guc)
if (!guc->submission_state.initialized)
return;
err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev,
guc_submit_wedged_fini, guc);
if (err) {
xe_gt_err(gt, "Failed to register clean-up in wedged.mode=%s; "
"Although device is wedged.\n",
xe_wedged_mode_to_string(XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET));
return;
}
if (xe->wedged.mode == 2) {
err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev,
guc_submit_wedged_fini, guc);
if (err) {
xe_gt_err(gt, "Failed to register clean-up on wedged.mode=2; "
"Although device is wedged.\n");
return;
}
mutex_lock(&guc->submission_state.lock);
xa_for_each(&guc->submission_state.exec_queue_lookup, index, q)
if (xe_exec_queue_get_unless_zero(q))
set_exec_queue_wedged(q);
mutex_unlock(&guc->submission_state.lock);
mutex_lock(&guc->submission_state.lock);
xa_for_each(&guc->submission_state.exec_queue_lookup, index, q)
if (xe_exec_queue_get_unless_zero(q))
set_exec_queue_wedged(q);
mutex_unlock(&guc->submission_state.lock);
} else {
/* Forcefully kill any remaining exec queues, signal fences */
guc_submit_reset_prepare(guc);
xe_guc_submit_stop(guc);
xe_guc_softreset(guc);
xe_uc_fw_sanitize(&guc->fw);
xe_guc_submit_pause_abort(guc);
}
}
static bool guc_submit_hint_wedged(struct xe_guc *guc)
@ -2230,6 +2258,7 @@ static const struct xe_exec_queue_ops guc_exec_queue_ops = {
static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
{
struct xe_gpu_scheduler *sched = &q->guc->sched;
bool do_destroy = false;
/* Stop scheduling + flush any DRM scheduler operations */
xe_sched_submission_stop(sched);
@ -2237,7 +2266,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
/* Clean up lost G2H + reset engine state */
if (exec_queue_registered(q)) {
if (exec_queue_destroyed(q))
__guc_exec_queue_destroy(guc, q);
do_destroy = true;
}
if (q->guc->suspend_pending) {
set_exec_queue_suspended(q);
@ -2273,18 +2302,15 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
xe_guc_exec_queue_trigger_cleanup(q);
}
}
if (do_destroy)
__guc_exec_queue_destroy(guc, q);
}
int xe_guc_submit_reset_prepare(struct xe_guc *guc)
static int guc_submit_reset_prepare(struct xe_guc *guc)
{
int ret;
if (xe_gt_WARN_ON(guc_to_gt(guc), vf_recovery(guc)))
return 0;
if (!guc->submission_state.initialized)
return 0;
/*
* Using an atomic here rather than submission_state.lock as this
* function can be called while holding the CT lock (engine reset
@ -2299,6 +2325,17 @@ int xe_guc_submit_reset_prepare(struct xe_guc *guc)
return ret;
}
int xe_guc_submit_reset_prepare(struct xe_guc *guc)
{
if (xe_gt_WARN_ON(guc_to_gt(guc), vf_recovery(guc)))
return 0;
if (!guc->submission_state.initialized)
return 0;
return guc_submit_reset_prepare(guc);
}
void xe_guc_submit_reset_wait(struct xe_guc *guc)
{
wait_event(guc->ct.wq, xe_device_wedged(guc_to_xe(guc)) ||
@ -2695,8 +2732,7 @@ void xe_guc_submit_pause_abort(struct xe_guc *guc)
continue;
xe_sched_submission_start(sched);
if (exec_queue_killed_or_banned_or_wedged(q))
xe_guc_exec_queue_trigger_cleanup(q);
guc_exec_queue_kill(q);
}
mutex_unlock(&guc->submission_state.lock);
}

View File

@ -2413,14 +2413,14 @@ static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts)
* @lrc: Pointer to the lrc.
*
* Return latest ctx timestamp. With support for active contexts, the
* calculation may bb slightly racy, so follow a read-again logic to ensure that
* calculation may be slightly racy, so follow a read-again logic to ensure that
* the context is still active before returning the right timestamp.
*
* Returns: New ctx timestamp value
*/
u64 xe_lrc_timestamp(struct xe_lrc *lrc)
{
u64 lrc_ts, reg_ts, new_ts;
u64 lrc_ts, reg_ts, new_ts = lrc->ctx_timestamp;
u32 engine_id;
lrc_ts = xe_lrc_ctx_timestamp(lrc);

View File

@ -543,8 +543,7 @@ static ssize_t xe_oa_read(struct file *file, char __user *buf,
size_t offset = 0;
int ret;
/* Can't read from disabled streams */
if (!stream->enabled || !stream->sample)
if (!stream->sample)
return -EINVAL;
if (!(file->f_flags & O_NONBLOCK)) {
@ -1460,6 +1459,10 @@ static void xe_oa_stream_disable(struct xe_oa_stream *stream)
if (stream->sample)
hrtimer_cancel(&stream->poll_check_timer);
/* Update stream->oa_buffer.tail to allow any final reports to be read */
if (xe_oa_buffer_check_unlocked(stream))
wake_up(&stream->poll_wq);
}
static int xe_oa_enable_preempt_timeslice(struct xe_oa_stream *stream)

View File

@ -1655,14 +1655,35 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
XE_WARN_ON(!level);
/* Check for leaf node */
if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) &&
(!xe_child->base.children || !xe_child->base.children[first])) {
xe_child->level <= MAX_HUGEPTE_LEVEL) {
struct iosys_map *leaf_map = &xe_child->bo->vmap;
pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk);
for (pgoff_t i = 0; i < count; i++) {
u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
u64 pte;
int ret;
/*
* If not a leaf pt, skip unless non-leaf pt is interleaved between
* leaf ptes which causes the page walk to skip over the child leaves
*/
if (xe_child->base.children && xe_child->base.children[first + i]) {
u64 pt_size = 1ULL << walk->shifts[xe_child->level];
bool edge_pt = (i == 0 && !IS_ALIGNED(addr, pt_size)) ||
(i == count - 1 && !IS_ALIGNED(next, pt_size));
if (!edge_pt) {
xe_page_reclaim_list_abort(xe_walk->tile->primary_gt,
xe_walk->prl,
"PT is skipped by walk at level=%u offset=%lu",
xe_child->level, first + i);
break;
}
continue;
}
pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
/*
* In rare scenarios, pte may not be written yet due to racy conditions.
* In such cases, invalidate the PRL and fallback to full PPC invalidation.
@ -1674,9 +1695,8 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
}
/* Ensure it is a defined page */
xe_tile_assert(xe_walk->tile,
xe_child->level == 0 ||
(pte & (XE_PTE_PS64 | XE_PDE_PS_2M | XE_PDPE_PS_1G)));
xe_tile_assert(xe_walk->tile, xe_child->level == 0 ||
(pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G)));
/* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */
if (pte & XE_PTE_PS64)
@ -1701,11 +1721,11 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
killed = xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk);
/*
* Verify PRL is active and if entry is not a leaf pte (base.children conditions),
* there is a potential need to invalidate the PRL if any PTE (num_live) are dropped.
* Verify if any PTE are potentially dropped at non-leaf levels, either from being
* killed or the page walk covers the region.
*/
if (xe_walk->prl && level > 1 && xe_child->num_live &&
xe_child->base.children && xe_child->base.children[first]) {
if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) &&
xe_child->level > MAX_HUGEPTE_LEVEL && xe_child->num_live) {
bool covered = xe_pt_covers(addr, next, xe_child->level, &xe_walk->base);
/*

View File

@ -314,15 +314,17 @@ int mshv_region_pin(struct mshv_mem_region *region)
ret = pin_user_pages_fast(userspace_addr, nr_pages,
FOLL_WRITE | FOLL_LONGTERM,
pages);
if (ret < 0)
if (ret != nr_pages)
goto release_pages;
}
return 0;
release_pages:
if (ret > 0)
done_count += ret;
mshv_region_invalidate_pages(region, 0, done_count);
return ret;
return ret < 0 ? ret : -ENOMEM;
}
static int mshv_region_chunk_unmap(struct mshv_mem_region *region,

View File

@ -190,7 +190,6 @@ struct hv_synic_pages {
};
struct mshv_root {
struct hv_synic_pages __percpu *synic_pages;
spinlock_t pt_ht_lock;
DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS);
struct hv_partition_property_vmm_capabilities vmm_caps;
@ -249,8 +248,8 @@ int mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb,
void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid);
void mshv_isr(void);
int mshv_synic_init(unsigned int cpu);
int mshv_synic_cleanup(unsigned int cpu);
int mshv_synic_init(struct device *dev);
void mshv_synic_exit(void);
static inline bool mshv_partition_encrypted(struct mshv_partition *partition)
{

View File

@ -120,7 +120,6 @@ static u16 mshv_passthru_hvcalls[] = {
HVCALL_SET_VP_REGISTERS,
HVCALL_TRANSLATE_VIRTUAL_ADDRESS,
HVCALL_CLEAR_VIRTUAL_INTERRUPT,
HVCALL_SCRUB_PARTITION,
HVCALL_REGISTER_INTERCEPT_RESULT,
HVCALL_ASSERT_VIRTUAL_INTERRUPT,
HVCALL_GET_GPA_PAGES_ACCESS_STATES,
@ -1289,7 +1288,7 @@ static int mshv_prepare_pinned_region(struct mshv_mem_region *region)
*/
static long
mshv_map_user_memory(struct mshv_partition *partition,
struct mshv_user_mem_region mem)
struct mshv_user_mem_region *mem)
{
struct mshv_mem_region *region;
struct vm_area_struct *vma;
@ -1297,12 +1296,12 @@ mshv_map_user_memory(struct mshv_partition *partition,
ulong mmio_pfn;
long ret;
if (mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP) ||
!access_ok((const void __user *)mem.userspace_addr, mem.size))
if (mem->flags & BIT(MSHV_SET_MEM_BIT_UNMAP) ||
!access_ok((const void __user *)mem->userspace_addr, mem->size))
return -EINVAL;
mmap_read_lock(current->mm);
vma = vma_lookup(current->mm, mem.userspace_addr);
vma = vma_lookup(current->mm, mem->userspace_addr);
is_mmio = vma ? !!(vma->vm_flags & (VM_IO | VM_PFNMAP)) : 0;
mmio_pfn = is_mmio ? vma->vm_pgoff : 0;
mmap_read_unlock(current->mm);
@ -1310,7 +1309,7 @@ mshv_map_user_memory(struct mshv_partition *partition,
if (!vma)
return -EINVAL;
ret = mshv_partition_create_region(partition, &mem, &region,
ret = mshv_partition_create_region(partition, mem, &region,
is_mmio);
if (ret)
return ret;
@ -1348,32 +1347,32 @@ mshv_map_user_memory(struct mshv_partition *partition,
return 0;
errout:
vfree(region);
mshv_region_put(region);
return ret;
}
/* Called for unmapping both the guest ram and the mmio space */
static long
mshv_unmap_user_memory(struct mshv_partition *partition,
struct mshv_user_mem_region mem)
struct mshv_user_mem_region *mem)
{
struct mshv_mem_region *region;
if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP)))
if (!(mem->flags & BIT(MSHV_SET_MEM_BIT_UNMAP)))
return -EINVAL;
spin_lock(&partition->pt_mem_regions_lock);
region = mshv_partition_region_by_gfn(partition, mem.guest_pfn);
region = mshv_partition_region_by_gfn(partition, mem->guest_pfn);
if (!region) {
spin_unlock(&partition->pt_mem_regions_lock);
return -ENOENT;
}
/* Paranoia check */
if (region->start_uaddr != mem.userspace_addr ||
region->start_gfn != mem.guest_pfn ||
region->nr_pages != HVPFN_DOWN(mem.size)) {
if (region->start_uaddr != mem->userspace_addr ||
region->start_gfn != mem->guest_pfn ||
region->nr_pages != HVPFN_DOWN(mem->size)) {
spin_unlock(&partition->pt_mem_regions_lock);
return -EINVAL;
}
@ -1404,9 +1403,9 @@ mshv_partition_ioctl_set_memory(struct mshv_partition *partition,
return -EINVAL;
if (mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP))
return mshv_unmap_user_memory(partition, mem);
return mshv_unmap_user_memory(partition, &mem);
return mshv_map_user_memory(partition, mem);
return mshv_map_user_memory(partition, &mem);
}
static long
@ -2064,7 +2063,6 @@ mshv_dev_release(struct inode *inode, struct file *filp)
return 0;
}
static int mshv_cpuhp_online;
static int mshv_root_sched_online;
static const char *scheduler_type_to_string(enum hv_scheduler_type type)
@ -2249,27 +2247,6 @@ root_scheduler_deinit(void)
free_percpu(root_scheduler_output);
}
static int mshv_reboot_notify(struct notifier_block *nb,
unsigned long code, void *unused)
{
cpuhp_remove_state(mshv_cpuhp_online);
return 0;
}
struct notifier_block mshv_reboot_nb = {
.notifier_call = mshv_reboot_notify,
};
static void mshv_root_partition_exit(void)
{
unregister_reboot_notifier(&mshv_reboot_nb);
}
static int __init mshv_root_partition_init(struct device *dev)
{
return register_reboot_notifier(&mshv_reboot_nb);
}
static int __init mshv_init_vmm_caps(struct device *dev)
{
int ret;
@ -2314,39 +2291,21 @@ static int __init mshv_parent_partition_init(void)
MSHV_HV_MAX_VERSION);
}
mshv_root.synic_pages = alloc_percpu(struct hv_synic_pages);
if (!mshv_root.synic_pages) {
dev_err(dev, "Failed to allocate percpu synic page\n");
ret = -ENOMEM;
ret = mshv_synic_init(dev);
if (ret)
goto device_deregister;
}
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic",
mshv_synic_init,
mshv_synic_cleanup);
if (ret < 0) {
dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret);
goto free_synic_pages;
}
mshv_cpuhp_online = ret;
ret = mshv_init_vmm_caps(dev);
if (ret)
goto remove_cpu_state;
goto synic_cleanup;
ret = mshv_retrieve_scheduler_type(dev);
if (ret)
goto remove_cpu_state;
if (hv_root_partition())
ret = mshv_root_partition_init(dev);
if (ret)
goto remove_cpu_state;
goto synic_cleanup;
ret = root_scheduler_init(dev);
if (ret)
goto exit_partition;
goto synic_cleanup;
ret = mshv_debugfs_init();
if (ret)
@ -2367,13 +2326,8 @@ static int __init mshv_parent_partition_init(void)
mshv_debugfs_exit();
deinit_root_scheduler:
root_scheduler_deinit();
exit_partition:
if (hv_root_partition())
mshv_root_partition_exit();
remove_cpu_state:
cpuhp_remove_state(mshv_cpuhp_online);
free_synic_pages:
free_percpu(mshv_root.synic_pages);
synic_cleanup:
mshv_synic_exit();
device_deregister:
misc_deregister(&mshv_dev);
return ret;
@ -2387,10 +2341,7 @@ static void __exit mshv_parent_partition_exit(void)
misc_deregister(&mshv_dev);
mshv_irqfd_wq_cleanup();
root_scheduler_deinit();
if (hv_root_partition())
mshv_root_partition_exit();
cpuhp_remove_state(mshv_cpuhp_online);
free_percpu(mshv_root.synic_pages);
mshv_synic_exit();
}
module_init(mshv_parent_partition_init);

View File

@ -10,13 +10,22 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/random.h>
#include <linux/cpuhotplug.h>
#include <linux/reboot.h>
#include <asm/mshyperv.h>
#include <linux/acpi.h>
#include "mshv_eventfd.h"
#include "mshv.h"
static int synic_cpuhp_online;
static struct hv_synic_pages __percpu *synic_pages;
static int mshv_sint_vector = -1; /* hwirq for the SynIC SINTs */
static int mshv_sint_irq = -1; /* Linux IRQ for mshv_sint_vector */
static u32 synic_event_ring_get_queued_port(u32 sint_index)
{
struct hv_synic_event_ring_page **event_ring_page;
@ -26,7 +35,7 @@ static u32 synic_event_ring_get_queued_port(u32 sint_index)
u32 message;
u8 tail;
spages = this_cpu_ptr(mshv_root.synic_pages);
spages = this_cpu_ptr(synic_pages);
event_ring_page = &spages->synic_event_ring_page;
synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
@ -393,7 +402,7 @@ mshv_intercept_isr(struct hv_message *msg)
void mshv_isr(void)
{
struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages);
struct hv_synic_pages *spages = this_cpu_ptr(synic_pages);
struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
struct hv_message *msg;
bool handled;
@ -437,25 +446,21 @@ void mshv_isr(void)
if (msg->header.message_flags.msg_pending)
hv_set_non_nested_msr(HV_MSR_EOM, 0);
#ifdef HYPERVISOR_CALLBACK_VECTOR
add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR);
#endif
add_interrupt_randomness(mshv_sint_vector);
} else {
pr_warn_once("%s: unknown message type 0x%x\n", __func__,
msg->header.message_type);
}
}
int mshv_synic_init(unsigned int cpu)
static int mshv_synic_cpu_init(unsigned int cpu)
{
union hv_synic_simp simp;
union hv_synic_siefp siefp;
union hv_synic_sirbp sirbp;
#ifdef HYPERVISOR_CALLBACK_VECTOR
union hv_synic_sint sint;
#endif
union hv_synic_scontrol sctrl;
struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages);
struct hv_synic_pages *spages = this_cpu_ptr(synic_pages);
struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
struct hv_synic_event_flags_page **event_flags_page =
&spages->synic_event_flags_page;
@ -496,10 +501,12 @@ int mshv_synic_init(unsigned int cpu)
hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
#ifdef HYPERVISOR_CALLBACK_VECTOR
if (mshv_sint_irq != -1)
enable_percpu_irq(mshv_sint_irq, 0);
/* Enable intercepts */
sint.as_uint64 = 0;
sint.vector = HYPERVISOR_CALLBACK_VECTOR;
sint.vector = mshv_sint_vector;
sint.masked = false;
sint.auto_eoi = hv_recommend_using_aeoi();
hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX,
@ -507,13 +514,12 @@ int mshv_synic_init(unsigned int cpu)
/* Doorbell SINT */
sint.as_uint64 = 0;
sint.vector = HYPERVISOR_CALLBACK_VECTOR;
sint.vector = mshv_sint_vector;
sint.masked = false;
sint.as_intercept = 1;
sint.auto_eoi = hv_recommend_using_aeoi();
hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX,
sint.as_uint64);
#endif
/* Enable global synic bit */
sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
@ -542,14 +548,14 @@ int mshv_synic_init(unsigned int cpu)
return -EFAULT;
}
int mshv_synic_cleanup(unsigned int cpu)
static int mshv_synic_cpu_exit(unsigned int cpu)
{
union hv_synic_sint sint;
union hv_synic_simp simp;
union hv_synic_siefp siefp;
union hv_synic_sirbp sirbp;
union hv_synic_scontrol sctrl;
struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages);
struct hv_synic_pages *spages = this_cpu_ptr(synic_pages);
struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
struct hv_synic_event_flags_page **event_flags_page =
&spages->synic_event_flags_page;
@ -568,6 +574,9 @@ int mshv_synic_cleanup(unsigned int cpu)
hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX,
sint.as_uint64);
if (mshv_sint_irq != -1)
disable_percpu_irq(mshv_sint_irq);
/* Disable Synic's event ring page */
sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
sirbp.sirbp_enabled = false;
@ -663,3 +672,152 @@ mshv_unregister_doorbell(u64 partition_id, int doorbell_portid)
mshv_portid_free(doorbell_portid);
}
static int mshv_synic_reboot_notify(struct notifier_block *nb,
unsigned long code, void *unused)
{
if (!hv_root_partition())
return 0;
cpuhp_remove_state(synic_cpuhp_online);
return 0;
}
static struct notifier_block mshv_synic_reboot_nb = {
.notifier_call = mshv_synic_reboot_notify,
};
#ifndef HYPERVISOR_CALLBACK_VECTOR
static DEFINE_PER_CPU(long, mshv_evt);
static irqreturn_t mshv_percpu_isr(int irq, void *dev_id)
{
mshv_isr();
return IRQ_HANDLED;
}
#ifdef CONFIG_ACPI
static int __init mshv_acpi_setup_sint_irq(void)
{
return acpi_register_gsi(NULL, mshv_sint_vector, ACPI_EDGE_SENSITIVE,
ACPI_ACTIVE_HIGH);
}
static void mshv_acpi_cleanup_sint_irq(void)
{
acpi_unregister_gsi(mshv_sint_vector);
}
#else
static int __init mshv_acpi_setup_sint_irq(void)
{
return -ENODEV;
}
static void mshv_acpi_cleanup_sint_irq(void)
{
}
#endif
static int __init mshv_sint_vector_setup(void)
{
int ret;
struct hv_register_assoc reg = {
.name = HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID,
};
union hv_input_vtl input_vtl = { 0 };
if (acpi_disabled)
return -ENODEV;
ret = hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF,
1, input_vtl, &reg);
if (ret || !reg.value.reg64)
return -ENODEV;
mshv_sint_vector = reg.value.reg64;
ret = mshv_acpi_setup_sint_irq();
if (ret < 0) {
pr_err("Failed to setup IRQ for MSHV SINT vector %d: %d\n",
mshv_sint_vector, ret);
goto out_fail;
}
mshv_sint_irq = ret;
ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV",
&mshv_evt);
if (ret)
goto out_unregister;
return 0;
out_unregister:
mshv_acpi_cleanup_sint_irq();
out_fail:
return ret;
}
static void mshv_sint_vector_cleanup(void)
{
free_percpu_irq(mshv_sint_irq, &mshv_evt);
mshv_acpi_cleanup_sint_irq();
}
#else /* !HYPERVISOR_CALLBACK_VECTOR */
static int __init mshv_sint_vector_setup(void)
{
mshv_sint_vector = HYPERVISOR_CALLBACK_VECTOR;
return 0;
}
static void mshv_sint_vector_cleanup(void)
{
}
#endif /* HYPERVISOR_CALLBACK_VECTOR */
int __init mshv_synic_init(struct device *dev)
{
int ret = 0;
ret = mshv_sint_vector_setup();
if (ret)
return ret;
synic_pages = alloc_percpu(struct hv_synic_pages);
if (!synic_pages) {
dev_err(dev, "Failed to allocate percpu synic page\n");
ret = -ENOMEM;
goto sint_vector_cleanup;
}
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic",
mshv_synic_cpu_init,
mshv_synic_cpu_exit);
if (ret < 0) {
dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret);
goto free_synic_pages;
}
synic_cpuhp_online = ret;
ret = register_reboot_notifier(&mshv_synic_reboot_nb);
if (ret)
goto remove_cpuhp_state;
return 0;
remove_cpuhp_state:
cpuhp_remove_state(synic_cpuhp_online);
free_synic_pages:
free_percpu(synic_pages);
sint_vector_cleanup:
mshv_sint_vector_cleanup();
return ret;
}
void mshv_synic_exit(void)
{
unregister_reboot_notifier(&mshv_synic_reboot_nb);
cpuhp_remove_state(synic_cpuhp_online);
free_percpu(synic_pages);
mshv_sint_vector_cleanup();
}

View File

@ -507,7 +507,7 @@ static int axi_fan_control_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, ctl->irq, NULL,
axi_fan_control_irq_handler,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
pdev->driver_override, ctl);
NULL, ctl);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"failed to request an irq\n");

View File

@ -232,7 +232,7 @@ static int max6639_read_fan(struct device *dev, u32 attr, int channel,
static int max6639_set_ppr(struct max6639_data *data, int channel, u8 ppr)
{
/* Decrement the PPR value and shift left by 6 to match the register format */
return regmap_write(data->regmap, MAX6639_REG_FAN_PPR(channel), ppr-- << 6);
return regmap_write(data->regmap, MAX6639_REG_FAN_PPR(channel), --ppr << 6);
}
static int max6639_write_fan(struct device *dev, u32 attr, int channel,
@ -524,8 +524,8 @@ static int max6639_probe_child_from_dt(struct i2c_client *client,
{
struct device *dev = &client->dev;
u32 i;
int err, val;
u32 i, val;
int err;
err = of_property_read_u32(child, "reg", &i);
if (err) {
@ -540,8 +540,8 @@ static int max6639_probe_child_from_dt(struct i2c_client *client,
err = of_property_read_u32(child, "pulses-per-revolution", &val);
if (!err) {
if (val < 1 || val > 5) {
dev_err(dev, "invalid pulses-per-revolution %d of %pOFn\n", val, child);
if (val < 1 || val > 4) {
dev_err(dev, "invalid pulses-per-revolution %u of %pOFn\n", val, child);
return -EINVAL;
}
data->ppr[i] = val;

View File

@ -58,6 +58,8 @@ static int hac300s_read_word_data(struct i2c_client *client, int page,
case PMBUS_MFR_VOUT_MIN:
case PMBUS_READ_VOUT:
rv = pmbus_read_word_data(client, page, phase, reg);
if (rv < 0)
return rv;
return FIELD_GET(LINEAR11_MANTISSA_MASK, rv);
default:
return -ENODATA;

View File

@ -67,6 +67,8 @@ static int ina233_read_word_data(struct i2c_client *client, int page,
switch (reg) {
case PMBUS_VIRT_READ_VMON:
ret = pmbus_read_word_data(client, 0, 0xff, MFR_READ_VSHUNT);
if (ret < 0)
return ret;
/* Adjust returned value to match VIN coefficients */
/* VIN: 1.25 mV VSHUNT: 2.5 uV LSB */

View File

@ -98,8 +98,11 @@ static ssize_t isl68137_avs_enable_show_page(struct i2c_client *client,
{
int val = pmbus_read_byte_data(client, page, PMBUS_OPERATION);
return sprintf(buf, "%d\n",
(val & ISL68137_VOUT_AVS) == ISL68137_VOUT_AVS ? 1 : 0);
if (val < 0)
return val;
return sysfs_emit(buf, "%d\n",
(val & ISL68137_VOUT_AVS) == ISL68137_VOUT_AVS);
}
static ssize_t isl68137_avs_enable_store_page(struct i2c_client *client,

View File

@ -165,7 +165,7 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct mp2869_data *data = to_mp2869_data(info);
int ret;
int ret, mfr;
switch (reg) {
case PMBUS_VOUT_MODE:
@ -188,11 +188,14 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg)
if (ret < 0)
return ret;
mfr = pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC);
if (mfr < 0)
return mfr;
ret = (ret & ~GENMASK(2, 2)) |
FIELD_PREP(GENMASK(2, 2),
FIELD_GET(GENMASK(1, 1),
pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC)));
FIELD_GET(GENMASK(1, 1), mfr));
break;
case PMBUS_STATUS_TEMPERATURE:
/*
@ -207,15 +210,16 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg)
if (ret < 0)
return ret;
mfr = pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC);
if (mfr < 0)
return mfr;
ret = (ret & ~GENMASK(7, 6)) |
FIELD_PREP(GENMASK(6, 6),
FIELD_GET(GENMASK(1, 1),
pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC))) |
FIELD_GET(GENMASK(1, 1), mfr)) |
FIELD_PREP(GENMASK(7, 7),
FIELD_GET(GENMASK(1, 1),
pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC)));
FIELD_GET(GENMASK(1, 1), mfr));
break;
default:
ret = -ENODATA;
@ -230,7 +234,7 @@ static int mp2869_read_word_data(struct i2c_client *client, int page, int phase,
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
struct mp2869_data *data = to_mp2869_data(info);
int ret;
int ret, mfr;
switch (reg) {
case PMBUS_STATUS_WORD:
@ -246,11 +250,14 @@ static int mp2869_read_word_data(struct i2c_client *client, int page, int phase,
if (ret < 0)
return ret;
mfr = pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC);
if (mfr < 0)
return mfr;
ret = (ret & ~GENMASK(2, 2)) |
FIELD_PREP(GENMASK(2, 2),
FIELD_GET(GENMASK(1, 1),
pmbus_read_byte_data(client, page,
PMBUS_STATUS_MFR_SPECIFIC)));
FIELD_GET(GENMASK(1, 1), mfr));
break;
case PMBUS_READ_VIN:
/*

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