mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 05:55:44 +02:00
Merge 9cfd9c4599 ("Merge tag 'char-misc-5.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc") into android-mainline
Steps on the way to 5.10-rc4 Resolves conflict in: arch/arm64/kvm/sys_regs.c Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Id188ccbec038cf7e30c204e9f5b7866f72b6640d
This commit is contained in:
commit
dccb6e8d02
|
|
@ -18186,6 +18186,14 @@ L: linux-usb@vger.kernel.org
|
|||
S: Supported
|
||||
F: drivers/usb/class/usblp.c
|
||||
|
||||
USB RAW GADGET DRIVER
|
||||
R: Andrey Konovalov <andreyknvl@gmail.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/usb/raw-gadget.rst
|
||||
F: drivers/usb/gadget/legacy/raw_gadget.c
|
||||
F: include/uapi/linux/usb/raw_gadget.h
|
||||
|
||||
USB QMI WWAN NETWORK DRIVER
|
||||
M: Bjørn Mork <bjorn@mork.no>
|
||||
L: netdev@vger.kernel.org
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ u64 perf_reg_abi(struct task_struct *task)
|
|||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ struct kvm_arch {
|
|||
*/
|
||||
unsigned long *pmu_filter;
|
||||
unsigned int pmuver;
|
||||
|
||||
u8 pfr0_csv2;
|
||||
};
|
||||
|
||||
struct kvm_vcpu_fault_info {
|
||||
|
|
|
|||
|
|
@ -372,6 +372,8 @@
|
|||
#define SYS_CONTEXTIDR_EL1 sys_reg(3, 0, 13, 0, 1)
|
||||
#define SYS_TPIDR_EL1 sys_reg(3, 0, 13, 0, 4)
|
||||
|
||||
#define SYS_SCXTNUM_EL1 sys_reg(3, 0, 13, 0, 7)
|
||||
|
||||
#define SYS_CNTKCTL_EL1 sys_reg(3, 0, 14, 1, 0)
|
||||
|
||||
#define SYS_CCSIDR_EL1 sys_reg(3, 1, 0, 0, 0)
|
||||
|
|
@ -404,6 +406,8 @@
|
|||
#define SYS_TPIDR_EL0 sys_reg(3, 3, 13, 0, 2)
|
||||
#define SYS_TPIDRRO_EL0 sys_reg(3, 3, 13, 0, 3)
|
||||
|
||||
#define SYS_SCXTNUM_EL0 sys_reg(3, 3, 13, 0, 7)
|
||||
|
||||
/* Definitions for system register interface to AMU for ARMv8.4 onwards */
|
||||
#define SYS_AM_EL0(crm, op2) sys_reg(3, 3, 13, (crm), (op2))
|
||||
#define SYS_AMCR_EL0 SYS_AM_EL0(2, 0)
|
||||
|
|
|
|||
|
|
@ -73,8 +73,7 @@ u64 perf_reg_abi(struct task_struct *task)
|
|||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
|
|
|
|||
|
|
@ -102,6 +102,20 @@ static int kvm_arm_default_max_vcpus(void)
|
|||
return vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS;
|
||||
}
|
||||
|
||||
static void set_default_csv2(struct kvm *kvm)
|
||||
{
|
||||
/*
|
||||
* The default is to expose CSV2 == 1 if the HW isn't affected.
|
||||
* Although this is a per-CPU feature, we make it global because
|
||||
* asymmetric systems are just a nuisance.
|
||||
*
|
||||
* Userspace can override this as long as it doesn't promise
|
||||
* the impossible.
|
||||
*/
|
||||
if (arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED)
|
||||
kvm->arch.pfr0_csv2 = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_arch_init_vm - initializes a VM data structure
|
||||
* @kvm: pointer to the KVM struct
|
||||
|
|
@ -127,6 +141,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
|||
/* The maximum number of VCPUs is limited by the host's GIC model */
|
||||
kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();
|
||||
|
||||
set_default_csv2(kvm);
|
||||
|
||||
return ret;
|
||||
out_free_stage2_pgd:
|
||||
kvm_free_stage2_pgd(&kvm->arch.mmu);
|
||||
|
|
|
|||
|
|
@ -1038,8 +1038,8 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
|||
{ SYS_DESC(SYS_PMEVTYPERn_EL0(n)), \
|
||||
access_pmu_evtyper, reset_unknown, (PMEVTYPER0_EL0 + n), }
|
||||
|
||||
static bool access_amu(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
static bool undef_access(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
kvm_inject_undefined(vcpu);
|
||||
|
||||
|
|
@ -1047,24 +1047,10 @@ static bool access_amu(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
|||
}
|
||||
|
||||
/* Macro to expand the AMU counter and type registers*/
|
||||
#define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), access_amu }
|
||||
#define AMU_AMEVTYPER0_EL0(n) { SYS_DESC(SYS_AMEVTYPER0_EL0(n)), access_amu }
|
||||
#define AMU_AMEVCNTR1_EL0(n) { SYS_DESC(SYS_AMEVCNTR1_EL0(n)), access_amu }
|
||||
#define AMU_AMEVTYPER1_EL0(n) { SYS_DESC(SYS_AMEVTYPER1_EL0(n)), access_amu }
|
||||
|
||||
static bool trap_ptrauth(struct kvm_vcpu *vcpu,
|
||||
struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *rd)
|
||||
{
|
||||
/*
|
||||
* If we land here, that is because we didn't fixup the access on exit
|
||||
* by allowing the PtrAuth sysregs. The only way this happens is when
|
||||
* the guest does not have PtrAuth support enabled.
|
||||
*/
|
||||
kvm_inject_undefined(vcpu);
|
||||
|
||||
return false;
|
||||
}
|
||||
#define AMU_AMEVCNTR0_EL0(n) { SYS_DESC(SYS_AMEVCNTR0_EL0(n)), undef_access }
|
||||
#define AMU_AMEVTYPER0_EL0(n) { SYS_DESC(SYS_AMEVTYPER0_EL0(n)), undef_access }
|
||||
#define AMU_AMEVCNTR1_EL0(n) { SYS_DESC(SYS_AMEVCNTR1_EL0(n)), undef_access }
|
||||
#define AMU_AMEVTYPER1_EL0(n) { SYS_DESC(SYS_AMEVTYPER1_EL0(n)), undef_access }
|
||||
|
||||
static unsigned int ptrauth_visibility(const struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *rd)
|
||||
|
|
@ -1072,8 +1058,14 @@ static unsigned int ptrauth_visibility(const struct kvm_vcpu *vcpu,
|
|||
return vcpu_has_ptrauth(vcpu) ? 0 : REG_HIDDEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we land here on a PtrAuth access, that is because we didn't
|
||||
* fixup the access on exit by allowing the PtrAuth sysregs. The only
|
||||
* way this happens is when the guest does not have PtrAuth support
|
||||
* enabled.
|
||||
*/
|
||||
#define __PTRAUTH_KEY(k) \
|
||||
{ SYS_DESC(SYS_## k), trap_ptrauth, reset_unknown, k, \
|
||||
{ SYS_DESC(SYS_## k), undef_access, reset_unknown, k, \
|
||||
.visibility = ptrauth_visibility}
|
||||
|
||||
#define PTRAUTH_KEY(k) \
|
||||
|
|
@ -1128,9 +1120,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
|
|||
if (!vcpu_has_sve(vcpu))
|
||||
val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
|
||||
val &= ~(0xfUL << ID_AA64PFR0_AMU_SHIFT);
|
||||
if (!(val & (0xfUL << ID_AA64PFR0_CSV2_SHIFT)) &&
|
||||
arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED)
|
||||
val |= (1UL << ID_AA64PFR0_CSV2_SHIFT);
|
||||
val &= ~(0xfUL << ID_AA64PFR0_CSV2_SHIFT);
|
||||
val |= ((u64)vcpu->kvm->arch.pfr0_csv2 << ID_AA64PFR0_CSV2_SHIFT);
|
||||
|
||||
if (!kvm_system_supports_32bit_el0()) {
|
||||
/*
|
||||
|
|
@ -1222,6 +1213,40 @@ static unsigned int sve_visibility(const struct kvm_vcpu *vcpu,
|
|||
return REG_HIDDEN;
|
||||
}
|
||||
|
||||
static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *rd,
|
||||
const struct kvm_one_reg *reg, void __user *uaddr)
|
||||
{
|
||||
const u64 id = sys_reg_to_index(rd);
|
||||
int err;
|
||||
u64 val;
|
||||
u8 csv2;
|
||||
|
||||
err = reg_from_user(&val, uaddr, id);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Allow AA64PFR0_EL1.CSV2 to be set from userspace as long as
|
||||
* it doesn't promise more than what is actually provided (the
|
||||
* guest could otherwise be covered in ectoplasmic residue).
|
||||
*/
|
||||
csv2 = cpuid_feature_extract_unsigned_field(val, ID_AA64PFR0_CSV2_SHIFT);
|
||||
if (csv2 > 1 ||
|
||||
(csv2 && arm64_get_spectre_v2_state() != SPECTRE_UNAFFECTED))
|
||||
return -EINVAL;
|
||||
|
||||
/* We can only differ with CSV2, and anything else is an error */
|
||||
val ^= read_id_reg(vcpu, rd, false);
|
||||
val &= ~(0xFUL << ID_AA64PFR0_CSV2_SHIFT);
|
||||
if (val)
|
||||
return -EINVAL;
|
||||
|
||||
vcpu->kvm->arch.pfr0_csv2 = csv2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cpufeature ID register user accessors
|
||||
*
|
||||
|
|
@ -1350,13 +1375,6 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool access_mte_regs(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
||||
const struct sys_reg_desc *r)
|
||||
{
|
||||
kvm_inject_undefined(vcpu);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* sys_reg_desc initialiser for known cpufeature ID registers */
|
||||
#define ID_SANITISED(name) { \
|
||||
SYS_DESC(SYS_##name), \
|
||||
|
|
@ -1481,7 +1499,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
|||
|
||||
/* AArch64 ID registers */
|
||||
/* CRm=4 */
|
||||
ID_SANITISED(ID_AA64PFR0_EL1),
|
||||
{ SYS_DESC(SYS_ID_AA64PFR0_EL1), .access = access_id_reg,
|
||||
.get_user = get_id_reg, .set_user = set_id_aa64pfr0_el1, },
|
||||
ID_SANITISED(ID_AA64PFR1_EL1),
|
||||
ID_UNALLOCATED(4,2),
|
||||
ID_UNALLOCATED(4,3),
|
||||
|
|
@ -1524,8 +1543,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
|||
{ SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 },
|
||||
{ SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
|
||||
|
||||
{ SYS_DESC(SYS_RGSR_EL1), access_mte_regs },
|
||||
{ SYS_DESC(SYS_GCR_EL1), access_mte_regs },
|
||||
{ SYS_DESC(SYS_RGSR_EL1), undef_access },
|
||||
{ SYS_DESC(SYS_GCR_EL1), undef_access },
|
||||
|
||||
{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility },
|
||||
{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
|
||||
|
|
@ -1551,8 +1570,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
|||
{ SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi },
|
||||
{ SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi },
|
||||
|
||||
{ SYS_DESC(SYS_TFSR_EL1), access_mte_regs },
|
||||
{ SYS_DESC(SYS_TFSRE0_EL1), access_mte_regs },
|
||||
{ SYS_DESC(SYS_TFSR_EL1), undef_access },
|
||||
{ SYS_DESC(SYS_TFSRE0_EL1), undef_access },
|
||||
|
||||
{ SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 },
|
||||
{ SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 },
|
||||
|
|
@ -1588,6 +1607,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
|||
{ SYS_DESC(SYS_CONTEXTIDR_EL1), access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
|
||||
{ SYS_DESC(SYS_TPIDR_EL1), NULL, reset_unknown, TPIDR_EL1 },
|
||||
|
||||
{ SYS_DESC(SYS_SCXTNUM_EL1), undef_access },
|
||||
|
||||
{ SYS_DESC(SYS_CNTKCTL_EL1), NULL, reset_val, CNTKCTL_EL1, 0},
|
||||
|
||||
{ SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
|
||||
|
|
@ -1616,14 +1637,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
|||
{ SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
|
||||
{ SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 },
|
||||
|
||||
{ SYS_DESC(SYS_AMCR_EL0), access_amu },
|
||||
{ SYS_DESC(SYS_AMCFGR_EL0), access_amu },
|
||||
{ SYS_DESC(SYS_AMCGCR_EL0), access_amu },
|
||||
{ SYS_DESC(SYS_AMUSERENR_EL0), access_amu },
|
||||
{ SYS_DESC(SYS_AMCNTENCLR0_EL0), access_amu },
|
||||
{ SYS_DESC(SYS_AMCNTENSET0_EL0), access_amu },
|
||||
{ SYS_DESC(SYS_AMCNTENCLR1_EL0), access_amu },
|
||||
{ SYS_DESC(SYS_AMCNTENSET1_EL0), access_amu },
|
||||
{ SYS_DESC(SYS_SCXTNUM_EL0), undef_access },
|
||||
|
||||
{ SYS_DESC(SYS_AMCR_EL0), undef_access },
|
||||
{ SYS_DESC(SYS_AMCFGR_EL0), undef_access },
|
||||
{ SYS_DESC(SYS_AMCGCR_EL0), undef_access },
|
||||
{ SYS_DESC(SYS_AMUSERENR_EL0), undef_access },
|
||||
{ SYS_DESC(SYS_AMCNTENCLR0_EL0), undef_access },
|
||||
{ SYS_DESC(SYS_AMCNTENSET0_EL0), undef_access },
|
||||
{ SYS_DESC(SYS_AMCNTENCLR1_EL0), undef_access },
|
||||
{ SYS_DESC(SYS_AMCNTENSET1_EL0), undef_access },
|
||||
AMU_AMEVCNTR0_EL0(0),
|
||||
AMU_AMEVCNTR0_EL0(1),
|
||||
AMU_AMEVCNTR0_EL0(2),
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ u64 perf_reg_abi(struct task_struct *task)
|
|||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
|
|
|
|||
|
|
@ -1336,7 +1336,7 @@ static void dump_trace_imc_data(struct perf_event *event)
|
|||
/* If this is a valid record, create the sample */
|
||||
struct perf_output_handle handle;
|
||||
|
||||
if (perf_output_begin(&handle, event, header.size))
|
||||
if (perf_output_begin(&handle, &data, event, header.size))
|
||||
return;
|
||||
|
||||
perf_output_sample(&handle, &header, &data, event);
|
||||
|
|
|
|||
|
|
@ -144,8 +144,7 @@ u64 perf_reg_abi(struct task_struct *task)
|
|||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :
|
||||
|
|
|
|||
|
|
@ -36,8 +36,7 @@ u64 perf_reg_abi(struct task_struct *task)
|
|||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
|
|
|
|||
|
|
@ -672,7 +672,7 @@ static void cpumsf_output_event_pid(struct perf_event *event,
|
|||
rcu_read_lock();
|
||||
|
||||
perf_prepare_sample(&header, data, event, regs);
|
||||
if (perf_output_begin(&handle, event, header.size))
|
||||
if (perf_output_begin(&handle, data, event, header.size))
|
||||
goto out;
|
||||
|
||||
/* Update the process ID (see also kernel/events/core.c) */
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ u64 perf_reg_abi(struct task_struct *task)
|
|||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
/*
|
||||
* Use the regs from the first interruption and let
|
||||
|
|
|
|||
|
|
@ -2630,7 +2630,7 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
|
|||
u64 pebs_enabled = cpuc->pebs_enabled;
|
||||
|
||||
handled++;
|
||||
x86_pmu.drain_pebs(regs);
|
||||
x86_pmu.drain_pebs(regs, &data);
|
||||
status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
|
||||
|
||||
/*
|
||||
|
|
@ -4987,6 +4987,12 @@ __init int intel_pmu_init(void)
|
|||
|
||||
x86_add_quirk(intel_arch_events_quirk); /* Install first, so it runs last */
|
||||
|
||||
if (version >= 5) {
|
||||
x86_pmu.intel_cap.anythread_deprecated = edx.split.anythread_deprecated;
|
||||
if (x86_pmu.intel_cap.anythread_deprecated)
|
||||
pr_cont(" AnyThread deprecated, ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Install the hw-cache-events table:
|
||||
*/
|
||||
|
|
@ -5512,6 +5518,10 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.intel_ctrl |=
|
||||
((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
|
||||
|
||||
/* AnyThread may be deprecated on arch perfmon v5 or later */
|
||||
if (x86_pmu.intel_cap.anythread_deprecated)
|
||||
x86_pmu.format_attrs = intel_arch_formats_attr;
|
||||
|
||||
if (x86_pmu.event_constraints) {
|
||||
/*
|
||||
* event on fixed counter2 (REF_CYCLES) only works on this
|
||||
|
|
|
|||
|
|
@ -642,8 +642,8 @@ int intel_pmu_drain_bts_buffer(void)
|
|||
rcu_read_lock();
|
||||
perf_prepare_sample(&header, &data, event, ®s);
|
||||
|
||||
if (perf_output_begin(&handle, event, header.size *
|
||||
(top - base - skip)))
|
||||
if (perf_output_begin(&handle, &data, event,
|
||||
header.size * (top - base - skip)))
|
||||
goto unlock;
|
||||
|
||||
for (at = base; at < top; at++) {
|
||||
|
|
@ -670,7 +670,9 @@ int intel_pmu_drain_bts_buffer(void)
|
|||
|
||||
static inline void intel_pmu_drain_pebs_buffer(void)
|
||||
{
|
||||
x86_pmu.drain_pebs(NULL);
|
||||
struct perf_sample_data data;
|
||||
|
||||
x86_pmu.drain_pebs(NULL, &data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1719,23 +1721,24 @@ intel_pmu_save_and_restart_reload(struct perf_event *event, int count)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __intel_pmu_pebs_event(struct perf_event *event,
|
||||
struct pt_regs *iregs,
|
||||
void *base, void *top,
|
||||
int bit, int count,
|
||||
void (*setup_sample)(struct perf_event *,
|
||||
struct pt_regs *,
|
||||
void *,
|
||||
struct perf_sample_data *,
|
||||
struct pt_regs *))
|
||||
static __always_inline void
|
||||
__intel_pmu_pebs_event(struct perf_event *event,
|
||||
struct pt_regs *iregs,
|
||||
struct perf_sample_data *data,
|
||||
void *base, void *top,
|
||||
int bit, int count,
|
||||
void (*setup_sample)(struct perf_event *,
|
||||
struct pt_regs *,
|
||||
void *,
|
||||
struct perf_sample_data *,
|
||||
struct pt_regs *))
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
struct perf_sample_data data;
|
||||
struct x86_perf_regs perf_regs;
|
||||
struct pt_regs *regs = &perf_regs.regs;
|
||||
void *at = get_next_pebs_record_by_bit(base, top, bit);
|
||||
struct pt_regs dummy_iregs;
|
||||
static struct pt_regs dummy_iregs;
|
||||
|
||||
if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) {
|
||||
/*
|
||||
|
|
@ -1752,14 +1755,14 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
|
|||
iregs = &dummy_iregs;
|
||||
|
||||
while (count > 1) {
|
||||
setup_sample(event, iregs, at, &data, regs);
|
||||
perf_event_output(event, &data, regs);
|
||||
setup_sample(event, iregs, at, data, regs);
|
||||
perf_event_output(event, data, regs);
|
||||
at += cpuc->pebs_record_size;
|
||||
at = get_next_pebs_record_by_bit(at, top, bit);
|
||||
count--;
|
||||
}
|
||||
|
||||
setup_sample(event, iregs, at, &data, regs);
|
||||
setup_sample(event, iregs, at, data, regs);
|
||||
if (iregs == &dummy_iregs) {
|
||||
/*
|
||||
* The PEBS records may be drained in the non-overflow context,
|
||||
|
|
@ -1767,18 +1770,18 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
|
|||
* last record the same as other PEBS records, and doesn't
|
||||
* invoke the generic overflow handler.
|
||||
*/
|
||||
perf_event_output(event, &data, regs);
|
||||
perf_event_output(event, data, regs);
|
||||
} else {
|
||||
/*
|
||||
* All but the last records are processed.
|
||||
* The last one is left to be able to call the overflow handler.
|
||||
*/
|
||||
if (perf_event_overflow(event, &data, regs))
|
||||
if (perf_event_overflow(event, data, regs))
|
||||
x86_pmu_stop(event, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
|
||||
static void intel_pmu_drain_pebs_core(struct pt_regs *iregs, struct perf_sample_data *data)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
struct debug_store *ds = cpuc->ds;
|
||||
|
|
@ -1812,7 +1815,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
|
|||
return;
|
||||
}
|
||||
|
||||
__intel_pmu_pebs_event(event, iregs, at, top, 0, n,
|
||||
__intel_pmu_pebs_event(event, iregs, data, at, top, 0, n,
|
||||
setup_pebs_fixed_sample_data);
|
||||
}
|
||||
|
||||
|
|
@ -1835,7 +1838,7 @@ static void intel_pmu_pebs_event_update_no_drain(struct cpu_hw_events *cpuc, int
|
|||
}
|
||||
}
|
||||
|
||||
static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
|
||||
static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_data *data)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
struct debug_store *ds = cpuc->ds;
|
||||
|
|
@ -1942,14 +1945,14 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
|
|||
}
|
||||
|
||||
if (counts[bit]) {
|
||||
__intel_pmu_pebs_event(event, iregs, base,
|
||||
__intel_pmu_pebs_event(event, iregs, data, base,
|
||||
top, bit, counts[bit],
|
||||
setup_pebs_fixed_sample_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs)
|
||||
static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs, struct perf_sample_data *data)
|
||||
{
|
||||
short counts[INTEL_PMC_IDX_FIXED + MAX_FIXED_PEBS_EVENTS] = {};
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
|
|
@ -1997,7 +2000,7 @@ static void intel_pmu_drain_pebs_icl(struct pt_regs *iregs)
|
|||
if (WARN_ON_ONCE(!event->attr.precise_ip))
|
||||
continue;
|
||||
|
||||
__intel_pmu_pebs_event(event, iregs, base,
|
||||
__intel_pmu_pebs_event(event, iregs, data, base,
|
||||
top, bit, counts[bit],
|
||||
setup_pebs_adaptive_sample_data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ enum perf_snb_uncore_imc_freerunning_types {
|
|||
static struct freerunning_counters snb_uncore_imc_freerunning[] = {
|
||||
[SNB_PCI_UNCORE_IMC_DATA_READS] = { SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
|
||||
0x0, 0x0, 1, 32 },
|
||||
[SNB_PCI_UNCORE_IMC_DATA_READS] = { SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE,
|
||||
[SNB_PCI_UNCORE_IMC_DATA_WRITES] = { SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE,
|
||||
0x0, 0x0, 1, 32 },
|
||||
[SNB_PCI_UNCORE_IMC_GT_REQUESTS] = { SNB_UNCORE_PCI_IMC_GT_REQUESTS_BASE,
|
||||
0x0, 0x0, 1, 32 },
|
||||
|
|
|
|||
|
|
@ -585,6 +585,7 @@ union perf_capabilities {
|
|||
u64 pebs_baseline:1;
|
||||
u64 perf_metrics:1;
|
||||
u64 pebs_output_pt_available:1;
|
||||
u64 anythread_deprecated:1;
|
||||
};
|
||||
u64 capabilities;
|
||||
};
|
||||
|
|
@ -727,7 +728,7 @@ struct x86_pmu {
|
|||
int pebs_record_size;
|
||||
int pebs_buffer_size;
|
||||
int max_pebs_events;
|
||||
void (*drain_pebs)(struct pt_regs *regs);
|
||||
void (*drain_pebs)(struct pt_regs *regs, struct perf_sample_data *data);
|
||||
struct event_constraint *pebs_constraints;
|
||||
void (*pebs_aliases)(struct perf_event *event);
|
||||
unsigned long large_pebs_flags;
|
||||
|
|
|
|||
|
|
@ -639,6 +639,7 @@ struct kvm_vcpu_arch {
|
|||
int cpuid_nent;
|
||||
struct kvm_cpuid_entry2 *cpuid_entries;
|
||||
|
||||
unsigned long cr3_lm_rsvd_bits;
|
||||
int maxphyaddr;
|
||||
int max_tdp_level;
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,9 @@ union cpuid10_edx {
|
|||
struct {
|
||||
unsigned int num_counters_fixed:5;
|
||||
unsigned int bit_width_fixed:8;
|
||||
unsigned int reserved:19;
|
||||
unsigned int reserved1:2;
|
||||
unsigned int anythread_deprecated:1;
|
||||
unsigned int reserved2:16;
|
||||
} split;
|
||||
unsigned int full;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,14 +2,8 @@
|
|||
#ifndef _ASM_X86_UV_UV_H
|
||||
#define _ASM_X86_UV_UV_H
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC};
|
||||
|
||||
struct cpumask;
|
||||
struct mm_struct;
|
||||
struct flush_tlb_info;
|
||||
|
||||
#ifdef CONFIG_X86_UV
|
||||
#include <linux/efi.h>
|
||||
|
||||
|
|
@ -44,10 +38,6 @@ static inline int is_uv_system(void) { return 0; }
|
|||
static inline int is_uv_hubbed(int uv) { return 0; }
|
||||
static inline void uv_cpu_init(void) { }
|
||||
static inline void uv_system_init(void) { }
|
||||
static inline const struct cpumask *
|
||||
uv_flush_tlb_others(const struct cpumask *cpumask,
|
||||
const struct flush_tlb_info *info)
|
||||
{ return cpumask; }
|
||||
|
||||
#endif /* X86_UV */
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ static union uvh_apicid uvh_apicid;
|
|||
static int uv_node_id;
|
||||
|
||||
/* Unpack AT/OEM/TABLE ID's to be NULL terminated strings */
|
||||
static u8 uv_archtype[UV_AT_SIZE];
|
||||
static u8 uv_archtype[UV_AT_SIZE + 1];
|
||||
static u8 oem_id[ACPI_OEM_ID_SIZE + 1];
|
||||
static u8 oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
|
||||
|
||||
|
|
@ -320,7 +320,7 @@ static int __init decode_arch_type(unsigned long ptr)
|
|||
|
||||
if (n > 0 && n < sizeof(uv_ate->archtype)) {
|
||||
pr_info("UV: UVarchtype received from BIOS\n");
|
||||
uv_stringify(UV_AT_SIZE, uv_archtype, uv_ate->archtype);
|
||||
uv_stringify(sizeof(uv_archtype), uv_archtype, uv_ate->archtype);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -378,7 +378,7 @@ static int __init uv_set_system_type(char *_oem_id, char *_oem_table_id)
|
|||
if (!early_get_arch_type())
|
||||
|
||||
/* If not use OEM ID for UVarchtype */
|
||||
uv_stringify(UV_AT_SIZE, uv_archtype, _oem_id);
|
||||
uv_stringify(sizeof(uv_archtype), uv_archtype, oem_id);
|
||||
|
||||
/* Check if not hubbed */
|
||||
if (strncmp(uv_archtype, "SGI", 3) != 0) {
|
||||
|
|
|
|||
|
|
@ -101,8 +101,7 @@ u64 perf_reg_abi(struct task_struct *task)
|
|||
}
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
|
|
@ -129,12 +128,20 @@ u64 perf_reg_abi(struct task_struct *task)
|
|||
return PERF_SAMPLE_REGS_ABI_64;
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(struct pt_regs, nmi_user_regs);
|
||||
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *regs_user_copy = this_cpu_ptr(&nmi_user_regs);
|
||||
struct pt_regs *user_regs = task_pt_regs(current);
|
||||
|
||||
if (!in_nmi()) {
|
||||
regs_user->regs = user_regs;
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're in an NMI that interrupted task_pt_regs setup, then
|
||||
* we can't sample user regs at all. This check isn't really
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
|
|||
vcpu->arch.cr4_guest_rsvd_bits =
|
||||
__cr4_reserved_bits(guest_cpuid_has, vcpu);
|
||||
|
||||
vcpu->arch.cr3_lm_rsvd_bits = rsvd_bits(cpuid_maxphyaddr(vcpu), 63);
|
||||
|
||||
/* Invoke the vendor callback only after the above state is updated. */
|
||||
kvm_x86_ops.vcpu_after_set_cpuid(vcpu);
|
||||
}
|
||||
|
|
@ -681,7 +683,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
|
|||
|
||||
edx.split.num_counters_fixed = min(cap.num_counters_fixed, MAX_FIXED_COUNTERS);
|
||||
edx.split.bit_width_fixed = cap.bit_width_fixed;
|
||||
edx.split.reserved = 0;
|
||||
edx.split.anythread_deprecated = 1;
|
||||
edx.split.reserved1 = 0;
|
||||
edx.split.reserved2 = 0;
|
||||
|
||||
entry->eax = eax.full;
|
||||
entry->ebx = cap.events_mask;
|
||||
|
|
|
|||
|
|
@ -4046,6 +4046,12 @@ static int em_clflush(struct x86_emulate_ctxt *ctxt)
|
|||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
static int em_clflushopt(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
/* emulating clflushopt regardless of cpuid */
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
static int em_movsxd(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
ctxt->dst.val = (s32) ctxt->src.val;
|
||||
|
|
@ -4585,7 +4591,7 @@ static const struct opcode group11[] = {
|
|||
};
|
||||
|
||||
static const struct gprefix pfx_0f_ae_7 = {
|
||||
I(SrcMem | ByteOp, em_clflush), N, N, N,
|
||||
I(SrcMem | ByteOp, em_clflush), I(SrcMem | ByteOp, em_clflushopt), N, N,
|
||||
};
|
||||
|
||||
static const struct group_dual group15 = { {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,14 @@ bool is_tdp_mmu_root(struct kvm *kvm, hpa_t hpa)
|
|||
{
|
||||
struct kvm_mmu_page *sp;
|
||||
|
||||
if (!kvm->arch.tdp_mmu_enabled)
|
||||
return false;
|
||||
if (WARN_ON(!VALID_PAGE(hpa)))
|
||||
return false;
|
||||
|
||||
sp = to_shadow_page(hpa);
|
||||
if (WARN_ON(!sp))
|
||||
return false;
|
||||
|
||||
return sp->tdp_mmu_page && sp->root_count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3741,6 +3741,7 @@ static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
|
|||
static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
vcpu->arch.xsaves_enabled = guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) &&
|
||||
boot_cpu_has(X86_FEATURE_XSAVE) &&
|
||||
|
|
@ -3753,6 +3754,13 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
|
|||
/* Check again if INVPCID interception if required */
|
||||
svm_check_invpcid(svm);
|
||||
|
||||
/* For sev guests, the memory encryption bit is not reserved in CR3. */
|
||||
if (sev_guest(vcpu->kvm)) {
|
||||
best = kvm_find_cpuid_entry(vcpu, 0x8000001F, 0);
|
||||
if (best)
|
||||
vcpu->arch.cr3_lm_rsvd_bits &= ~(1UL << (best->ebx & 0x3f));
|
||||
}
|
||||
|
||||
if (!kvm_vcpu_apicv_active(vcpu))
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -1041,7 +1041,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
|
|||
}
|
||||
|
||||
if (is_long_mode(vcpu) &&
|
||||
(cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 63)))
|
||||
(cr3 & vcpu->arch.cr3_lm_rsvd_bits))
|
||||
return 1;
|
||||
else if (is_pae_paging(vcpu) &&
|
||||
!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3))
|
||||
|
|
|
|||
|
|
@ -357,7 +357,6 @@ static void speakup_cut(struct vc_data *vc)
|
|||
mark_cut_flag = 0;
|
||||
synth_printf("%s\n", spk_msg_get(MSG_CUT));
|
||||
|
||||
speakup_clear_selection();
|
||||
ret = speakup_set_selection(tty);
|
||||
|
||||
switch (ret) {
|
||||
|
|
|
|||
|
|
@ -22,13 +22,6 @@ struct speakup_selection_work {
|
|||
struct tty_struct *tty;
|
||||
};
|
||||
|
||||
void speakup_clear_selection(void)
|
||||
{
|
||||
console_lock();
|
||||
clear_selection();
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
static void __speakup_set_selection(struct work_struct *work)
|
||||
{
|
||||
struct speakup_selection_work *ssw =
|
||||
|
|
@ -51,6 +44,10 @@ static void __speakup_set_selection(struct work_struct *work)
|
|||
goto unref;
|
||||
}
|
||||
|
||||
console_lock();
|
||||
clear_selection();
|
||||
console_unlock();
|
||||
|
||||
set_selection_kernel(&sel, tty);
|
||||
|
||||
unref:
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ void spk_do_flush(void);
|
|||
void speakup_start_ttys(void);
|
||||
void synth_buffer_add(u16 ch);
|
||||
void synth_buffer_clear(void);
|
||||
void speakup_clear_selection(void);
|
||||
int speakup_set_selection(struct tty_struct *tty);
|
||||
void speakup_cancel_selection(void);
|
||||
int speakup_paste_selection(struct tty_struct *tty);
|
||||
|
|
|
|||
|
|
@ -298,11 +298,13 @@ static unsigned char ttyio_in(int timeout)
|
|||
struct spk_ldisc_data *ldisc_data = speakup_tty->disc_data;
|
||||
char rv;
|
||||
|
||||
if (wait_for_completion_timeout(&ldisc_data->completion,
|
||||
if (!timeout) {
|
||||
if (!try_wait_for_completion(&ldisc_data->completion))
|
||||
return 0xff;
|
||||
} else if (wait_for_completion_timeout(&ldisc_data->completion,
|
||||
usecs_to_jiffies(timeout)) == 0) {
|
||||
if (timeout)
|
||||
pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
|
||||
timeout);
|
||||
pr_warn("spk_ttyio: timeout (%d) while waiting for input\n",
|
||||
timeout);
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ enum {
|
|||
E_NEW_DEFAULT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: add new members at the end, speakupmap.h depends on the values of the
|
||||
* enum starting from SPELL_DELAY (see inc_dec_var)
|
||||
*/
|
||||
enum var_id_t {
|
||||
VERSION = 0, SYNTH, SILENT, SYNTH_DIRECT,
|
||||
KEYMAP, CHARS,
|
||||
|
|
@ -42,9 +46,9 @@ enum var_id_t {
|
|||
SAY_CONTROL, SAY_WORD_CTL, NO_INTERRUPT, KEY_ECHO,
|
||||
SPELL_DELAY, PUNC_LEVEL, READING_PUNC,
|
||||
ATTRIB_BLEEP, BLEEPS,
|
||||
RATE, PITCH, INFLECTION, VOL, TONE, PUNCT, VOICE, FREQUENCY, LANG,
|
||||
RATE, PITCH, VOL, TONE, PUNCT, VOICE, FREQUENCY, LANG,
|
||||
DIRECT, PAUSE,
|
||||
CAPS_START, CAPS_STOP, CHARTAB,
|
||||
CAPS_START, CAPS_STOP, CHARTAB, INFLECTION,
|
||||
MAXVARS
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -435,12 +435,12 @@ static struct port_buffer *alloc_buf(struct virtio_device *vdev, size_t buf_size
|
|||
/*
|
||||
* Allocate DMA memory from ancestor. When a virtio
|
||||
* device is created by remoteproc, the DMA memory is
|
||||
* associated with the grandparent device:
|
||||
* vdev => rproc => platform-dev.
|
||||
* associated with the parent device:
|
||||
* virtioY => remoteprocX#vdevYbuffer.
|
||||
*/
|
||||
if (!vdev->dev.parent || !vdev->dev.parent->parent)
|
||||
buf->dev = vdev->dev.parent;
|
||||
if (!buf->dev)
|
||||
goto free_buf;
|
||||
buf->dev = vdev->dev.parent->parent;
|
||||
|
||||
/* Increase device refcnt to avoid freeing it */
|
||||
get_device(buf->dev);
|
||||
|
|
|
|||
|
|
@ -147,6 +147,9 @@ static int zynqmp_pm_feature(u32 api_id)
|
|||
return 0;
|
||||
|
||||
/* Return value if feature is already checked */
|
||||
if (api_id > ARRAY_SIZE(zynqmp_pm_features))
|
||||
return PM_FEATURE_INVALID;
|
||||
|
||||
if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
|
||||
return zynqmp_pm_features[api_id];
|
||||
|
||||
|
|
|
|||
|
|
@ -333,6 +333,11 @@ static void dmar_pci_bus_del_dev(struct dmar_pci_notify_info *info)
|
|||
dmar_iommu_notify_scope_dev(info);
|
||||
}
|
||||
|
||||
static inline void vf_inherit_msi_domain(struct pci_dev *pdev)
|
||||
{
|
||||
dev_set_msi_domain(&pdev->dev, dev_get_msi_domain(&pdev->physfn->dev));
|
||||
}
|
||||
|
||||
static int dmar_pci_bus_notifier(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
|
|
@ -342,8 +347,20 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
|
|||
/* Only care about add/remove events for physical functions.
|
||||
* For VFs we actually do the lookup based on the corresponding
|
||||
* PF in device_to_iommu() anyway. */
|
||||
if (pdev->is_virtfn)
|
||||
if (pdev->is_virtfn) {
|
||||
/*
|
||||
* Ensure that the VF device inherits the irq domain of the
|
||||
* PF device. Ideally the device would inherit the domain
|
||||
* from the bus, but DMAR can have multiple units per bus
|
||||
* which makes this impossible. The VF 'bus' could inherit
|
||||
* from the PF device, but that's yet another x86'sism to
|
||||
* inflict on everybody else.
|
||||
*/
|
||||
if (action == BUS_NOTIFY_ADD_DEVICE)
|
||||
vf_inherit_msi_domain(pdev);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
if (action != BUS_NOTIFY_ADD_DEVICE &&
|
||||
action != BUS_NOTIFY_REMOVED_DEVICE)
|
||||
return NOTIFY_DONE;
|
||||
|
|
|
|||
|
|
@ -142,11 +142,10 @@ static void cb_fini(struct hl_device *hdev, struct hl_cb *cb)
|
|||
{
|
||||
if (cb->is_internal)
|
||||
gen_pool_free(hdev->internal_cb_pool,
|
||||
cb->kernel_address, cb->size);
|
||||
(uintptr_t)cb->kernel_address, cb->size);
|
||||
else
|
||||
hdev->asic_funcs->asic_dma_free_coherent(hdev, cb->size,
|
||||
(void *) (uintptr_t) cb->kernel_address,
|
||||
cb->bus_address);
|
||||
cb->kernel_address, cb->bus_address);
|
||||
|
||||
kfree(cb);
|
||||
}
|
||||
|
|
@ -230,7 +229,7 @@ static struct hl_cb *hl_cb_alloc(struct hl_device *hdev, u32 cb_size,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
cb->kernel_address = (u64) (uintptr_t) p;
|
||||
cb->kernel_address = p;
|
||||
cb->size = cb_size;
|
||||
|
||||
return cb;
|
||||
|
|
@ -509,7 +508,7 @@ int hl_cb_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma)
|
|||
|
||||
vma->vm_private_data = cb;
|
||||
|
||||
rc = hdev->asic_funcs->cb_mmap(hdev, vma, (void *) cb->kernel_address,
|
||||
rc = hdev->asic_funcs->cb_mmap(hdev, vma, cb->kernel_address,
|
||||
cb->bus_address, cb->size);
|
||||
if (rc) {
|
||||
spin_lock(&cb->lock);
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ struct hl_cb {
|
|||
struct list_head pool_list;
|
||||
struct list_head va_block_list;
|
||||
u64 id;
|
||||
u64 kernel_address;
|
||||
void *kernel_address;
|
||||
dma_addr_t bus_address;
|
||||
u32 mmap_size;
|
||||
u32 size;
|
||||
|
|
@ -515,7 +515,7 @@ struct hl_hw_queue {
|
|||
struct hl_hw_sob hw_sob[HL_RSVD_SOBS];
|
||||
struct hl_cs_job **shadow_queue;
|
||||
enum hl_queue_type queue_type;
|
||||
u64 kernel_address;
|
||||
void *kernel_address;
|
||||
dma_addr_t bus_address;
|
||||
u32 pi;
|
||||
atomic_t ci;
|
||||
|
|
@ -544,7 +544,7 @@ struct hl_hw_queue {
|
|||
*/
|
||||
struct hl_cq {
|
||||
struct hl_device *hdev;
|
||||
u64 kernel_address;
|
||||
void *kernel_address;
|
||||
dma_addr_t bus_address;
|
||||
u32 cq_idx;
|
||||
u32 hw_queue_id;
|
||||
|
|
@ -562,7 +562,7 @@ struct hl_cq {
|
|||
*/
|
||||
struct hl_eq {
|
||||
struct hl_device *hdev;
|
||||
u64 kernel_address;
|
||||
void *kernel_address;
|
||||
dma_addr_t bus_address;
|
||||
u32 ci;
|
||||
};
|
||||
|
|
@ -757,7 +757,7 @@ struct hl_asic_funcs {
|
|||
u32 (*get_dma_desc_list_size)(struct hl_device *hdev,
|
||||
struct sg_table *sgt);
|
||||
void (*add_end_of_cb_packets)(struct hl_device *hdev,
|
||||
u64 kernel_address, u32 len,
|
||||
void *kernel_address, u32 len,
|
||||
u64 cq_addr, u32 cq_val, u32 msix_num,
|
||||
bool eb);
|
||||
void (*update_eq_ci)(struct hl_device *hdev, u32 val);
|
||||
|
|
@ -1382,13 +1382,13 @@ void hl_wreg(struct hl_device *hdev, u32 reg, u32 val);
|
|||
for (;;) { \
|
||||
/* Verify we read updates done by other cores or by device */ \
|
||||
mb(); \
|
||||
(val) = *((u32 *) (uintptr_t) (addr)); \
|
||||
(val) = *((u32 *)(addr)); \
|
||||
if (mem_written_by_device) \
|
||||
(val) = le32_to_cpu(*(__le32 *) &(val)); \
|
||||
if (cond) \
|
||||
break; \
|
||||
if (timeout_us && ktime_compare(ktime_get(), __timeout) > 0) { \
|
||||
(val) = *((u32 *) (uintptr_t) (addr)); \
|
||||
(val) = *((u32 *)(addr)); \
|
||||
if (mem_written_by_device) \
|
||||
(val) = le32_to_cpu(*(__le32 *) &(val)); \
|
||||
break; \
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ static void ext_and_hw_queue_submit_bd(struct hl_device *hdev,
|
|||
{
|
||||
struct hl_bd *bd;
|
||||
|
||||
bd = (struct hl_bd *) (uintptr_t) q->kernel_address;
|
||||
bd = q->kernel_address;
|
||||
bd += hl_pi_2_offset(q->pi);
|
||||
bd->ctl = cpu_to_le32(ctl);
|
||||
bd->len = cpu_to_le32(len);
|
||||
|
|
@ -335,8 +335,7 @@ static void int_queue_schedule_job(struct hl_cs_job *job)
|
|||
bd.len = cpu_to_le32(job->job_cb_size);
|
||||
bd.ptr = cpu_to_le64((u64) (uintptr_t) job->user_cb);
|
||||
|
||||
pi = (__le64 *) (uintptr_t) (q->kernel_address +
|
||||
((q->pi & (q->int_queue_len - 1)) * sizeof(bd)));
|
||||
pi = q->kernel_address + (q->pi & (q->int_queue_len - 1)) * sizeof(bd);
|
||||
|
||||
q->pi++;
|
||||
q->pi &= ((q->int_queue_len << 1) - 1);
|
||||
|
|
@ -630,7 +629,7 @@ static int ext_and_cpu_queue_init(struct hl_device *hdev, struct hl_hw_queue *q,
|
|||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
q->kernel_address = (u64) (uintptr_t) p;
|
||||
q->kernel_address = p;
|
||||
|
||||
q->shadow_queue = kmalloc_array(HL_QUEUE_LENGTH,
|
||||
sizeof(*q->shadow_queue),
|
||||
|
|
@ -653,11 +652,11 @@ static int ext_and_cpu_queue_init(struct hl_device *hdev, struct hl_hw_queue *q,
|
|||
if (is_cpu_queue)
|
||||
hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
|
||||
HL_QUEUE_SIZE_IN_BYTES,
|
||||
(void *) (uintptr_t) q->kernel_address);
|
||||
q->kernel_address);
|
||||
else
|
||||
hdev->asic_funcs->asic_dma_free_coherent(hdev,
|
||||
HL_QUEUE_SIZE_IN_BYTES,
|
||||
(void *) (uintptr_t) q->kernel_address,
|
||||
q->kernel_address,
|
||||
q->bus_address);
|
||||
|
||||
return rc;
|
||||
|
|
@ -676,7 +675,7 @@ static int int_queue_init(struct hl_device *hdev, struct hl_hw_queue *q)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
q->kernel_address = (u64) (uintptr_t) p;
|
||||
q->kernel_address = p;
|
||||
q->pi = 0;
|
||||
atomic_set(&q->ci, 0);
|
||||
|
||||
|
|
@ -704,7 +703,7 @@ static int hw_queue_init(struct hl_device *hdev, struct hl_hw_queue *q)
|
|||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
q->kernel_address = (u64) (uintptr_t) p;
|
||||
q->kernel_address = p;
|
||||
|
||||
/* Make sure read/write pointers are initialized to start of queue */
|
||||
atomic_set(&q->ci, 0);
|
||||
|
|
@ -839,11 +838,11 @@ static void queue_fini(struct hl_device *hdev, struct hl_hw_queue *q)
|
|||
if (q->queue_type == QUEUE_TYPE_CPU)
|
||||
hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
|
||||
HL_QUEUE_SIZE_IN_BYTES,
|
||||
(void *) (uintptr_t) q->kernel_address);
|
||||
q->kernel_address);
|
||||
else
|
||||
hdev->asic_funcs->asic_dma_free_coherent(hdev,
|
||||
HL_QUEUE_SIZE_IN_BYTES,
|
||||
(void *) (uintptr_t) q->kernel_address,
|
||||
q->kernel_address,
|
||||
q->bus_address);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ irqreturn_t hl_irq_handler_cq(int irq, void *arg)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
cq_base = (struct hl_cq_entry *) (uintptr_t) cq->kernel_address;
|
||||
cq_base = cq->kernel_address;
|
||||
|
||||
while (1) {
|
||||
bool entry_ready = ((le32_to_cpu(cq_base[cq->ci].data) &
|
||||
|
|
@ -152,7 +152,7 @@ irqreturn_t hl_irq_handler_eq(int irq, void *arg)
|
|||
struct hl_eq_entry *eq_base;
|
||||
struct hl_eqe_work *handle_eqe_work;
|
||||
|
||||
eq_base = (struct hl_eq_entry *) (uintptr_t) eq->kernel_address;
|
||||
eq_base = eq->kernel_address;
|
||||
|
||||
while (1) {
|
||||
bool entry_ready =
|
||||
|
|
@ -221,7 +221,7 @@ int hl_cq_init(struct hl_device *hdev, struct hl_cq *q, u32 hw_queue_id)
|
|||
return -ENOMEM;
|
||||
|
||||
q->hdev = hdev;
|
||||
q->kernel_address = (u64) (uintptr_t) p;
|
||||
q->kernel_address = p;
|
||||
q->hw_queue_id = hw_queue_id;
|
||||
q->ci = 0;
|
||||
q->pi = 0;
|
||||
|
|
@ -242,7 +242,8 @@ int hl_cq_init(struct hl_device *hdev, struct hl_cq *q, u32 hw_queue_id)
|
|||
void hl_cq_fini(struct hl_device *hdev, struct hl_cq *q)
|
||||
{
|
||||
hdev->asic_funcs->asic_dma_free_coherent(hdev, HL_CQ_SIZE_IN_BYTES,
|
||||
(void *) (uintptr_t) q->kernel_address, q->bus_address);
|
||||
q->kernel_address,
|
||||
q->bus_address);
|
||||
}
|
||||
|
||||
void hl_cq_reset(struct hl_device *hdev, struct hl_cq *q)
|
||||
|
|
@ -259,7 +260,7 @@ void hl_cq_reset(struct hl_device *hdev, struct hl_cq *q)
|
|||
* when the device is operational again
|
||||
*/
|
||||
|
||||
memset((void *) (uintptr_t) q->kernel_address, 0, HL_CQ_SIZE_IN_BYTES);
|
||||
memset(q->kernel_address, 0, HL_CQ_SIZE_IN_BYTES);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -282,7 +283,7 @@ int hl_eq_init(struct hl_device *hdev, struct hl_eq *q)
|
|||
return -ENOMEM;
|
||||
|
||||
q->hdev = hdev;
|
||||
q->kernel_address = (u64) (uintptr_t) p;
|
||||
q->kernel_address = p;
|
||||
q->ci = 0;
|
||||
|
||||
return 0;
|
||||
|
|
@ -302,7 +303,7 @@ void hl_eq_fini(struct hl_device *hdev, struct hl_eq *q)
|
|||
|
||||
hdev->asic_funcs->cpu_accessible_dma_pool_free(hdev,
|
||||
HL_EQ_SIZE_IN_BYTES,
|
||||
(void *) (uintptr_t) q->kernel_address);
|
||||
q->kernel_address);
|
||||
}
|
||||
|
||||
void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q)
|
||||
|
|
@ -316,5 +317,5 @@ void hl_eq_reset(struct hl_device *hdev, struct hl_eq *q)
|
|||
* when the device is operational again
|
||||
*/
|
||||
|
||||
memset((void *) (uintptr_t) q->kernel_address, 0, HL_EQ_SIZE_IN_BYTES);
|
||||
memset(q->kernel_address, 0, HL_EQ_SIZE_IN_BYTES);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -680,8 +680,7 @@ static int _gaudi_init_tpc_mem(struct hl_device *hdev,
|
|||
if (!cb)
|
||||
return -EFAULT;
|
||||
|
||||
init_tpc_mem_pkt = (struct packet_lin_dma *) (uintptr_t)
|
||||
cb->kernel_address;
|
||||
init_tpc_mem_pkt = cb->kernel_address;
|
||||
cb_size = sizeof(*init_tpc_mem_pkt);
|
||||
memset(init_tpc_mem_pkt, 0, cb_size);
|
||||
|
||||
|
|
@ -3811,8 +3810,7 @@ static int gaudi_validate_cb(struct hl_device *hdev,
|
|||
u16 pkt_size;
|
||||
struct gaudi_packet *user_pkt;
|
||||
|
||||
user_pkt = (struct gaudi_packet *) (uintptr_t)
|
||||
(parser->user_cb->kernel_address + cb_parsed_length);
|
||||
user_pkt = parser->user_cb->kernel_address + cb_parsed_length;
|
||||
|
||||
pkt_id = (enum packet_id) (
|
||||
(le64_to_cpu(user_pkt->header) &
|
||||
|
|
@ -4035,11 +4033,9 @@ static int gaudi_patch_cb(struct hl_device *hdev,
|
|||
u32 new_pkt_size = 0;
|
||||
struct gaudi_packet *user_pkt, *kernel_pkt;
|
||||
|
||||
user_pkt = (struct gaudi_packet *) (uintptr_t)
|
||||
(parser->user_cb->kernel_address + cb_parsed_length);
|
||||
kernel_pkt = (struct gaudi_packet *) (uintptr_t)
|
||||
(parser->patched_cb->kernel_address +
|
||||
cb_patched_cur_length);
|
||||
user_pkt = parser->user_cb->kernel_address + cb_parsed_length;
|
||||
kernel_pkt = parser->patched_cb->kernel_address +
|
||||
cb_patched_cur_length;
|
||||
|
||||
pkt_id = (enum packet_id) (
|
||||
(le64_to_cpu(user_pkt->header) &
|
||||
|
|
@ -4155,8 +4151,8 @@ static int gaudi_parse_cb_mmu(struct hl_device *hdev,
|
|||
* The check that parser->user_cb_size <= parser->user_cb->size was done
|
||||
* in validate_queue_index().
|
||||
*/
|
||||
memcpy((void *) (uintptr_t) parser->patched_cb->kernel_address,
|
||||
(void *) (uintptr_t) parser->user_cb->kernel_address,
|
||||
memcpy(parser->patched_cb->kernel_address,
|
||||
parser->user_cb->kernel_address,
|
||||
parser->user_cb_size);
|
||||
|
||||
patched_cb_size = parser->patched_cb_size;
|
||||
|
|
@ -4290,7 +4286,7 @@ static int gaudi_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser)
|
|||
}
|
||||
|
||||
static void gaudi_add_end_of_cb_packets(struct hl_device *hdev,
|
||||
u64 kernel_address, u32 len,
|
||||
void *kernel_address, u32 len,
|
||||
u64 cq_addr, u32 cq_val, u32 msi_vec,
|
||||
bool eb)
|
||||
{
|
||||
|
|
@ -4298,8 +4294,7 @@ static void gaudi_add_end_of_cb_packets(struct hl_device *hdev,
|
|||
struct packet_msg_prot *cq_pkt;
|
||||
u32 tmp;
|
||||
|
||||
cq_pkt = (struct packet_msg_prot *) (uintptr_t)
|
||||
(kernel_address + len - (sizeof(struct packet_msg_prot) * 2));
|
||||
cq_pkt = kernel_address + len - (sizeof(struct packet_msg_prot) * 2);
|
||||
|
||||
tmp = FIELD_PREP(GAUDI_PKT_CTL_OPCODE_MASK, PACKET_MSG_PROT);
|
||||
tmp |= FIELD_PREP(GAUDI_PKT_CTL_MB_MASK, 1);
|
||||
|
|
@ -4342,7 +4337,7 @@ static int gaudi_memset_device_memory(struct hl_device *hdev, u64 addr,
|
|||
if (!cb)
|
||||
return -EFAULT;
|
||||
|
||||
lin_dma_pkt = (struct packet_lin_dma *) (uintptr_t) cb->kernel_address;
|
||||
lin_dma_pkt = cb->kernel_address;
|
||||
memset(lin_dma_pkt, 0, sizeof(*lin_dma_pkt));
|
||||
cb_size = sizeof(*lin_dma_pkt);
|
||||
|
||||
|
|
@ -4747,7 +4742,7 @@ static void gaudi_write_pte(struct hl_device *hdev, u64 addr, u64 val)
|
|||
(addr - gaudi->hbm_bar_cur_addr));
|
||||
}
|
||||
|
||||
static void gaudi_mmu_prepare_reg(struct hl_device *hdev, u64 reg, u32 asid)
|
||||
void gaudi_mmu_prepare_reg(struct hl_device *hdev, u64 reg, u32 asid)
|
||||
{
|
||||
/* mask to zero the MMBP and ASID bits */
|
||||
WREG32_AND(reg, ~0x7FF);
|
||||
|
|
@ -4915,9 +4910,6 @@ static void gaudi_mmu_prepare(struct hl_device *hdev, u32 asid)
|
|||
gaudi_mmu_prepare_reg(hdev, mmMME2_ACC_WBC, asid);
|
||||
gaudi_mmu_prepare_reg(hdev, mmMME3_ACC_WBC, asid);
|
||||
|
||||
gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_ARUSER, asid);
|
||||
gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_AWUSER, asid);
|
||||
|
||||
hdev->asic_funcs->set_clock_gating(hdev);
|
||||
|
||||
mutex_unlock(&gaudi->clk_gate_mutex);
|
||||
|
|
@ -4954,8 +4946,8 @@ static int gaudi_send_job_on_qman0(struct hl_device *hdev,
|
|||
|
||||
cb = job->patched_cb;
|
||||
|
||||
fence_pkt = (struct packet_msg_prot *) (uintptr_t) (cb->kernel_address +
|
||||
job->job_cb_size - sizeof(struct packet_msg_prot));
|
||||
fence_pkt = cb->kernel_address +
|
||||
job->job_cb_size - sizeof(struct packet_msg_prot);
|
||||
|
||||
tmp = FIELD_PREP(GAUDI_PKT_CTL_OPCODE_MASK, PACKET_MSG_PROT);
|
||||
tmp |= FIELD_PREP(GAUDI_PKT_CTL_EB_MASK, 1);
|
||||
|
|
@ -6386,7 +6378,7 @@ static void gaudi_gen_signal_cb(struct hl_device *hdev, void *data, u16 sob_id)
|
|||
struct packet_msg_short *pkt;
|
||||
u32 value, ctl;
|
||||
|
||||
pkt = (struct packet_msg_short *) (uintptr_t) cb->kernel_address;
|
||||
pkt = cb->kernel_address;
|
||||
memset(pkt, 0, sizeof(*pkt));
|
||||
|
||||
/* Inc by 1, Mode ADD */
|
||||
|
|
@ -6478,7 +6470,7 @@ static void gaudi_gen_wait_cb(struct hl_device *hdev, void *data, u16 sob_id,
|
|||
u16 sob_val, u16 mon_id, u32 q_idx)
|
||||
{
|
||||
struct hl_cb *cb = (struct hl_cb *) data;
|
||||
void *buf = (void *) (uintptr_t) cb->kernel_address;
|
||||
void *buf = cb->kernel_address;
|
||||
u64 monitor_base, fence_addr = 0;
|
||||
u32 size = 0;
|
||||
u16 msg_addr_offset;
|
||||
|
|
|
|||
|
|
@ -271,5 +271,6 @@ void gaudi_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq);
|
|||
int gaudi_debug_coresight(struct hl_device *hdev, void *data);
|
||||
void gaudi_halt_coresight(struct hl_device *hdev);
|
||||
int gaudi_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk);
|
||||
void gaudi_mmu_prepare_reg(struct hl_device *hdev, u64 reg, u32 asid);
|
||||
|
||||
#endif /* GAUDIP_H_ */
|
||||
|
|
|
|||
|
|
@ -623,6 +623,11 @@ static int gaudi_config_etr(struct hl_device *hdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_ARUSER,
|
||||
hdev->compute_ctx->asid);
|
||||
gaudi_mmu_prepare_reg(hdev, mmPSOC_GLOBAL_CONF_TRACE_AWUSER,
|
||||
hdev->compute_ctx->asid);
|
||||
|
||||
msb = upper_32_bits(input->buffer_address) >> 8;
|
||||
msb &= PSOC_GLOBAL_CONF_TRACE_ADDR_MSB_MASK;
|
||||
WREG32(mmPSOC_GLOBAL_CONF_TRACE_ADDR, msb);
|
||||
|
|
|
|||
|
|
@ -2882,8 +2882,8 @@ static int goya_send_job_on_qman0(struct hl_device *hdev, struct hl_cs_job *job)
|
|||
|
||||
cb = job->patched_cb;
|
||||
|
||||
fence_pkt = (struct packet_msg_prot *) (uintptr_t) (cb->kernel_address +
|
||||
job->job_cb_size - sizeof(struct packet_msg_prot));
|
||||
fence_pkt = cb->kernel_address +
|
||||
job->job_cb_size - sizeof(struct packet_msg_prot);
|
||||
|
||||
tmp = (PACKET_MSG_PROT << GOYA_PKT_CTL_OPCODE_SHIFT) |
|
||||
(1 << GOYA_PKT_CTL_EB_SHIFT) |
|
||||
|
|
@ -3475,8 +3475,7 @@ static int goya_validate_cb(struct hl_device *hdev,
|
|||
u16 pkt_size;
|
||||
struct goya_packet *user_pkt;
|
||||
|
||||
user_pkt = (struct goya_packet *) (uintptr_t)
|
||||
(parser->user_cb->kernel_address + cb_parsed_length);
|
||||
user_pkt = parser->user_cb->kernel_address + cb_parsed_length;
|
||||
|
||||
pkt_id = (enum packet_id) (
|
||||
(le64_to_cpu(user_pkt->header) &
|
||||
|
|
@ -3713,11 +3712,9 @@ static int goya_patch_cb(struct hl_device *hdev,
|
|||
u32 new_pkt_size = 0;
|
||||
struct goya_packet *user_pkt, *kernel_pkt;
|
||||
|
||||
user_pkt = (struct goya_packet *) (uintptr_t)
|
||||
(parser->user_cb->kernel_address + cb_parsed_length);
|
||||
kernel_pkt = (struct goya_packet *) (uintptr_t)
|
||||
(parser->patched_cb->kernel_address +
|
||||
cb_patched_cur_length);
|
||||
user_pkt = parser->user_cb->kernel_address + cb_parsed_length;
|
||||
kernel_pkt = parser->patched_cb->kernel_address +
|
||||
cb_patched_cur_length;
|
||||
|
||||
pkt_id = (enum packet_id) (
|
||||
(le64_to_cpu(user_pkt->header) &
|
||||
|
|
@ -3841,8 +3838,8 @@ static int goya_parse_cb_mmu(struct hl_device *hdev,
|
|||
* The check that parser->user_cb_size <= parser->user_cb->size was done
|
||||
* in validate_queue_index().
|
||||
*/
|
||||
memcpy((void *) (uintptr_t) parser->patched_cb->kernel_address,
|
||||
(void *) (uintptr_t) parser->user_cb->kernel_address,
|
||||
memcpy(parser->patched_cb->kernel_address,
|
||||
parser->user_cb->kernel_address,
|
||||
parser->user_cb_size);
|
||||
|
||||
patched_cb_size = parser->patched_cb_size;
|
||||
|
|
@ -3974,15 +3971,14 @@ int goya_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser)
|
|||
return goya_parse_cb_no_mmu(hdev, parser);
|
||||
}
|
||||
|
||||
void goya_add_end_of_cb_packets(struct hl_device *hdev, u64 kernel_address,
|
||||
void goya_add_end_of_cb_packets(struct hl_device *hdev, void *kernel_address,
|
||||
u32 len, u64 cq_addr, u32 cq_val, u32 msix_vec,
|
||||
bool eb)
|
||||
{
|
||||
struct packet_msg_prot *cq_pkt;
|
||||
u32 tmp;
|
||||
|
||||
cq_pkt = (struct packet_msg_prot *) (uintptr_t)
|
||||
(kernel_address + len - (sizeof(struct packet_msg_prot) * 2));
|
||||
cq_pkt = kernel_address + len - (sizeof(struct packet_msg_prot) * 2);
|
||||
|
||||
tmp = (PACKET_MSG_PROT << GOYA_PKT_CTL_OPCODE_SHIFT) |
|
||||
(1 << GOYA_PKT_CTL_EB_SHIFT) |
|
||||
|
|
@ -4746,7 +4742,7 @@ static int goya_memset_device_memory(struct hl_device *hdev, u64 addr, u64 size,
|
|||
if (!cb)
|
||||
return -ENOMEM;
|
||||
|
||||
lin_dma_pkt = (struct packet_lin_dma *) (uintptr_t) cb->kernel_address;
|
||||
lin_dma_pkt = cb->kernel_address;
|
||||
|
||||
do {
|
||||
memset(lin_dma_pkt, 0, sizeof(*lin_dma_pkt));
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ int goya_resume(struct hl_device *hdev);
|
|||
void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry);
|
||||
void *goya_get_events_stat(struct hl_device *hdev, bool aggregate, u32 *size);
|
||||
|
||||
void goya_add_end_of_cb_packets(struct hl_device *hdev, u64 kernel_address,
|
||||
void goya_add_end_of_cb_packets(struct hl_device *hdev, void *kernel_address,
|
||||
u32 len, u64 cq_addr, u32 cq_val, u32 msix_vec,
|
||||
bool eb);
|
||||
int goya_cs_parser(struct hl_device *hdev, struct hl_cs_parser *parser);
|
||||
|
|
|
|||
|
|
@ -421,7 +421,6 @@ enum axi_id {
|
|||
|
||||
#define QM_ARB_ERR_MSG_EN_MASK (\
|
||||
QM_ARB_ERR_MSG_EN_CHOISE_OVF_MASK |\
|
||||
QM_ARB_ERR_MSG_EN_CHOISE_WDT_MASK |\
|
||||
QM_ARB_ERR_MSG_EN_AXI_LBW_ERR_MASK)
|
||||
|
||||
#define PCIE_AUX_FLR_CTRL_HW_CTRL_MASK 0x1
|
||||
|
|
|
|||
|
|
@ -182,11 +182,11 @@ static inline u8 mei_cl_me_id(const struct mei_cl *cl)
|
|||
*
|
||||
* @cl: host client
|
||||
*
|
||||
* Return: mtu
|
||||
* Return: mtu or 0 if client is not connected
|
||||
*/
|
||||
static inline size_t mei_cl_mtu(const struct mei_cl *cl)
|
||||
{
|
||||
return cl->me_cl->props.max_msg_length;
|
||||
return cl->me_cl ? cl->me_cl->props.max_msg_length : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "tb.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -2284,6 +2284,8 @@ struct tb *icm_probe(struct tb_nhi *nhi)
|
|||
|
||||
case PCI_DEVICE_ID_INTEL_TGL_NHI0:
|
||||
case PCI_DEVICE_ID_INTEL_TGL_NHI1:
|
||||
case PCI_DEVICE_ID_INTEL_TGL_H_NHI0:
|
||||
case PCI_DEVICE_ID_INTEL_TGL_H_NHI1:
|
||||
icm->is_supported = icm_tgl_is_supported;
|
||||
icm->driver_ready = icm_icl_driver_ready;
|
||||
icm->set_uuid = icm_icl_set_uuid;
|
||||
|
|
|
|||
|
|
@ -406,12 +406,23 @@ static int ring_request_msix(struct tb_ring *ring, bool no_suspend)
|
|||
|
||||
ring->vector = ret;
|
||||
|
||||
ring->irq = pci_irq_vector(ring->nhi->pdev, ring->vector);
|
||||
if (ring->irq < 0)
|
||||
return ring->irq;
|
||||
ret = pci_irq_vector(ring->nhi->pdev, ring->vector);
|
||||
if (ret < 0)
|
||||
goto err_ida_remove;
|
||||
|
||||
ring->irq = ret;
|
||||
|
||||
irqflags = no_suspend ? IRQF_NO_SUSPEND : 0;
|
||||
return request_irq(ring->irq, ring_msix, irqflags, "thunderbolt", ring);
|
||||
ret = request_irq(ring->irq, ring_msix, irqflags, "thunderbolt", ring);
|
||||
if (ret)
|
||||
goto err_ida_remove;
|
||||
|
||||
return 0;
|
||||
|
||||
err_ida_remove:
|
||||
ida_simple_remove(&nhi->msix_ida, ring->vector);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ring_release_msix(struct tb_ring *ring)
|
||||
|
|
@ -1334,6 +1345,10 @@ static struct pci_device_id nhi_ids[] = {
|
|||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_NHI1),
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_H_NHI0),
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGL_H_NHI1),
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
|
||||
/* Any USB4 compliant host */
|
||||
{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_USB4, ~0) },
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ extern const struct tb_nhi_ops icl_nhi_ops;
|
|||
#define PCI_DEVICE_ID_INTEL_ICL_NHI0 0x8a17
|
||||
#define PCI_DEVICE_ID_INTEL_TGL_NHI0 0x9a1b
|
||||
#define PCI_DEVICE_ID_INTEL_TGL_NHI1 0x9a1d
|
||||
#define PCI_DEVICE_ID_INTEL_TGL_H_NHI0 0x9a1f
|
||||
#define PCI_DEVICE_ID_INTEL_TGL_H_NHI1 0x9a21
|
||||
|
||||
#define PCI_CLASS_SERIAL_USB_USB4 0x0c0340
|
||||
|
||||
|
|
|
|||
|
|
@ -784,6 +784,8 @@ static inline bool tb_switch_is_tiger_lake(const struct tb_switch *sw)
|
|||
switch (sw->config.device_id) {
|
||||
case PCI_DEVICE_ID_INTEL_TGL_NHI0:
|
||||
case PCI_DEVICE_ID_INTEL_TGL_NHI1:
|
||||
case PCI_DEVICE_ID_INTEL_TGL_H_NHI0:
|
||||
case PCI_DEVICE_ID_INTEL_TGL_H_NHI1:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -421,8 +421,12 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags)
|
|||
* upstream USB4 port.
|
||||
*/
|
||||
tb_switch_for_each_port(sw, port) {
|
||||
if (!tb_port_is_null(port))
|
||||
continue;
|
||||
if (!route && tb_is_upstream_port(port))
|
||||
continue;
|
||||
if (!port->cap_usb4)
|
||||
continue;
|
||||
|
||||
ret = tb_port_read(port, &val, TB_CFG_PORT,
|
||||
port->cap_usb4 + PORT_CS_19, 1);
|
||||
|
|
|
|||
|
|
@ -881,6 +881,7 @@ static void enumerate_services(struct tb_xdomain *xd)
|
|||
|
||||
id = ida_simple_get(&xd->service_ids, 0, 0, GFP_KERNEL);
|
||||
if (id < 0) {
|
||||
kfree(svc->key);
|
||||
kfree(svc);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -413,10 +413,10 @@ static int uio_get_minor(struct uio_device *idev)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static void uio_free_minor(struct uio_device *idev)
|
||||
static void uio_free_minor(unsigned long minor)
|
||||
{
|
||||
mutex_lock(&minor_lock);
|
||||
idr_remove(&uio_idr, idev->minor);
|
||||
idr_remove(&uio_idr, minor);
|
||||
mutex_unlock(&minor_lock);
|
||||
}
|
||||
|
||||
|
|
@ -990,7 +990,7 @@ int __uio_register_device(struct module *owner,
|
|||
err_uio_dev_add_attributes:
|
||||
device_del(&idev->dev);
|
||||
err_device_create:
|
||||
uio_free_minor(idev);
|
||||
uio_free_minor(idev->minor);
|
||||
put_device(&idev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1042,11 +1042,13 @@ EXPORT_SYMBOL_GPL(__devm_uio_register_device);
|
|||
void uio_unregister_device(struct uio_info *info)
|
||||
{
|
||||
struct uio_device *idev;
|
||||
unsigned long minor;
|
||||
|
||||
if (!info || !info->uio_dev)
|
||||
return;
|
||||
|
||||
idev = info->uio_dev;
|
||||
minor = idev->minor;
|
||||
|
||||
mutex_lock(&idev->info_lock);
|
||||
uio_dev_del_attributes(idev);
|
||||
|
|
@ -1062,7 +1064,7 @@ void uio_unregister_device(struct uio_info *info)
|
|||
|
||||
device_unregister(&idev->dev);
|
||||
|
||||
uio_free_minor(idev);
|
||||
uio_free_minor(minor);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1693,6 +1693,15 @@ static const struct usb_device_id acm_ids[] = {
|
|||
{ USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
|
||||
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
|
||||
},
|
||||
{ USB_DEVICE(0x045b, 0x023c), /* Renesas USB Download mode */
|
||||
.driver_info = DISABLE_ECHO, /* Don't echo banner */
|
||||
},
|
||||
{ USB_DEVICE(0x045b, 0x0248), /* Renesas USB Download mode */
|
||||
.driver_info = DISABLE_ECHO, /* Don't echo banner */
|
||||
},
|
||||
{ USB_DEVICE(0x045b, 0x024D), /* Renesas USB Download mode */
|
||||
.driver_info = DISABLE_ECHO, /* Don't echo banner */
|
||||
},
|
||||
{ USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */
|
||||
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
|
||||
},
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ static int xhci_histb_probe(struct platform_device *pdev)
|
|||
/* Initialize dma_mask and coherent_dma_mask to 32-bits */
|
||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
return ret;
|
||||
goto disable_pm;
|
||||
|
||||
hcd = usb_create_hcd(driver, dev, dev_name(dev));
|
||||
if (!hcd) {
|
||||
|
|
|
|||
|
|
@ -429,10 +429,12 @@ static int dsps_musb_init(struct musb *musb)
|
|||
struct platform_device *parent = to_platform_device(dev->parent);
|
||||
const struct dsps_musb_wrapper *wrp = glue->wrp;
|
||||
void __iomem *reg_base;
|
||||
struct resource *r;
|
||||
u32 rev, val;
|
||||
int ret;
|
||||
|
||||
reg_base = devm_platform_ioremap_resource_byname(parent, "control");
|
||||
r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control");
|
||||
reg_base = devm_ioremap_resource(dev, r);
|
||||
if (IS_ERR(reg_base))
|
||||
return PTR_ERR(reg_base);
|
||||
musb->ctrl_base = reg_base;
|
||||
|
|
|
|||
|
|
@ -238,4 +238,13 @@ void ucsi_unregister_port_psy(struct ucsi_connector *con)
|
|||
return;
|
||||
|
||||
power_supply_unregister(con->psy);
|
||||
con->psy = NULL;
|
||||
}
|
||||
|
||||
void ucsi_port_psy_changed(struct ucsi_connector *con)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(con->psy))
|
||||
return;
|
||||
|
||||
power_supply_changed(con->psy);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -643,8 +643,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
|
|||
role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
|
||||
|
||||
if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE ||
|
||||
con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE)
|
||||
con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE) {
|
||||
ucsi_pwr_opmode_change(con);
|
||||
ucsi_port_psy_changed(con);
|
||||
}
|
||||
|
||||
if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
|
||||
typec_set_pwr_role(con->port, role);
|
||||
|
|
@ -674,6 +676,8 @@ static void ucsi_handle_connector_change(struct work_struct *work)
|
|||
ucsi_register_partner(con);
|
||||
else
|
||||
ucsi_unregister_partner(con);
|
||||
|
||||
ucsi_port_psy_changed(con);
|
||||
}
|
||||
|
||||
if (con->status.change & UCSI_CONSTAT_CAM_CHANGE) {
|
||||
|
|
@ -994,6 +998,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
|
|||
!!(con->status.flags & UCSI_CONSTAT_PWR_DIR));
|
||||
ucsi_pwr_opmode_change(con);
|
||||
ucsi_register_partner(con);
|
||||
ucsi_port_psy_changed(con);
|
||||
}
|
||||
|
||||
if (con->partner) {
|
||||
|
|
|
|||
|
|
@ -340,9 +340,11 @@ int ucsi_resume(struct ucsi *ucsi);
|
|||
#if IS_ENABLED(CONFIG_POWER_SUPPLY)
|
||||
int ucsi_register_port_psy(struct ucsi_connector *con);
|
||||
void ucsi_unregister_port_psy(struct ucsi_connector *con);
|
||||
void ucsi_port_psy_changed(struct ucsi_connector *con);
|
||||
#else
|
||||
static inline int ucsi_register_port_psy(struct ucsi_connector *con) { return 0; }
|
||||
static inline void ucsi_unregister_port_psy(struct ucsi_connector *con) { }
|
||||
static inline void ucsi_port_psy_changed(struct ucsi_connector *con) { }
|
||||
#endif /* CONFIG_POWER_SUPPLY */
|
||||
|
||||
#if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE)
|
||||
|
|
|
|||
|
|
@ -1505,10 +1505,8 @@ static __poll_t ne_enclave_poll(struct file *file, poll_table *wait)
|
|||
|
||||
poll_wait(file, &ne_enclave->eventq, wait);
|
||||
|
||||
if (!ne_enclave->has_event)
|
||||
return mask;
|
||||
|
||||
mask = POLLHUP;
|
||||
if (ne_enclave->has_event)
|
||||
mask |= EPOLLHUP;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,21 +114,21 @@ do { \
|
|||
|
||||
#define __this_cpu_generic_read_nopreempt(pcp) \
|
||||
({ \
|
||||
typeof(pcp) __ret; \
|
||||
typeof(pcp) ___ret; \
|
||||
preempt_disable_notrace(); \
|
||||
__ret = READ_ONCE(*raw_cpu_ptr(&(pcp))); \
|
||||
___ret = READ_ONCE(*raw_cpu_ptr(&(pcp))); \
|
||||
preempt_enable_notrace(); \
|
||||
__ret; \
|
||||
___ret; \
|
||||
})
|
||||
|
||||
#define __this_cpu_generic_read_noirq(pcp) \
|
||||
({ \
|
||||
typeof(pcp) __ret; \
|
||||
unsigned long __flags; \
|
||||
raw_local_irq_save(__flags); \
|
||||
__ret = raw_cpu_generic_read(pcp); \
|
||||
raw_local_irq_restore(__flags); \
|
||||
__ret; \
|
||||
typeof(pcp) ___ret; \
|
||||
unsigned long ___flags; \
|
||||
raw_local_irq_save(___flags); \
|
||||
___ret = raw_cpu_generic_read(pcp); \
|
||||
raw_local_irq_restore(___flags); \
|
||||
___ret; \
|
||||
})
|
||||
|
||||
#define this_cpu_generic_read(pcp) \
|
||||
|
|
|
|||
|
|
@ -1022,13 +1022,7 @@ struct perf_sample_data {
|
|||
struct perf_callchain_entry *callchain;
|
||||
u64 aux_size;
|
||||
|
||||
/*
|
||||
* regs_user may point to task_pt_regs or to regs_user_copy, depending
|
||||
* on arch details.
|
||||
*/
|
||||
struct perf_regs regs_user;
|
||||
struct pt_regs regs_user_copy;
|
||||
|
||||
struct perf_regs regs_intr;
|
||||
u64 stack_user_size;
|
||||
|
||||
|
|
@ -1400,11 +1394,14 @@ perf_event_addr_filters(struct perf_event *event)
|
|||
extern void perf_event_addr_filters_sync(struct perf_event *event);
|
||||
|
||||
extern int perf_output_begin(struct perf_output_handle *handle,
|
||||
struct perf_sample_data *data,
|
||||
struct perf_event *event, unsigned int size);
|
||||
extern int perf_output_begin_forward(struct perf_output_handle *handle,
|
||||
struct perf_event *event,
|
||||
unsigned int size);
|
||||
struct perf_sample_data *data,
|
||||
struct perf_event *event,
|
||||
unsigned int size);
|
||||
extern int perf_output_begin_backward(struct perf_output_handle *handle,
|
||||
struct perf_sample_data *data,
|
||||
struct perf_event *event,
|
||||
unsigned int size);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ u64 perf_reg_value(struct pt_regs *regs, int idx);
|
|||
int perf_reg_validate(u64 mask);
|
||||
u64 perf_reg_abi(struct task_struct *task);
|
||||
void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy);
|
||||
struct pt_regs *regs);
|
||||
#else
|
||||
|
||||
#define PERF_REG_EXTENDED_MASK 0
|
||||
|
|
@ -42,8 +41,7 @@ static inline u64 perf_reg_abi(struct task_struct *task)
|
|||
}
|
||||
|
||||
static inline void perf_get_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
regs_user->regs = task_pt_regs(current);
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
|
|
|
|||
|
|
@ -2312,9 +2312,6 @@ group_sched_out(struct perf_event *group_event,
|
|||
event_sched_out(event, cpuctx, ctx);
|
||||
|
||||
perf_pmu_enable(ctx->pmu);
|
||||
|
||||
if (group_event->attr.exclusive)
|
||||
cpuctx->exclusive = 0;
|
||||
}
|
||||
|
||||
#define DETACH_GROUP 0x01UL
|
||||
|
|
@ -2583,11 +2580,8 @@ group_sched_in(struct perf_event *group_event,
|
|||
|
||||
pmu->start_txn(pmu, PERF_PMU_TXN_ADD);
|
||||
|
||||
if (event_sched_in(group_event, cpuctx, ctx)) {
|
||||
pmu->cancel_txn(pmu);
|
||||
perf_mux_hrtimer_restart(cpuctx);
|
||||
return -EAGAIN;
|
||||
}
|
||||
if (event_sched_in(group_event, cpuctx, ctx))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Schedule in siblings as one group (if any):
|
||||
|
|
@ -2616,10 +2610,8 @@ group_sched_in(struct perf_event *group_event,
|
|||
}
|
||||
event_sched_out(group_event, cpuctx, ctx);
|
||||
|
||||
error:
|
||||
pmu->cancel_txn(pmu);
|
||||
|
||||
perf_mux_hrtimer_restart(cpuctx);
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
|
@ -2645,7 +2637,7 @@ static int group_can_go_on(struct perf_event *event,
|
|||
* If this group is exclusive and there are already
|
||||
* events on the CPU, it can't go on.
|
||||
*/
|
||||
if (event->attr.exclusive && cpuctx->active_oncpu)
|
||||
if (event->attr.exclusive && !list_empty(get_event_list(event)))
|
||||
return 0;
|
||||
/*
|
||||
* Otherwise, try to add it if all previous groups were able
|
||||
|
|
@ -3679,6 +3671,7 @@ static int merge_sched_in(struct perf_event *event, void *data)
|
|||
|
||||
*can_add_hw = 0;
|
||||
ctx->rotate_necessary = 1;
|
||||
perf_mux_hrtimer_restart(cpuctx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -6375,14 +6368,13 @@ perf_output_sample_regs(struct perf_output_handle *handle,
|
|||
}
|
||||
|
||||
static void perf_sample_regs_user(struct perf_regs *regs_user,
|
||||
struct pt_regs *regs,
|
||||
struct pt_regs *regs_user_copy)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (user_mode(regs)) {
|
||||
regs_user->abi = perf_reg_abi(current);
|
||||
regs_user->regs = regs;
|
||||
} else if (!(current->flags & PF_KTHREAD)) {
|
||||
perf_get_regs_user(regs_user, regs, regs_user_copy);
|
||||
perf_get_regs_user(regs_user, regs);
|
||||
} else {
|
||||
regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE;
|
||||
regs_user->regs = NULL;
|
||||
|
|
@ -7084,8 +7076,7 @@ void perf_prepare_sample(struct perf_event_header *header,
|
|||
}
|
||||
|
||||
if (sample_type & (PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER))
|
||||
perf_sample_regs_user(&data->regs_user, regs,
|
||||
&data->regs_user_copy);
|
||||
perf_sample_regs_user(&data->regs_user, regs);
|
||||
|
||||
if (sample_type & PERF_SAMPLE_REGS_USER) {
|
||||
/* regs dump ABI info */
|
||||
|
|
@ -7187,6 +7178,7 @@ __perf_event_output(struct perf_event *event,
|
|||
struct perf_sample_data *data,
|
||||
struct pt_regs *regs,
|
||||
int (*output_begin)(struct perf_output_handle *,
|
||||
struct perf_sample_data *,
|
||||
struct perf_event *,
|
||||
unsigned int))
|
||||
{
|
||||
|
|
@ -7199,7 +7191,7 @@ __perf_event_output(struct perf_event *event,
|
|||
|
||||
perf_prepare_sample(&header, data, event, regs);
|
||||
|
||||
err = output_begin(&handle, event, header.size);
|
||||
err = output_begin(&handle, data, event, header.size);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
|
|
@ -7265,7 +7257,7 @@ perf_event_read_event(struct perf_event *event,
|
|||
int ret;
|
||||
|
||||
perf_event_header__init_id(&read_event.header, &sample, event);
|
||||
ret = perf_output_begin(&handle, event, read_event.header.size);
|
||||
ret = perf_output_begin(&handle, &sample, event, read_event.header.size);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
|
|
@ -7534,7 +7526,7 @@ static void perf_event_task_output(struct perf_event *event,
|
|||
|
||||
perf_event_header__init_id(&task_event->event_id.header, &sample, event);
|
||||
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
task_event->event_id.header.size);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -7637,7 +7629,7 @@ static void perf_event_comm_output(struct perf_event *event,
|
|||
return;
|
||||
|
||||
perf_event_header__init_id(&comm_event->event_id.header, &sample, event);
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
comm_event->event_id.header.size);
|
||||
|
||||
if (ret)
|
||||
|
|
@ -7737,7 +7729,7 @@ static void perf_event_namespaces_output(struct perf_event *event,
|
|||
|
||||
perf_event_header__init_id(&namespaces_event->event_id.header,
|
||||
&sample, event);
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
namespaces_event->event_id.header.size);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -7864,7 +7856,7 @@ static void perf_event_cgroup_output(struct perf_event *event, void *data)
|
|||
|
||||
perf_event_header__init_id(&cgroup_event->event_id.header,
|
||||
&sample, event);
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
cgroup_event->event_id.header.size);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -7990,7 +7982,7 @@ static void perf_event_mmap_output(struct perf_event *event,
|
|||
}
|
||||
|
||||
perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
mmap_event->event_id.header.size);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
|
@ -8300,7 +8292,7 @@ void perf_event_aux_event(struct perf_event *event, unsigned long head,
|
|||
int ret;
|
||||
|
||||
perf_event_header__init_id(&rec.header, &sample, event);
|
||||
ret = perf_output_begin(&handle, event, rec.header.size);
|
||||
ret = perf_output_begin(&handle, &sample, event, rec.header.size);
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
|
@ -8334,7 +8326,7 @@ void perf_log_lost_samples(struct perf_event *event, u64 lost)
|
|||
|
||||
perf_event_header__init_id(&lost_samples_event.header, &sample, event);
|
||||
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
lost_samples_event.header.size);
|
||||
if (ret)
|
||||
return;
|
||||
|
|
@ -8389,7 +8381,7 @@ static void perf_event_switch_output(struct perf_event *event, void *data)
|
|||
|
||||
perf_event_header__init_id(&se->event_id.header, &sample, event);
|
||||
|
||||
ret = perf_output_begin(&handle, event, se->event_id.header.size);
|
||||
ret = perf_output_begin(&handle, &sample, event, se->event_id.header.size);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
|
|
@ -8464,7 +8456,7 @@ static void perf_log_throttle(struct perf_event *event, int enable)
|
|||
|
||||
perf_event_header__init_id(&throttle_event.header, &sample, event);
|
||||
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
throttle_event.header.size);
|
||||
if (ret)
|
||||
return;
|
||||
|
|
@ -8507,7 +8499,7 @@ static void perf_event_ksymbol_output(struct perf_event *event, void *data)
|
|||
|
||||
perf_event_header__init_id(&ksymbol_event->event_id.header,
|
||||
&sample, event);
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
ksymbol_event->event_id.header.size);
|
||||
if (ret)
|
||||
return;
|
||||
|
|
@ -8597,7 +8589,7 @@ static void perf_event_bpf_output(struct perf_event *event, void *data)
|
|||
|
||||
perf_event_header__init_id(&bpf_event->event_id.header,
|
||||
&sample, event);
|
||||
ret = perf_output_begin(&handle, event,
|
||||
ret = perf_output_begin(&handle, data, event,
|
||||
bpf_event->event_id.header.size);
|
||||
if (ret)
|
||||
return;
|
||||
|
|
@ -8706,7 +8698,8 @@ static void perf_event_text_poke_output(struct perf_event *event, void *data)
|
|||
|
||||
perf_event_header__init_id(&text_poke_event->event_id.header, &sample, event);
|
||||
|
||||
ret = perf_output_begin(&handle, event, text_poke_event->event_id.header.size);
|
||||
ret = perf_output_begin(&handle, &sample, event,
|
||||
text_poke_event->event_id.header.size);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
|
|
@ -8787,7 +8780,7 @@ static void perf_log_itrace_start(struct perf_event *event)
|
|||
rec.tid = perf_event_tid(event, current);
|
||||
|
||||
perf_event_header__init_id(&rec.header, &sample, event);
|
||||
ret = perf_output_begin(&handle, event, rec.header.size);
|
||||
ret = perf_output_begin(&handle, &sample, event, rec.header.size);
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -205,16 +205,12 @@ DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user)
|
|||
|
||||
static inline int get_recursion_context(int *recursion)
|
||||
{
|
||||
int rctx;
|
||||
unsigned int pc = preempt_count();
|
||||
unsigned char rctx = 0;
|
||||
|
||||
if (unlikely(in_nmi()))
|
||||
rctx = 3;
|
||||
else if (in_irq())
|
||||
rctx = 2;
|
||||
else if (in_softirq())
|
||||
rctx = 1;
|
||||
else
|
||||
rctx = 0;
|
||||
rctx += !!(pc & (NMI_MASK));
|
||||
rctx += !!(pc & (NMI_MASK | HARDIRQ_MASK));
|
||||
rctx += !!(pc & (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET));
|
||||
|
||||
if (recursion[rctx])
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ ring_buffer_has_space(unsigned long head, unsigned long tail,
|
|||
|
||||
static __always_inline int
|
||||
__perf_output_begin(struct perf_output_handle *handle,
|
||||
struct perf_sample_data *data,
|
||||
struct perf_event *event, unsigned int size,
|
||||
bool backward)
|
||||
{
|
||||
|
|
@ -237,18 +238,16 @@ __perf_output_begin(struct perf_output_handle *handle,
|
|||
handle->size = (1UL << page_shift) - offset;
|
||||
|
||||
if (unlikely(have_lost)) {
|
||||
struct perf_sample_data sample_data;
|
||||
|
||||
lost_event.header.size = sizeof(lost_event);
|
||||
lost_event.header.type = PERF_RECORD_LOST;
|
||||
lost_event.header.misc = 0;
|
||||
lost_event.id = event->id;
|
||||
lost_event.lost = local_xchg(&rb->lost, 0);
|
||||
|
||||
perf_event_header__init_id(&lost_event.header,
|
||||
&sample_data, event);
|
||||
/* XXX mostly redundant; @data is already fully initializes */
|
||||
perf_event_header__init_id(&lost_event.header, data, event);
|
||||
perf_output_put(handle, lost_event);
|
||||
perf_event__output_id_sample(event, handle, &sample_data);
|
||||
perf_event__output_id_sample(event, handle, data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -263,22 +262,25 @@ __perf_output_begin(struct perf_output_handle *handle,
|
|||
}
|
||||
|
||||
int perf_output_begin_forward(struct perf_output_handle *handle,
|
||||
struct perf_event *event, unsigned int size)
|
||||
struct perf_sample_data *data,
|
||||
struct perf_event *event, unsigned int size)
|
||||
{
|
||||
return __perf_output_begin(handle, event, size, false);
|
||||
return __perf_output_begin(handle, data, event, size, false);
|
||||
}
|
||||
|
||||
int perf_output_begin_backward(struct perf_output_handle *handle,
|
||||
struct perf_sample_data *data,
|
||||
struct perf_event *event, unsigned int size)
|
||||
{
|
||||
return __perf_output_begin(handle, event, size, true);
|
||||
return __perf_output_begin(handle, data, event, size, true);
|
||||
}
|
||||
|
||||
int perf_output_begin(struct perf_output_handle *handle,
|
||||
struct perf_sample_data *data,
|
||||
struct perf_event *event, unsigned int size)
|
||||
{
|
||||
|
||||
return __perf_output_begin(handle, event, size,
|
||||
return __perf_output_begin(handle, data, event, size,
|
||||
unlikely(is_write_backward(event)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -789,8 +789,9 @@ static void put_pi_state(struct futex_pi_state *pi_state)
|
|||
*/
|
||||
if (pi_state->owner) {
|
||||
struct task_struct *owner;
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
raw_spin_lock_irqsave(&pi_state->pi_mutex.wait_lock, flags);
|
||||
owner = pi_state->owner;
|
||||
if (owner) {
|
||||
raw_spin_lock(&owner->pi_lock);
|
||||
|
|
@ -798,7 +799,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
|
|||
raw_spin_unlock(&owner->pi_lock);
|
||||
}
|
||||
rt_mutex_proxy_unlock(&pi_state->pi_mutex, owner);
|
||||
raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
|
||||
raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags);
|
||||
}
|
||||
|
||||
if (current->pi_state_cache) {
|
||||
|
|
|
|||
|
|
@ -2765,7 +2765,9 @@ print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
|
|||
* (Note that this has to be done separately, because the graph cannot
|
||||
* detect such classes of deadlocks.)
|
||||
*
|
||||
* Returns: 0 on deadlock detected, 1 on OK, 2 on recursive read
|
||||
* Returns: 0 on deadlock detected, 1 on OK, 2 if another lock with the same
|
||||
* lock class is held but nest_lock is also held, i.e. we rely on the
|
||||
* nest_lock to avoid the deadlock.
|
||||
*/
|
||||
static int
|
||||
check_deadlock(struct task_struct *curr, struct held_lock *next)
|
||||
|
|
@ -2788,7 +2790,7 @@ check_deadlock(struct task_struct *curr, struct held_lock *next)
|
|||
* lock class (i.e. read_lock(lock)+read_lock(lock)):
|
||||
*/
|
||||
if ((next->read == 2) && prev->read)
|
||||
return 2;
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We're holding the nest_lock, which serializes this lock's
|
||||
|
|
@ -3592,16 +3594,13 @@ static int validate_chain(struct task_struct *curr,
|
|||
|
||||
if (!ret)
|
||||
return 0;
|
||||
/*
|
||||
* Mark recursive read, as we jump over it when
|
||||
* building dependencies (just like we jump over
|
||||
* trylock entries):
|
||||
*/
|
||||
if (ret == 2)
|
||||
hlock->read = 2;
|
||||
/*
|
||||
* Add dependency only if this lock is not the head
|
||||
* of the chain, and if it's not a secondary read-lock:
|
||||
* of the chain, and if the new lock introduces no more
|
||||
* lock dependency (because we already hold a lock with the
|
||||
* same lock class) nor deadlock (because the nest_lock
|
||||
* serializes nesting locks), see the comments for
|
||||
* check_deadlock().
|
||||
*/
|
||||
if (!chain_head && ret != 2) {
|
||||
if (!check_prevs_add(curr, hlock))
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ static int sd_ctl_doflags(struct ctl_table *table, int write,
|
|||
unsigned long flags = *(unsigned long *)table->data;
|
||||
size_t data_size = 0;
|
||||
size_t len = 0;
|
||||
char *tmp;
|
||||
char *tmp, *buf;
|
||||
int idx;
|
||||
|
||||
if (write)
|
||||
|
|
@ -269,17 +269,17 @@ static int sd_ctl_doflags(struct ctl_table *table, int write,
|
|||
return 0;
|
||||
}
|
||||
|
||||
tmp = kcalloc(data_size + 1, sizeof(*tmp), GFP_KERNEL);
|
||||
if (!tmp)
|
||||
buf = kcalloc(data_size + 1, sizeof(*buf), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_set_bit(idx, &flags, __SD_FLAG_CNT) {
|
||||
char *name = sd_flag_debug[idx].name;
|
||||
|
||||
len += snprintf(tmp + len, strlen(name) + 2, "%s ", name);
|
||||
len += snprintf(buf + len, strlen(name) + 2, "%s ", name);
|
||||
}
|
||||
|
||||
tmp += *ppos;
|
||||
tmp = buf + *ppos;
|
||||
len -= *ppos;
|
||||
|
||||
if (len > *lenp)
|
||||
|
|
@ -294,7 +294,7 @@ static int sd_ctl_doflags(struct ctl_table *table, int write,
|
|||
*lenp = len;
|
||||
*ppos += len;
|
||||
|
||||
kfree(tmp);
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6175,21 +6175,21 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t
|
|||
static int
|
||||
select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
|
||||
{
|
||||
unsigned long best_cap = 0;
|
||||
unsigned long task_util, best_cap = 0;
|
||||
int cpu, best_cpu = -1;
|
||||
struct cpumask *cpus;
|
||||
|
||||
sync_entity_load_avg(&p->se);
|
||||
|
||||
cpus = this_cpu_cpumask_var_ptr(select_idle_mask);
|
||||
cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr);
|
||||
|
||||
task_util = uclamp_task_util(p);
|
||||
|
||||
for_each_cpu_wrap(cpu, cpus, target) {
|
||||
unsigned long cpu_cap = capacity_of(cpu);
|
||||
|
||||
if (!available_idle_cpu(cpu) && !sched_idle_cpu(cpu))
|
||||
continue;
|
||||
if (task_fits_capacity(p, cpu_cap))
|
||||
if (fits_capacity(task_util, cpu_cap))
|
||||
return cpu;
|
||||
|
||||
if (cpu_cap > best_cap) {
|
||||
|
|
@ -6201,44 +6201,42 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
|
|||
return best_cpu;
|
||||
}
|
||||
|
||||
static inline bool asym_fits_capacity(int task_util, int cpu)
|
||||
{
|
||||
if (static_branch_unlikely(&sched_asym_cpucapacity))
|
||||
return fits_capacity(task_util, capacity_of(cpu));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try and locate an idle core/thread in the LLC cache domain.
|
||||
*/
|
||||
static int select_idle_sibling(struct task_struct *p, int prev, int target)
|
||||
{
|
||||
struct sched_domain *sd;
|
||||
unsigned long task_util;
|
||||
int i, recent_used_cpu;
|
||||
|
||||
/*
|
||||
* For asymmetric CPU capacity systems, our domain of interest is
|
||||
* sd_asym_cpucapacity rather than sd_llc.
|
||||
* On asymmetric system, update task utilization because we will check
|
||||
* that the task fits with cpu's capacity.
|
||||
*/
|
||||
if (static_branch_unlikely(&sched_asym_cpucapacity)) {
|
||||
sd = rcu_dereference(per_cpu(sd_asym_cpucapacity, target));
|
||||
/*
|
||||
* On an asymmetric CPU capacity system where an exclusive
|
||||
* cpuset defines a symmetric island (i.e. one unique
|
||||
* capacity_orig value through the cpuset), the key will be set
|
||||
* but the CPUs within that cpuset will not have a domain with
|
||||
* SD_ASYM_CPUCAPACITY. These should follow the usual symmetric
|
||||
* capacity path.
|
||||
*/
|
||||
if (!sd)
|
||||
goto symmetric;
|
||||
|
||||
i = select_idle_capacity(p, sd, target);
|
||||
return ((unsigned)i < nr_cpumask_bits) ? i : target;
|
||||
sync_entity_load_avg(&p->se);
|
||||
task_util = uclamp_task_util(p);
|
||||
}
|
||||
|
||||
symmetric:
|
||||
if (available_idle_cpu(target) || sched_idle_cpu(target))
|
||||
if ((available_idle_cpu(target) || sched_idle_cpu(target)) &&
|
||||
asym_fits_capacity(task_util, target))
|
||||
return target;
|
||||
|
||||
/*
|
||||
* If the previous CPU is cache affine and idle, don't be stupid:
|
||||
*/
|
||||
if (prev != target && cpus_share_cache(prev, target) &&
|
||||
(available_idle_cpu(prev) || sched_idle_cpu(prev)))
|
||||
(available_idle_cpu(prev) || sched_idle_cpu(prev)) &&
|
||||
asym_fits_capacity(task_util, prev))
|
||||
return prev;
|
||||
|
||||
/*
|
||||
|
|
@ -6261,7 +6259,8 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
|
|||
recent_used_cpu != target &&
|
||||
cpus_share_cache(recent_used_cpu, target) &&
|
||||
(available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
|
||||
cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr)) {
|
||||
cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) &&
|
||||
asym_fits_capacity(task_util, recent_used_cpu)) {
|
||||
/*
|
||||
* Replace recent_used_cpu with prev as it is a potential
|
||||
* candidate for the next wake:
|
||||
|
|
@ -6270,6 +6269,26 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
|
|||
return recent_used_cpu;
|
||||
}
|
||||
|
||||
/*
|
||||
* For asymmetric CPU capacity systems, our domain of interest is
|
||||
* sd_asym_cpucapacity rather than sd_llc.
|
||||
*/
|
||||
if (static_branch_unlikely(&sched_asym_cpucapacity)) {
|
||||
sd = rcu_dereference(per_cpu(sd_asym_cpucapacity, target));
|
||||
/*
|
||||
* On an asymmetric CPU capacity system where an exclusive
|
||||
* cpuset defines a symmetric island (i.e. one unique
|
||||
* capacity_orig value through the cpuset), the key will be set
|
||||
* but the CPUs within that cpuset will not have a domain with
|
||||
* SD_ASYM_CPUCAPACITY. These should follow the usual symmetric
|
||||
* capacity path.
|
||||
*/
|
||||
if (sd) {
|
||||
i = select_idle_capacity(p, sd, target);
|
||||
return ((unsigned)i < nr_cpumask_bits) ? i : target;
|
||||
}
|
||||
}
|
||||
|
||||
sd = rcu_dereference(per_cpu(sd_llc, target));
|
||||
if (!sd)
|
||||
return target;
|
||||
|
|
@ -9088,7 +9107,8 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
|
|||
* emptying busiest.
|
||||
*/
|
||||
if (local->group_type == group_has_spare) {
|
||||
if (busiest->group_type > group_fully_busy) {
|
||||
if ((busiest->group_type > group_fully_busy) &&
|
||||
!(env->sd->flags & SD_SHARE_PKG_RESOURCES)) {
|
||||
/*
|
||||
* If busiest is overloaded, try to fill spare
|
||||
* capacity. This might end up creating spare capacity
|
||||
|
|
|
|||
|
|
@ -1315,8 +1315,8 @@ static struct pcpu_chunk * __init pcpu_alloc_first_chunk(unsigned long tmp_addr,
|
|||
region_size = ALIGN(start_offset + map_size, lcm_align);
|
||||
|
||||
/* allocate chunk */
|
||||
alloc_size = sizeof(struct pcpu_chunk) +
|
||||
BITS_TO_LONGS(region_size >> PAGE_SHIFT) * sizeof(unsigned long);
|
||||
alloc_size = struct_size(chunk, populated,
|
||||
BITS_TO_LONGS(region_size >> PAGE_SHIFT));
|
||||
chunk = memblock_alloc(alloc_size, SMP_CACHE_BYTES);
|
||||
if (!chunk)
|
||||
panic("%s: Failed to allocate %zu bytes\n", __func__,
|
||||
|
|
@ -2521,8 +2521,8 @@ void __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
|
|||
pcpu_unit_pages = ai->unit_size >> PAGE_SHIFT;
|
||||
pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;
|
||||
pcpu_atom_size = ai->atom_size;
|
||||
pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) +
|
||||
BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long);
|
||||
pcpu_chunk_struct_size = struct_size(chunk, populated,
|
||||
BITS_TO_LONGS(pcpu_unit_pages));
|
||||
|
||||
pcpu_stats_save_ai(ai);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user