mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 03:04:51 +01:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-6.17-rc7). No conflicts. Adjacent changes: drivers/net/ethernet/mellanox/mlx5/core/en/fs.h9536fbe10c("net/mlx5e: Add PSP steering in local NIC RX")7601a0a462("net/mlx5e: Add a miss level for ipsec crypto offload") Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
f2cdc4c22b
229 changed files with 2557 additions and 1342 deletions
|
|
@ -92,8 +92,12 @@ required:
|
|||
anyOf:
|
||||
- required:
|
||||
- qcom,powered-remotely
|
||||
- num-channels
|
||||
- qcom,num-ees
|
||||
- required:
|
||||
- qcom,controlled-remotely
|
||||
- num-channels
|
||||
- qcom,num-ees
|
||||
- required:
|
||||
- clocks
|
||||
- clock-names
|
||||
|
|
|
|||
|
|
@ -47,21 +47,19 @@ properties:
|
|||
const: 0
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
description: Reference clocks for CP110; MG clock, MG Core clock, AXI clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mg_clk
|
||||
- const: mg_core_clk
|
||||
- const: axi_clk
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
marvell,system-controller:
|
||||
description: Phandle to the Marvell system controller (CP110 only)
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
patternProperties:
|
||||
'^phy@[0-2]$':
|
||||
'^phy@[0-5]$':
|
||||
description: A COMPHY lane child node
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
|
@ -69,10 +67,14 @@ patternProperties:
|
|||
properties:
|
||||
reg:
|
||||
description: COMPHY lane number
|
||||
maximum: 5
|
||||
|
||||
'#phy-cells':
|
||||
const: 1
|
||||
|
||||
connector:
|
||||
type: object
|
||||
|
||||
required:
|
||||
- reg
|
||||
- '#phy-cells'
|
||||
|
|
@ -91,13 +93,24 @@ allOf:
|
|||
|
||||
then:
|
||||
properties:
|
||||
clocks: false
|
||||
clock-names: false
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names:
|
||||
const: xtal
|
||||
|
||||
required:
|
||||
- reg-names
|
||||
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: mg_clk
|
||||
- const: mg_core_clk
|
||||
- const: axi_clk
|
||||
|
||||
required:
|
||||
- marvell,system-controller
|
||||
|
||||
|
|
|
|||
|
|
@ -176,6 +176,8 @@ allOf:
|
|||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sa8775p-qmp-gen4x2-pcie-phy
|
||||
- qcom,sa8775p-qmp-gen4x4-pcie-phy
|
||||
- qcom,sc8280xp-qmp-gen3x1-pcie-phy
|
||||
- qcom,sc8280xp-qmp-gen3x2-pcie-phy
|
||||
- qcom,sc8280xp-qmp-gen3x4-pcie-phy
|
||||
|
|
@ -197,8 +199,6 @@ allOf:
|
|||
contains:
|
||||
enum:
|
||||
- qcom,qcs8300-qmp-gen4x2-pcie-phy
|
||||
- qcom,sa8775p-qmp-gen4x2-pcie-phy
|
||||
- qcom,sa8775p-qmp-gen4x4-pcie-phy
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ allOf:
|
|||
oneOf:
|
||||
- required: [ clock-frequency ]
|
||||
- required: [ clocks ]
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -60,12 +59,39 @@ allOf:
|
|||
items:
|
||||
- const: uartclk
|
||||
- const: reg
|
||||
else:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: spacemit,k1-uart
|
||||
then:
|
||||
properties:
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: bus
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- spacemit,k1-uart
|
||||
- nxp,lpc1850-uart
|
||||
then:
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
clock-names:
|
||||
minItems: 2
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names:
|
||||
maxItems: 1
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -162,6 +188,9 @@ properties:
|
|||
minItems: 1
|
||||
maxItems: 2
|
||||
oneOf:
|
||||
- enum:
|
||||
- main
|
||||
- uart
|
||||
- items:
|
||||
- const: core
|
||||
- const: bus
|
||||
|
|
@ -264,29 +293,6 @@ required:
|
|||
- reg
|
||||
- interrupts
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- spacemit,k1-uart
|
||||
- nxp,lpc1850-uart
|
||||
then:
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
clock-names:
|
||||
minItems: 2
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
clock-names:
|
||||
maxItems: 1
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ properties:
|
|||
- const: dma_intr2
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: sw_baud
|
||||
|
|
|
|||
|
|
@ -575,8 +575,8 @@ operations:
|
|||
- nat-dst
|
||||
- timeout
|
||||
- mark
|
||||
- counter-orig
|
||||
- counter-reply
|
||||
- counters-orig
|
||||
- counters-reply
|
||||
- use
|
||||
- id
|
||||
- nat-dst
|
||||
|
|
@ -591,7 +591,6 @@ operations:
|
|||
request:
|
||||
value: 0x101
|
||||
attributes:
|
||||
- nfgen-family
|
||||
- mark
|
||||
- filter
|
||||
- status
|
||||
|
|
@ -608,8 +607,8 @@ operations:
|
|||
- nat-dst
|
||||
- timeout
|
||||
- mark
|
||||
- counter-orig
|
||||
- counter-reply
|
||||
- counters-orig
|
||||
- counters-reply
|
||||
- use
|
||||
- id
|
||||
- nat-dst
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@ definitions:
|
|||
traffic-patterns it can take a long time until the
|
||||
MPTCP_EVENT_ESTABLISHED is sent.
|
||||
Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport,
|
||||
dport, server-side.
|
||||
dport, server-side, [flags].
|
||||
-
|
||||
name: established
|
||||
doc: >-
|
||||
A MPTCP connection is established (can start new subflows).
|
||||
Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport,
|
||||
dport, server-side.
|
||||
dport, server-side, [flags].
|
||||
-
|
||||
name: closed
|
||||
doc: >-
|
||||
|
|
|
|||
30
MAINTAINERS
30
MAINTAINERS
|
|
@ -7238,15 +7238,15 @@ F: include/linux/swiotlb.h
|
|||
F: kernel/dma/
|
||||
|
||||
DMA MAPPING HELPERS DEVICE DRIVER API [RUST]
|
||||
M: Abdiel Janulgue <abdiel.janulgue@gmail.com>
|
||||
M: Danilo Krummrich <dakr@kernel.org>
|
||||
R: Abdiel Janulgue <abdiel.janulgue@gmail.com>
|
||||
R: Daniel Almeida <daniel.almeida@collabora.com>
|
||||
R: Robin Murphy <robin.murphy@arm.com>
|
||||
R: Andreas Hindborg <a.hindborg@kernel.org>
|
||||
L: rust-for-linux@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://rust-for-linux.com
|
||||
T: git https://github.com/Rust-for-Linux/linux.git alloc-next
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
|
||||
F: rust/helpers/dma.c
|
||||
F: rust/kernel/dma.rs
|
||||
F: samples/rust/rust_dma.rs
|
||||
|
|
@ -7431,7 +7431,7 @@ S: Supported
|
|||
F: Documentation/devicetree/bindings/dpll/dpll-device.yaml
|
||||
F: Documentation/devicetree/bindings/dpll/dpll-pin.yaml
|
||||
F: Documentation/driver-api/dpll.rst
|
||||
F: drivers/dpll/*
|
||||
F: drivers/dpll/
|
||||
F: include/linux/dpll.h
|
||||
F: include/uapi/linux/dpll.h
|
||||
|
||||
|
|
@ -8079,7 +8079,6 @@ F: Documentation/devicetree/bindings/gpu/
|
|||
F: Documentation/gpu/
|
||||
F: drivers/gpu/drm/
|
||||
F: drivers/gpu/vga/
|
||||
F: rust/kernel/drm/
|
||||
F: include/drm/drm
|
||||
F: include/linux/vga*
|
||||
F: include/uapi/drm/
|
||||
|
|
@ -8091,11 +8090,21 @@ X: drivers/gpu/drm/i915/
|
|||
X: drivers/gpu/drm/kmb/
|
||||
X: drivers/gpu/drm/mediatek/
|
||||
X: drivers/gpu/drm/msm/
|
||||
X: drivers/gpu/drm/nouveau/
|
||||
X: drivers/gpu/drm/nova/
|
||||
X: drivers/gpu/drm/radeon/
|
||||
X: drivers/gpu/drm/tegra/
|
||||
X: drivers/gpu/drm/xe/
|
||||
|
||||
DRM DRIVERS AND COMMON INFRASTRUCTURE [RUST]
|
||||
M: Danilo Krummrich <dakr@kernel.org>
|
||||
M: Alice Ryhl <aliceryhl@google.com>
|
||||
S: Supported
|
||||
W: https://drm.pages.freedesktop.org/maintainer-tools/drm-rust.html
|
||||
T: git https://gitlab.freedesktop.org/drm/rust/kernel.git
|
||||
F: drivers/gpu/drm/nova/
|
||||
F: drivers/gpu/nova-core/
|
||||
F: rust/kernel/drm/
|
||||
|
||||
DRM DRIVERS FOR ALLWINNER A10
|
||||
M: Maxime Ripard <mripard@kernel.org>
|
||||
M: Chen-Yu Tsai <wens@csie.org>
|
||||
|
|
@ -15738,13 +15747,6 @@ S: Supported
|
|||
W: http://www.melexis.com
|
||||
F: drivers/iio/temperature/mlx90635.c
|
||||
|
||||
MELFAS MIP4 TOUCHSCREEN DRIVER
|
||||
M: Sangwon Jee <jeesw@melfas.com>
|
||||
S: Supported
|
||||
W: http://www.melfas.com
|
||||
F: Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt
|
||||
F: drivers/input/touchscreen/melfas_mip4.c
|
||||
|
||||
MELLANOX BLUEFIELD I2C DRIVER
|
||||
M: Khalil Blaiech <kblaiech@nvidia.com>
|
||||
M: Asmaa Mnebhi <asmaa@nvidia.com>
|
||||
|
|
@ -16193,6 +16195,7 @@ R: Rik van Riel <riel@surriel.com>
|
|||
R: Liam R. Howlett <Liam.Howlett@oracle.com>
|
||||
R: Vlastimil Babka <vbabka@suse.cz>
|
||||
R: Harry Yoo <harry.yoo@oracle.com>
|
||||
R: Jann Horn <jannh@google.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: include/linux/rmap.h
|
||||
|
|
@ -16237,6 +16240,7 @@ R: Nico Pache <npache@redhat.com>
|
|||
R: Ryan Roberts <ryan.roberts@arm.com>
|
||||
R: Dev Jain <dev.jain@arm.com>
|
||||
R: Barry Song <baohua@kernel.org>
|
||||
R: Lance Yang <lance.yang@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
W: http://www.linux-mm.org
|
||||
|
|
@ -24271,7 +24275,7 @@ F: Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
|
|||
F: drivers/input/keyboard/sun4i-lradc-keys.c
|
||||
|
||||
SUNDANCE NETWORK DRIVER
|
||||
M: Denis Kirjanov <dkirjanov@suse.de>
|
||||
M: Denis Kirjanov <kirjanov@gmail.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/ethernet/dlink/sundance.c
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 6
|
||||
PATCHLEVEL = 17
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc6
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -1369,6 +1369,7 @@ static inline bool kvm_system_needs_idmapped_vectors(void)
|
|||
}
|
||||
|
||||
void kvm_init_host_debug_data(void);
|
||||
void kvm_debug_init_vhe(void);
|
||||
void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu);
|
||||
void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu);
|
||||
void kvm_debug_set_guest_ownership(struct kvm_vcpu *vcpu);
|
||||
|
|
|
|||
|
|
@ -355,11 +355,6 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke
|
|||
return pteref;
|
||||
}
|
||||
|
||||
static inline kvm_pte_t *kvm_dereference_pteref_raw(kvm_pteref_t pteref)
|
||||
{
|
||||
return pteref;
|
||||
}
|
||||
|
||||
static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker)
|
||||
{
|
||||
/*
|
||||
|
|
@ -389,11 +384,6 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke
|
|||
return rcu_dereference_check(pteref, !(walker->flags & KVM_PGTABLE_WALK_SHARED));
|
||||
}
|
||||
|
||||
static inline kvm_pte_t *kvm_dereference_pteref_raw(kvm_pteref_t pteref)
|
||||
{
|
||||
return rcu_dereference_raw(pteref);
|
||||
}
|
||||
|
||||
static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker)
|
||||
{
|
||||
if (walker->flags & KVM_PGTABLE_WALK_SHARED)
|
||||
|
|
@ -561,26 +551,6 @@ static inline int kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2
|
|||
*/
|
||||
void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt);
|
||||
|
||||
/**
|
||||
* kvm_pgtable_stage2_destroy_range() - Destroy the unlinked range of addresses.
|
||||
* @pgt: Page-table structure initialised by kvm_pgtable_stage2_init*().
|
||||
* @addr: Intermediate physical address at which to place the mapping.
|
||||
* @size: Size of the mapping.
|
||||
*
|
||||
* The page-table is assumed to be unreachable by any hardware walkers prior
|
||||
* to freeing and therefore no TLB invalidation is performed.
|
||||
*/
|
||||
void kvm_pgtable_stage2_destroy_range(struct kvm_pgtable *pgt,
|
||||
u64 addr, u64 size);
|
||||
|
||||
/**
|
||||
* kvm_pgtable_stage2_destroy_pgd() - Destroy the PGD of guest stage-2 page-table.
|
||||
* @pgt: Page-table structure initialised by kvm_pgtable_stage2_init*().
|
||||
*
|
||||
* It is assumed that the rest of the page-table is freed before this operation.
|
||||
*/
|
||||
void kvm_pgtable_stage2_destroy_pgd(struct kvm_pgtable *pgt);
|
||||
|
||||
/**
|
||||
* kvm_pgtable_stage2_free_unlinked() - Free an unlinked stage-2 paging structure.
|
||||
* @mm_ops: Memory management callbacks.
|
||||
|
|
|
|||
|
|
@ -179,9 +179,7 @@ struct pkvm_mapping {
|
|||
|
||||
int pkvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu,
|
||||
struct kvm_pgtable_mm_ops *mm_ops);
|
||||
void pkvm_pgtable_stage2_destroy_range(struct kvm_pgtable *pgt,
|
||||
u64 addr, u64 size);
|
||||
void pkvm_pgtable_stage2_destroy_pgd(struct kvm_pgtable *pgt);
|
||||
void pkvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt);
|
||||
int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size, u64 phys,
|
||||
enum kvm_pgtable_prot prot, void *mc,
|
||||
enum kvm_pgtable_walk_flags flags);
|
||||
|
|
|
|||
|
|
@ -2113,8 +2113,10 @@ static void cpu_hyp_init_features(void)
|
|||
{
|
||||
cpu_set_hyp_vector();
|
||||
|
||||
if (is_kernel_in_hyp_mode())
|
||||
if (is_kernel_in_hyp_mode()) {
|
||||
kvm_timer_init_vhe();
|
||||
kvm_debug_init_vhe();
|
||||
}
|
||||
|
||||
if (vgic_present)
|
||||
kvm_vgic_init_cpu_hardware();
|
||||
|
|
|
|||
|
|
@ -96,6 +96,13 @@ void kvm_init_host_debug_data(void)
|
|||
}
|
||||
}
|
||||
|
||||
void kvm_debug_init_vhe(void)
|
||||
{
|
||||
/* Clear PMSCR_EL1.E{0,1}SPE which reset to UNKNOWN values. */
|
||||
if (SYS_FIELD_GET(ID_AA64DFR0_EL1, PMSVer, read_sysreg(id_aa64dfr0_el1)))
|
||||
write_sysreg_el1(0, SYS_PMSCR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configures the 'external' MDSCR_EL1 value for the guest, i.e. when the host
|
||||
* has taken over MDSCR_EL1.
|
||||
|
|
@ -138,6 +145,9 @@ void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu)
|
|||
/* Must be called before kvm_vcpu_load_vhe() */
|
||||
KVM_BUG_ON(vcpu_get_flag(vcpu, SYSREGS_ON_CPU), vcpu->kvm);
|
||||
|
||||
if (has_vhe())
|
||||
*host_data_ptr(host_debug_state.mdcr_el2) = read_sysreg(mdcr_el2);
|
||||
|
||||
/*
|
||||
* Determine which of the possible debug states we're in:
|
||||
*
|
||||
|
|
@ -184,6 +194,9 @@ void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu)
|
|||
|
||||
void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (has_vhe())
|
||||
write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2);
|
||||
|
||||
if (likely(!(vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -431,9 +431,6 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
|
|||
vcpu_set_flag(vcpu, PMUSERENR_ON_CPU);
|
||||
}
|
||||
|
||||
*host_data_ptr(host_debug_state.mdcr_el2) = read_sysreg(mdcr_el2);
|
||||
write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
|
||||
|
||||
if (cpus_have_final_cap(ARM64_HAS_HCX)) {
|
||||
u64 hcrx = vcpu->arch.hcrx_el2;
|
||||
if (is_nested_ctxt(vcpu)) {
|
||||
|
|
@ -454,8 +451,6 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt);
|
||||
|
||||
write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2);
|
||||
|
||||
write_sysreg(0, hstr_el2);
|
||||
if (system_supports_pmuv3()) {
|
||||
write_sysreg(ctxt_sys_reg(hctxt, PMUSERENR_EL0), pmuserenr_el0);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc);
|
|||
static void __activate_traps(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
___activate_traps(vcpu, vcpu->arch.hcr_el2);
|
||||
|
||||
*host_data_ptr(host_debug_state.mdcr_el2) = read_sysreg(mdcr_el2);
|
||||
write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
|
||||
|
||||
__activate_traps_common(vcpu);
|
||||
__activate_cptr_traps(vcpu);
|
||||
|
||||
|
|
@ -93,6 +97,8 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
|
|||
isb();
|
||||
}
|
||||
|
||||
write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2);
|
||||
|
||||
__deactivate_traps_common(vcpu);
|
||||
|
||||
write_sysreg_hcr(this_cpu_ptr(&kvm_init_params)->hcr_el2);
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
|
|||
|
||||
*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
|
||||
*vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR);
|
||||
__vcpu_assign_sys_reg(vcpu, read_sysreg_el1(SYS_VBAR), VBAR_EL1);
|
||||
__vcpu_assign_sys_reg(vcpu, VBAR_EL1, read_sysreg_el1(SYS_VBAR));
|
||||
|
||||
kvm_pend_exception(vcpu, EXCEPT_AA64_EL1_SYNC);
|
||||
|
||||
|
|
|
|||
|
|
@ -1551,38 +1551,21 @@ static int stage2_free_walker(const struct kvm_pgtable_visit_ctx *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void kvm_pgtable_stage2_destroy_range(struct kvm_pgtable *pgt,
|
||||
u64 addr, u64 size)
|
||||
void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt)
|
||||
{
|
||||
size_t pgd_sz;
|
||||
struct kvm_pgtable_walker walker = {
|
||||
.cb = stage2_free_walker,
|
||||
.flags = KVM_PGTABLE_WALK_LEAF |
|
||||
KVM_PGTABLE_WALK_TABLE_POST,
|
||||
};
|
||||
|
||||
WARN_ON(kvm_pgtable_walk(pgt, addr, size, &walker));
|
||||
}
|
||||
|
||||
void kvm_pgtable_stage2_destroy_pgd(struct kvm_pgtable *pgt)
|
||||
{
|
||||
size_t pgd_sz;
|
||||
|
||||
WARN_ON(kvm_pgtable_walk(pgt, 0, BIT(pgt->ia_bits), &walker));
|
||||
pgd_sz = kvm_pgd_pages(pgt->ia_bits, pgt->start_level) * PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Since the pgtable is unlinked at this point, and not shared with
|
||||
* other walkers, safely deference pgd with kvm_dereference_pteref_raw()
|
||||
*/
|
||||
pgt->mm_ops->free_pages_exact(kvm_dereference_pteref_raw(pgt->pgd), pgd_sz);
|
||||
pgt->mm_ops->free_pages_exact(kvm_dereference_pteref(&walker, pgt->pgd), pgd_sz);
|
||||
pgt->pgd = NULL;
|
||||
}
|
||||
|
||||
void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt)
|
||||
{
|
||||
kvm_pgtable_stage2_destroy_range(pgt, 0, BIT(pgt->ia_bits));
|
||||
kvm_pgtable_stage2_destroy_pgd(pgt);
|
||||
}
|
||||
|
||||
void kvm_pgtable_stage2_free_unlinked(struct kvm_pgtable_mm_ops *mm_ops, void *pgtable, s8 level)
|
||||
{
|
||||
kvm_pteref_t ptep = (kvm_pteref_t)pgtable;
|
||||
|
|
|
|||
|
|
@ -904,38 +904,6 @@ static int kvm_init_ipa_range(struct kvm_s2_mmu *mmu, unsigned long type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume that @pgt is valid and unlinked from the KVM MMU to free the
|
||||
* page-table without taking the kvm_mmu_lock and without performing any
|
||||
* TLB invalidations.
|
||||
*
|
||||
* Also, the range of addresses can be large enough to cause need_resched
|
||||
* warnings, for instance on CONFIG_PREEMPT_NONE kernels. Hence, invoke
|
||||
* cond_resched() periodically to prevent hogging the CPU for a long time
|
||||
* and schedule something else, if required.
|
||||
*/
|
||||
static void stage2_destroy_range(struct kvm_pgtable *pgt, phys_addr_t addr,
|
||||
phys_addr_t end)
|
||||
{
|
||||
u64 next;
|
||||
|
||||
do {
|
||||
next = stage2_range_addr_end(addr, end);
|
||||
KVM_PGT_FN(kvm_pgtable_stage2_destroy_range)(pgt, addr,
|
||||
next - addr);
|
||||
if (next != end)
|
||||
cond_resched();
|
||||
} while (addr = next, addr != end);
|
||||
}
|
||||
|
||||
static void kvm_stage2_destroy(struct kvm_pgtable *pgt)
|
||||
{
|
||||
unsigned int ia_bits = VTCR_EL2_IPA(pgt->mmu->vtcr);
|
||||
|
||||
stage2_destroy_range(pgt, 0, BIT(ia_bits));
|
||||
KVM_PGT_FN(kvm_pgtable_stage2_destroy_pgd)(pgt);
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_init_stage2_mmu - Initialise a S2 MMU structure
|
||||
* @kvm: The pointer to the KVM structure
|
||||
|
|
@ -1012,7 +980,7 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t
|
|||
return 0;
|
||||
|
||||
out_destroy_pgtable:
|
||||
kvm_stage2_destroy(pgt);
|
||||
KVM_PGT_FN(kvm_pgtable_stage2_destroy)(pgt);
|
||||
out_free_pgtable:
|
||||
kfree(pgt);
|
||||
return err;
|
||||
|
|
@ -1106,10 +1074,14 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
|
|||
mmu->pgt = NULL;
|
||||
free_percpu(mmu->last_vcpu_ran);
|
||||
}
|
||||
|
||||
if (kvm_is_nested_s2_mmu(kvm, mmu))
|
||||
kvm_init_nested_s2_mmu(mmu);
|
||||
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
|
||||
if (pgt) {
|
||||
kvm_stage2_destroy(pgt);
|
||||
KVM_PGT_FN(kvm_pgtable_stage2_destroy)(pgt);
|
||||
kfree(pgt);
|
||||
}
|
||||
}
|
||||
|
|
@ -1541,11 +1513,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
|||
exec_fault = kvm_vcpu_trap_is_exec_fault(vcpu);
|
||||
VM_BUG_ON(write_fault && exec_fault);
|
||||
|
||||
if (fault_is_perm && !write_fault && !exec_fault) {
|
||||
kvm_err("Unexpected L2 read permission error\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!is_protected_kvm_enabled())
|
||||
memcache = &vcpu->arch.mmu_page_cache;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -847,7 +847,7 @@ static void kvm_invalidate_vncr_ipa(struct kvm *kvm, u64 start, u64 end)
|
|||
|
||||
ipa_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift,
|
||||
vt->wr.level));
|
||||
ipa_start = vt->wr.pa & (ipa_size - 1);
|
||||
ipa_start = vt->wr.pa & ~(ipa_size - 1);
|
||||
ipa_end = ipa_start + ipa_size;
|
||||
|
||||
if (ipa_end <= start || ipa_start >= end)
|
||||
|
|
@ -887,7 +887,7 @@ static void invalidate_vncr_va(struct kvm *kvm,
|
|||
|
||||
va_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift,
|
||||
vt->wr.level));
|
||||
va_start = vt->gva & (va_size - 1);
|
||||
va_start = vt->gva & ~(va_size - 1);
|
||||
va_end = va_start + va_size;
|
||||
|
||||
switch (scope->type) {
|
||||
|
|
@ -1276,7 +1276,7 @@ static bool kvm_vncr_tlb_lookup(struct kvm_vcpu *vcpu)
|
|||
!(tcr & TCR_ASID16))
|
||||
asid &= GENMASK(7, 0);
|
||||
|
||||
return asid != vt->wr.asid;
|
||||
return asid == vt->wr.asid;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -316,16 +316,9 @@ static int __pkvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 start, u64 e
|
|||
return 0;
|
||||
}
|
||||
|
||||
void pkvm_pgtable_stage2_destroy_range(struct kvm_pgtable *pgt,
|
||||
u64 addr, u64 size)
|
||||
void pkvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt)
|
||||
{
|
||||
__pkvm_pgtable_stage2_unmap(pgt, addr, addr + size);
|
||||
}
|
||||
|
||||
void pkvm_pgtable_stage2_destroy_pgd(struct kvm_pgtable *pgt)
|
||||
{
|
||||
/* Expected to be called after all pKVM mappings have been released. */
|
||||
WARN_ON_ONCE(!RB_EMPTY_ROOT(&pgt->pkvm_mappings.rb_root));
|
||||
__pkvm_pgtable_stage2_unmap(pgt, 0, ~(0ULL));
|
||||
}
|
||||
|
||||
int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ static int iter_mark_lpis(struct kvm *kvm)
|
|||
int nr_lpis = 0;
|
||||
|
||||
xa_for_each(&dist->lpi_xa, intid, irq) {
|
||||
if (!vgic_try_get_irq_kref(irq))
|
||||
if (!vgic_try_get_irq_ref(irq))
|
||||
continue;
|
||||
|
||||
xa_set_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ void kvm_vgic_early_init(struct kvm *kvm)
|
|||
{
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
|
||||
xa_init_flags(&dist->lpi_xa, XA_FLAGS_LOCK_IRQ);
|
||||
xa_init(&dist->lpi_xa);
|
||||
}
|
||||
|
||||
/* CREATION */
|
||||
|
|
@ -208,7 +208,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
|
|||
raw_spin_lock_init(&irq->irq_lock);
|
||||
irq->vcpu = NULL;
|
||||
irq->target_vcpu = vcpu0;
|
||||
kref_init(&irq->refcount);
|
||||
refcount_set(&irq->refcount, 0);
|
||||
switch (dist->vgic_model) {
|
||||
case KVM_DEV_TYPE_ARM_VGIC_V2:
|
||||
irq->targets = 0;
|
||||
|
|
@ -277,7 +277,7 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
|
|||
irq->intid = i;
|
||||
irq->vcpu = NULL;
|
||||
irq->target_vcpu = vcpu;
|
||||
kref_init(&irq->refcount);
|
||||
refcount_set(&irq->refcount, 0);
|
||||
if (vgic_irq_is_sgi(i)) {
|
||||
/* SGIs */
|
||||
irq->enabled = 1;
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
|
|||
{
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
struct vgic_irq *irq = vgic_get_irq(kvm, intid), *oldirq;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
/* In this case there is no put, since we keep the reference. */
|
||||
|
|
@ -89,7 +88,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
|
|||
if (!irq)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = xa_reserve_irq(&dist->lpi_xa, intid, GFP_KERNEL_ACCOUNT);
|
||||
ret = xa_reserve(&dist->lpi_xa, intid, GFP_KERNEL_ACCOUNT);
|
||||
if (ret) {
|
||||
kfree(irq);
|
||||
return ERR_PTR(ret);
|
||||
|
|
@ -99,19 +98,19 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
|
|||
raw_spin_lock_init(&irq->irq_lock);
|
||||
|
||||
irq->config = VGIC_CONFIG_EDGE;
|
||||
kref_init(&irq->refcount);
|
||||
refcount_set(&irq->refcount, 1);
|
||||
irq->intid = intid;
|
||||
irq->target_vcpu = vcpu;
|
||||
irq->group = 1;
|
||||
|
||||
xa_lock_irqsave(&dist->lpi_xa, flags);
|
||||
xa_lock(&dist->lpi_xa);
|
||||
|
||||
/*
|
||||
* There could be a race with another vgic_add_lpi(), so we need to
|
||||
* check that we don't add a second list entry with the same LPI.
|
||||
*/
|
||||
oldirq = xa_load(&dist->lpi_xa, intid);
|
||||
if (vgic_try_get_irq_kref(oldirq)) {
|
||||
if (vgic_try_get_irq_ref(oldirq)) {
|
||||
/* Someone was faster with adding this LPI, lets use that. */
|
||||
kfree(irq);
|
||||
irq = oldirq;
|
||||
|
|
@ -126,7 +125,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
|
|||
}
|
||||
|
||||
out_unlock:
|
||||
xa_unlock_irqrestore(&dist->lpi_xa, flags);
|
||||
xa_unlock(&dist->lpi_xa);
|
||||
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
|
@ -547,7 +546,7 @@ static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db,
|
|||
rcu_read_lock();
|
||||
|
||||
irq = xa_load(&its->translation_cache, cache_key);
|
||||
if (!vgic_try_get_irq_kref(irq))
|
||||
if (!vgic_try_get_irq_ref(irq))
|
||||
irq = NULL;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
@ -571,7 +570,7 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
|
|||
* its_lock, as the ITE (and the reference it holds) cannot be freed.
|
||||
*/
|
||||
lockdep_assert_held(&its->its_lock);
|
||||
vgic_get_irq_kref(irq);
|
||||
vgic_get_irq_ref(irq);
|
||||
|
||||
old = xa_store(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT);
|
||||
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ static struct vgic_irq *__vgic_host_irq_get_vlpi(struct kvm *kvm, int host_irq)
|
|||
if (!irq->hw || irq->host_irq != host_irq)
|
||||
continue;
|
||||
|
||||
if (!vgic_try_get_irq_kref(irq))
|
||||
if (!vgic_try_get_irq_ref(irq))
|
||||
return NULL;
|
||||
|
||||
return irq;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = {
|
|||
* kvm->arch.config_lock (mutex)
|
||||
* its->cmd_lock (mutex)
|
||||
* its->its_lock (mutex)
|
||||
* vgic_cpu->ap_list_lock must be taken with IRQs disabled
|
||||
* vgic_dist->lpi_xa.xa_lock must be taken with IRQs disabled
|
||||
* vgic_dist->lpi_xa.xa_lock
|
||||
* vgic_cpu->ap_list_lock must be taken with IRQs disabled
|
||||
* vgic_irq->irq_lock must be taken with IRQs disabled
|
||||
*
|
||||
* As the ap_list_lock might be taken from the timer interrupt handler,
|
||||
|
|
@ -71,7 +71,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
|
|||
rcu_read_lock();
|
||||
|
||||
irq = xa_load(&dist->lpi_xa, intid);
|
||||
if (!vgic_try_get_irq_kref(irq))
|
||||
if (!vgic_try_get_irq_ref(irq))
|
||||
irq = NULL;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
@ -114,37 +114,66 @@ struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid)
|
|||
return vgic_get_irq(vcpu->kvm, intid);
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't do anything in here, because we lack the kvm pointer to
|
||||
* lock and remove the item from the lpi_list. So we keep this function
|
||||
* empty and use the return value of kref_put() to trigger the freeing.
|
||||
*/
|
||||
static void vgic_irq_release(struct kref *ref)
|
||||
static void vgic_release_lpi_locked(struct vgic_dist *dist, struct vgic_irq *irq)
|
||||
{
|
||||
lockdep_assert_held(&dist->lpi_xa.xa_lock);
|
||||
__xa_erase(&dist->lpi_xa, irq->intid);
|
||||
kfree_rcu(irq, rcu);
|
||||
}
|
||||
|
||||
static __must_check bool __vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
|
||||
{
|
||||
if (irq->intid < VGIC_MIN_LPI)
|
||||
return false;
|
||||
|
||||
return refcount_dec_and_test(&irq->refcount);
|
||||
}
|
||||
|
||||
static __must_check bool vgic_put_irq_norelease(struct kvm *kvm, struct vgic_irq *irq)
|
||||
{
|
||||
if (!__vgic_put_irq(kvm, irq))
|
||||
return false;
|
||||
|
||||
irq->pending_release = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
|
||||
{
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq->intid < VGIC_MIN_LPI)
|
||||
if (irq->intid >= VGIC_MIN_LPI)
|
||||
might_lock(&dist->lpi_xa.xa_lock);
|
||||
|
||||
if (!__vgic_put_irq(kvm, irq))
|
||||
return;
|
||||
|
||||
if (!kref_put(&irq->refcount, vgic_irq_release))
|
||||
return;
|
||||
xa_lock(&dist->lpi_xa);
|
||||
vgic_release_lpi_locked(dist, irq);
|
||||
xa_unlock(&dist->lpi_xa);
|
||||
}
|
||||
|
||||
xa_lock_irqsave(&dist->lpi_xa, flags);
|
||||
__xa_erase(&dist->lpi_xa, irq->intid);
|
||||
xa_unlock_irqrestore(&dist->lpi_xa, flags);
|
||||
static void vgic_release_deleted_lpis(struct kvm *kvm)
|
||||
{
|
||||
struct vgic_dist *dist = &kvm->arch.vgic;
|
||||
unsigned long intid;
|
||||
struct vgic_irq *irq;
|
||||
|
||||
kfree_rcu(irq, rcu);
|
||||
xa_lock(&dist->lpi_xa);
|
||||
|
||||
xa_for_each(&dist->lpi_xa, intid, irq) {
|
||||
if (irq->pending_release)
|
||||
vgic_release_lpi_locked(dist, irq);
|
||||
}
|
||||
|
||||
xa_unlock(&dist->lpi_xa);
|
||||
}
|
||||
|
||||
void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||
struct vgic_irq *irq, *tmp;
|
||||
bool deleted = false;
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);
|
||||
|
|
@ -155,11 +184,14 @@ void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu)
|
|||
list_del(&irq->ap_list);
|
||||
irq->vcpu = NULL;
|
||||
raw_spin_unlock(&irq->irq_lock);
|
||||
vgic_put_irq(vcpu->kvm, irq);
|
||||
deleted |= vgic_put_irq_norelease(vcpu->kvm, irq);
|
||||
}
|
||||
}
|
||||
|
||||
raw_spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
|
||||
|
||||
if (deleted)
|
||||
vgic_release_deleted_lpis(vcpu->kvm);
|
||||
}
|
||||
|
||||
void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending)
|
||||
|
|
@ -399,7 +431,7 @@ retry:
|
|||
* now in the ap_list. This is safe as the caller must already hold a
|
||||
* reference on the irq.
|
||||
*/
|
||||
vgic_get_irq_kref(irq);
|
||||
vgic_get_irq_ref(irq);
|
||||
list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
|
||||
irq->vcpu = vcpu;
|
||||
|
||||
|
|
@ -630,6 +662,7 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||
struct vgic_irq *irq, *tmp;
|
||||
bool deleted_lpis = false;
|
||||
|
||||
DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
|
||||
|
||||
|
|
@ -657,12 +690,12 @@ retry:
|
|||
|
||||
/*
|
||||
* This vgic_put_irq call matches the
|
||||
* vgic_get_irq_kref in vgic_queue_irq_unlock,
|
||||
* vgic_get_irq_ref in vgic_queue_irq_unlock,
|
||||
* where we added the LPI to the ap_list. As
|
||||
* we remove the irq from the list, we drop
|
||||
* also drop the refcount.
|
||||
*/
|
||||
vgic_put_irq(vcpu->kvm, irq);
|
||||
deleted_lpis |= vgic_put_irq_norelease(vcpu->kvm, irq);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -725,6 +758,9 @@ retry:
|
|||
}
|
||||
|
||||
raw_spin_unlock(&vgic_cpu->ap_list_lock);
|
||||
|
||||
if (unlikely(deleted_lpis))
|
||||
vgic_release_deleted_lpis(vcpu->kvm);
|
||||
}
|
||||
|
||||
static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -818,7 +854,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
|
|||
* the AP list has been sorted already.
|
||||
*/
|
||||
if (multi_sgi && irq->priority > prio) {
|
||||
_raw_spin_unlock(&irq->irq_lock);
|
||||
raw_spin_unlock(&irq->irq_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ void vgic_v2_put(struct kvm_vcpu *vcpu);
|
|||
void vgic_v2_save_state(struct kvm_vcpu *vcpu);
|
||||
void vgic_v2_restore_state(struct kvm_vcpu *vcpu);
|
||||
|
||||
static inline bool vgic_try_get_irq_kref(struct vgic_irq *irq)
|
||||
static inline bool vgic_try_get_irq_ref(struct vgic_irq *irq)
|
||||
{
|
||||
if (!irq)
|
||||
return false;
|
||||
|
|
@ -275,12 +275,12 @@ static inline bool vgic_try_get_irq_kref(struct vgic_irq *irq)
|
|||
if (irq->intid < VGIC_MIN_LPI)
|
||||
return true;
|
||||
|
||||
return kref_get_unless_zero(&irq->refcount);
|
||||
return refcount_inc_not_zero(&irq->refcount);
|
||||
}
|
||||
|
||||
static inline void vgic_get_irq_kref(struct vgic_irq *irq)
|
||||
static inline void vgic_get_irq_ref(struct vgic_irq *irq)
|
||||
{
|
||||
WARN_ON_ONCE(!vgic_try_get_irq_kref(irq));
|
||||
WARN_ON_ONCE(!vgic_try_get_irq_ref(irq));
|
||||
}
|
||||
|
||||
void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
|
||||
|
|
|
|||
|
|
@ -2778,12 +2778,19 @@ static unsigned long get_ind_bit(__u64 addr, unsigned long bit_nr, bool swap)
|
|||
|
||||
static struct page *get_map_page(struct kvm *kvm, u64 uaddr)
|
||||
{
|
||||
struct mm_struct *mm = kvm->mm;
|
||||
struct page *page = NULL;
|
||||
int locked = 1;
|
||||
|
||||
if (mmget_not_zero(mm)) {
|
||||
mmap_read_lock(mm);
|
||||
get_user_pages_remote(mm, uaddr, 1, FOLL_WRITE,
|
||||
&page, &locked);
|
||||
if (locked)
|
||||
mmap_read_unlock(mm);
|
||||
mmput(mm);
|
||||
}
|
||||
|
||||
mmap_read_lock(kvm->mm);
|
||||
get_user_pages_remote(kvm->mm, uaddr, 1, FOLL_WRITE,
|
||||
&page, NULL);
|
||||
mmap_read_unlock(kvm->mm);
|
||||
return page;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4864,12 +4864,12 @@ static void kvm_s390_assert_primary_as(struct kvm_vcpu *vcpu)
|
|||
* @vcpu: the vCPU whose gmap is to be fixed up
|
||||
* @gfn: the guest frame number used for memslots (including fake memslots)
|
||||
* @gaddr: the gmap address, does not have to match @gfn for ucontrol gmaps
|
||||
* @flags: FOLL_* flags
|
||||
* @foll: FOLL_* flags
|
||||
*
|
||||
* Return: 0 on success, < 0 in case of error.
|
||||
* Context: The mm lock must not be held before calling. May sleep.
|
||||
*/
|
||||
int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, unsigned int flags)
|
||||
int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, unsigned int foll)
|
||||
{
|
||||
struct kvm_memory_slot *slot;
|
||||
unsigned int fault_flags;
|
||||
|
|
@ -4883,13 +4883,13 @@ int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, u
|
|||
if (!slot || slot->flags & KVM_MEMSLOT_INVALID)
|
||||
return vcpu_post_run_addressing_exception(vcpu);
|
||||
|
||||
fault_flags = flags & FOLL_WRITE ? FAULT_FLAG_WRITE : 0;
|
||||
fault_flags = foll & FOLL_WRITE ? FAULT_FLAG_WRITE : 0;
|
||||
if (vcpu->arch.gmap->pfault_enabled)
|
||||
flags |= FOLL_NOWAIT;
|
||||
foll |= FOLL_NOWAIT;
|
||||
vmaddr = __gfn_to_hva_memslot(slot, gfn);
|
||||
|
||||
try_again:
|
||||
pfn = __kvm_faultin_pfn(slot, gfn, flags, &writable, &page);
|
||||
pfn = __kvm_faultin_pfn(slot, gfn, foll, &writable, &page);
|
||||
|
||||
/* Access outside memory, inject addressing exception */
|
||||
if (is_noslot_pfn(pfn))
|
||||
|
|
@ -4905,7 +4905,7 @@ try_again:
|
|||
return 0;
|
||||
vcpu->stat.pfault_sync++;
|
||||
/* Could not setup async pfault, try again synchronously */
|
||||
flags &= ~FOLL_NOWAIT;
|
||||
foll &= ~FOLL_NOWAIT;
|
||||
goto try_again;
|
||||
}
|
||||
/* Any other error */
|
||||
|
|
@ -4925,7 +4925,7 @@ try_again:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, unsigned int flags)
|
||||
static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, unsigned int foll)
|
||||
{
|
||||
unsigned long gaddr_tmp;
|
||||
gfn_t gfn;
|
||||
|
|
@ -4950,18 +4950,18 @@ static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, un
|
|||
}
|
||||
gfn = gpa_to_gfn(gaddr_tmp);
|
||||
}
|
||||
return __kvm_s390_handle_dat_fault(vcpu, gfn, gaddr, flags);
|
||||
return __kvm_s390_handle_dat_fault(vcpu, gfn, gaddr, foll);
|
||||
}
|
||||
|
||||
static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
unsigned int foll = 0;
|
||||
unsigned long gaddr;
|
||||
int rc;
|
||||
|
||||
gaddr = current->thread.gmap_teid.addr * PAGE_SIZE;
|
||||
if (kvm_s390_cur_gmap_fault_is_write())
|
||||
flags = FAULT_FLAG_WRITE;
|
||||
foll = FOLL_WRITE;
|
||||
|
||||
switch (current->thread.gmap_int_code & PGM_INT_CODE_MASK) {
|
||||
case 0:
|
||||
|
|
@ -5003,7 +5003,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu)
|
|||
send_sig(SIGSEGV, current, 0);
|
||||
if (rc != -ENXIO)
|
||||
break;
|
||||
flags = FAULT_FLAG_WRITE;
|
||||
foll = FOLL_WRITE;
|
||||
fallthrough;
|
||||
case PGM_PROTECTION:
|
||||
case PGM_SEGMENT_TRANSLATION:
|
||||
|
|
@ -5013,7 +5013,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu)
|
|||
case PGM_REGION_SECOND_TRANS:
|
||||
case PGM_REGION_THIRD_TRANS:
|
||||
kvm_s390_assert_primary_as(vcpu);
|
||||
return vcpu_dat_fault_handler(vcpu, gaddr, flags);
|
||||
return vcpu_dat_fault_handler(vcpu, gaddr, foll);
|
||||
default:
|
||||
KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx",
|
||||
current->thread.gmap_int_code, current->thread.gmap_teid.val);
|
||||
|
|
|
|||
|
|
@ -624,6 +624,17 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
|
|||
int cc, ret;
|
||||
u16 dummy;
|
||||
|
||||
/* Add the notifier only once. No races because we hold kvm->lock */
|
||||
if (kvm->arch.pv.mmu_notifier.ops != &kvm_s390_pv_mmu_notifier_ops) {
|
||||
/* The notifier will be unregistered when the VM is destroyed */
|
||||
kvm->arch.pv.mmu_notifier.ops = &kvm_s390_pv_mmu_notifier_ops;
|
||||
ret = mmu_notifier_register(&kvm->arch.pv.mmu_notifier, kvm->mm);
|
||||
if (ret) {
|
||||
kvm->arch.pv.mmu_notifier.ops = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = kvm_s390_pv_alloc_vm(kvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -659,11 +670,6 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
|
|||
return -EIO;
|
||||
}
|
||||
kvm->arch.gmap->guest_handle = uvcb.guest_handle;
|
||||
/* Add the notifier only once. No races because we hold kvm->lock */
|
||||
if (kvm->arch.pv.mmu_notifier.ops != &kvm_s390_pv_mmu_notifier_ops) {
|
||||
kvm->arch.pv.mmu_notifier.ops = &kvm_s390_pv_mmu_notifier_ops;
|
||||
mmu_notifier_register(&kvm->arch.pv.mmu_notifier, kvm->mm);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1250,10 +1250,12 @@ static int virtio_uml_probe(struct platform_device *pdev)
|
|||
device_set_wakeup_capable(&vu_dev->vdev.dev, true);
|
||||
|
||||
rc = register_virtio_device(&vu_dev->vdev);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
put_device(&vu_dev->vdev.dev);
|
||||
return rc;
|
||||
}
|
||||
vu_dev->registered = 1;
|
||||
return rc;
|
||||
return 0;
|
||||
|
||||
error_init:
|
||||
os_close_file(vu_dev->sock);
|
||||
|
|
|
|||
|
|
@ -535,7 +535,7 @@ ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds,
|
|||
cmsg->cmsg_type != SCM_RIGHTS)
|
||||
return n;
|
||||
|
||||
memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len);
|
||||
memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len - CMSG_LEN(0));
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@
|
|||
|
||||
void stack_protections(unsigned long address)
|
||||
{
|
||||
if (mprotect((void *) address, UM_THREAD_SIZE,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
|
||||
if (mprotect((void *) address, UM_THREAD_SIZE, PROT_READ | PROT_WRITE) < 0)
|
||||
panic("protecting stack failed, errno = %d", errno);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,27 +175,30 @@ static void topoext_fixup(struct topo_scan *tscan)
|
|||
|
||||
static void parse_topology_amd(struct topo_scan *tscan)
|
||||
{
|
||||
bool has_topoext = false;
|
||||
|
||||
/*
|
||||
* If the extended topology leaf 0x8000_001e is available
|
||||
* try to get SMT, CORE, TILE, and DIE shifts from extended
|
||||
* Try to get SMT, CORE, TILE, and DIE shifts from extended
|
||||
* CPUID leaf 0x8000_0026 on supported processors first. If
|
||||
* extended CPUID leaf 0x8000_0026 is not supported, try to
|
||||
* get SMT and CORE shift from leaf 0xb first, then try to
|
||||
* get the CORE shift from leaf 0x8000_0008.
|
||||
* get SMT and CORE shift from leaf 0xb. If either leaf is
|
||||
* available, cpu_parse_topology_ext() will return true.
|
||||
*/
|
||||
if (cpu_feature_enabled(X86_FEATURE_TOPOEXT))
|
||||
has_topoext = cpu_parse_topology_ext(tscan);
|
||||
bool has_xtopology = cpu_parse_topology_ext(tscan);
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES))
|
||||
tscan->c->topo.cpu_type = cpuid_ebx(0x80000026);
|
||||
|
||||
if (!has_topoext && !parse_8000_0008(tscan))
|
||||
/*
|
||||
* If XTOPOLOGY leaves (0x26/0xb) are not available, try to
|
||||
* get the CORE shift from leaf 0x8000_0008 first.
|
||||
*/
|
||||
if (!has_xtopology && !parse_8000_0008(tscan))
|
||||
return;
|
||||
|
||||
/* Prefer leaf 0x8000001e if available */
|
||||
if (parse_8000_001e(tscan, has_topoext))
|
||||
/*
|
||||
* Prefer leaf 0x8000001e if available to get the SMT shift and
|
||||
* the initial APIC ID if XTOPOLOGY leaves are not available.
|
||||
*/
|
||||
if (parse_8000_001e(tscan, has_xtopology))
|
||||
return;
|
||||
|
||||
/* Try the NODEID MSR */
|
||||
|
|
|
|||
|
|
@ -4046,8 +4046,7 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
|
|||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
u64 cr8;
|
||||
|
||||
if (nested_svm_virtualize_tpr(vcpu) ||
|
||||
kvm_vcpu_apicv_active(vcpu))
|
||||
if (nested_svm_virtualize_tpr(vcpu))
|
||||
return;
|
||||
|
||||
cr8 = kvm_get_cr8(vcpu);
|
||||
|
|
|
|||
|
|
@ -1795,6 +1795,7 @@ static int write_same_filled_page(struct zram *zram, unsigned long fill,
|
|||
u32 index)
|
||||
{
|
||||
zram_slot_lock(zram, index);
|
||||
zram_free_page(zram, index);
|
||||
zram_set_flag(zram, index, ZRAM_SAME);
|
||||
zram_set_handle(zram, index, fill);
|
||||
zram_slot_unlock(zram, index);
|
||||
|
|
@ -1832,6 +1833,7 @@ static int write_incompressible_page(struct zram *zram, struct page *page,
|
|||
kunmap_local(src);
|
||||
|
||||
zram_slot_lock(zram, index);
|
||||
zram_free_page(zram, index);
|
||||
zram_set_flag(zram, index, ZRAM_HUGE);
|
||||
zram_set_handle(zram, index, handle);
|
||||
zram_set_obj_size(zram, index, PAGE_SIZE);
|
||||
|
|
@ -1855,11 +1857,6 @@ static int zram_write_page(struct zram *zram, struct page *page, u32 index)
|
|||
unsigned long element;
|
||||
bool same_filled;
|
||||
|
||||
/* First, free memory allocated to this slot (if any) */
|
||||
zram_slot_lock(zram, index);
|
||||
zram_free_page(zram, index);
|
||||
zram_slot_unlock(zram, index);
|
||||
|
||||
mem = kmap_local_page(page);
|
||||
same_filled = page_same_filled(mem, &element);
|
||||
kunmap_local(mem);
|
||||
|
|
@ -1901,6 +1898,7 @@ static int zram_write_page(struct zram *zram, struct page *page, u32 index)
|
|||
zcomp_stream_put(zstrm);
|
||||
|
||||
zram_slot_lock(zram, index);
|
||||
zram_free_page(zram, index);
|
||||
zram_set_handle(zram, index, handle);
|
||||
zram_set_obj_size(zram, index, comp_len);
|
||||
zram_slot_unlock(zram, index);
|
||||
|
|
|
|||
|
|
@ -48,12 +48,16 @@ static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec,
|
|||
u32 mask;
|
||||
int ret;
|
||||
|
||||
if (dma_spec->args_count != RNZ1_DMAMUX_NCELLS)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (dma_spec->args_count != RNZ1_DMAMUX_NCELLS) {
|
||||
ret = -EINVAL;
|
||||
goto put_device;
|
||||
}
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (!map) {
|
||||
ret = -ENOMEM;
|
||||
goto put_device;
|
||||
}
|
||||
|
||||
chan = dma_spec->args[0];
|
||||
map->req_idx = dma_spec->args[4];
|
||||
|
|
@ -94,12 +98,15 @@ static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec,
|
|||
if (ret)
|
||||
goto clear_bitmap;
|
||||
|
||||
put_device(&pdev->dev);
|
||||
return map;
|
||||
|
||||
clear_bitmap:
|
||||
clear_bit(map->req_idx, dmamux->used_chans);
|
||||
free_map:
|
||||
kfree(map);
|
||||
put_device:
|
||||
put_device(&pdev->dev);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,27 +189,30 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
|||
idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!idxd->wq_enable_map) {
|
||||
rc = -ENOMEM;
|
||||
goto err_bitmap;
|
||||
goto err_free_wqs;
|
||||
}
|
||||
|
||||
for (i = 0; i < idxd->max_wqs; i++) {
|
||||
wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev));
|
||||
if (!wq) {
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
goto err_unwind;
|
||||
}
|
||||
|
||||
idxd_dev_set_type(&wq->idxd_dev, IDXD_DEV_WQ);
|
||||
conf_dev = wq_confdev(wq);
|
||||
wq->id = i;
|
||||
wq->idxd = idxd;
|
||||
device_initialize(wq_confdev(wq));
|
||||
device_initialize(conf_dev);
|
||||
conf_dev->parent = idxd_confdev(idxd);
|
||||
conf_dev->bus = &dsa_bus_type;
|
||||
conf_dev->type = &idxd_wq_device_type;
|
||||
rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
if (rc < 0) {
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
goto err_unwind;
|
||||
}
|
||||
|
||||
mutex_init(&wq->wq_lock);
|
||||
init_waitqueue_head(&wq->err_queue);
|
||||
|
|
@ -220,15 +223,20 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
|||
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
|
||||
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!wq->wqcfg) {
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
goto err_unwind;
|
||||
}
|
||||
|
||||
if (idxd->hw.wq_cap.op_config) {
|
||||
wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL);
|
||||
if (!wq->opcap_bmap) {
|
||||
kfree(wq->wqcfg);
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
rc = -ENOMEM;
|
||||
goto err_opcap_bmap;
|
||||
goto err_unwind;
|
||||
}
|
||||
bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
|
||||
}
|
||||
|
|
@ -239,13 +247,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
|||
|
||||
return 0;
|
||||
|
||||
err_opcap_bmap:
|
||||
kfree(wq->wqcfg);
|
||||
|
||||
err:
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
|
||||
err_unwind:
|
||||
while (--i >= 0) {
|
||||
wq = idxd->wqs[i];
|
||||
if (idxd->hw.wq_cap.op_config)
|
||||
|
|
@ -254,11 +256,10 @@ err:
|
|||
conf_dev = wq_confdev(wq);
|
||||
put_device(conf_dev);
|
||||
kfree(wq);
|
||||
|
||||
}
|
||||
bitmap_free(idxd->wq_enable_map);
|
||||
|
||||
err_bitmap:
|
||||
err_free_wqs:
|
||||
kfree(idxd->wqs);
|
||||
|
||||
return rc;
|
||||
|
|
@ -1291,10 +1292,12 @@ static void idxd_remove(struct pci_dev *pdev)
|
|||
device_unregister(idxd_confdev(idxd));
|
||||
idxd_shutdown(pdev);
|
||||
idxd_device_remove_debugfs(idxd);
|
||||
idxd_cleanup(idxd);
|
||||
perfmon_pmu_remove(idxd);
|
||||
idxd_cleanup_interrupts(idxd);
|
||||
if (device_pasid_enabled(idxd))
|
||||
idxd_disable_system_pasid(idxd);
|
||||
pci_iounmap(pdev, idxd->reg_base);
|
||||
put_device(idxd_confdev(idxd));
|
||||
idxd_free(idxd);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1283,13 +1283,17 @@ static int bam_dma_probe(struct platform_device *pdev)
|
|||
if (!bdev->bamclk) {
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "num-channels",
|
||||
&bdev->num_channels);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(bdev->dev, "num-channels unspecified in dt\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-ees",
|
||||
&bdev->num_ees);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(bdev->dev, "num-ees unspecified in dt\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(bdev->bamclk);
|
||||
|
|
|
|||
|
|
@ -2064,8 +2064,8 @@ static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
|
|||
* priority. So Q0 is the highest priority queue and the last queue has
|
||||
* the lowest priority.
|
||||
*/
|
||||
queue_priority_map = devm_kcalloc(dev, ecc->num_tc + 1, sizeof(s8),
|
||||
GFP_KERNEL);
|
||||
queue_priority_map = devm_kcalloc(dev, ecc->num_tc + 1,
|
||||
sizeof(*queue_priority_map), GFP_KERNEL);
|
||||
if (!queue_priority_map)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -211,8 +211,8 @@ static int
|
|||
dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1) = { 0 };
|
||||
const struct dpll_device_ops *ops = dpll_device_ops(dpll);
|
||||
DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 };
|
||||
enum dpll_clock_quality_level ql;
|
||||
int ret;
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll,
|
|||
ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack);
|
||||
if (ret)
|
||||
return ret;
|
||||
for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX)
|
||||
for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1)
|
||||
if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql))
|
||||
return -EMSGSIZE;
|
||||
|
||||
|
|
|
|||
|
|
@ -213,19 +213,35 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
|
|||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||
|
||||
if (kfd_mem_limit.system_mem_used + system_mem_needed >
|
||||
kfd_mem_limit.max_system_mem_limit)
|
||||
kfd_mem_limit.max_system_mem_limit) {
|
||||
pr_debug("Set no_system_mem_limit=1 if using shared memory\n");
|
||||
if (!no_system_mem_limit) {
|
||||
ret = -ENOMEM;
|
||||
goto release;
|
||||
}
|
||||
}
|
||||
|
||||
if ((kfd_mem_limit.system_mem_used + system_mem_needed >
|
||||
kfd_mem_limit.max_system_mem_limit && !no_system_mem_limit) ||
|
||||
(kfd_mem_limit.ttm_mem_used + ttm_mem_needed >
|
||||
kfd_mem_limit.max_ttm_mem_limit) ||
|
||||
(adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed >
|
||||
vram_size - reserved_for_pt - reserved_for_ras - atomic64_read(&adev->vram_pin_size))) {
|
||||
if (kfd_mem_limit.ttm_mem_used + ttm_mem_needed >
|
||||
kfd_mem_limit.max_ttm_mem_limit) {
|
||||
ret = -ENOMEM;
|
||||
goto release;
|
||||
}
|
||||
|
||||
/*if is_app_apu is false and apu_prefer_gtt is true, it is an APU with
|
||||
* carve out < gtt. In that case, VRAM allocation will go to gtt domain, skip
|
||||
* VRAM check since ttm_mem_limit check already cover this allocation
|
||||
*/
|
||||
|
||||
if (adev && xcp_id >= 0 && (!adev->apu_prefer_gtt || adev->gmc.is_app_apu)) {
|
||||
uint64_t vram_available =
|
||||
vram_size - reserved_for_pt - reserved_for_ras -
|
||||
atomic64_read(&adev->vram_pin_size);
|
||||
if (adev->kfd.vram_used[xcp_id] + vram_needed > vram_available) {
|
||||
ret = -ENOMEM;
|
||||
goto release;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update memory accounting by decreasing available system
|
||||
* memory, TTM memory and GPU memory as computed above
|
||||
*/
|
||||
|
|
@ -1626,11 +1642,15 @@ size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev,
|
|||
uint64_t vram_available, system_mem_available, ttm_mem_available;
|
||||
|
||||
spin_lock(&kfd_mem_limit.mem_limit_lock);
|
||||
vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id)
|
||||
- adev->kfd.vram_used_aligned[xcp_id]
|
||||
- atomic64_read(&adev->vram_pin_size)
|
||||
- reserved_for_pt
|
||||
- reserved_for_ras;
|
||||
if (adev->apu_prefer_gtt && !adev->gmc.is_app_apu)
|
||||
vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id)
|
||||
- adev->kfd.vram_used_aligned[xcp_id];
|
||||
else
|
||||
vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id)
|
||||
- adev->kfd.vram_used_aligned[xcp_id]
|
||||
- atomic64_read(&adev->vram_pin_size)
|
||||
- reserved_for_pt
|
||||
- reserved_for_ras;
|
||||
|
||||
if (adev->apu_prefer_gtt) {
|
||||
system_mem_available = no_system_mem_limit ?
|
||||
|
|
|
|||
|
|
@ -421,8 +421,6 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
|
|||
dma_fence_put(ring->vmid_wait);
|
||||
ring->vmid_wait = NULL;
|
||||
ring->me = 0;
|
||||
|
||||
ring->adev->rings[ring->idx] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "amdgpu.h"
|
||||
#include "isp_v4_1_1.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/isp_4_1_1.bin");
|
||||
|
||||
#define ISP_PERFORMANCE_STATE_LOW 0
|
||||
#define ISP_PERFORMANCE_STATE_HIGH 1
|
||||
|
||||
|
|
|
|||
|
|
@ -149,12 +149,12 @@ static int psp_v11_0_wait_for_bootloader(struct psp_context *psp)
|
|||
int ret;
|
||||
int retry_loop;
|
||||
|
||||
for (retry_loop = 0; retry_loop < 10; retry_loop++) {
|
||||
for (retry_loop = 0; retry_loop < 20; retry_loop++) {
|
||||
/* Wait for bootloader to signify that is
|
||||
ready having bit 31 of C2PMSG_35 set to 1 */
|
||||
ret = psp_wait_for(
|
||||
psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
|
||||
0x80000000, 0x80000000, PSP_WAITREG_NOVERBOSE);
|
||||
0x80000000, 0x8000FFFF, PSP_WAITREG_NOVERBOSE);
|
||||
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
|
@ -397,18 +397,6 @@ static int psp_v11_0_mode1_reset(struct psp_context *psp)
|
|||
|
||||
msleep(500);
|
||||
|
||||
offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33);
|
||||
|
||||
ret = psp_wait_for(psp, offset, MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK,
|
||||
0);
|
||||
|
||||
if (ret) {
|
||||
DRM_INFO("psp mode 1 reset failed!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_INFO("psp mode1 reset succeed \n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -665,7 +653,8 @@ static const struct psp_funcs psp_v11_0_funcs = {
|
|||
.ring_get_wptr = psp_v11_0_ring_get_wptr,
|
||||
.ring_set_wptr = psp_v11_0_ring_set_wptr,
|
||||
.load_usbc_pd_fw = psp_v11_0_load_usbc_pd_fw,
|
||||
.read_usbc_pd_fw = psp_v11_0_read_usbc_pd_fw
|
||||
.read_usbc_pd_fw = psp_v11_0_read_usbc_pd_fw,
|
||||
.wait_for_bootloader = psp_v11_0_wait_for_bootloader
|
||||
};
|
||||
|
||||
void psp_v11_0_set_psp_funcs(struct psp_context *psp)
|
||||
|
|
|
|||
|
|
@ -1888,15 +1888,19 @@ static int vcn_v3_0_limit_sched(struct amdgpu_cs_parser *p,
|
|||
struct amdgpu_job *job)
|
||||
{
|
||||
struct drm_gpu_scheduler **scheds;
|
||||
|
||||
/* The create msg must be in the first IB submitted */
|
||||
if (atomic_read(&job->base.entity->fence_seq))
|
||||
return -EINVAL;
|
||||
struct dma_fence *fence;
|
||||
|
||||
/* if VCN0 is harvested, we can't support AV1 */
|
||||
if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0)
|
||||
return -EINVAL;
|
||||
|
||||
/* wait for all jobs to finish before switching to instance 0 */
|
||||
fence = amdgpu_ctx_get_fence(p->ctx, job->base.entity, ~0ull);
|
||||
if (fence) {
|
||||
dma_fence_wait(fence, false);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
|
||||
scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_DEC]
|
||||
[AMDGPU_RING_PRIO_DEFAULT].sched;
|
||||
drm_sched_entity_modify_sched(job->base.entity, scheds, 1);
|
||||
|
|
|
|||
|
|
@ -1808,15 +1808,19 @@ static int vcn_v4_0_limit_sched(struct amdgpu_cs_parser *p,
|
|||
struct amdgpu_job *job)
|
||||
{
|
||||
struct drm_gpu_scheduler **scheds;
|
||||
|
||||
/* The create msg must be in the first IB submitted */
|
||||
if (atomic_read(&job->base.entity->fence_seq))
|
||||
return -EINVAL;
|
||||
struct dma_fence *fence;
|
||||
|
||||
/* if VCN0 is harvested, we can't support AV1 */
|
||||
if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0)
|
||||
return -EINVAL;
|
||||
|
||||
/* wait for all jobs to finish before switching to instance 0 */
|
||||
fence = amdgpu_ctx_get_fence(p->ctx, job->base.entity, ~0ull);
|
||||
if (fence) {
|
||||
dma_fence_wait(fence, false);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
|
||||
scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC]
|
||||
[AMDGPU_RING_PRIO_0].sched;
|
||||
drm_sched_entity_modify_sched(job->base.entity, scheds, 1);
|
||||
|
|
@ -1907,22 +1911,16 @@ out:
|
|||
|
||||
#define RADEON_VCN_ENGINE_TYPE_ENCODE (0x00000002)
|
||||
#define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003)
|
||||
|
||||
#define RADEON_VCN_ENGINE_INFO (0x30000001)
|
||||
#define RADEON_VCN_ENGINE_INFO_MAX_OFFSET 16
|
||||
|
||||
#define RENCODE_ENCODE_STANDARD_AV1 2
|
||||
#define RENCODE_IB_PARAM_SESSION_INIT 0x00000003
|
||||
#define RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET 64
|
||||
|
||||
/* return the offset in ib if id is found, -1 otherwise
|
||||
* to speed up the searching we only search upto max_offset
|
||||
*/
|
||||
static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int max_offset)
|
||||
/* return the offset in ib if id is found, -1 otherwise */
|
||||
static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ib->length_dw && i < max_offset && ib->ptr[i] >= 8; i += ib->ptr[i]/4) {
|
||||
for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) {
|
||||
if (ib->ptr[i + 1] == id)
|
||||
return i;
|
||||
}
|
||||
|
|
@ -1937,33 +1935,29 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
|
|||
struct amdgpu_vcn_decode_buffer *decode_buffer;
|
||||
uint64_t addr;
|
||||
uint32_t val;
|
||||
int idx;
|
||||
int idx = 0, sidx;
|
||||
|
||||
/* The first instance can decode anything */
|
||||
if (!ring->me)
|
||||
return 0;
|
||||
|
||||
/* RADEON_VCN_ENGINE_INFO is at the top of ib block */
|
||||
idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO,
|
||||
RADEON_VCN_ENGINE_INFO_MAX_OFFSET);
|
||||
if (idx < 0) /* engine info is missing */
|
||||
return 0;
|
||||
while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
|
||||
val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
|
||||
if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
|
||||
decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
|
||||
|
||||
val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
|
||||
if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
|
||||
decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6];
|
||||
if (!(decode_buffer->valid_buf_flag & 0x1))
|
||||
return 0;
|
||||
|
||||
if (!(decode_buffer->valid_buf_flag & 0x1))
|
||||
return 0;
|
||||
|
||||
addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
|
||||
decode_buffer->msg_buffer_address_lo;
|
||||
return vcn_v4_0_dec_msg(p, job, addr);
|
||||
} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
|
||||
idx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT,
|
||||
RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET);
|
||||
if (idx >= 0 && ib->ptr[idx + 2] == RENCODE_ENCODE_STANDARD_AV1)
|
||||
return vcn_v4_0_limit_sched(p, job);
|
||||
addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
|
||||
decode_buffer->msg_buffer_address_lo;
|
||||
return vcn_v4_0_dec_msg(p, job, addr);
|
||||
} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
|
||||
sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
|
||||
if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1)
|
||||
return vcn_v4_0_limit_sched(p, job);
|
||||
}
|
||||
idx += ib->ptr[idx] / 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1587,7 +1587,8 @@ static int kfd_dev_create_p2p_links(void)
|
|||
break;
|
||||
if (!dev->gpu || !dev->gpu->adev ||
|
||||
(dev->gpu->kfd->hive_id &&
|
||||
dev->gpu->kfd->hive_id == new_dev->gpu->kfd->hive_id))
|
||||
dev->gpu->kfd->hive_id == new_dev->gpu->kfd->hive_id &&
|
||||
amdgpu_xgmi_get_is_sharing_enabled(dev->gpu->adev, new_dev->gpu->adev)))
|
||||
goto next;
|
||||
|
||||
/* check if node(s) is/are peer accessible in one direction or bi-direction */
|
||||
|
|
|
|||
|
|
@ -2913,6 +2913,17 @@ static int dm_oem_i2c_hw_init(struct amdgpu_device *adev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dm_oem_i2c_hw_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_display_manager *dm = &adev->dm;
|
||||
|
||||
if (dm->oem_i2c) {
|
||||
i2c_del_adapter(&dm->oem_i2c->base);
|
||||
kfree(dm->oem_i2c);
|
||||
dm->oem_i2c = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_hw_init() - Initialize DC device
|
||||
* @ip_block: Pointer to the amdgpu_ip_block for this hw instance.
|
||||
|
|
@ -2963,7 +2974,7 @@ static int dm_hw_fini(struct amdgpu_ip_block *ip_block)
|
|||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
kfree(adev->dm.oem_i2c);
|
||||
dm_oem_i2c_hw_fini(adev);
|
||||
|
||||
amdgpu_dm_hpd_fini(adev);
|
||||
|
||||
|
|
@ -3127,25 +3138,6 @@ static void dm_destroy_cached_state(struct amdgpu_device *adev)
|
|||
dm->cached_state = NULL;
|
||||
}
|
||||
|
||||
static void dm_complete(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
dm_destroy_cached_state(adev);
|
||||
}
|
||||
|
||||
static int dm_prepare_suspend(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (amdgpu_in_reset(adev))
|
||||
return 0;
|
||||
|
||||
WARN_ON(adev->dm.cached_state);
|
||||
|
||||
return dm_cache_state(adev);
|
||||
}
|
||||
|
||||
static int dm_suspend(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
|
@ -3571,10 +3563,8 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = {
|
|||
.early_fini = amdgpu_dm_early_fini,
|
||||
.hw_init = dm_hw_init,
|
||||
.hw_fini = dm_hw_fini,
|
||||
.prepare_suspend = dm_prepare_suspend,
|
||||
.suspend = dm_suspend,
|
||||
.resume = dm_resume,
|
||||
.complete = dm_complete,
|
||||
.is_idle = dm_is_idle,
|
||||
.wait_for_idle = dm_wait_for_idle,
|
||||
.check_soft_reset = dm_check_soft_reset,
|
||||
|
|
|
|||
|
|
@ -809,6 +809,7 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
|
|||
drm_dp_aux_init(&aconnector->dm_dp_aux.aux);
|
||||
drm_dp_cec_register_connector(&aconnector->dm_dp_aux.aux,
|
||||
&aconnector->base);
|
||||
drm_dp_dpcd_set_probe(&aconnector->dm_dp_aux.aux, false);
|
||||
|
||||
if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_eDP)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1145,6 +1145,7 @@ struct dc_debug_options {
|
|||
bool enable_hblank_borrow;
|
||||
bool force_subvp_df_throttle;
|
||||
uint32_t acpi_transition_bitmasks[MAX_PIPES];
|
||||
bool enable_pg_cntl_debug_logs;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -133,30 +133,34 @@ enum dsc_clk_source {
|
|||
};
|
||||
|
||||
|
||||
static void dccg35_set_dsc_clk_rcg(struct dccg *dccg, int inst, bool enable)
|
||||
static void dccg35_set_dsc_clk_rcg(struct dccg *dccg, int inst, bool allow_rcg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc && enable)
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc && allow_rcg)
|
||||
return;
|
||||
|
||||
switch (inst) {
|
||||
case 0:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
|
||||
break;
|
||||
case 3:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for clock to ramp */
|
||||
if (!allow_rcg)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void dccg35_set_symclk32_se_rcg(
|
||||
|
|
@ -385,35 +389,34 @@ static void dccg35_set_dtbclk_p_rcg(struct dccg *dccg, int inst, bool enable)
|
|||
}
|
||||
}
|
||||
|
||||
static void dccg35_set_dppclk_rcg(struct dccg *dccg,
|
||||
int inst, bool enable)
|
||||
static void dccg35_set_dppclk_rcg(struct dccg *dccg, int inst, bool allow_rcg)
|
||||
{
|
||||
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && enable)
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && allow_rcg)
|
||||
return;
|
||||
|
||||
switch (inst) {
|
||||
case 0:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
|
||||
break;
|
||||
case 3:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable ? 0 : 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
break;
|
||||
}
|
||||
//DC_LOG_DEBUG("%s: inst(%d) DPPCLK rcg_disable: %d\n", __func__, inst, enable ? 0 : 1);
|
||||
|
||||
/* Wait for clock to ramp */
|
||||
if (!allow_rcg)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void dccg35_set_dpstreamclk_rcg(
|
||||
|
|
@ -1177,32 +1180,34 @@ static void dccg35_update_dpp_dto(struct dccg *dccg, int dpp_inst,
|
|||
}
|
||||
|
||||
static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg,
|
||||
uint32_t dpp_inst, uint32_t enable)
|
||||
uint32_t dpp_inst, uint32_t disallow_rcg)
|
||||
{
|
||||
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
|
||||
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp)
|
||||
if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && !disallow_rcg)
|
||||
return;
|
||||
|
||||
|
||||
switch (dpp_inst) {
|
||||
case 0:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, disallow_rcg);
|
||||
break;
|
||||
case 1:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, disallow_rcg);
|
||||
break;
|
||||
case 2:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, disallow_rcg);
|
||||
break;
|
||||
case 3:
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, disallow_rcg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//DC_LOG_DEBUG("%s: dpp_inst(%d) rcg: %d\n", __func__, dpp_inst, enable);
|
||||
|
||||
/* Wait for clock to ramp */
|
||||
if (disallow_rcg)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void dccg35_get_pixel_rate_div(
|
||||
|
|
@ -1782,8 +1787,7 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
|
|||
//Disable DTO
|
||||
switch (inst) {
|
||||
case 0:
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1);
|
||||
|
||||
REG_UPDATE_2(DSCCLK0_DTO_PARAM,
|
||||
DSCCLK0_DTO_PHASE, 0,
|
||||
|
|
@ -1791,8 +1795,7 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
|
|||
REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1);
|
||||
break;
|
||||
case 1:
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1);
|
||||
|
||||
REG_UPDATE_2(DSCCLK1_DTO_PARAM,
|
||||
DSCCLK1_DTO_PHASE, 0,
|
||||
|
|
@ -1800,8 +1803,7 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
|
|||
REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1);
|
||||
break;
|
||||
case 2:
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1);
|
||||
|
||||
REG_UPDATE_2(DSCCLK2_DTO_PARAM,
|
||||
DSCCLK2_DTO_PHASE, 0,
|
||||
|
|
@ -1809,8 +1811,7 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
|
|||
REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1);
|
||||
break;
|
||||
case 3:
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc)
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1);
|
||||
REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1);
|
||||
|
||||
REG_UPDATE_2(DSCCLK3_DTO_PARAM,
|
||||
DSCCLK3_DTO_PHASE, 0,
|
||||
|
|
@ -1821,6 +1822,9 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst)
|
|||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for clock to ramp */
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void dccg35_disable_dscclk(struct dccg *dccg,
|
||||
|
|
@ -1864,6 +1868,9 @@ static void dccg35_disable_dscclk(struct dccg *dccg,
|
|||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for clock ramp */
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
|
||||
|
|
@ -2349,10 +2356,7 @@ static void dccg35_disable_symclk_se_cb(
|
|||
|
||||
void dccg35_root_gate_disable_control(struct dccg *dccg, uint32_t pipe_idx, uint32_t disable_clock_gating)
|
||||
{
|
||||
|
||||
if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) {
|
||||
dccg35_set_dppclk_root_clock_gating(dccg, pipe_idx, disable_clock_gating);
|
||||
}
|
||||
dccg35_set_dppclk_root_clock_gating(dccg, pipe_idx, disable_clock_gating);
|
||||
}
|
||||
|
||||
static const struct dccg_funcs dccg35_funcs_new = {
|
||||
|
|
|
|||
|
|
@ -955,7 +955,7 @@ enum dc_status dcn20_enable_stream_timing(
|
|||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
fsleep(stream->timing.v_total * (stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz));
|
||||
udelay(stream->timing.v_total * (stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz));
|
||||
|
||||
params.vertical_total_min = stream->adjust.v_total_min;
|
||||
params.vertical_total_max = stream->adjust.v_total_max;
|
||||
|
|
|
|||
|
|
@ -113,6 +113,14 @@ static void enable_memory_low_power(struct dc *dc)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log)
|
||||
{
|
||||
if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) {
|
||||
if (dc->res_pool->pg_cntl->funcs->print_pg_status)
|
||||
dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log);
|
||||
}
|
||||
}
|
||||
|
||||
void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable)
|
||||
{
|
||||
REG_UPDATE_3(DMU_CLK_CNTL,
|
||||
|
|
@ -137,6 +145,8 @@ void dcn35_init_hw(struct dc *dc)
|
|||
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
|
||||
int i;
|
||||
|
||||
print_pg_status(dc, __func__, ": start");
|
||||
|
||||
if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
|
||||
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
|
||||
|
||||
|
|
@ -200,10 +210,7 @@ void dcn35_init_hw(struct dc *dc)
|
|||
|
||||
/* we want to turn off all dp displays before doing detection */
|
||||
dc->link_srv->blank_all_dp_displays(dc);
|
||||
/*
|
||||
if (hws->funcs.enable_power_gating_plane)
|
||||
hws->funcs.enable_power_gating_plane(dc->hwseq, true);
|
||||
*/
|
||||
|
||||
if (res_pool->hubbub && res_pool->hubbub->funcs->dchubbub_init)
|
||||
res_pool->hubbub->funcs->dchubbub_init(dc->res_pool->hubbub);
|
||||
/* If taking control over from VBIOS, we may want to optimize our first
|
||||
|
|
@ -236,6 +243,8 @@ void dcn35_init_hw(struct dc *dc)
|
|||
}
|
||||
|
||||
hws->funcs.init_pipes(dc, dc->current_state);
|
||||
print_pg_status(dc, __func__, ": after init_pipes");
|
||||
|
||||
if (dc->res_pool->hubbub->funcs->allow_self_refresh_control &&
|
||||
!dc->res_pool->hubbub->ctx->dc->debug.disable_stutter)
|
||||
dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
|
||||
|
|
@ -312,6 +321,7 @@ void dcn35_init_hw(struct dc *dc)
|
|||
if (dc->res_pool->pg_cntl->funcs->init_pg_status)
|
||||
dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl);
|
||||
}
|
||||
print_pg_status(dc, __func__, ": after init_pg_status");
|
||||
}
|
||||
|
||||
static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
|
||||
|
|
@ -500,97 +510,6 @@ void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_
|
|||
}
|
||||
}
|
||||
|
||||
void dcn35_dsc_pg_control(
|
||||
struct dce_hwseq *hws,
|
||||
unsigned int dsc_inst,
|
||||
bool power_on)
|
||||
{
|
||||
uint32_t power_gate = power_on ? 0 : 1;
|
||||
uint32_t pwr_status = power_on ? 0 : 2;
|
||||
uint32_t org_ip_request_cntl = 0;
|
||||
|
||||
if (hws->ctx->dc->debug.disable_dsc_power_gate)
|
||||
return;
|
||||
if (hws->ctx->dc->debug.ignore_pg)
|
||||
return;
|
||||
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
|
||||
if (org_ip_request_cntl == 0)
|
||||
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
|
||||
|
||||
switch (dsc_inst) {
|
||||
case 0: /* DSC0 */
|
||||
REG_UPDATE(DOMAIN16_PG_CONFIG,
|
||||
DOMAIN_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN16_PG_STATUS,
|
||||
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 1: /* DSC1 */
|
||||
REG_UPDATE(DOMAIN17_PG_CONFIG,
|
||||
DOMAIN_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN17_PG_STATUS,
|
||||
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 2: /* DSC2 */
|
||||
REG_UPDATE(DOMAIN18_PG_CONFIG,
|
||||
DOMAIN_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN18_PG_STATUS,
|
||||
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
case 3: /* DSC3 */
|
||||
REG_UPDATE(DOMAIN19_PG_CONFIG,
|
||||
DOMAIN_POWER_GATE, power_gate);
|
||||
|
||||
REG_WAIT(DOMAIN19_PG_STATUS,
|
||||
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
break;
|
||||
}
|
||||
|
||||
if (org_ip_request_cntl == 0)
|
||||
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
|
||||
}
|
||||
|
||||
void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable)
|
||||
{
|
||||
bool force_on = true; /* disable power gating */
|
||||
uint32_t org_ip_request_cntl = 0;
|
||||
|
||||
if (hws->ctx->dc->debug.disable_hubp_power_gate)
|
||||
return;
|
||||
if (hws->ctx->dc->debug.ignore_pg)
|
||||
return;
|
||||
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
|
||||
if (org_ip_request_cntl == 0)
|
||||
REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
|
||||
/* DCHUBP0/1/2/3/4/5 */
|
||||
REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
|
||||
REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
|
||||
/* DPP0/1/2/3/4/5 */
|
||||
REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
|
||||
REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
|
||||
|
||||
force_on = true; /* disable power gating */
|
||||
if (enable && !hws->ctx->dc->debug.disable_dsc_power_gate)
|
||||
force_on = false;
|
||||
|
||||
/* DCS0/1/2/3/4 */
|
||||
REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
|
||||
REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
|
||||
REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
|
||||
REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* In headless boot cases, DIG may be turned
|
||||
* on which causes HW/SW discrepancies.
|
||||
* To avoid this, power down hardware on boot
|
||||
|
|
@ -1453,6 +1372,8 @@ void dcn35_prepare_bandwidth(
|
|||
}
|
||||
|
||||
dcn20_prepare_bandwidth(dc, context);
|
||||
|
||||
print_pg_status(dc, __func__, ": after rcg and power up");
|
||||
}
|
||||
|
||||
void dcn35_optimize_bandwidth(
|
||||
|
|
@ -1461,6 +1382,8 @@ void dcn35_optimize_bandwidth(
|
|||
{
|
||||
struct pg_block_update pg_update_state;
|
||||
|
||||
print_pg_status(dc, __func__, ": before rcg and power up");
|
||||
|
||||
dcn20_optimize_bandwidth(dc, context);
|
||||
|
||||
if (dc->hwss.calc_blocks_to_gate) {
|
||||
|
|
@ -1472,6 +1395,8 @@ void dcn35_optimize_bandwidth(
|
|||
if (dc->hwss.root_clock_control)
|
||||
dc->hwss.root_clock_control(dc, &pg_update_state, false);
|
||||
}
|
||||
|
||||
print_pg_status(dc, __func__, ": after rcg and power up");
|
||||
}
|
||||
|
||||
void dcn35_set_drr(struct pipe_ctx **pipe_ctx,
|
||||
|
|
|
|||
|
|
@ -115,7 +115,6 @@ static const struct hw_sequencer_funcs dcn35_funcs = {
|
|||
.exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
|
||||
.update_visual_confirm_color = dcn10_update_visual_confirm_color,
|
||||
.apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations,
|
||||
.update_dsc_pg = dcn32_update_dsc_pg,
|
||||
.calc_blocks_to_gate = dcn35_calc_blocks_to_gate,
|
||||
.calc_blocks_to_ungate = dcn35_calc_blocks_to_ungate,
|
||||
.hw_block_power_up = dcn35_hw_block_power_up,
|
||||
|
|
@ -150,7 +149,6 @@ static const struct hwseq_private_funcs dcn35_private_funcs = {
|
|||
.plane_atomic_disable = dcn35_plane_atomic_disable,
|
||||
//.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/
|
||||
//.hubp_pg_control = dcn35_hubp_pg_control,
|
||||
.enable_power_gating_plane = dcn35_enable_power_gating_plane,
|
||||
.dpp_root_clock_control = dcn35_dpp_root_clock_control,
|
||||
.dpstream_root_clock_control = dcn35_dpstream_root_clock_control,
|
||||
.physymclk_root_clock_control = dcn35_physymclk_root_clock_control,
|
||||
|
|
@ -165,7 +163,6 @@ static const struct hwseq_private_funcs dcn35_private_funcs = {
|
|||
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
|
||||
.resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio,
|
||||
.is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy,
|
||||
.dsc_pg_control = dcn35_dsc_pg_control,
|
||||
.dsc_pg_status = dcn32_dsc_pg_status,
|
||||
.enable_plane = dcn35_enable_plane,
|
||||
.wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed,
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ static const struct hw_sequencer_funcs dcn351_funcs = {
|
|||
.exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
|
||||
.update_visual_confirm_color = dcn10_update_visual_confirm_color,
|
||||
.apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations,
|
||||
.update_dsc_pg = dcn32_update_dsc_pg,
|
||||
.calc_blocks_to_gate = dcn351_calc_blocks_to_gate,
|
||||
.calc_blocks_to_ungate = dcn351_calc_blocks_to_ungate,
|
||||
.hw_block_power_up = dcn351_hw_block_power_up,
|
||||
|
|
@ -145,7 +144,6 @@ static const struct hwseq_private_funcs dcn351_private_funcs = {
|
|||
.plane_atomic_disable = dcn35_plane_atomic_disable,
|
||||
//.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/
|
||||
//.hubp_pg_control = dcn35_hubp_pg_control,
|
||||
.enable_power_gating_plane = dcn35_enable_power_gating_plane,
|
||||
.dpp_root_clock_control = dcn35_dpp_root_clock_control,
|
||||
.dpstream_root_clock_control = dcn35_dpstream_root_clock_control,
|
||||
.physymclk_root_clock_control = dcn35_physymclk_root_clock_control,
|
||||
|
|
@ -159,7 +157,6 @@ static const struct hwseq_private_funcs dcn351_private_funcs = {
|
|||
.setup_hpo_hw_control = dcn35_setup_hpo_hw_control,
|
||||
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
|
||||
.is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy,
|
||||
.dsc_pg_control = dcn35_dsc_pg_control,
|
||||
.dsc_pg_status = dcn32_dsc_pg_status,
|
||||
.enable_plane = dcn35_enable_plane,
|
||||
.wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ struct pg_cntl_funcs {
|
|||
void (*mem_pg_control)(struct pg_cntl *pg_cntl, bool power_on);
|
||||
void (*dio_pg_control)(struct pg_cntl *pg_cntl, bool power_on);
|
||||
void (*init_pg_status)(struct pg_cntl *pg_cntl);
|
||||
void (*print_pg_status)(struct pg_cntl *pg_cntl, const char *debug_func, const char *debug_log);
|
||||
};
|
||||
|
||||
#endif //__DC_PG_CNTL_H__
|
||||
|
|
|
|||
|
|
@ -79,16 +79,12 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo
|
|||
uint32_t power_gate = power_on ? 0 : 1;
|
||||
uint32_t pwr_status = power_on ? 0 : 2;
|
||||
uint32_t org_ip_request_cntl = 0;
|
||||
bool block_enabled;
|
||||
bool block_enabled = false;
|
||||
bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg ||
|
||||
pg_cntl->ctx->dc->debug.disable_dsc_power_gate ||
|
||||
pg_cntl->ctx->dc->idle_optimizations_allowed;
|
||||
|
||||
/*need to enable dscclk regardless DSC_PG*/
|
||||
if (pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc && power_on)
|
||||
pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc(
|
||||
pg_cntl->ctx->dc->res_pool->dccg, dsc_inst);
|
||||
|
||||
if (pg_cntl->ctx->dc->debug.ignore_pg ||
|
||||
pg_cntl->ctx->dc->debug.disable_dsc_power_gate ||
|
||||
pg_cntl->ctx->dc->idle_optimizations_allowed)
|
||||
if (skip_pg && !power_on)
|
||||
return;
|
||||
|
||||
block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, dsc_inst);
|
||||
|
|
@ -111,7 +107,7 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo
|
|||
|
||||
REG_WAIT(DOMAIN16_PG_STATUS,
|
||||
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
1, 10000);
|
||||
break;
|
||||
case 1: /* DSC1 */
|
||||
REG_UPDATE(DOMAIN17_PG_CONFIG,
|
||||
|
|
@ -119,7 +115,7 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo
|
|||
|
||||
REG_WAIT(DOMAIN17_PG_STATUS,
|
||||
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
1, 10000);
|
||||
break;
|
||||
case 2: /* DSC2 */
|
||||
REG_UPDATE(DOMAIN18_PG_CONFIG,
|
||||
|
|
@ -127,7 +123,7 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo
|
|||
|
||||
REG_WAIT(DOMAIN18_PG_STATUS,
|
||||
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
1, 10000);
|
||||
break;
|
||||
case 3: /* DSC3 */
|
||||
REG_UPDATE(DOMAIN19_PG_CONFIG,
|
||||
|
|
@ -135,7 +131,7 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo
|
|||
|
||||
REG_WAIT(DOMAIN19_PG_STATUS,
|
||||
DOMAIN_PGFSM_PWR_STATUS, pwr_status,
|
||||
1, 1000);
|
||||
1, 10000);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
|
|
@ -144,12 +140,6 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo
|
|||
|
||||
if (dsc_inst < MAX_PIPES)
|
||||
pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on;
|
||||
|
||||
if (pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on) {
|
||||
/*this is to disable dscclk*/
|
||||
pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc(
|
||||
pg_cntl->ctx->dc->res_pool->dccg, dsc_inst);
|
||||
}
|
||||
}
|
||||
|
||||
static bool pg_cntl35_hubp_dpp_pg_status(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst)
|
||||
|
|
@ -189,11 +179,12 @@ void pg_cntl35_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dp
|
|||
uint32_t pwr_status = power_on ? 0 : 2;
|
||||
uint32_t org_ip_request_cntl;
|
||||
bool block_enabled;
|
||||
bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg ||
|
||||
pg_cntl->ctx->dc->debug.disable_hubp_power_gate ||
|
||||
pg_cntl->ctx->dc->debug.disable_dpp_power_gate ||
|
||||
pg_cntl->ctx->dc->idle_optimizations_allowed;
|
||||
|
||||
if (pg_cntl->ctx->dc->debug.ignore_pg ||
|
||||
pg_cntl->ctx->dc->debug.disable_hubp_power_gate ||
|
||||
pg_cntl->ctx->dc->debug.disable_dpp_power_gate ||
|
||||
pg_cntl->ctx->dc->idle_optimizations_allowed)
|
||||
if (skip_pg && !power_on)
|
||||
return;
|
||||
|
||||
block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst);
|
||||
|
|
@ -213,22 +204,22 @@ void pg_cntl35_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dp
|
|||
case 0:
|
||||
/* DPP0 & HUBP0 */
|
||||
REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
|
||||
REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
|
||||
REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000);
|
||||
break;
|
||||
case 1:
|
||||
/* DPP1 & HUBP1 */
|
||||
REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
|
||||
REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
|
||||
REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000);
|
||||
break;
|
||||
case 2:
|
||||
/* DPP2 & HUBP2 */
|
||||
REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
|
||||
REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
|
||||
REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000);
|
||||
break;
|
||||
case 3:
|
||||
/* DPP3 & HUBP3 */
|
||||
REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
|
||||
REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
|
||||
REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
|
|
@ -501,6 +492,36 @@ void pg_cntl35_init_pg_status(struct pg_cntl *pg_cntl)
|
|||
pg_cntl->pg_res_enable[PG_DWB] = block_enabled;
|
||||
}
|
||||
|
||||
static void pg_cntl35_print_pg_status(struct pg_cntl *pg_cntl, const char *debug_func, const char *debug_log)
|
||||
{
|
||||
int i = 0;
|
||||
bool block_enabled = false;
|
||||
|
||||
DC_LOG_DEBUG("%s: %s", debug_func, debug_log);
|
||||
|
||||
DC_LOG_DEBUG("PG_CNTL status:\n");
|
||||
|
||||
block_enabled = pg_cntl35_io_clk_status(pg_cntl);
|
||||
DC_LOG_DEBUG("ONO0=%d (DCCG, DIO, DCIO)\n", block_enabled ? 1 : 0);
|
||||
|
||||
block_enabled = pg_cntl35_mem_status(pg_cntl);
|
||||
DC_LOG_DEBUG("ONO1=%d (DCHUBBUB, DCHVM, DCHUBBUBMEM)\n", block_enabled ? 1 : 0);
|
||||
|
||||
block_enabled = pg_cntl35_plane_otg_status(pg_cntl);
|
||||
DC_LOG_DEBUG("ONO2=%d (MPC, OPP, OPTC, DWB)\n", block_enabled ? 1 : 0);
|
||||
|
||||
block_enabled = pg_cntl35_hpo_pg_status(pg_cntl);
|
||||
DC_LOG_DEBUG("ONO3=%d (HPO)\n", block_enabled ? 1 : 0);
|
||||
|
||||
for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
|
||||
block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, i);
|
||||
DC_LOG_DEBUG("ONO%d=%d (DCHUBP%d, DPP%d)\n", 4 + i * 2, block_enabled ? 1 : 0, i, i);
|
||||
|
||||
block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, i);
|
||||
DC_LOG_DEBUG("ONO%d=%d (DSC%d)\n", 5 + i * 2, block_enabled ? 1 : 0, i);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pg_cntl_funcs pg_cntl35_funcs = {
|
||||
.init_pg_status = pg_cntl35_init_pg_status,
|
||||
.dsc_pg_control = pg_cntl35_dsc_pg_control,
|
||||
|
|
@ -511,7 +532,8 @@ static const struct pg_cntl_funcs pg_cntl35_funcs = {
|
|||
.mpcc_pg_control = pg_cntl35_mpcc_pg_control,
|
||||
.opp_pg_control = pg_cntl35_opp_pg_control,
|
||||
.optc_pg_control = pg_cntl35_optc_pg_control,
|
||||
.dwb_pg_control = pg_cntl35_dwb_pg_control
|
||||
.dwb_pg_control = pg_cntl35_dwb_pg_control,
|
||||
.print_pg_status = pg_cntl35_print_pg_status
|
||||
};
|
||||
|
||||
struct pg_cntl *pg_cntl35_create(
|
||||
|
|
|
|||
|
|
@ -1172,7 +1172,7 @@ static void icl_mbus_init(struct intel_display *display)
|
|||
if (DISPLAY_VER(display) == 12)
|
||||
abox_regs |= BIT(0);
|
||||
|
||||
for_each_set_bit(i, &abox_regs, sizeof(abox_regs))
|
||||
for_each_set_bit(i, &abox_regs, BITS_PER_TYPE(abox_regs))
|
||||
intel_de_rmw(display, MBUS_ABOX_CTL(i), mask, val);
|
||||
}
|
||||
|
||||
|
|
@ -1629,11 +1629,11 @@ static void tgl_bw_buddy_init(struct intel_display *display)
|
|||
if (table[config].page_mask == 0) {
|
||||
drm_dbg_kms(display->drm,
|
||||
"Unknown memory configuration; disabling address buddy logic.\n");
|
||||
for_each_set_bit(i, &abox_mask, sizeof(abox_mask))
|
||||
for_each_set_bit(i, &abox_mask, BITS_PER_TYPE(abox_mask))
|
||||
intel_de_write(display, BW_BUDDY_CTL(i),
|
||||
BW_BUDDY_DISABLE);
|
||||
} else {
|
||||
for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) {
|
||||
for_each_set_bit(i, &abox_mask, BITS_PER_TYPE(abox_mask)) {
|
||||
intel_de_write(display, BW_BUDDY_PAGE_MASK(i),
|
||||
table[config].page_mask);
|
||||
|
||||
|
|
|
|||
|
|
@ -387,19 +387,21 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
|
|||
|
||||
of_id = of_match_node(mtk_drm_of_ids, node);
|
||||
if (!of_id)
|
||||
goto next_put_node;
|
||||
continue;
|
||||
|
||||
pdev = of_find_device_by_node(node);
|
||||
if (!pdev)
|
||||
goto next_put_node;
|
||||
continue;
|
||||
|
||||
drm_dev = device_find_child(&pdev->dev, NULL, mtk_drm_match);
|
||||
put_device(&pdev->dev);
|
||||
if (!drm_dev)
|
||||
goto next_put_device_pdev_dev;
|
||||
continue;
|
||||
|
||||
temp_drm_priv = dev_get_drvdata(drm_dev);
|
||||
put_device(drm_dev);
|
||||
if (!temp_drm_priv)
|
||||
goto next_put_device_drm_dev;
|
||||
continue;
|
||||
|
||||
if (temp_drm_priv->data->main_len)
|
||||
all_drm_priv[CRTC_MAIN] = temp_drm_priv;
|
||||
|
|
@ -411,17 +413,10 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
|
|||
if (temp_drm_priv->mtk_drm_bound)
|
||||
cnt++;
|
||||
|
||||
next_put_device_drm_dev:
|
||||
put_device(drm_dev);
|
||||
|
||||
next_put_device_pdev_dev:
|
||||
put_device(&pdev->dev);
|
||||
|
||||
next_put_node:
|
||||
of_node_put(node);
|
||||
|
||||
if (cnt == MAX_CRTC)
|
||||
if (cnt == MAX_CRTC) {
|
||||
of_node_put(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (drm_priv->data->mmsys_dev_num == cnt) {
|
||||
|
|
|
|||
|
|
@ -240,21 +240,6 @@ nouveau_fence_emit(struct nouveau_fence *fence)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_fence_cancel(struct nouveau_fence *fence)
|
||||
{
|
||||
struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&fctx->lock, flags);
|
||||
if (!dma_fence_is_signaled_locked(&fence->base)) {
|
||||
dma_fence_set_error(&fence->base, -ECANCELED);
|
||||
if (nouveau_fence_signal(fence))
|
||||
nvif_event_block(&fctx->event);
|
||||
}
|
||||
spin_unlock_irqrestore(&fctx->lock, flags);
|
||||
}
|
||||
|
||||
bool
|
||||
nouveau_fence_done(struct nouveau_fence *fence)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ void nouveau_fence_unref(struct nouveau_fence **);
|
|||
|
||||
int nouveau_fence_emit(struct nouveau_fence *);
|
||||
bool nouveau_fence_done(struct nouveau_fence *);
|
||||
void nouveau_fence_cancel(struct nouveau_fence *fence);
|
||||
int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
|
||||
int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include "nouveau_exec.h"
|
||||
#include "nouveau_abi16.h"
|
||||
#include "nouveau_sched.h"
|
||||
#include "nouveau_chan.h"
|
||||
|
||||
#define NOUVEAU_SCHED_JOB_TIMEOUT_MS 10000
|
||||
|
||||
|
|
@ -122,9 +121,11 @@ nouveau_job_done(struct nouveau_job *job)
|
|||
{
|
||||
struct nouveau_sched *sched = job->sched;
|
||||
|
||||
spin_lock(&sched->job_list.lock);
|
||||
spin_lock(&sched->job.list.lock);
|
||||
list_del(&job->entry);
|
||||
spin_unlock(&sched->job_list.lock);
|
||||
spin_unlock(&sched->job.list.lock);
|
||||
|
||||
wake_up(&sched->job.wq);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -305,9 +306,9 @@ nouveau_job_submit(struct nouveau_job *job)
|
|||
}
|
||||
|
||||
/* Submit was successful; add the job to the schedulers job list. */
|
||||
spin_lock(&sched->job_list.lock);
|
||||
list_add(&job->entry, &sched->job_list.head);
|
||||
spin_unlock(&sched->job_list.lock);
|
||||
spin_lock(&sched->job.list.lock);
|
||||
list_add(&job->entry, &sched->job.list.head);
|
||||
spin_unlock(&sched->job.list.lock);
|
||||
|
||||
drm_sched_job_arm(&job->base);
|
||||
job->done_fence = dma_fence_get(&job->base.s_fence->finished);
|
||||
|
|
@ -392,23 +393,10 @@ nouveau_sched_free_job(struct drm_sched_job *sched_job)
|
|||
nouveau_job_fini(job);
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_sched_cancel_job(struct drm_sched_job *sched_job)
|
||||
{
|
||||
struct nouveau_fence *fence;
|
||||
struct nouveau_job *job;
|
||||
|
||||
job = to_nouveau_job(sched_job);
|
||||
fence = to_nouveau_fence(job->done_fence);
|
||||
|
||||
nouveau_fence_cancel(fence);
|
||||
}
|
||||
|
||||
static const struct drm_sched_backend_ops nouveau_sched_ops = {
|
||||
.run_job = nouveau_sched_run_job,
|
||||
.timedout_job = nouveau_sched_timedout_job,
|
||||
.free_job = nouveau_sched_free_job,
|
||||
.cancel_job = nouveau_sched_cancel_job,
|
||||
};
|
||||
|
||||
static int
|
||||
|
|
@ -458,8 +446,9 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm,
|
|||
goto fail_sched;
|
||||
|
||||
mutex_init(&sched->mutex);
|
||||
spin_lock_init(&sched->job_list.lock);
|
||||
INIT_LIST_HEAD(&sched->job_list.head);
|
||||
spin_lock_init(&sched->job.list.lock);
|
||||
INIT_LIST_HEAD(&sched->job.list.head);
|
||||
init_waitqueue_head(&sched->job.wq);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -493,12 +482,16 @@ nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nouveau_sched_fini(struct nouveau_sched *sched)
|
||||
{
|
||||
struct drm_gpu_scheduler *drm_sched = &sched->base;
|
||||
struct drm_sched_entity *entity = &sched->entity;
|
||||
|
||||
rmb(); /* for list_empty to work without lock */
|
||||
wait_event(sched->job.wq, list_empty(&sched->job.list.head));
|
||||
|
||||
drm_sched_entity_fini(entity);
|
||||
drm_sched_fini(drm_sched);
|
||||
|
||||
|
|
|
|||
|
|
@ -103,9 +103,12 @@ struct nouveau_sched {
|
|||
struct mutex mutex;
|
||||
|
||||
struct {
|
||||
struct list_head head;
|
||||
spinlock_t lock;
|
||||
} job_list;
|
||||
struct {
|
||||
struct list_head head;
|
||||
spinlock_t lock;
|
||||
} list;
|
||||
struct wait_queue_head wq;
|
||||
} job;
|
||||
};
|
||||
|
||||
int nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm,
|
||||
|
|
|
|||
|
|
@ -1019,8 +1019,8 @@ bind_validate_map_sparse(struct nouveau_job *job, u64 addr, u64 range)
|
|||
u64 end = addr + range;
|
||||
|
||||
again:
|
||||
spin_lock(&sched->job_list.lock);
|
||||
list_for_each_entry(__job, &sched->job_list.head, entry) {
|
||||
spin_lock(&sched->job.list.lock);
|
||||
list_for_each_entry(__job, &sched->job.list.head, entry) {
|
||||
struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(__job);
|
||||
|
||||
list_for_each_op(op, &bind_job->ops) {
|
||||
|
|
@ -1030,7 +1030,7 @@ again:
|
|||
|
||||
if (!(end <= op_addr || addr >= op_end)) {
|
||||
nouveau_uvmm_bind_job_get(bind_job);
|
||||
spin_unlock(&sched->job_list.lock);
|
||||
spin_unlock(&sched->job.list.lock);
|
||||
wait_for_completion(&bind_job->complete);
|
||||
nouveau_uvmm_bind_job_put(bind_job);
|
||||
goto again;
|
||||
|
|
@ -1038,7 +1038,7 @@ again:
|
|||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&sched->job_list.lock);
|
||||
spin_unlock(&sched->job.list.lock);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -1094,7 +1094,7 @@ static int panthor_ioctl_group_create(struct drm_device *ddev, void *data,
|
|||
struct drm_panthor_queue_create *queue_args;
|
||||
int ret;
|
||||
|
||||
if (!args->queues.count)
|
||||
if (!args->queues.count || args->queues.count > MAX_CS_PER_CSG)
|
||||
return -EINVAL;
|
||||
|
||||
ret = PANTHOR_UOBJ_GET_ARRAY(queue_args, &args->queues);
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ static int evict_test_run_tile(struct xe_device *xe, struct xe_tile *tile, struc
|
|||
}
|
||||
|
||||
xe_bo_lock(external, false);
|
||||
err = xe_bo_pin_external(external);
|
||||
err = xe_bo_pin_external(external, false);
|
||||
xe_bo_unlock(external);
|
||||
if (err) {
|
||||
KUNIT_FAIL(test, "external bo pin err=%pe\n",
|
||||
|
|
|
|||
|
|
@ -89,15 +89,7 @@ static void check_residency(struct kunit *test, struct xe_bo *exported,
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If on different devices, the exporter is kept in system if
|
||||
* possible, saving a migration step as the transfer is just
|
||||
* likely as fast from system memory.
|
||||
*/
|
||||
if (params->mem_mask & XE_BO_FLAG_SYSTEM)
|
||||
KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, XE_PL_TT));
|
||||
else
|
||||
KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type));
|
||||
KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type));
|
||||
|
||||
if (params->force_different_devices)
|
||||
KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(imported, XE_PL_TT));
|
||||
|
|
|
|||
|
|
@ -186,6 +186,8 @@ static void try_add_system(struct xe_device *xe, struct xe_bo *bo,
|
|||
|
||||
bo->placements[*c] = (struct ttm_place) {
|
||||
.mem_type = XE_PL_TT,
|
||||
.flags = (bo_flags & XE_BO_FLAG_VRAM_MASK) ?
|
||||
TTM_PL_FLAG_FALLBACK : 0,
|
||||
};
|
||||
*c += 1;
|
||||
}
|
||||
|
|
@ -2269,6 +2271,7 @@ uint64_t vram_region_gpu_offset(struct ttm_resource *res)
|
|||
/**
|
||||
* xe_bo_pin_external - pin an external BO
|
||||
* @bo: buffer object to be pinned
|
||||
* @in_place: Pin in current placement, don't attempt to migrate.
|
||||
*
|
||||
* Pin an external (not tied to a VM, can be exported via dma-buf / prime FD)
|
||||
* BO. Unique call compared to xe_bo_pin as this function has it own set of
|
||||
|
|
@ -2276,7 +2279,7 @@ uint64_t vram_region_gpu_offset(struct ttm_resource *res)
|
|||
*
|
||||
* Returns 0 for success, negative error code otherwise.
|
||||
*/
|
||||
int xe_bo_pin_external(struct xe_bo *bo)
|
||||
int xe_bo_pin_external(struct xe_bo *bo, bool in_place)
|
||||
{
|
||||
struct xe_device *xe = xe_bo_device(bo);
|
||||
int err;
|
||||
|
|
@ -2285,9 +2288,11 @@ int xe_bo_pin_external(struct xe_bo *bo)
|
|||
xe_assert(xe, xe_bo_is_user(bo));
|
||||
|
||||
if (!xe_bo_is_pinned(bo)) {
|
||||
err = xe_bo_validate(bo, NULL, false);
|
||||
if (err)
|
||||
return err;
|
||||
if (!in_place) {
|
||||
err = xe_bo_validate(bo, NULL, false);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
spin_lock(&xe->pinned.lock);
|
||||
list_add_tail(&bo->pinned_link, &xe->pinned.late.external);
|
||||
|
|
@ -2440,6 +2445,9 @@ int xe_bo_validate(struct xe_bo *bo, struct xe_vm *vm, bool allow_res_evict)
|
|||
};
|
||||
int ret;
|
||||
|
||||
if (xe_bo_is_pinned(bo))
|
||||
return 0;
|
||||
|
||||
if (vm) {
|
||||
lockdep_assert_held(&vm->lock);
|
||||
xe_vm_assert_held(vm);
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ static inline void xe_bo_unlock_vm_held(struct xe_bo *bo)
|
|||
}
|
||||
}
|
||||
|
||||
int xe_bo_pin_external(struct xe_bo *bo);
|
||||
int xe_bo_pin_external(struct xe_bo *bo, bool in_place);
|
||||
int xe_bo_pin(struct xe_bo *bo);
|
||||
void xe_bo_unpin_external(struct xe_bo *bo);
|
||||
void xe_bo_unpin(struct xe_bo *bo);
|
||||
|
|
|
|||
|
|
@ -553,6 +553,12 @@ struct xe_device {
|
|||
|
||||
/** @pm_notifier: Our PM notifier to perform actions in response to various PM events. */
|
||||
struct notifier_block pm_notifier;
|
||||
/** @pm_block: Completion to block validating tasks on suspend / hibernate prepare */
|
||||
struct completion pm_block;
|
||||
/** @rebind_resume_list: List of wq items to kick on resume. */
|
||||
struct list_head rebind_resume_list;
|
||||
/** @rebind_resume_lock: Lock to protect the rebind_resume_list */
|
||||
struct mutex rebind_resume_lock;
|
||||
|
||||
/** @pmt: Support the PMT driver callback interface */
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ static int xe_dma_buf_pin(struct dma_buf_attachment *attach)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = xe_bo_pin_external(bo);
|
||||
ret = xe_bo_pin_external(bo, true);
|
||||
xe_assert(xe, !ret);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -237,6 +237,15 @@ retry:
|
|||
goto err_unlock_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's OK to block interruptible here with the vm lock held, since
|
||||
* on task freezing during suspend / hibernate, the call will
|
||||
* return -ERESTARTSYS and the IOCTL will be rerun.
|
||||
*/
|
||||
err = wait_for_completion_interruptible(&xe->pm_block);
|
||||
if (err)
|
||||
goto err_unlock_list;
|
||||
|
||||
vm_exec.vm = &vm->gpuvm;
|
||||
vm_exec.flags = DRM_EXEC_INTERRUPTIBLE_WAIT;
|
||||
if (xe_vm_in_lr_mode(vm)) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "xe_pcode.h"
|
||||
#include "xe_pxp.h"
|
||||
#include "xe_trace.h"
|
||||
#include "xe_vm.h"
|
||||
#include "xe_wa.h"
|
||||
|
||||
/**
|
||||
|
|
@ -290,6 +291,19 @@ static u32 vram_threshold_value(struct xe_device *xe)
|
|||
return DEFAULT_VRAM_THRESHOLD;
|
||||
}
|
||||
|
||||
static void xe_pm_wake_rebind_workers(struct xe_device *xe)
|
||||
{
|
||||
struct xe_vm *vm, *next;
|
||||
|
||||
mutex_lock(&xe->rebind_resume_lock);
|
||||
list_for_each_entry_safe(vm, next, &xe->rebind_resume_list,
|
||||
preempt.pm_activate_link) {
|
||||
list_del_init(&vm->preempt.pm_activate_link);
|
||||
xe_vm_resume_rebind_worker(vm);
|
||||
}
|
||||
mutex_unlock(&xe->rebind_resume_lock);
|
||||
}
|
||||
|
||||
static int xe_pm_notifier_callback(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
|
|
@ -299,30 +313,30 @@ static int xe_pm_notifier_callback(struct notifier_block *nb,
|
|||
switch (action) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
case PM_SUSPEND_PREPARE:
|
||||
reinit_completion(&xe->pm_block);
|
||||
xe_pm_runtime_get(xe);
|
||||
err = xe_bo_evict_all_user(xe);
|
||||
if (err) {
|
||||
if (err)
|
||||
drm_dbg(&xe->drm, "Notifier evict user failed (%d)\n", err);
|
||||
xe_pm_runtime_put(xe);
|
||||
break;
|
||||
}
|
||||
|
||||
err = xe_bo_notifier_prepare_all_pinned(xe);
|
||||
if (err) {
|
||||
if (err)
|
||||
drm_dbg(&xe->drm, "Notifier prepare pin failed (%d)\n", err);
|
||||
xe_pm_runtime_put(xe);
|
||||
}
|
||||
/*
|
||||
* Keep the runtime pm reference until post hibernation / post suspend to
|
||||
* avoid a runtime suspend interfering with evicted objects or backup
|
||||
* allocations.
|
||||
*/
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
case PM_POST_SUSPEND:
|
||||
complete_all(&xe->pm_block);
|
||||
xe_pm_wake_rebind_workers(xe);
|
||||
xe_bo_notifier_unprepare_all_pinned(xe);
|
||||
xe_pm_runtime_put(xe);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err)
|
||||
return NOTIFY_BAD;
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
|
|
@ -344,6 +358,14 @@ int xe_pm_init(struct xe_device *xe)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = drmm_mutex_init(&xe->drm, &xe->rebind_resume_lock);
|
||||
if (err)
|
||||
goto err_unregister;
|
||||
|
||||
init_completion(&xe->pm_block);
|
||||
complete_all(&xe->pm_block);
|
||||
INIT_LIST_HEAD(&xe->rebind_resume_list);
|
||||
|
||||
/* For now suspend/resume is only allowed with GuC */
|
||||
if (!xe_device_uc_enabled(xe))
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
*
|
||||
* # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode
|
||||
*
|
||||
* It is the responsibility of the user to clear the mode once firmware flash is complete.
|
||||
*
|
||||
* Refer :ref:`xe_configfs` for more details on how to use configfs
|
||||
*
|
||||
* Survivability mode is indicated by the below admin-only readable sysfs which provides additional
|
||||
|
|
@ -147,7 +149,6 @@ static void xe_survivability_mode_fini(void *arg)
|
|||
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
xe_configfs_clear_survivability_mode(pdev);
|
||||
sysfs_remove_file(&dev->kobj, &dev_attr_survivability_mode.attr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -393,6 +393,9 @@ static int xe_gpuvm_validate(struct drm_gpuvm_bo *vm_bo, struct drm_exec *exec)
|
|||
list_move_tail(&gpuva_to_vma(gpuva)->combined_links.rebind,
|
||||
&vm->rebind_list);
|
||||
|
||||
if (!try_wait_for_completion(&vm->xe->pm_block))
|
||||
return -EAGAIN;
|
||||
|
||||
ret = xe_bo_validate(gem_to_xe_bo(vm_bo->obj), vm, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -479,6 +482,33 @@ static int xe_preempt_work_begin(struct drm_exec *exec, struct xe_vm *vm,
|
|||
return xe_vm_validate_rebind(vm, exec, vm->preempt.num_exec_queues);
|
||||
}
|
||||
|
||||
static bool vm_suspend_rebind_worker(struct xe_vm *vm)
|
||||
{
|
||||
struct xe_device *xe = vm->xe;
|
||||
bool ret = false;
|
||||
|
||||
mutex_lock(&xe->rebind_resume_lock);
|
||||
if (!try_wait_for_completion(&vm->xe->pm_block)) {
|
||||
ret = true;
|
||||
list_move_tail(&vm->preempt.pm_activate_link, &xe->rebind_resume_list);
|
||||
}
|
||||
mutex_unlock(&xe->rebind_resume_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_vm_resume_rebind_worker() - Resume the rebind worker.
|
||||
* @vm: The vm whose preempt worker to resume.
|
||||
*
|
||||
* Resume a preempt worker that was previously suspended by
|
||||
* vm_suspend_rebind_worker().
|
||||
*/
|
||||
void xe_vm_resume_rebind_worker(struct xe_vm *vm)
|
||||
{
|
||||
queue_work(vm->xe->ordered_wq, &vm->preempt.rebind_work);
|
||||
}
|
||||
|
||||
static void preempt_rebind_work_func(struct work_struct *w)
|
||||
{
|
||||
struct xe_vm *vm = container_of(w, struct xe_vm, preempt.rebind_work);
|
||||
|
|
@ -502,6 +532,11 @@ static void preempt_rebind_work_func(struct work_struct *w)
|
|||
}
|
||||
|
||||
retry:
|
||||
if (!try_wait_for_completion(&vm->xe->pm_block) && vm_suspend_rebind_worker(vm)) {
|
||||
up_write(&vm->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xe_vm_userptr_check_repin(vm)) {
|
||||
err = xe_vm_userptr_pin(vm);
|
||||
if (err)
|
||||
|
|
@ -1714,6 +1749,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)
|
|||
if (flags & XE_VM_FLAG_LR_MODE) {
|
||||
INIT_WORK(&vm->preempt.rebind_work, preempt_rebind_work_func);
|
||||
xe_pm_runtime_get_noresume(xe);
|
||||
INIT_LIST_HEAD(&vm->preempt.pm_activate_link);
|
||||
}
|
||||
|
||||
if (flags & XE_VM_FLAG_FAULT_MODE) {
|
||||
|
|
@ -1895,8 +1931,12 @@ void xe_vm_close_and_put(struct xe_vm *vm)
|
|||
xe_assert(xe, !vm->preempt.num_exec_queues);
|
||||
|
||||
xe_vm_close(vm);
|
||||
if (xe_vm_in_preempt_fence_mode(vm))
|
||||
if (xe_vm_in_preempt_fence_mode(vm)) {
|
||||
mutex_lock(&xe->rebind_resume_lock);
|
||||
list_del_init(&vm->preempt.pm_activate_link);
|
||||
mutex_unlock(&xe->rebind_resume_lock);
|
||||
flush_work(&vm->preempt.rebind_work);
|
||||
}
|
||||
if (xe_vm_in_fault_mode(vm))
|
||||
xe_svm_close(vm);
|
||||
|
||||
|
|
|
|||
|
|
@ -273,6 +273,8 @@ struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo,
|
|||
struct xe_exec_queue *q, u64 addr,
|
||||
enum xe_cache_level cache_lvl);
|
||||
|
||||
void xe_vm_resume_rebind_worker(struct xe_vm *vm);
|
||||
|
||||
/**
|
||||
* xe_vm_resv() - Return's the vm's reservation object
|
||||
* @vm: The vm
|
||||
|
|
|
|||
|
|
@ -293,6 +293,11 @@ struct xe_vm {
|
|||
* BOs
|
||||
*/
|
||||
struct work_struct rebind_work;
|
||||
/**
|
||||
* @preempt.pm_activate_link: Link to list of rebind workers to be
|
||||
* kicked on resume.
|
||||
*/
|
||||
struct list_head pm_activate_link;
|
||||
} preempt;
|
||||
|
||||
/** @um: unified memory state */
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@
|
|||
16022287689 GRAPHICS_VERSION(2001)
|
||||
GRAPHICS_VERSION(2004)
|
||||
13011645652 GRAPHICS_VERSION(2004)
|
||||
GRAPHICS_VERSION(3001)
|
||||
GRAPHICS_VERSION_RANGE(3000, 3001)
|
||||
GRAPHICS_VERSION(3003)
|
||||
14022293748 GRAPHICS_VERSION_RANGE(2001, 2002)
|
||||
GRAPHICS_VERSION(2004)
|
||||
GRAPHICS_VERSION_RANGE(3000, 3001)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
config NOVA_CORE
|
||||
tristate "Nova Core GPU driver"
|
||||
depends on 64BIT
|
||||
depends on PCI
|
||||
depends on RUST
|
||||
depends on RUST_FW_LOADER_ABSTRACTIONS
|
||||
|
|
|
|||
|
|
@ -422,6 +422,7 @@ static const struct xpad_device {
|
|||
{ 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE },
|
||||
{ 0x366c, 0x0005, "ByoWave Proteus Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE, FLAG_DELAY_INIT },
|
||||
{ 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX },
|
||||
{ 0x37d7, 0x2501, "Flydigi Apex 5", 0, XTYPE_XBOX360 },
|
||||
{ 0x413d, 0x2104, "Black Shark Green Ghost Gamepad", 0, XTYPE_XBOX360 },
|
||||
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
|
||||
{ 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
|
||||
|
|
@ -578,6 +579,7 @@ static const struct usb_device_id xpad_table[] = {
|
|||
XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x366c), /* ByoWave controllers */
|
||||
XPAD_XBOX360_VENDOR(0x37d7), /* Flydigi Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x413d), /* Black Shark Green Ghost Controller */
|
||||
{ }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ struct mtk_pmic_regs {
|
|||
const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT];
|
||||
u32 pmic_rst_reg;
|
||||
u32 rst_lprst_mask; /* Long-press reset timeout bitmask */
|
||||
bool key_release_irq;
|
||||
};
|
||||
|
||||
static const struct mtk_pmic_regs mt6397_regs = {
|
||||
|
|
@ -116,6 +117,7 @@ static const struct mtk_pmic_regs mt6358_regs = {
|
|||
MTK_PMIC_HOMEKEY_RST),
|
||||
.pmic_rst_reg = MT6358_TOP_RST_MISC,
|
||||
.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
|
||||
.key_release_irq = true,
|
||||
};
|
||||
|
||||
static const struct mtk_pmic_regs mt6359_regs = {
|
||||
|
|
@ -129,6 +131,7 @@ static const struct mtk_pmic_regs mt6359_regs = {
|
|||
MTK_PMIC_HOMEKEY_RST),
|
||||
.pmic_rst_reg = MT6359_TOP_RST_MISC,
|
||||
.rst_lprst_mask = MTK_PMIC_RST_DU_MASK,
|
||||
.key_release_irq = true,
|
||||
};
|
||||
|
||||
struct mtk_pmic_keys_info {
|
||||
|
|
@ -368,7 +371,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
|
|||
if (keys->keys[index].irq < 0)
|
||||
return keys->keys[index].irq;
|
||||
|
||||
if (of_device_is_compatible(node, "mediatek,mt6358-keys")) {
|
||||
if (mtk_pmic_regs->key_release_irq) {
|
||||
keys->keys[index].irq_r = platform_get_irq_byname(pdev,
|
||||
irqnames_r[index]);
|
||||
|
||||
|
|
|
|||
|
|
@ -2427,6 +2427,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
if (!iqs7222->kp_type[chan_index][i])
|
||||
continue;
|
||||
|
||||
if (!dev_desc->event_offset)
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -1155,6 +1155,20 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
|
|||
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
||||
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "XxHP4NAx"),
|
||||
},
|
||||
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
||||
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"),
|
||||
},
|
||||
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
||||
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||
},
|
||||
/*
|
||||
* A lot of modern Clevo barebones have touchpad and/or keyboard issues
|
||||
* after suspend fixable with the forcenorestore quirk.
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ struct journal_sector {
|
|||
commit_id_t commit_id;
|
||||
};
|
||||
|
||||
#define MAX_TAG_SIZE (JOURNAL_SECTOR_DATA - JOURNAL_MAC_PER_SECTOR - offsetof(struct journal_entry, last_bytes[MAX_SECTORS_PER_BLOCK]))
|
||||
#define MAX_TAG_SIZE 255
|
||||
|
||||
#define METADATA_PADDING_SECTORS 8
|
||||
|
||||
|
|
|
|||
|
|
@ -3813,8 +3813,10 @@ static void raid_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
|||
struct raid_set *rs = ti->private;
|
||||
unsigned int chunk_size_bytes = to_bytes(rs->md.chunk_sectors);
|
||||
|
||||
limits->io_min = chunk_size_bytes;
|
||||
limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs);
|
||||
if (chunk_size_bytes) {
|
||||
limits->io_min = chunk_size_bytes;
|
||||
limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs);
|
||||
}
|
||||
}
|
||||
|
||||
static void raid_presuspend(struct dm_target *ti)
|
||||
|
|
|
|||
|
|
@ -456,11 +456,15 @@ static void stripe_io_hints(struct dm_target *ti,
|
|||
struct queue_limits *limits)
|
||||
{
|
||||
struct stripe_c *sc = ti->private;
|
||||
unsigned int chunk_size = sc->chunk_size << SECTOR_SHIFT;
|
||||
unsigned int io_min, io_opt;
|
||||
|
||||
limits->chunk_sectors = sc->chunk_size;
|
||||
limits->io_min = chunk_size;
|
||||
limits->io_opt = chunk_size * sc->stripes;
|
||||
|
||||
if (!check_shl_overflow(sc->chunk_size, SECTOR_SHIFT, &io_min) &&
|
||||
!check_mul_overflow(io_min, sc->stripes, &io_opt)) {
|
||||
limits->io_min = io_min;
|
||||
limits->io_opt = io_opt;
|
||||
}
|
||||
}
|
||||
|
||||
static struct target_type stripe_target = {
|
||||
|
|
|
|||
|
|
@ -185,8 +185,8 @@ config MTD_POWERNV_FLASH
|
|||
|
||||
config MTD_INTEL_DG
|
||||
tristate "Intel Discrete Graphics non-volatile memory driver"
|
||||
depends on AUXILIARY_BUS
|
||||
depends on MTD
|
||||
depends on AUXILIARY_BUS && MTD
|
||||
depends on DRM_I915!=n || DRM_XE!=n || COMPILE_TEST
|
||||
help
|
||||
This provides an MTD device to access Intel Discrete Graphics
|
||||
non-volatile memory.
|
||||
|
|
|
|||
|
|
@ -1377,14 +1377,24 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Read setup timing depends on the operation done on the NAND:
|
||||
*
|
||||
* NRD_SETUP = max(tAR, tCLR)
|
||||
*/
|
||||
timeps = max(conf->timings.sdr.tAR_min, conf->timings.sdr.tCLR_min);
|
||||
ncycles = DIV_ROUND_UP(timeps, mckperiodps);
|
||||
totalcycles += ncycles;
|
||||
ret = atmel_smc_cs_conf_set_setup(smcconf, ATMEL_SMC_NRD_SHIFT, ncycles);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* The read cycle timing is directly matching tRC, but is also
|
||||
* dependent on the setup and hold timings we calculated earlier,
|
||||
* which gives:
|
||||
*
|
||||
* NRD_CYCLE = max(tRC, NRD_PULSE + NRD_HOLD)
|
||||
*
|
||||
* NRD_SETUP is always 0.
|
||||
* NRD_CYCLE = max(tRC, NRD_SETUP + NRD_PULSE + NRD_HOLD)
|
||||
*/
|
||||
ncycles = DIV_ROUND_UP(conf->timings.sdr.tRC_min, mckperiodps);
|
||||
ncycles = max(totalcycles, ncycles);
|
||||
|
|
|
|||
|
|
@ -935,10 +935,10 @@ static void ma35_chips_cleanup(struct ma35_nand_info *nand)
|
|||
|
||||
static int ma35_nand_chips_init(struct device *dev, struct ma35_nand_info *nand)
|
||||
{
|
||||
struct device_node *np = dev->of_node, *nand_np;
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
|
||||
for_each_child_of_node(np, nand_np) {
|
||||
for_each_child_of_node_scoped(np, nand_np) {
|
||||
ret = ma35_nand_chip_init(dev, nand, nand_np);
|
||||
if (ret) {
|
||||
ma35_chips_cleanup(nand);
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ struct stm32_fmc2_nfc {
|
|||
struct sg_table dma_data_sg;
|
||||
struct sg_table dma_ecc_sg;
|
||||
u8 *ecc_buf;
|
||||
dma_addr_t dma_ecc_addr;
|
||||
int dma_ecc_len;
|
||||
u32 tx_dma_max_burst;
|
||||
u32 rx_dma_max_burst;
|
||||
|
|
@ -902,17 +903,10 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
|
||||
if (!write_data && !raw) {
|
||||
/* Configure DMA ECC status */
|
||||
p = nfc->ecc_buf;
|
||||
for_each_sg(nfc->dma_ecc_sg.sgl, sg, eccsteps, s) {
|
||||
sg_set_buf(sg, p, nfc->dma_ecc_len);
|
||||
p += nfc->dma_ecc_len;
|
||||
}
|
||||
|
||||
ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
|
||||
eccsteps, dma_data_dir);
|
||||
if (!ret) {
|
||||
ret = -EIO;
|
||||
goto err_unmap_data;
|
||||
sg_dma_address(sg) = nfc->dma_ecc_addr +
|
||||
s * nfc->dma_ecc_len;
|
||||
sg_dma_len(sg) = nfc->dma_ecc_len;
|
||||
}
|
||||
|
||||
desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch,
|
||||
|
|
@ -921,7 +915,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
DMA_PREP_INTERRUPT);
|
||||
if (!desc_ecc) {
|
||||
ret = -ENOMEM;
|
||||
goto err_unmap_ecc;
|
||||
goto err_unmap_data;
|
||||
}
|
||||
|
||||
reinit_completion(&nfc->dma_ecc_complete);
|
||||
|
|
@ -929,7 +923,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
desc_ecc->callback_param = &nfc->dma_ecc_complete;
|
||||
ret = dma_submit_error(dmaengine_submit(desc_ecc));
|
||||
if (ret)
|
||||
goto err_unmap_ecc;
|
||||
goto err_unmap_data;
|
||||
|
||||
dma_async_issue_pending(nfc->dma_ecc_ch);
|
||||
}
|
||||
|
|
@ -949,7 +943,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
if (!write_data && !raw)
|
||||
dmaengine_terminate_all(nfc->dma_ecc_ch);
|
||||
ret = -ETIMEDOUT;
|
||||
goto err_unmap_ecc;
|
||||
goto err_unmap_data;
|
||||
}
|
||||
|
||||
/* Wait DMA data transfer completion */
|
||||
|
|
@ -969,11 +963,6 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
|
|||
}
|
||||
}
|
||||
|
||||
err_unmap_ecc:
|
||||
if (!write_data && !raw)
|
||||
dma_unmap_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
|
||||
eccsteps, dma_data_dir);
|
||||
|
||||
err_unmap_data:
|
||||
dma_unmap_sg(nfc->dev, nfc->dma_data_sg.sgl, eccsteps, dma_data_dir);
|
||||
|
||||
|
|
@ -996,9 +985,21 @@ static int stm32_fmc2_nfc_seq_write(struct nand_chip *chip, const u8 *buf,
|
|||
|
||||
/* Write oob */
|
||||
if (oob_required) {
|
||||
ret = nand_change_write_column_op(chip, mtd->writesize,
|
||||
chip->oob_poi, mtd->oobsize,
|
||||
false);
|
||||
unsigned int offset_in_page = mtd->writesize;
|
||||
const void *buf = chip->oob_poi;
|
||||
unsigned int len = mtd->oobsize;
|
||||
|
||||
if (!raw) {
|
||||
struct mtd_oob_region oob_free;
|
||||
|
||||
mtd_ooblayout_free(mtd, 0, &oob_free);
|
||||
offset_in_page += oob_free.offset;
|
||||
buf += oob_free.offset;
|
||||
len = oob_free.length;
|
||||
}
|
||||
|
||||
ret = nand_change_write_column_op(chip, offset_in_page,
|
||||
buf, len, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1610,7 +1611,8 @@ static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc)
|
|||
return ret;
|
||||
|
||||
/* Allocate a buffer to store ECC status registers */
|
||||
nfc->ecc_buf = devm_kzalloc(nfc->dev, FMC2_MAX_ECC_BUF_LEN, GFP_KERNEL);
|
||||
nfc->ecc_buf = dmam_alloc_coherent(nfc->dev, FMC2_MAX_ECC_BUF_LEN,
|
||||
&nfc->dma_ecc_addr, GFP_KERNEL);
|
||||
if (!nfc->ecc_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -176,6 +176,36 @@ static const struct mtd_ooblayout_ops w25n02kv_ooblayout = {
|
|||
.free = w25n02kv_ooblayout_free,
|
||||
};
|
||||
|
||||
static int w25n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section > 3)
|
||||
return -ERANGE;
|
||||
|
||||
region->offset = (16 * section) + 12;
|
||||
region->length = 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int w25n01jw_ooblayout_free(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
if (section > 3)
|
||||
return -ERANGE;
|
||||
|
||||
region->offset = (16 * section);
|
||||
region->length = 12;
|
||||
|
||||
/* Extract BBM */
|
||||
if (!section) {
|
||||
region->offset += 2;
|
||||
region->length -= 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
|
||||
struct mtd_oob_region *region)
|
||||
{
|
||||
|
|
@ -206,6 +236,11 @@ static int w35n01jw_ooblayout_free(struct mtd_info *mtd, int section,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtd_ooblayout_ops w25n01jw_ooblayout = {
|
||||
.ecc = w25n01jw_ooblayout_ecc,
|
||||
.free = w25n01jw_ooblayout_free,
|
||||
};
|
||||
|
||||
static const struct mtd_ooblayout_ops w35n01jw_ooblayout = {
|
||||
.ecc = w35n01jw_ooblayout_ecc,
|
||||
.free = w35n01jw_ooblayout_free,
|
||||
|
|
@ -394,7 +429,7 @@ static const struct spinand_info winbond_spinand_table[] = {
|
|||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
0,
|
||||
SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
|
||||
SPINAND_ECCINFO(&w25n01jw_ooblayout, NULL),
|
||||
SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)),
|
||||
SPINAND_INFO("W25N01KV", /* 3.3V */
|
||||
SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),
|
||||
|
|
|
|||
|
|
@ -2053,6 +2053,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
|
|||
memcpy(ss.__data, bond_dev->dev_addr, bond_dev->addr_len);
|
||||
} else if (bond->params.fail_over_mac == BOND_FOM_FOLLOW &&
|
||||
BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP &&
|
||||
bond_has_slaves(bond) &&
|
||||
memcmp(slave_dev->dev_addr, bond_dev->dev_addr, bond_dev->addr_len) == 0) {
|
||||
/* Set slave to random address to avoid duplicate mac
|
||||
* address in later fail over.
|
||||
|
|
@ -3257,7 +3258,6 @@ static void bond_ns_send_all(struct bonding *bond, struct slave *slave)
|
|||
/* Find out through which dev should the packet go */
|
||||
memset(&fl6, 0, sizeof(struct flowi6));
|
||||
fl6.daddr = targets[i];
|
||||
fl6.flowi6_oif = bond->dev->ifindex;
|
||||
|
||||
dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6);
|
||||
if (dst->error) {
|
||||
|
|
|
|||
|
|
@ -4230,8 +4230,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
|
|||
|
||||
cnic_bnx2x_delete_wait(dev, 0);
|
||||
|
||||
cancel_delayed_work(&cp->delete_task);
|
||||
flush_workqueue(cnic_wq);
|
||||
cancel_delayed_work_sync(&cp->delete_task);
|
||||
|
||||
if (atomic_read(&cp->iscsi_conn) != 0)
|
||||
netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n",
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ int octeon_init_instr_queue(struct octeon_device *oct,
|
|||
oct->io_qmask.iq |= BIT_ULL(iq_no);
|
||||
|
||||
/* Set the 32B/64B mode for each input queue */
|
||||
oct->io_qmask.iq64B |= ((conf->instr_type == 64) << iq_no);
|
||||
oct->io_qmask.iq64B |= ((u64)(conf->instr_type == 64) << iq_no);
|
||||
iq->iqcmd_64B = (conf->instr_type == 64);
|
||||
|
||||
oct->fn_list.setup_iq_regs(oct, iq_no);
|
||||
|
|
|
|||
|
|
@ -2736,7 +2736,7 @@ static int dpaa2_switch_setup_dpbp(struct ethsw_core *ethsw)
|
|||
dev_err(dev, "dpsw_ctrl_if_set_pools() failed\n");
|
||||
goto err_get_attr;
|
||||
}
|
||||
ethsw->bpid = dpbp_attrs.id;
|
||||
ethsw->bpid = dpbp_attrs.bpid;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -948,9 +948,6 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
|
|||
if (!eop_desc)
|
||||
break;
|
||||
|
||||
/* prevent any other reads prior to eop_desc */
|
||||
smp_rmb();
|
||||
|
||||
i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf);
|
||||
/* we have caught up to head, no work left to do */
|
||||
if (tx_head == tx_desc)
|
||||
|
|
|
|||
|
|
@ -894,10 +894,6 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
|
|||
__skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page,
|
||||
rx_buf->page_offset, size);
|
||||
sinfo->xdp_frags_size += size;
|
||||
/* remember frag count before XDP prog execution; bpf_xdp_adjust_tail()
|
||||
* can pop off frags but driver has to handle it on its own
|
||||
*/
|
||||
rx_ring->nr_frags = sinfo->nr_frags;
|
||||
|
||||
if (page_is_pfmemalloc(rx_buf->page))
|
||||
xdp_buff_set_frag_pfmemalloc(xdp);
|
||||
|
|
@ -968,20 +964,20 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,
|
|||
/**
|
||||
* ice_get_pgcnts - grab page_count() for gathered fragments
|
||||
* @rx_ring: Rx descriptor ring to store the page counts on
|
||||
* @ntc: the next to clean element (not included in this frame!)
|
||||
*
|
||||
* This function is intended to be called right before running XDP
|
||||
* program so that the page recycling mechanism will be able to take
|
||||
* a correct decision regarding underlying pages; this is done in such
|
||||
* way as XDP program can change the refcount of page
|
||||
*/
|
||||
static void ice_get_pgcnts(struct ice_rx_ring *rx_ring)
|
||||
static void ice_get_pgcnts(struct ice_rx_ring *rx_ring, unsigned int ntc)
|
||||
{
|
||||
u32 nr_frags = rx_ring->nr_frags + 1;
|
||||
u32 idx = rx_ring->first_desc;
|
||||
struct ice_rx_buf *rx_buf;
|
||||
u32 cnt = rx_ring->count;
|
||||
|
||||
for (int i = 0; i < nr_frags; i++) {
|
||||
while (idx != ntc) {
|
||||
rx_buf = &rx_ring->rx_buf[idx];
|
||||
rx_buf->pgcnt = page_count(rx_buf->page);
|
||||
|
||||
|
|
@ -1153,62 +1149,51 @@ ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf)
|
|||
}
|
||||
|
||||
/**
|
||||
* ice_put_rx_mbuf - ice_put_rx_buf() caller, for all frame frags
|
||||
* ice_put_rx_mbuf - ice_put_rx_buf() caller, for all buffers in frame
|
||||
* @rx_ring: Rx ring with all the auxiliary data
|
||||
* @xdp: XDP buffer carrying linear + frags part
|
||||
* @xdp_xmit: XDP_TX/XDP_REDIRECT verdict storage
|
||||
* @ntc: a current next_to_clean value to be stored at rx_ring
|
||||
* @ntc: the next to clean element (not included in this frame!)
|
||||
* @verdict: return code from XDP program execution
|
||||
*
|
||||
* Walk through gathered fragments and satisfy internal page
|
||||
* recycle mechanism; we take here an action related to verdict
|
||||
* returned by XDP program;
|
||||
* Called after XDP program is completed, or on error with verdict set to
|
||||
* ICE_XDP_CONSUMED.
|
||||
*
|
||||
* Walk through buffers from first_desc to the end of the frame, releasing
|
||||
* buffers and satisfying internal page recycle mechanism. The action depends
|
||||
* on verdict from XDP program.
|
||||
*/
|
||||
static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
|
||||
u32 *xdp_xmit, u32 ntc, u32 verdict)
|
||||
u32 ntc, u32 verdict)
|
||||
{
|
||||
u32 nr_frags = rx_ring->nr_frags + 1;
|
||||
u32 idx = rx_ring->first_desc;
|
||||
u32 cnt = rx_ring->count;
|
||||
u32 post_xdp_frags = 1;
|
||||
struct ice_rx_buf *buf;
|
||||
int i;
|
||||
u32 xdp_frags = 0;
|
||||
int i = 0;
|
||||
|
||||
if (unlikely(xdp_buff_has_frags(xdp)))
|
||||
post_xdp_frags += xdp_get_shared_info_from_buff(xdp)->nr_frags;
|
||||
xdp_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags;
|
||||
|
||||
for (i = 0; i < post_xdp_frags; i++) {
|
||||
while (idx != ntc) {
|
||||
buf = &rx_ring->rx_buf[idx];
|
||||
if (++idx == cnt)
|
||||
idx = 0;
|
||||
|
||||
if (verdict & (ICE_XDP_TX | ICE_XDP_REDIR)) {
|
||||
/* An XDP program could release fragments from the end of the
|
||||
* buffer. For these, we need to keep the pagecnt_bias as-is.
|
||||
* To do this, only adjust pagecnt_bias for fragments up to
|
||||
* the total remaining after the XDP program has run.
|
||||
*/
|
||||
if (verdict != ICE_XDP_CONSUMED)
|
||||
ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz);
|
||||
*xdp_xmit |= verdict;
|
||||
} else if (verdict & ICE_XDP_CONSUMED) {
|
||||
else if (i++ <= xdp_frags)
|
||||
buf->pagecnt_bias++;
|
||||
} else if (verdict == ICE_XDP_PASS) {
|
||||
ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz);
|
||||
}
|
||||
|
||||
ice_put_rx_buf(rx_ring, buf);
|
||||
|
||||
if (++idx == cnt)
|
||||
idx = 0;
|
||||
}
|
||||
/* handle buffers that represented frags released by XDP prog;
|
||||
* for these we keep pagecnt_bias as-is; refcount from struct page
|
||||
* has been decremented within XDP prog and we do not have to increase
|
||||
* the biased refcnt
|
||||
*/
|
||||
for (; i < nr_frags; i++) {
|
||||
buf = &rx_ring->rx_buf[idx];
|
||||
ice_put_rx_buf(rx_ring, buf);
|
||||
if (++idx == cnt)
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
xdp->data = NULL;
|
||||
rx_ring->first_desc = ntc;
|
||||
rx_ring->nr_frags = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1316,6 +1301,10 @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
|||
/* retrieve a buffer from the ring */
|
||||
rx_buf = ice_get_rx_buf(rx_ring, size, ntc);
|
||||
|
||||
/* Increment ntc before calls to ice_put_rx_mbuf() */
|
||||
if (++ntc == cnt)
|
||||
ntc = 0;
|
||||
|
||||
if (!xdp->data) {
|
||||
void *hard_start;
|
||||
|
||||
|
|
@ -1324,24 +1313,23 @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
|||
xdp_prepare_buff(xdp, hard_start, offset, size, !!offset);
|
||||
xdp_buff_clear_frags_flag(xdp);
|
||||
} else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) {
|
||||
ice_put_rx_mbuf(rx_ring, xdp, NULL, ntc, ICE_XDP_CONSUMED);
|
||||
ice_put_rx_mbuf(rx_ring, xdp, ntc, ICE_XDP_CONSUMED);
|
||||
break;
|
||||
}
|
||||
if (++ntc == cnt)
|
||||
ntc = 0;
|
||||
|
||||
/* skip if it is NOP desc */
|
||||
if (ice_is_non_eop(rx_ring, rx_desc))
|
||||
continue;
|
||||
|
||||
ice_get_pgcnts(rx_ring);
|
||||
ice_get_pgcnts(rx_ring, ntc);
|
||||
xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc);
|
||||
if (xdp_verdict == ICE_XDP_PASS)
|
||||
goto construct_skb;
|
||||
total_rx_bytes += xdp_get_buff_len(xdp);
|
||||
total_rx_pkts++;
|
||||
|
||||
ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict);
|
||||
ice_put_rx_mbuf(rx_ring, xdp, ntc, xdp_verdict);
|
||||
xdp_xmit |= xdp_verdict & (ICE_XDP_TX | ICE_XDP_REDIR);
|
||||
|
||||
continue;
|
||||
construct_skb:
|
||||
|
|
@ -1354,7 +1342,7 @@ construct_skb:
|
|||
rx_ring->ring_stats->rx_stats.alloc_buf_failed++;
|
||||
xdp_verdict = ICE_XDP_CONSUMED;
|
||||
}
|
||||
ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict);
|
||||
ice_put_rx_mbuf(rx_ring, xdp, ntc, xdp_verdict);
|
||||
|
||||
if (!skb)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -358,7 +358,6 @@ struct ice_rx_ring {
|
|||
struct ice_tx_ring *xdp_ring;
|
||||
struct ice_rx_ring *next; /* pointer to next ring in q_vector */
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
u32 nr_frags;
|
||||
u16 max_frame;
|
||||
u16 rx_buf_len;
|
||||
dma_addr_t dma; /* physical address of ring */
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ struct igc_adapter {
|
|||
/* LEDs */
|
||||
struct mutex led_mutex;
|
||||
struct igc_led_classdev *leds;
|
||||
bool leds_available;
|
||||
};
|
||||
|
||||
void igc_up(struct igc_adapter *adapter);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue