mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
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:
commit
9ebcf66cd6
1
.mailmap
1
.mailmap
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
4
Makefile
4
Makefile
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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__);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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) ||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) ||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1124,14 +1124,14 @@ static int guc_wait_ucode(struct xe_guc *guc)
|
|||
struct xe_guc_pc *guc_pc = >->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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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, ®ion,
|
||||
ret = mshv_partition_create_region(partition, mem, ®ion,
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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, ®);
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue
Block a user