Merge 6.12.18 into android16-6.12
GKI (arm64) relevant 37 out of 149 changes, affecting 60 files +390/-338659bfea591scsi: ufs: core: Fix ufshcd_is_ufs_dev_busy() and ufshcd_eh_timed_out() [1 file, +4/-4]3594aad97eovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up [1 file, +1/-1]a3ae6a60baSUNRPC: Prevent looping due to rpc_signal_task() races [3 files, +2/-6]b5038504dascsi: core: Clear driver private data when retrying request [1 file, +7/-7]465a814323scsi: ufs: core: Set default runtime/system PM levels before ufshcd_hba_init() [1 file, +15/-15]ee5d6cb5ccALSA: usb-audio: Avoid dropping MIDI events at closing multiple ports [1 file, +1/-1]5c9921f1daBluetooth: L2CAP: Fix L2CAP_ECRED_CONN_RSP response [1 file, +7/-2]f22df335b2net: loopback: Avoid sending IP packets without an Ethernet header [1 file, +14/-0]915d64a78fnet: set the minimum for net_hotdata.netdev_budget_usecs [1 file, +2/-1]db8b2a613dipv4: Convert icmp_route_lookup() to dscp_t. [1 file, +9/-10]97c455c3c2ipv4: Convert ip_route_input() to dscp_t. [6 files, +18/-9]8ffd0390fcipvs: Always clear ipvs_property flag in skb_scrub_packet() [1 file, +1/-1]c417b1e4d8tcp: devmem: don't write truncated dmabuf CMSGs to userspace [3 files, +22/-16]33d782e38dtcp: Defer ts_recent changes until req is owned [1 file, +4/-6]902d576296net: Clear old fragment checksum value in napi_reuse_skb [1 file, +1/-0]806437d047thermal: gov_power_allocator: Fix incorrect calculation in divvy_up_power() [1 file, +1/-1]7d582eb6e4perf/core: Order the PMU list to fix warning about unordered pmu_ctx_list [1 file, +9/-2]13cca2b73euprobes: Reject the shared zeropage in uprobe_write_opcode() [1 file, +5/-0]07a82c78d8thermal: of: Simplify thermal_of_should_bind with scoped for each OF child [1 file, +2/-3]e11df3bffdthermal/of: Fix cdev lookup in thermal_of_should_bind() [1 file, +29/-21]19cd2dc4d4thermal: core: Move lists of thermal instances to trip descriptors [7 files, +62/-64]27a144c3bethermal: gov_power_allocator: Update total_weight on bind and cdev updates [1 file, +22/-8]546c19eb69io_uring/net: save msg_control for compat [1 file, +3/-1]8cc451444cunreachable: Unify [2 files, +7/-15]2cfd0e5084objtool: Remove annotate_{,un}reachable() [2 files, +2/-68]a00e900c9bobjtool: Fix C jump table annotations for Clang [3 files, +6/-5]435d2964aftracing: Fix bad hist from corrupting named_triggers list [1 file, +15/-15]8e31d9fb2fALSA: usb-audio: Re-add sample rate quirk for Pioneer DJM-900NXS2 [1 file, +1/-0]b9de147b2cKVM: arm64: Ensure a VMID is allocated before programming VTTBR_EL2 [3 files, +14/-21]a2475ccad6perf/core: Add RCU read lock protection to perf_iterate_ctx() [1 file, +2/-1]322cb23e24perf/core: Fix low freq setting via IOC_PERIOD [1 file, +9/-8]8f6369c3cdarm64/mm: Fix Boot panic on Ampere Altra [1 file, +1/-6]2f572c42bbblock: Remove zone write plugs when handling native zone append writes [2 files, +73/-10]29b6d5ad3ercuref: Plug slowpath race in rcuref_put() [2 files, +8/-6]0362847c52sched/core: Prevent rescheduling when interrupts are disabled [1 file, +1/-1]59455f968cscsi: ufs: core: bsg: Fix crash when arpmb command fails [1 file, +4/-2]72cbaf8b41thermal: gov_power_allocator: Add missing NULL pointer check [1 file, +6/-1] Changes in 6.12.18 RDMA/mlx5: Fix the recovery flow of the UMR QP IB/mlx5: Set and get correct qp_num for a DCT QP RDMA/mlx5: Fix a race for DMABUF MR which can lead to CQE with error RDMA/mlx5: Fix a WARN during dereg_mr for DM type RDMA/mana_ib: Allocate PAGE aligned doorbell index RDMA/hns: Fix mbox timing out by adding retry mechanism RDMA/bnxt_re: Fail probe early when not enough MSI-x vectors are reserved RDMA/bnxt_re: Refactor NQ allocation RDMA/bnxt_re: Cache MSIx info to a local structure RDMA/bnxt_re: Add sanity checks on rdev validity RDMA/bnxt_re: Allocate dev_attr information dynamically RDMA/bnxt_re: Fix the statistics for Gen P7 VF landlock: Fix non-TCP sockets restriction scsi: ufs: core: Fix ufshcd_is_ufs_dev_busy() and ufshcd_eh_timed_out() ovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up NFS: O_DIRECT writes must check and adjust the file length NFS: Adjust delegated timestamps for O_DIRECT reads and writes SUNRPC: Prevent looping due to rpc_signal_task() races NFSv4: Fix a deadlock when recovering state on a sillyrenamed file SUNRPC: Handle -ETIMEDOUT return from tlshd RDMA/mlx5: Fix implicit ODP hang on parent deregistration RDMA/mlx5: Fix AH static rate parsing scsi: core: Clear driver private data when retrying request scsi: ufs: core: Set default runtime/system PM levels before ufshcd_hba_init() RDMA/mlx5: Fix bind QP error cleanup flow RDMA/bnxt_re: Fix the page details for the srq created by kernel consumers sunrpc: suppress warnings for unused procfs functions ALSA: usb-audio: Avoid dropping MIDI events at closing multiple ports Bluetooth: L2CAP: Fix L2CAP_ECRED_CONN_RSP response rxrpc: rxperf: Fix missing decoding of terminal magic cookie afs: Fix the server_list to unuse a displaced server rather than putting it afs: Give an afs_server object a ref on the afs_cell object it points to net: loopback: Avoid sending IP packets without an Ethernet header net: set the minimum for net_hotdata.netdev_budget_usecs ipv4: Convert icmp_route_lookup() to dscp_t. ipv4: Convert ip_route_input() to dscp_t. ipvlan: Prepare ipvlan_process_v4_outbound() to future .flowi4_tos conversion. ipvlan: ensure network headers are in skb linear part net: cadence: macb: Synchronize stats calculations net: dsa: rtl8366rb: Fix compilation problem ASoC: es8328: fix route from DAC to output ASoC: fsl: Rename stream name of SAI DAI driver ipvs: Always clear ipvs_property flag in skb_scrub_packet() drm/xe/oa: Signal output fences drm/xe/oa: Move functions up so they can be reused for config ioctl drm/xe/oa: Add syncs support to OA config ioctl drm/xe/oa: Allow only certain property changes from config drm/xe/oa: Allow oa_exponent value of 0 firmware: cs_dsp: Remove async regmap writes ASoC: cs35l56: Prevent races when soft-resetting using SPI control ALSA: hda/realtek: Fix wrong mic setup for ASUS VivoBook 15 net: ethernet: ti: am65-cpsw: select PAGE_POOL tcp: devmem: don't write truncated dmabuf CMSGs to userspace ice: add E830 HW VF mailbox message limit support ice: Fix deinitializing VF in error path ice: Avoid setting default Rx VSI twice in switchdev setup tcp: Defer ts_recent changes until req is owned net: Clear old fragment checksum value in napi_reuse_skb net: mvpp2: cls: Fixed Non IP flow, with vlan tag flow defination. net/mlx5: IRQ, Fix null string in debug print net: ipv6: fix dst ref loop on input in seg6 lwt net: ipv6: fix dst ref loop on input in rpl lwt selftests: drv-net: Check if combined-count exists idpf: fix checksums set in idpf_rx_rsc() net: ti: icss-iep: Reject perout generation request thermal: gov_power_allocator: Fix incorrect calculation in divvy_up_power() perf/core: Order the PMU list to fix warning about unordered pmu_ctx_list uprobes: Reject the shared zeropage in uprobe_write_opcode() thermal: of: Simplify thermal_of_should_bind with scoped for each OF child thermal/of: Fix cdev lookup in thermal_of_should_bind() thermal: core: Move lists of thermal instances to trip descriptors thermal: gov_power_allocator: Update total_weight on bind and cdev updates io_uring/net: save msg_control for compat unreachable: Unify objtool: Remove annotate_{,un}reachable() objtool: Fix C jump table annotations for Clang x86/CPU: Fix warm boot hang regression on AMD SC1100 SoC systems phy: rockchip: fix Kconfig dependency more phy: rockchip: naneng-combphy: compatible reset with old DT riscv: KVM: Fix hart suspend status check riscv: KVM: Fix hart suspend_type use riscv: KVM: Fix SBI IPI error generation riscv: KVM: Fix SBI TIME error generation tracing: Fix bad hist from corrupting named_triggers list ftrace: Avoid potential division by zero in function_stat_show() ALSA: usb-audio: Re-add sample rate quirk for Pioneer DJM-900NXS2 ALSA: hda/realtek: Fix microphone regression on ASUS N705UD KVM: arm64: Ensure a VMID is allocated before programming VTTBR_EL2 perf/core: Add RCU read lock protection to perf_iterate_ctx() perf/x86: Fix low freqency setting issue perf/core: Fix low freq setting via IOC_PERIOD drm/xe/regs: remove a duplicate definition for RING_CTL_SIZE(size) drm/xe/userptr: restore invalidation list on error drm/xe/userptr: fix EFAULT handling drm/amdkfd: Preserve cp_hqd_pq_control on update_mqd drm/amdgpu: disable BAR resize on Dell G5 SE drm/amdgpu: init return value in amdgpu_ttm_clear_buffer drm/amd/display: Disable PSR-SU on eDP panels drm/amd/display: add a quirk to enable eDP0 on DP1 drm/amd/display: Fix HPD after gpu reset arm64/mm: Fix Boot panic on Ampere Altra block: Remove zone write plugs when handling native zone append writes i2c: npcm: disable interrupt enable bit before devm_request_irq i2c: ls2x: Fix frequency division register access usbnet: gl620a: fix endpoint checking in genelink_bind() net: stmmac: dwmac-loongson: Add fix_soc_reset() callback net: phy: qcom: qca807x fix condition for DAC_DSP_BIAS_CURRENT net: enetc: fix the off-by-one issue in enetc_map_tx_buffs() net: enetc: keep track of correct Tx BD count in enetc_map_tx_tso_buffs() net: enetc: VFs do not support HWTSTAMP_TX_ONESTEP_SYNC net: enetc: update UDP checksum when updating originTimestamp field net: enetc: correct the xdp_tx statistics net: enetc: fix the off-by-one issue in enetc_map_tx_tso_buffs() phy: tegra: xusb: reset VBUS & ID OVERRIDE phy: exynos5-usbdrd: fix MPLL_MULTIPLIER and SSC_REFCLKSEL masks in refclk phy: exynos5-usbdrd: gs101: ensure power is gated to SS phy in phy_exit() iommu/vt-d: Remove device comparison in context_setup_pass_through_cb iommu/vt-d: Fix suspicious RCU usage intel_idle: Handle older CPUs, which stop the TSC in deeper C states, correctly mptcp: always handle address removal under msk socket lock mptcp: reset when MPTCP opts are dropped after join selftests/landlock: Test that MPTCP actions are not restricted vmlinux.lds: Ensure that const vars with relocations are mapped R/O rcuref: Plug slowpath race in rcuref_put() sched/core: Prevent rescheduling when interrupts are disabled sched_ext: Fix pick_task_scx() picking non-queued tasks when it's called without balance() selftests/landlock: Test TCP accesses with protocol=IPPROTO_TCP dm-integrity: Avoid divide by zero in table status in Inline mode dm vdo: add missing spin_lock_init ima: Reset IMA_NONACTION_RULE_FLAGS after post_setattr scsi: ufs: core: bsg: Fix crash when arpmb command fails rseq/selftests: Fix riscv rseq_offset_deref_addv inline asm riscv/futex: sign extend compare value in atomic cmpxchg riscv: signal: fix signal frame size riscv: cacheinfo: Use of_property_present() for non-boolean properties riscv: signal: fix signal_minsigstksz riscv: cpufeature: use bitmap_equal() instead of memcmp() efi: Don't map the entire mokvar table to determine its size amdgpu/pm/legacy: fix suspend/resume issues x86/microcode/AMD: Return bool from find_blobs_in_containers() x86/microcode/AMD: Have __apply_microcode_amd() return bool x86/microcode/AMD: Remove ugly linebreak in __verify_patch_section() signature x86/microcode/AMD: Remove unused save_microcode_in_initrd_amd() declarations x86/microcode/AMD: Merge early_apply_microcode() into its single callsite x86/microcode/AMD: Get rid of the _load_microcode_amd() forward declaration x86/microcode/AMD: Add get_patch_level() x86/microcode/AMD: Load only SHA256-checksummed patches thermal: gov_power_allocator: Add missing NULL pointer check Linux 6.12.18 Change-Id: Id06a9c751e3315bfd1a6e642b2c0f276edb46319 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 12
|
||||
SUBLEVEL = 17
|
||||
SUBLEVEL = 18
|
||||
EXTRAVERSION =
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
|
||||
@@ -1383,7 +1383,7 @@ int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
|
||||
extern unsigned int __ro_after_init kvm_arm_vmid_bits;
|
||||
int __init kvm_arm_vmid_alloc_init(void);
|
||||
void __init kvm_arm_vmid_alloc_free(void);
|
||||
bool kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
|
||||
void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
|
||||
void kvm_arm_vmid_clear_active(void);
|
||||
|
||||
static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
|
||||
|
||||
+10
-12
@@ -590,6 +590,16 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
mmu = vcpu->arch.hw_mmu;
|
||||
last_ran = this_cpu_ptr(mmu->last_vcpu_ran);
|
||||
|
||||
/*
|
||||
* Ensure a VMID is allocated for the MMU before programming VTTBR_EL2,
|
||||
* which happens eagerly in VHE.
|
||||
*
|
||||
* Also, the VMID allocator only preserves VMIDs that are active at the
|
||||
* time of rollover, so KVM might need to grab a new VMID for the MMU if
|
||||
* this is called from kvm_sched_in().
|
||||
*/
|
||||
kvm_arm_vmid_update(&mmu->vmid);
|
||||
|
||||
/*
|
||||
* We guarantee that both TLBs and I-cache are private to each
|
||||
* vcpu. If detecting that a vcpu from the same VM has
|
||||
@@ -1184,18 +1194,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
preempt_disable();
|
||||
|
||||
/*
|
||||
* The VMID allocator only tracks active VMIDs per
|
||||
* physical CPU, and therefore the VMID allocated may not be
|
||||
* preserved on VMID roll-over if the task was preempted,
|
||||
* making a thread's VMID inactive. So we need to call
|
||||
* kvm_arm_vmid_update() in non-premptible context.
|
||||
*/
|
||||
if (kvm_arm_vmid_update(&vcpu->arch.hw_mmu->vmid) &&
|
||||
has_vhe())
|
||||
__load_stage2(vcpu->arch.hw_mmu,
|
||||
vcpu->arch.hw_mmu->arch);
|
||||
|
||||
kvm_pmu_flush_hwstate(vcpu);
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
@@ -135,11 +135,10 @@ void kvm_arm_vmid_clear_active(void)
|
||||
atomic64_set(this_cpu_ptr(&active_vmids), VMID_ACTIVE_INVALID);
|
||||
}
|
||||
|
||||
bool kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
|
||||
void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
|
||||
{
|
||||
unsigned long flags;
|
||||
u64 vmid, old_active_vmid;
|
||||
bool updated = false;
|
||||
|
||||
vmid = atomic64_read(&kvm_vmid->id);
|
||||
|
||||
@@ -157,21 +156,17 @@ bool kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
|
||||
if (old_active_vmid != 0 && vmid_gen_match(vmid) &&
|
||||
0 != atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_vmids),
|
||||
old_active_vmid, vmid))
|
||||
return false;
|
||||
return;
|
||||
|
||||
raw_spin_lock_irqsave(&cpu_vmid_lock, flags);
|
||||
|
||||
/* Check that our VMID belongs to the current generation. */
|
||||
vmid = atomic64_read(&kvm_vmid->id);
|
||||
if (!vmid_gen_match(vmid)) {
|
||||
if (!vmid_gen_match(vmid))
|
||||
vmid = new_vmid(kvm_vmid);
|
||||
updated = true;
|
||||
}
|
||||
|
||||
atomic64_set(this_cpu_ptr(&active_vmids), vmid);
|
||||
raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags);
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -93,7 +93,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %[r]) \
|
||||
_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %[r]) \
|
||||
: [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr), [t] "=&r" (tmp)
|
||||
: [ov] "Jr" (oldval), [nv] "Jr" (newval)
|
||||
: [ov] "Jr" ((long)(int)oldval), [nv] "Jr" (newval)
|
||||
: "memory");
|
||||
__disable_user_access();
|
||||
|
||||
|
||||
@@ -108,11 +108,11 @@ int populate_cache_leaves(unsigned int cpu)
|
||||
if (!np)
|
||||
return -ENOENT;
|
||||
|
||||
if (of_property_read_bool(np, "cache-size"))
|
||||
if (of_property_present(np, "cache-size"))
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_UNIFIED, level);
|
||||
if (of_property_read_bool(np, "i-cache-size"))
|
||||
if (of_property_present(np, "i-cache-size"))
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
|
||||
if (of_property_read_bool(np, "d-cache-size"))
|
||||
if (of_property_present(np, "d-cache-size"))
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
|
||||
|
||||
prev = np;
|
||||
@@ -125,11 +125,11 @@ int populate_cache_leaves(unsigned int cpu)
|
||||
break;
|
||||
if (level <= levels)
|
||||
break;
|
||||
if (of_property_read_bool(np, "cache-size"))
|
||||
if (of_property_present(np, "cache-size"))
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_UNIFIED, level);
|
||||
if (of_property_read_bool(np, "i-cache-size"))
|
||||
if (of_property_present(np, "i-cache-size"))
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
|
||||
if (of_property_read_bool(np, "d-cache-size"))
|
||||
if (of_property_present(np, "d-cache-size"))
|
||||
ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
|
||||
levels = level;
|
||||
}
|
||||
|
||||
@@ -454,7 +454,7 @@ static void __init riscv_resolve_isa(unsigned long *source_isa,
|
||||
if (bit < RISCV_ISA_EXT_BASE)
|
||||
*this_hwcap |= isa2hwcap[bit];
|
||||
}
|
||||
} while (loop && memcmp(prev_resolved_isa, resolved_isa, sizeof(prev_resolved_isa)));
|
||||
} while (loop && !bitmap_equal(prev_resolved_isa, resolved_isa, RISCV_ISA_EXT_MAX));
|
||||
}
|
||||
|
||||
static void __init match_isa_ext(const char *name, const char *name_end, unsigned long *bitmap)
|
||||
|
||||
@@ -288,8 +288,8 @@ void __init setup_arch(char **cmdline_p)
|
||||
|
||||
riscv_init_cbo_blocksizes();
|
||||
riscv_fill_hwcap();
|
||||
init_rt_signal_env();
|
||||
apply_boot_alternatives();
|
||||
init_rt_signal_env();
|
||||
|
||||
if (IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM) &&
|
||||
riscv_isa_extension_available(NULL, ZICBOM))
|
||||
|
||||
@@ -215,12 +215,6 @@ static size_t get_rt_frame_size(bool cal_all)
|
||||
if (cal_all || riscv_v_vstate_query(task_pt_regs(current)))
|
||||
total_context_size += riscv_v_sc_size;
|
||||
}
|
||||
/*
|
||||
* Preserved a __riscv_ctx_hdr for END signal context header if an
|
||||
* extension uses __riscv_extra_ext_header
|
||||
*/
|
||||
if (total_context_size)
|
||||
total_context_size += sizeof(struct __riscv_ctx_hdr);
|
||||
|
||||
frame_size += total_context_size;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/wordpart.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/kvm_vcpu_sbi.h>
|
||||
|
||||
@@ -79,12 +80,12 @@ static int kvm_sbi_hsm_vcpu_get_status(struct kvm_vcpu *vcpu)
|
||||
target_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, target_vcpuid);
|
||||
if (!target_vcpu)
|
||||
return SBI_ERR_INVALID_PARAM;
|
||||
if (!kvm_riscv_vcpu_stopped(target_vcpu))
|
||||
return SBI_HSM_STATE_STARTED;
|
||||
else if (vcpu->stat.generic.blocking)
|
||||
if (kvm_riscv_vcpu_stopped(target_vcpu))
|
||||
return SBI_HSM_STATE_STOPPED;
|
||||
else if (target_vcpu->stat.generic.blocking)
|
||||
return SBI_HSM_STATE_SUSPENDED;
|
||||
else
|
||||
return SBI_HSM_STATE_STOPPED;
|
||||
return SBI_HSM_STATE_STARTED;
|
||||
}
|
||||
|
||||
static int kvm_sbi_ext_hsm_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
@@ -109,7 +110,7 @@ static int kvm_sbi_ext_hsm_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
}
|
||||
return 0;
|
||||
case SBI_EXT_HSM_HART_SUSPEND:
|
||||
switch (cp->a0) {
|
||||
switch (lower_32_bits(cp->a0)) {
|
||||
case SBI_HSM_SUSPEND_RET_DEFAULT:
|
||||
kvm_riscv_vcpu_wfi(vcpu);
|
||||
break;
|
||||
|
||||
@@ -21,7 +21,7 @@ static int kvm_sbi_ext_time_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
u64 next_cycle;
|
||||
|
||||
if (cp->a6 != SBI_EXT_TIME_SET_TIMER) {
|
||||
retdata->err_val = SBI_ERR_INVALID_PARAM;
|
||||
retdata->err_val = SBI_ERR_NOT_SUPPORTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -51,9 +51,10 @@ static int kvm_sbi_ext_ipi_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
|
||||
unsigned long hmask = cp->a0;
|
||||
unsigned long hbase = cp->a1;
|
||||
unsigned long hart_bit = 0, sentmask = 0;
|
||||
|
||||
if (cp->a6 != SBI_EXT_IPI_SEND_IPI) {
|
||||
retdata->err_val = SBI_ERR_INVALID_PARAM;
|
||||
retdata->err_val = SBI_ERR_NOT_SUPPORTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -62,15 +63,23 @@ static int kvm_sbi_ext_ipi_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
if (hbase != -1UL) {
|
||||
if (tmp->vcpu_id < hbase)
|
||||
continue;
|
||||
if (!(hmask & (1UL << (tmp->vcpu_id - hbase))))
|
||||
hart_bit = tmp->vcpu_id - hbase;
|
||||
if (hart_bit >= __riscv_xlen)
|
||||
goto done;
|
||||
if (!(hmask & (1UL << hart_bit)))
|
||||
continue;
|
||||
}
|
||||
ret = kvm_riscv_vcpu_set_interrupt(tmp, IRQ_VS_SOFT);
|
||||
if (ret < 0)
|
||||
break;
|
||||
sentmask |= 1UL << hart_bit;
|
||||
kvm_riscv_vcpu_pmu_incr_fw(tmp, SBI_PMU_FW_IPI_RCVD);
|
||||
}
|
||||
|
||||
done:
|
||||
if (hbase != -1UL && (hmask ^ sentmask))
|
||||
retdata->err_val = SBI_ERR_INVALID_PARAM;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1334,6 +1334,7 @@ config X86_REBOOTFIXUPS
|
||||
config MICROCODE
|
||||
def_bool y
|
||||
depends on CPU_SUP_AMD || CPU_SUP_INTEL
|
||||
select CRYPTO_LIB_SHA256 if CPU_SUP_AMD
|
||||
|
||||
config MICROCODE_INITRD32
|
||||
def_bool y
|
||||
|
||||
@@ -628,7 +628,7 @@ int x86_pmu_hw_config(struct perf_event *event)
|
||||
if (event->attr.type == event->pmu->type)
|
||||
event->hw.config |= x86_pmu_get_event_config(event);
|
||||
|
||||
if (event->attr.sample_period && x86_pmu.limit_period) {
|
||||
if (!event->attr.freq && x86_pmu.limit_period) {
|
||||
s64 left = event->attr.sample_period;
|
||||
x86_pmu.limit_period(event, &left);
|
||||
if (left > event->attr.sample_period)
|
||||
|
||||
@@ -153,8 +153,8 @@ static void geode_configure(void)
|
||||
u8 ccr3;
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Suspend on halt power saving and enable #SUSP pin */
|
||||
setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
|
||||
/* Suspend on halt power saving */
|
||||
setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x08);
|
||||
|
||||
ccr3 = getCx86(CX86_CCR3);
|
||||
setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
|
||||
|
||||
@@ -23,14 +23,18 @@
|
||||
|
||||
#include <linux/earlycpio.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <crypto/sha2.h>
|
||||
|
||||
#include <asm/microcode.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/cmdline.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/msr.h>
|
||||
@@ -145,6 +149,107 @@ ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin";
|
||||
*/
|
||||
static u32 bsp_cpuid_1_eax __ro_after_init;
|
||||
|
||||
static bool sha_check = true;
|
||||
|
||||
struct patch_digest {
|
||||
u32 patch_id;
|
||||
u8 sha256[SHA256_DIGEST_SIZE];
|
||||
};
|
||||
|
||||
#include "amd_shas.c"
|
||||
|
||||
static int cmp_id(const void *key, const void *elem)
|
||||
{
|
||||
struct patch_digest *pd = (struct patch_digest *)elem;
|
||||
u32 patch_id = *(u32 *)key;
|
||||
|
||||
if (patch_id == pd->patch_id)
|
||||
return 0;
|
||||
else if (patch_id < pd->patch_id)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool need_sha_check(u32 cur_rev)
|
||||
{
|
||||
switch (cur_rev >> 8) {
|
||||
case 0x80012: return cur_rev <= 0x800126f; break;
|
||||
case 0x83010: return cur_rev <= 0x830107c; break;
|
||||
case 0x86001: return cur_rev <= 0x860010e; break;
|
||||
case 0x86081: return cur_rev <= 0x8608108; break;
|
||||
case 0x87010: return cur_rev <= 0x8701034; break;
|
||||
case 0x8a000: return cur_rev <= 0x8a0000a; break;
|
||||
case 0xa0011: return cur_rev <= 0xa0011da; break;
|
||||
case 0xa0012: return cur_rev <= 0xa001243; break;
|
||||
case 0xa1011: return cur_rev <= 0xa101153; break;
|
||||
case 0xa1012: return cur_rev <= 0xa10124e; break;
|
||||
case 0xa1081: return cur_rev <= 0xa108109; break;
|
||||
case 0xa2010: return cur_rev <= 0xa20102f; break;
|
||||
case 0xa2012: return cur_rev <= 0xa201212; break;
|
||||
case 0xa6012: return cur_rev <= 0xa60120a; break;
|
||||
case 0xa7041: return cur_rev <= 0xa704109; break;
|
||||
case 0xa7052: return cur_rev <= 0xa705208; break;
|
||||
case 0xa7080: return cur_rev <= 0xa708009; break;
|
||||
case 0xa70c0: return cur_rev <= 0xa70C009; break;
|
||||
case 0xaa002: return cur_rev <= 0xaa00218; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
pr_info("You should not be seeing this. Please send the following couple of lines to x86-<at>-kernel.org\n");
|
||||
pr_info("CPUID(1).EAX: 0x%x, current revision: 0x%x\n", bsp_cpuid_1_eax, cur_rev);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool verify_sha256_digest(u32 patch_id, u32 cur_rev, const u8 *data, unsigned int len)
|
||||
{
|
||||
struct patch_digest *pd = NULL;
|
||||
u8 digest[SHA256_DIGEST_SIZE];
|
||||
struct sha256_state s;
|
||||
int i;
|
||||
|
||||
if (x86_family(bsp_cpuid_1_eax) < 0x17 ||
|
||||
x86_family(bsp_cpuid_1_eax) > 0x19)
|
||||
return true;
|
||||
|
||||
if (!need_sha_check(cur_rev))
|
||||
return true;
|
||||
|
||||
if (!sha_check)
|
||||
return true;
|
||||
|
||||
pd = bsearch(&patch_id, phashes, ARRAY_SIZE(phashes), sizeof(struct patch_digest), cmp_id);
|
||||
if (!pd) {
|
||||
pr_err("No sha256 digest for patch ID: 0x%x found\n", patch_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
sha256_init(&s);
|
||||
sha256_update(&s, data, len);
|
||||
sha256_final(&s, digest);
|
||||
|
||||
if (memcmp(digest, pd->sha256, sizeof(digest))) {
|
||||
pr_err("Patch 0x%x SHA256 digest mismatch!\n", patch_id);
|
||||
|
||||
for (i = 0; i < SHA256_DIGEST_SIZE; i++)
|
||||
pr_cont("0x%x ", digest[i]);
|
||||
pr_info("\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 get_patch_level(void)
|
||||
{
|
||||
u32 rev, dummy __always_unused;
|
||||
|
||||
native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
|
||||
|
||||
return rev;
|
||||
}
|
||||
|
||||
static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val)
|
||||
{
|
||||
union zen_patch_rev p;
|
||||
@@ -246,8 +351,7 @@ static bool verify_equivalence_table(const u8 *buf, size_t buf_size)
|
||||
* On success, @sh_psize returns the patch size according to the section header,
|
||||
* to the caller.
|
||||
*/
|
||||
static bool
|
||||
__verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize)
|
||||
static bool __verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize)
|
||||
{
|
||||
u32 p_type, p_size;
|
||||
const u32 *hdr;
|
||||
@@ -484,10 +588,13 @@ static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc)
|
||||
}
|
||||
}
|
||||
|
||||
static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
|
||||
static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev,
|
||||
unsigned int psize)
|
||||
{
|
||||
unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
|
||||
u32 rev, dummy;
|
||||
|
||||
if (!verify_sha256_digest(mc->hdr.patch_id, *cur_rev, (const u8 *)p_addr, psize))
|
||||
return -1;
|
||||
|
||||
native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
|
||||
|
||||
@@ -505,47 +612,13 @@ static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
|
||||
}
|
||||
|
||||
/* verify patch application was successful */
|
||||
native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
|
||||
*cur_rev = get_patch_level();
|
||||
if (*cur_rev != mc->hdr.patch_id)
|
||||
return false;
|
||||
|
||||
if (rev != mc->hdr.patch_id)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Early load occurs before we can vmalloc(). So we look for the microcode
|
||||
* patch container file in initrd, traverse equivalent cpu table, look for a
|
||||
* matching microcode patch, and update, all in initrd memory in place.
|
||||
* When vmalloc() is available for use later -- on 64-bit during first AP load,
|
||||
* and on 32-bit during save_microcode_in_initrd_amd() -- we can call
|
||||
* load_microcode_amd() to save equivalent cpu table and microcode patches in
|
||||
* kernel heap memory.
|
||||
*
|
||||
* Returns true if container found (sets @desc), false otherwise.
|
||||
*/
|
||||
static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size)
|
||||
{
|
||||
struct cont_desc desc = { 0 };
|
||||
struct microcode_amd *mc;
|
||||
bool ret = false;
|
||||
|
||||
scan_containers(ucode, size, &desc);
|
||||
|
||||
mc = desc.mc;
|
||||
if (!mc)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Allow application of the same revision to pick up SMT-specific
|
||||
* changes even if the revision of the other SMT thread is already
|
||||
* up-to-date.
|
||||
*/
|
||||
if (old_rev > mc->hdr.patch_id)
|
||||
return ret;
|
||||
|
||||
return !__apply_microcode_amd(mc, desc.psize);
|
||||
}
|
||||
|
||||
static bool get_builtin_microcode(struct cpio_data *cp)
|
||||
{
|
||||
@@ -569,64 +642,74 @@ static bool get_builtin_microcode(struct cpio_data *cp)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __init find_blobs_in_containers(struct cpio_data *ret)
|
||||
static bool __init find_blobs_in_containers(struct cpio_data *ret)
|
||||
{
|
||||
struct cpio_data cp;
|
||||
bool found;
|
||||
|
||||
if (!get_builtin_microcode(&cp))
|
||||
cp = find_microcode_in_initrd(ucode_path);
|
||||
|
||||
*ret = cp;
|
||||
found = cp.data && cp.size;
|
||||
if (found)
|
||||
*ret = cp;
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* Early load occurs before we can vmalloc(). So we look for the microcode
|
||||
* patch container file in initrd, traverse equivalent cpu table, look for a
|
||||
* matching microcode patch, and update, all in initrd memory in place.
|
||||
* When vmalloc() is available for use later -- on 64-bit during first AP load,
|
||||
* and on 32-bit during save_microcode_in_initrd() -- we can call
|
||||
* load_microcode_amd() to save equivalent cpu table and microcode patches in
|
||||
* kernel heap memory.
|
||||
*/
|
||||
void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax)
|
||||
{
|
||||
struct cont_desc desc = { };
|
||||
struct microcode_amd *mc;
|
||||
struct cpio_data cp = { };
|
||||
u32 dummy;
|
||||
char buf[4];
|
||||
u32 rev;
|
||||
|
||||
if (cmdline_find_option(boot_command_line, "microcode.amd_sha_check", buf, 4)) {
|
||||
if (!strncmp(buf, "off", 3)) {
|
||||
sha_check = false;
|
||||
pr_warn_once("It is a very very bad idea to disable the blobs SHA check!\n");
|
||||
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
|
||||
}
|
||||
}
|
||||
|
||||
bsp_cpuid_1_eax = cpuid_1_eax;
|
||||
|
||||
native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy);
|
||||
rev = get_patch_level();
|
||||
ed->old_rev = rev;
|
||||
|
||||
/* Needed in load_microcode_amd() */
|
||||
ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
|
||||
|
||||
find_blobs_in_containers(&cp);
|
||||
if (!(cp.data && cp.size))
|
||||
if (!find_blobs_in_containers(&cp))
|
||||
return;
|
||||
|
||||
if (early_apply_microcode(ed->old_rev, cp.data, cp.size))
|
||||
native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
|
||||
}
|
||||
|
||||
static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size);
|
||||
|
||||
static int __init save_microcode_in_initrd(void)
|
||||
{
|
||||
unsigned int cpuid_1_eax = native_cpuid_eax(1);
|
||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
struct cont_desc desc = { 0 };
|
||||
enum ucode_state ret;
|
||||
struct cpio_data cp;
|
||||
|
||||
if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
|
||||
return 0;
|
||||
|
||||
find_blobs_in_containers(&cp);
|
||||
if (!(cp.data && cp.size))
|
||||
return -EINVAL;
|
||||
|
||||
scan_containers(cp.data, cp.size, &desc);
|
||||
if (!desc.mc)
|
||||
return -EINVAL;
|
||||
|
||||
ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
|
||||
if (ret > UCODE_UPDATED)
|
||||
return -EINVAL;
|
||||
mc = desc.mc;
|
||||
if (!mc)
|
||||
return;
|
||||
|
||||
return 0;
|
||||
/*
|
||||
* Allow application of the same revision to pick up SMT-specific
|
||||
* changes even if the revision of the other SMT thread is already
|
||||
* up-to-date.
|
||||
*/
|
||||
if (ed->old_rev > mc->hdr.patch_id)
|
||||
return;
|
||||
|
||||
if (__apply_microcode_amd(mc, &rev, desc.psize))
|
||||
ed->new_rev = rev;
|
||||
}
|
||||
early_initcall(save_microcode_in_initrd);
|
||||
|
||||
static inline bool patch_cpus_equivalent(struct ucode_patch *p,
|
||||
struct ucode_patch *n,
|
||||
@@ -727,14 +810,9 @@ static void free_cache(void)
|
||||
static struct ucode_patch *find_patch(unsigned int cpu)
|
||||
{
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
||||
u32 rev, dummy __always_unused;
|
||||
u16 equiv_id = 0;
|
||||
|
||||
/* fetch rev if not populated yet: */
|
||||
if (!uci->cpu_sig.rev) {
|
||||
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
|
||||
uci->cpu_sig.rev = rev;
|
||||
}
|
||||
uci->cpu_sig.rev = get_patch_level();
|
||||
|
||||
if (x86_family(bsp_cpuid_1_eax) < 0x17) {
|
||||
equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
|
||||
@@ -757,22 +835,20 @@ void reload_ucode_amd(unsigned int cpu)
|
||||
|
||||
mc = p->data;
|
||||
|
||||
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
|
||||
|
||||
rev = get_patch_level();
|
||||
if (rev < mc->hdr.patch_id) {
|
||||
if (!__apply_microcode_amd(mc, p->size))
|
||||
pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
|
||||
if (__apply_microcode_amd(mc, &rev, p->size))
|
||||
pr_info_once("reload revision: 0x%08x\n", rev);
|
||||
}
|
||||
}
|
||||
|
||||
static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
||||
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
||||
struct ucode_patch *p;
|
||||
|
||||
csig->sig = cpuid_eax(0x00000001);
|
||||
csig->rev = c->microcode;
|
||||
csig->rev = get_patch_level();
|
||||
|
||||
/*
|
||||
* a patch could have been loaded early, set uci->mc so that
|
||||
@@ -813,7 +889,7 @@ static enum ucode_state apply_microcode_amd(int cpu)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (__apply_microcode_amd(mc_amd, p->size)) {
|
||||
if (!__apply_microcode_amd(mc_amd, &rev, p->size)) {
|
||||
pr_err("CPU%d: update failed for patch_level=0x%08x\n",
|
||||
cpu, mc_amd->hdr.patch_id);
|
||||
return UCODE_ERROR;
|
||||
@@ -935,8 +1011,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,
|
||||
}
|
||||
|
||||
/* Scan the blob in @data and add microcode patches to the cache. */
|
||||
static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
|
||||
size_t size)
|
||||
static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, size_t size)
|
||||
{
|
||||
u8 *fw = (u8 *)data;
|
||||
size_t offset;
|
||||
@@ -1011,6 +1086,32 @@ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t siz
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init save_microcode_in_initrd(void)
|
||||
{
|
||||
unsigned int cpuid_1_eax = native_cpuid_eax(1);
|
||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
struct cont_desc desc = { 0 };
|
||||
enum ucode_state ret;
|
||||
struct cpio_data cp;
|
||||
|
||||
if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
|
||||
return 0;
|
||||
|
||||
if (!find_blobs_in_containers(&cp))
|
||||
return -EINVAL;
|
||||
|
||||
scan_containers(cp.data, cp.size, &desc);
|
||||
if (!desc.mc)
|
||||
return -EINVAL;
|
||||
|
||||
ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
|
||||
if (ret > UCODE_UPDATED)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_initcall(save_microcode_in_initrd);
|
||||
|
||||
/*
|
||||
* AMD microcode firmware naming convention, up to family 15h they are in
|
||||
* the legacy file:
|
||||
|
||||
@@ -0,0 +1,444 @@
|
||||
/* Keep 'em sorted. */
|
||||
static const struct patch_digest phashes[] = {
|
||||
{ 0x8001227, {
|
||||
0x99,0xc0,0x9b,0x2b,0xcc,0x9f,0x52,0x1b,
|
||||
0x1a,0x5f,0x1d,0x83,0xa1,0x6c,0xc4,0x46,
|
||||
0xe2,0x6c,0xda,0x73,0xfb,0x2d,0x23,0xa8,
|
||||
0x77,0xdc,0x15,0x31,0x33,0x4a,0x46,0x18,
|
||||
}
|
||||
},
|
||||
{ 0x8001250, {
|
||||
0xc0,0x0b,0x6b,0x19,0xfd,0x5c,0x39,0x60,
|
||||
0xd5,0xc3,0x57,0x46,0x54,0xe4,0xd1,0xaa,
|
||||
0xa8,0xf7,0x1f,0xa8,0x6a,0x60,0x3e,0xe3,
|
||||
0x27,0x39,0x8e,0x53,0x30,0xf8,0x49,0x19,
|
||||
}
|
||||
},
|
||||
{ 0x800126e, {
|
||||
0xf3,0x8b,0x2b,0xb6,0x34,0xe3,0xc8,0x2c,
|
||||
0xef,0xec,0x63,0x6d,0xc8,0x76,0x77,0xb3,
|
||||
0x25,0x5a,0xb7,0x52,0x8c,0x83,0x26,0xe6,
|
||||
0x4c,0xbe,0xbf,0xe9,0x7d,0x22,0x6a,0x43,
|
||||
}
|
||||
},
|
||||
{ 0x800126f, {
|
||||
0x2b,0x5a,0xf2,0x9c,0xdd,0xd2,0x7f,0xec,
|
||||
0xec,0x96,0x09,0x57,0xb0,0x96,0x29,0x8b,
|
||||
0x2e,0x26,0x91,0xf0,0x49,0x33,0x42,0x18,
|
||||
0xdd,0x4b,0x65,0x5a,0xd4,0x15,0x3d,0x33,
|
||||
}
|
||||
},
|
||||
{ 0x800820d, {
|
||||
0x68,0x98,0x83,0xcd,0x22,0x0d,0xdd,0x59,
|
||||
0x73,0x2c,0x5b,0x37,0x1f,0x84,0x0e,0x67,
|
||||
0x96,0x43,0x83,0x0c,0x46,0x44,0xab,0x7c,
|
||||
0x7b,0x65,0x9e,0x57,0xb5,0x90,0x4b,0x0e,
|
||||
}
|
||||
},
|
||||
{ 0x8301025, {
|
||||
0xe4,0x7d,0xdb,0x1e,0x14,0xb4,0x5e,0x36,
|
||||
0x8f,0x3e,0x48,0x88,0x3c,0x6d,0x76,0xa1,
|
||||
0x59,0xc6,0xc0,0x72,0x42,0xdf,0x6c,0x30,
|
||||
0x6f,0x0b,0x28,0x16,0x61,0xfc,0x79,0x77,
|
||||
}
|
||||
},
|
||||
{ 0x8301055, {
|
||||
0x81,0x7b,0x99,0x1b,0xae,0x2d,0x4f,0x9a,
|
||||
0xef,0x13,0xce,0xb5,0x10,0xaf,0x6a,0xea,
|
||||
0xe5,0xb0,0x64,0x98,0x10,0x68,0x34,0x3b,
|
||||
0x9d,0x7a,0xd6,0x22,0x77,0x5f,0xb3,0x5b,
|
||||
}
|
||||
},
|
||||
{ 0x8301072, {
|
||||
0xcf,0x76,0xa7,0x1a,0x49,0xdf,0x2a,0x5e,
|
||||
0x9e,0x40,0x70,0xe5,0xdd,0x8a,0xa8,0x28,
|
||||
0x20,0xdc,0x91,0xd8,0x2c,0xa6,0xa0,0xb1,
|
||||
0x2d,0x22,0x26,0x94,0x4b,0x40,0x85,0x30,
|
||||
}
|
||||
},
|
||||
{ 0x830107a, {
|
||||
0x2a,0x65,0x8c,0x1a,0x5e,0x07,0x21,0x72,
|
||||
0xdf,0x90,0xa6,0x51,0x37,0xd3,0x4b,0x34,
|
||||
0xc4,0xda,0x03,0xe1,0x8a,0x6c,0xfb,0x20,
|
||||
0x04,0xb2,0x81,0x05,0xd4,0x87,0xf4,0x0a,
|
||||
}
|
||||
},
|
||||
{ 0x830107b, {
|
||||
0xb3,0x43,0x13,0x63,0x56,0xc1,0x39,0xad,
|
||||
0x10,0xa6,0x2b,0xcc,0x02,0xe6,0x76,0x2a,
|
||||
0x1e,0x39,0x58,0x3e,0x23,0x6e,0xa4,0x04,
|
||||
0x95,0xea,0xf9,0x6d,0xc2,0x8a,0x13,0x19,
|
||||
}
|
||||
},
|
||||
{ 0x830107c, {
|
||||
0x21,0x64,0xde,0xfb,0x9f,0x68,0x96,0x47,
|
||||
0x70,0x5c,0xe2,0x8f,0x18,0x52,0x6a,0xac,
|
||||
0xa4,0xd2,0x2e,0xe0,0xde,0x68,0x66,0xc3,
|
||||
0xeb,0x1e,0xd3,0x3f,0xbc,0x51,0x1d,0x38,
|
||||
}
|
||||
},
|
||||
{ 0x860010d, {
|
||||
0x86,0xb6,0x15,0x83,0xbc,0x3b,0x9c,0xe0,
|
||||
0xb3,0xef,0x1d,0x99,0x84,0x35,0x15,0xf7,
|
||||
0x7c,0x2a,0xc6,0x42,0xdb,0x73,0x07,0x5c,
|
||||
0x7d,0xc3,0x02,0xb5,0x43,0x06,0x5e,0xf8,
|
||||
}
|
||||
},
|
||||
{ 0x8608108, {
|
||||
0x14,0xfe,0x57,0x86,0x49,0xc8,0x68,0xe2,
|
||||
0x11,0xa3,0xcb,0x6e,0xff,0x6e,0xd5,0x38,
|
||||
0xfe,0x89,0x1a,0xe0,0x67,0xbf,0xc4,0xcc,
|
||||
0x1b,0x9f,0x84,0x77,0x2b,0x9f,0xaa,0xbd,
|
||||
}
|
||||
},
|
||||
{ 0x8701034, {
|
||||
0xc3,0x14,0x09,0xa8,0x9c,0x3f,0x8d,0x83,
|
||||
0x9b,0x4c,0xa5,0xb7,0x64,0x8b,0x91,0x5d,
|
||||
0x85,0x6a,0x39,0x26,0x1e,0x14,0x41,0xa8,
|
||||
0x75,0xea,0xa6,0xf9,0xc9,0xd1,0xea,0x2b,
|
||||
}
|
||||
},
|
||||
{ 0x8a00008, {
|
||||
0xd7,0x2a,0x93,0xdc,0x05,0x2f,0xa5,0x6e,
|
||||
0x0c,0x61,0x2c,0x07,0x9f,0x38,0xe9,0x8e,
|
||||
0xef,0x7d,0x2a,0x05,0x4d,0x56,0xaf,0x72,
|
||||
0xe7,0x56,0x47,0x6e,0x60,0x27,0xd5,0x8c,
|
||||
}
|
||||
},
|
||||
{ 0x8a0000a, {
|
||||
0x73,0x31,0x26,0x22,0xd4,0xf9,0xee,0x3c,
|
||||
0x07,0x06,0xe7,0xb9,0xad,0xd8,0x72,0x44,
|
||||
0x33,0x31,0xaa,0x7d,0xc3,0x67,0x0e,0xdb,
|
||||
0x47,0xb5,0xaa,0xbc,0xf5,0xbb,0xd9,0x20,
|
||||
}
|
||||
},
|
||||
{ 0xa00104c, {
|
||||
0x3c,0x8a,0xfe,0x04,0x62,0xd8,0x6d,0xbe,
|
||||
0xa7,0x14,0x28,0x64,0x75,0xc0,0xa3,0x76,
|
||||
0xb7,0x92,0x0b,0x97,0x0a,0x8e,0x9c,0x5b,
|
||||
0x1b,0xc8,0x9d,0x3a,0x1e,0x81,0x3d,0x3b,
|
||||
}
|
||||
},
|
||||
{ 0xa00104e, {
|
||||
0xc4,0x35,0x82,0x67,0xd2,0x86,0xe5,0xb2,
|
||||
0xfd,0x69,0x12,0x38,0xc8,0x77,0xba,0xe0,
|
||||
0x70,0xf9,0x77,0x89,0x10,0xa6,0x74,0x4e,
|
||||
0x56,0x58,0x13,0xf5,0x84,0x70,0x28,0x0b,
|
||||
}
|
||||
},
|
||||
{ 0xa001053, {
|
||||
0x92,0x0e,0xf4,0x69,0x10,0x3b,0xf9,0x9d,
|
||||
0x31,0x1b,0xa6,0x99,0x08,0x7d,0xd7,0x25,
|
||||
0x7e,0x1e,0x89,0xba,0x35,0x8d,0xac,0xcb,
|
||||
0x3a,0xb4,0xdf,0x58,0x12,0xcf,0xc0,0xc3,
|
||||
}
|
||||
},
|
||||
{ 0xa001058, {
|
||||
0x33,0x7d,0xa9,0xb5,0x4e,0x62,0x13,0x36,
|
||||
0xef,0x66,0xc9,0xbd,0x0a,0xa6,0x3b,0x19,
|
||||
0xcb,0xf5,0xc2,0xc3,0x55,0x47,0x20,0xec,
|
||||
0x1f,0x7b,0xa1,0x44,0x0e,0x8e,0xa4,0xb2,
|
||||
}
|
||||
},
|
||||
{ 0xa001075, {
|
||||
0x39,0x02,0x82,0xd0,0x7c,0x26,0x43,0xe9,
|
||||
0x26,0xa3,0xd9,0x96,0xf7,0x30,0x13,0x0a,
|
||||
0x8a,0x0e,0xac,0xe7,0x1d,0xdc,0xe2,0x0f,
|
||||
0xcb,0x9e,0x8d,0xbc,0xd2,0xa2,0x44,0xe0,
|
||||
}
|
||||
},
|
||||
{ 0xa001078, {
|
||||
0x2d,0x67,0xc7,0x35,0xca,0xef,0x2f,0x25,
|
||||
0x4c,0x45,0x93,0x3f,0x36,0x01,0x8c,0xce,
|
||||
0xa8,0x5b,0x07,0xd3,0xc1,0x35,0x3c,0x04,
|
||||
0x20,0xa2,0xfc,0xdc,0xe6,0xce,0x26,0x3e,
|
||||
}
|
||||
},
|
||||
{ 0xa001079, {
|
||||
0x43,0xe2,0x05,0x9c,0xfd,0xb7,0x5b,0xeb,
|
||||
0x5b,0xe9,0xeb,0x3b,0x96,0xf4,0xe4,0x93,
|
||||
0x73,0x45,0x3e,0xac,0x8d,0x3b,0xe4,0xdb,
|
||||
0x10,0x31,0xc1,0xe4,0xa2,0xd0,0x5a,0x8a,
|
||||
}
|
||||
},
|
||||
{ 0xa00107a, {
|
||||
0x5f,0x92,0xca,0xff,0xc3,0x59,0x22,0x5f,
|
||||
0x02,0xa0,0x91,0x3b,0x4a,0x45,0x10,0xfd,
|
||||
0x19,0xe1,0x8a,0x6d,0x9a,0x92,0xc1,0x3f,
|
||||
0x75,0x78,0xac,0x78,0x03,0x1d,0xdb,0x18,
|
||||
}
|
||||
},
|
||||
{ 0xa001143, {
|
||||
0x56,0xca,0xf7,0x43,0x8a,0x4c,0x46,0x80,
|
||||
0xec,0xde,0xe5,0x9c,0x50,0x84,0x9a,0x42,
|
||||
0x27,0xe5,0x51,0x84,0x8f,0x19,0xc0,0x8d,
|
||||
0x0c,0x25,0xb4,0xb0,0x8f,0x10,0xf3,0xf8,
|
||||
}
|
||||
},
|
||||
{ 0xa001144, {
|
||||
0x42,0xd5,0x9b,0xa7,0xd6,0x15,0x29,0x41,
|
||||
0x61,0xc4,0x72,0x3f,0xf3,0x06,0x78,0x4b,
|
||||
0x65,0xf3,0x0e,0xfa,0x9c,0x87,0xde,0x25,
|
||||
0xbd,0xb3,0x9a,0xf4,0x75,0x13,0x53,0xdc,
|
||||
}
|
||||
},
|
||||
{ 0xa00115d, {
|
||||
0xd4,0xc4,0x49,0x36,0x89,0x0b,0x47,0xdd,
|
||||
0xfb,0x2f,0x88,0x3b,0x5f,0xf2,0x8e,0x75,
|
||||
0xc6,0x6c,0x37,0x5a,0x90,0x25,0x94,0x3e,
|
||||
0x36,0x9c,0xae,0x02,0x38,0x6c,0xf5,0x05,
|
||||
}
|
||||
},
|
||||
{ 0xa001173, {
|
||||
0x28,0xbb,0x9b,0xd1,0xa0,0xa0,0x7e,0x3a,
|
||||
0x59,0x20,0xc0,0xa9,0xb2,0x5c,0xc3,0x35,
|
||||
0x53,0x89,0xe1,0x4c,0x93,0x2f,0x1d,0xc3,
|
||||
0xe5,0xf7,0xf3,0xc8,0x9b,0x61,0xaa,0x9e,
|
||||
}
|
||||
},
|
||||
{ 0xa0011a8, {
|
||||
0x97,0xc6,0x16,0x65,0x99,0xa4,0x85,0x3b,
|
||||
0xf6,0xce,0xaa,0x49,0x4a,0x3a,0xc5,0xb6,
|
||||
0x78,0x25,0xbc,0x53,0xaf,0x5d,0xcf,0xf4,
|
||||
0x23,0x12,0xbb,0xb1,0xbc,0x8a,0x02,0x2e,
|
||||
}
|
||||
},
|
||||
{ 0xa0011ce, {
|
||||
0xcf,0x1c,0x90,0xa3,0x85,0x0a,0xbf,0x71,
|
||||
0x94,0x0e,0x80,0x86,0x85,0x4f,0xd7,0x86,
|
||||
0xae,0x38,0x23,0x28,0x2b,0x35,0x9b,0x4e,
|
||||
0xfe,0xb8,0xcd,0x3d,0x3d,0x39,0xc9,0x6a,
|
||||
}
|
||||
},
|
||||
{ 0xa0011d1, {
|
||||
0xdf,0x0e,0xca,0xde,0xf6,0xce,0x5c,0x1e,
|
||||
0x4c,0xec,0xd7,0x71,0x83,0xcc,0xa8,0x09,
|
||||
0xc7,0xc5,0xfe,0xb2,0xf7,0x05,0xd2,0xc5,
|
||||
0x12,0xdd,0xe4,0xf3,0x92,0x1c,0x3d,0xb8,
|
||||
}
|
||||
},
|
||||
{ 0xa0011d3, {
|
||||
0x91,0xe6,0x10,0xd7,0x57,0xb0,0x95,0x0b,
|
||||
0x9a,0x24,0xee,0xf7,0xcf,0x56,0xc1,0xa6,
|
||||
0x4a,0x52,0x7d,0x5f,0x9f,0xdf,0xf6,0x00,
|
||||
0x65,0xf7,0xea,0xe8,0x2a,0x88,0xe2,0x26,
|
||||
}
|
||||
},
|
||||
{ 0xa0011d5, {
|
||||
0xed,0x69,0x89,0xf4,0xeb,0x64,0xc2,0x13,
|
||||
0xe0,0x51,0x1f,0x03,0x26,0x52,0x7d,0xb7,
|
||||
0x93,0x5d,0x65,0xca,0xb8,0x12,0x1d,0x62,
|
||||
0x0d,0x5b,0x65,0x34,0x69,0xb2,0x62,0x21,
|
||||
}
|
||||
},
|
||||
{ 0xa001223, {
|
||||
0xfb,0x32,0x5f,0xc6,0x83,0x4f,0x8c,0xb8,
|
||||
0xa4,0x05,0xf9,0x71,0x53,0x01,0x16,0xc4,
|
||||
0x83,0x75,0x94,0xdd,0xeb,0x7e,0xb7,0x15,
|
||||
0x8e,0x3b,0x50,0x29,0x8a,0x9c,0xcc,0x45,
|
||||
}
|
||||
},
|
||||
{ 0xa001224, {
|
||||
0x0e,0x0c,0xdf,0xb4,0x89,0xee,0x35,0x25,
|
||||
0xdd,0x9e,0xdb,0xc0,0x69,0x83,0x0a,0xad,
|
||||
0x26,0xa9,0xaa,0x9d,0xfc,0x3c,0xea,0xf9,
|
||||
0x6c,0xdc,0xd5,0x6d,0x8b,0x6e,0x85,0x4a,
|
||||
}
|
||||
},
|
||||
{ 0xa001227, {
|
||||
0xab,0xc6,0x00,0x69,0x4b,0x50,0x87,0xad,
|
||||
0x5f,0x0e,0x8b,0xea,0x57,0x38,0xce,0x1d,
|
||||
0x0f,0x75,0x26,0x02,0xf6,0xd6,0x96,0xe9,
|
||||
0x87,0xb9,0xd6,0x20,0x27,0x7c,0xd2,0xe0,
|
||||
}
|
||||
},
|
||||
{ 0xa001229, {
|
||||
0x7f,0x49,0x49,0x48,0x46,0xa5,0x50,0xa6,
|
||||
0x28,0x89,0x98,0xe2,0x9e,0xb4,0x7f,0x75,
|
||||
0x33,0xa7,0x04,0x02,0xe4,0x82,0xbf,0xb4,
|
||||
0xa5,0x3a,0xba,0x24,0x8d,0x31,0x10,0x1d,
|
||||
}
|
||||
},
|
||||
{ 0xa00122e, {
|
||||
0x56,0x94,0xa9,0x5d,0x06,0x68,0xfe,0xaf,
|
||||
0xdf,0x7a,0xff,0x2d,0xdf,0x74,0x0f,0x15,
|
||||
0x66,0xfb,0x00,0xb5,0x51,0x97,0x9b,0xfa,
|
||||
0xcb,0x79,0x85,0x46,0x25,0xb4,0xd2,0x10,
|
||||
}
|
||||
},
|
||||
{ 0xa001231, {
|
||||
0x0b,0x46,0xa5,0xfc,0x18,0x15,0xa0,0x9e,
|
||||
0xa6,0xdc,0xb7,0xff,0x17,0xf7,0x30,0x64,
|
||||
0xd4,0xda,0x9e,0x1b,0xc3,0xfc,0x02,0x3b,
|
||||
0xe2,0xc6,0x0e,0x41,0x54,0xb5,0x18,0xdd,
|
||||
}
|
||||
},
|
||||
{ 0xa001234, {
|
||||
0x88,0x8d,0xed,0xab,0xb5,0xbd,0x4e,0xf7,
|
||||
0x7f,0xd4,0x0e,0x95,0x34,0x91,0xff,0xcc,
|
||||
0xfb,0x2a,0xcd,0xf7,0xd5,0xdb,0x4c,0x9b,
|
||||
0xd6,0x2e,0x73,0x50,0x8f,0x83,0x79,0x1a,
|
||||
}
|
||||
},
|
||||
{ 0xa001236, {
|
||||
0x3d,0x30,0x00,0xb9,0x71,0xba,0x87,0x78,
|
||||
0xa8,0x43,0x55,0xc4,0x26,0x59,0xcf,0x9d,
|
||||
0x93,0xce,0x64,0x0e,0x8b,0x72,0x11,0x8b,
|
||||
0xa3,0x8f,0x51,0xe9,0xca,0x98,0xaa,0x25,
|
||||
}
|
||||
},
|
||||
{ 0xa001238, {
|
||||
0x72,0xf7,0x4b,0x0c,0x7d,0x58,0x65,0xcc,
|
||||
0x00,0xcc,0x57,0x16,0x68,0x16,0xf8,0x2a,
|
||||
0x1b,0xb3,0x8b,0xe1,0xb6,0x83,0x8c,0x7e,
|
||||
0xc0,0xcd,0x33,0xf2,0x8d,0xf9,0xef,0x59,
|
||||
}
|
||||
},
|
||||
{ 0xa00820c, {
|
||||
0xa8,0x0c,0x81,0xc0,0xa6,0x00,0xe7,0xf3,
|
||||
0x5f,0x65,0xd3,0xb9,0x6f,0xea,0x93,0x63,
|
||||
0xf1,0x8c,0x88,0x45,0xd7,0x82,0x80,0xd1,
|
||||
0xe1,0x3b,0x8d,0xb2,0xf8,0x22,0x03,0xe2,
|
||||
}
|
||||
},
|
||||
{ 0xa10113e, {
|
||||
0x05,0x3c,0x66,0xd7,0xa9,0x5a,0x33,0x10,
|
||||
0x1b,0xf8,0x9c,0x8f,0xed,0xfc,0xa7,0xa0,
|
||||
0x15,0xe3,0x3f,0x4b,0x1d,0x0d,0x0a,0xd5,
|
||||
0xfa,0x90,0xc4,0xed,0x9d,0x90,0xaf,0x53,
|
||||
}
|
||||
},
|
||||
{ 0xa101144, {
|
||||
0xb3,0x0b,0x26,0x9a,0xf8,0x7c,0x02,0x26,
|
||||
0x35,0x84,0x53,0xa4,0xd3,0x2c,0x7c,0x09,
|
||||
0x68,0x7b,0x96,0xb6,0x93,0xef,0xde,0xbc,
|
||||
0xfd,0x4b,0x15,0xd2,0x81,0xd3,0x51,0x47,
|
||||
}
|
||||
},
|
||||
{ 0xa101148, {
|
||||
0x20,0xd5,0x6f,0x40,0x4a,0xf6,0x48,0x90,
|
||||
0xc2,0x93,0x9a,0xc2,0xfd,0xac,0xef,0x4f,
|
||||
0xfa,0xc0,0x3d,0x92,0x3c,0x6d,0x01,0x08,
|
||||
0xf1,0x5e,0xb0,0xde,0xb4,0x98,0xae,0xc4,
|
||||
}
|
||||
},
|
||||
{ 0xa10123e, {
|
||||
0x03,0xb9,0x2c,0x76,0x48,0x93,0xc9,0x18,
|
||||
0xfb,0x56,0xfd,0xf7,0xe2,0x1d,0xca,0x4d,
|
||||
0x1d,0x13,0x53,0x63,0xfe,0x42,0x6f,0xfc,
|
||||
0x19,0x0f,0xf1,0xfc,0xa7,0xdd,0x89,0x1b,
|
||||
}
|
||||
},
|
||||
{ 0xa101244, {
|
||||
0x71,0x56,0xb5,0x9f,0x21,0xbf,0xb3,0x3c,
|
||||
0x8c,0xd7,0x36,0xd0,0x34,0x52,0x1b,0xb1,
|
||||
0x46,0x2f,0x04,0xf0,0x37,0xd8,0x1e,0x72,
|
||||
0x24,0xa2,0x80,0x84,0x83,0x65,0x84,0xc0,
|
||||
}
|
||||
},
|
||||
{ 0xa101248, {
|
||||
0xed,0x3b,0x95,0xa6,0x68,0xa7,0x77,0x3e,
|
||||
0xfc,0x17,0x26,0xe2,0x7b,0xd5,0x56,0x22,
|
||||
0x2c,0x1d,0xef,0xeb,0x56,0xdd,0xba,0x6e,
|
||||
0x1b,0x7d,0x64,0x9d,0x4b,0x53,0x13,0x75,
|
||||
}
|
||||
},
|
||||
{ 0xa108108, {
|
||||
0xed,0xc2,0xec,0xa1,0x15,0xc6,0x65,0xe9,
|
||||
0xd0,0xef,0x39,0xaa,0x7f,0x55,0x06,0xc6,
|
||||
0xf5,0xd4,0x3f,0x7b,0x14,0xd5,0x60,0x2c,
|
||||
0x28,0x1e,0x9c,0x59,0x69,0x99,0x4d,0x16,
|
||||
}
|
||||
},
|
||||
{ 0xa20102d, {
|
||||
0xf9,0x6e,0xf2,0x32,0xd3,0x0f,0x5f,0x11,
|
||||
0x59,0xa1,0xfe,0xcc,0xcd,0x9b,0x42,0x89,
|
||||
0x8b,0x89,0x2f,0xb5,0xbb,0x82,0xef,0x23,
|
||||
0x8c,0xe9,0x19,0x3e,0xcc,0x3f,0x7b,0xb4,
|
||||
}
|
||||
},
|
||||
{ 0xa201210, {
|
||||
0xe8,0x6d,0x51,0x6a,0x8e,0x72,0xf3,0xfe,
|
||||
0x6e,0x16,0xbc,0x62,0x59,0x40,0x17,0xe9,
|
||||
0x6d,0x3d,0x0e,0x6b,0xa7,0xac,0xe3,0x68,
|
||||
0xf7,0x55,0xf0,0x13,0xbb,0x22,0xf6,0x41,
|
||||
}
|
||||
},
|
||||
{ 0xa404107, {
|
||||
0xbb,0x04,0x4e,0x47,0xdd,0x5e,0x26,0x45,
|
||||
0x1a,0xc9,0x56,0x24,0xa4,0x4c,0x82,0xb0,
|
||||
0x8b,0x0d,0x9f,0xf9,0x3a,0xdf,0xc6,0x81,
|
||||
0x13,0xbc,0xc5,0x25,0xe4,0xc5,0xc3,0x99,
|
||||
}
|
||||
},
|
||||
{ 0xa500011, {
|
||||
0x23,0x3d,0x70,0x7d,0x03,0xc3,0xc4,0xf4,
|
||||
0x2b,0x82,0xc6,0x05,0xda,0x80,0x0a,0xf1,
|
||||
0xd7,0x5b,0x65,0x3a,0x7d,0xab,0xdf,0xa2,
|
||||
0x11,0x5e,0x96,0x7e,0x71,0xe9,0xfc,0x74,
|
||||
}
|
||||
},
|
||||
{ 0xa601209, {
|
||||
0x66,0x48,0xd4,0x09,0x05,0xcb,0x29,0x32,
|
||||
0x66,0xb7,0x9a,0x76,0xcd,0x11,0xf3,0x30,
|
||||
0x15,0x86,0xcc,0x5d,0x97,0x0f,0xc0,0x46,
|
||||
0xe8,0x73,0xe2,0xd6,0xdb,0xd2,0x77,0x1d,
|
||||
}
|
||||
},
|
||||
{ 0xa704107, {
|
||||
0xf3,0xc6,0x58,0x26,0xee,0xac,0x3f,0xd6,
|
||||
0xce,0xa1,0x72,0x47,0x3b,0xba,0x2b,0x93,
|
||||
0x2a,0xad,0x8e,0x6b,0xea,0x9b,0xb7,0xc2,
|
||||
0x64,0x39,0x71,0x8c,0xce,0xe7,0x41,0x39,
|
||||
}
|
||||
},
|
||||
{ 0xa705206, {
|
||||
0x8d,0xc0,0x76,0xbd,0x58,0x9f,0x8f,0xa4,
|
||||
0x12,0x9d,0x21,0xfb,0x48,0x21,0xbc,0xe7,
|
||||
0x67,0x6f,0x04,0x18,0xae,0x20,0x87,0x4b,
|
||||
0x03,0x35,0xe9,0xbe,0xfb,0x06,0xdf,0xfc,
|
||||
}
|
||||
},
|
||||
{ 0xa708007, {
|
||||
0x6b,0x76,0xcc,0x78,0xc5,0x8a,0xa3,0xe3,
|
||||
0x32,0x2d,0x79,0xe4,0xc3,0x80,0xdb,0xb2,
|
||||
0x07,0xaa,0x3a,0xe0,0x57,0x13,0x72,0x80,
|
||||
0xdf,0x92,0x73,0x84,0x87,0x3c,0x73,0x93,
|
||||
}
|
||||
},
|
||||
{ 0xa70c005, {
|
||||
0x88,0x5d,0xfb,0x79,0x64,0xd8,0x46,0x3b,
|
||||
0x4a,0x83,0x8e,0x77,0x7e,0xcf,0xb3,0x0f,
|
||||
0x1f,0x1f,0xf1,0x97,0xeb,0xfe,0x56,0x55,
|
||||
0xee,0x49,0xac,0xe1,0x8b,0x13,0xc5,0x13,
|
||||
}
|
||||
},
|
||||
{ 0xaa00116, {
|
||||
0xe8,0x4c,0x2c,0x88,0xa1,0xac,0x24,0x63,
|
||||
0x65,0xe5,0xaa,0x2d,0x16,0xa9,0xc3,0xf5,
|
||||
0xfe,0x1d,0x5e,0x65,0xc7,0xaa,0x92,0x4d,
|
||||
0x91,0xee,0x76,0xbb,0x4c,0x66,0x78,0xc9,
|
||||
}
|
||||
},
|
||||
{ 0xaa00212, {
|
||||
0xbd,0x57,0x5d,0x0a,0x0a,0x30,0xc1,0x75,
|
||||
0x95,0x58,0x5e,0x93,0x02,0x28,0x43,0x71,
|
||||
0xed,0x42,0x29,0xc8,0xec,0x34,0x2b,0xb2,
|
||||
0x1a,0x65,0x4b,0xfe,0x07,0x0f,0x34,0xa1,
|
||||
}
|
||||
},
|
||||
{ 0xaa00213, {
|
||||
0xed,0x58,0xb7,0x76,0x81,0x7f,0xd9,0x3a,
|
||||
0x1a,0xff,0x8b,0x34,0xb8,0x4a,0x99,0x0f,
|
||||
0x28,0x49,0x6c,0x56,0x2b,0xdc,0xb7,0xed,
|
||||
0x96,0xd5,0x9d,0xc1,0x7a,0xd4,0x51,0x9b,
|
||||
}
|
||||
},
|
||||
{ 0xaa00215, {
|
||||
0x55,0xd3,0x28,0xcb,0x87,0xa9,0x32,0xe9,
|
||||
0x4e,0x85,0x4b,0x7c,0x6b,0xd5,0x7c,0xd4,
|
||||
0x1b,0x51,0x71,0x3a,0x0e,0x0b,0xdc,0x9b,
|
||||
0x68,0x2f,0x46,0xee,0xfe,0xc6,0x6d,0xef,
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -100,14 +100,12 @@ extern bool force_minrev;
|
||||
#ifdef CONFIG_CPU_SUP_AMD
|
||||
void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family);
|
||||
void load_ucode_amd_ap(unsigned int family);
|
||||
int save_microcode_in_initrd_amd(unsigned int family);
|
||||
void reload_ucode_amd(unsigned int cpu);
|
||||
struct microcode_ops *init_amd_microcode(void);
|
||||
void exit_amd_microcode(void);
|
||||
#else /* CONFIG_CPU_SUP_AMD */
|
||||
static inline void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family) { }
|
||||
static inline void load_ucode_amd_ap(unsigned int family) { }
|
||||
static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
|
||||
static inline void reload_ucode_amd(unsigned int cpu) { }
|
||||
static inline struct microcode_ops *init_amd_microcode(void) { return NULL; }
|
||||
static inline void exit_amd_microcode(void) { }
|
||||
|
||||
+69
-7
@@ -427,13 +427,14 @@ static bool disk_insert_zone_wplug(struct gendisk *disk,
|
||||
}
|
||||
}
|
||||
hlist_add_head_rcu(&zwplug->node, &disk->zone_wplugs_hash[idx]);
|
||||
atomic_inc(&disk->nr_zone_wplugs);
|
||||
spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct blk_zone_wplug *disk_get_zone_wplug(struct gendisk *disk,
|
||||
sector_t sector)
|
||||
static struct blk_zone_wplug *disk_get_hashed_zone_wplug(struct gendisk *disk,
|
||||
sector_t sector)
|
||||
{
|
||||
unsigned int zno = disk_zone_no(disk, sector);
|
||||
unsigned int idx = hash_32(zno, disk->zone_wplugs_hash_bits);
|
||||
@@ -454,6 +455,15 @@ static struct blk_zone_wplug *disk_get_zone_wplug(struct gendisk *disk,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct blk_zone_wplug *disk_get_zone_wplug(struct gendisk *disk,
|
||||
sector_t sector)
|
||||
{
|
||||
if (!atomic_read(&disk->nr_zone_wplugs))
|
||||
return NULL;
|
||||
|
||||
return disk_get_hashed_zone_wplug(disk, sector);
|
||||
}
|
||||
|
||||
static void disk_free_zone_wplug_rcu(struct rcu_head *rcu_head)
|
||||
{
|
||||
struct blk_zone_wplug *zwplug =
|
||||
@@ -518,6 +528,7 @@ static void disk_remove_zone_wplug(struct gendisk *disk,
|
||||
zwplug->flags |= BLK_ZONE_WPLUG_UNHASHED;
|
||||
spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
|
||||
hlist_del_init_rcu(&zwplug->node);
|
||||
atomic_dec(&disk->nr_zone_wplugs);
|
||||
spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
|
||||
disk_put_zone_wplug(zwplug);
|
||||
}
|
||||
@@ -607,6 +618,11 @@ static void disk_zone_wplug_abort(struct blk_zone_wplug *zwplug)
|
||||
{
|
||||
struct bio *bio;
|
||||
|
||||
if (bio_list_empty(&zwplug->bio_list))
|
||||
return;
|
||||
|
||||
pr_warn_ratelimited("%s: zone %u: Aborting plugged BIOs\n",
|
||||
zwplug->disk->disk_name, zwplug->zone_no);
|
||||
while ((bio = bio_list_pop(&zwplug->bio_list)))
|
||||
blk_zone_wplug_bio_io_error(zwplug, bio);
|
||||
}
|
||||
@@ -1055,6 +1071,47 @@ plug:
|
||||
return true;
|
||||
}
|
||||
|
||||
static void blk_zone_wplug_handle_native_zone_append(struct bio *bio)
|
||||
{
|
||||
struct gendisk *disk = bio->bi_bdev->bd_disk;
|
||||
struct blk_zone_wplug *zwplug;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* We have native support for zone append operations, so we are not
|
||||
* going to handle @bio through plugging. However, we may already have a
|
||||
* zone write plug for the target zone if that zone was previously
|
||||
* partially written using regular writes. In such case, we risk leaving
|
||||
* the plug in the disk hash table if the zone is fully written using
|
||||
* zone append operations. Avoid this by removing the zone write plug.
|
||||
*/
|
||||
zwplug = disk_get_zone_wplug(disk, bio->bi_iter.bi_sector);
|
||||
if (likely(!zwplug))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&zwplug->lock, flags);
|
||||
|
||||
/*
|
||||
* We are about to remove the zone write plug. But if the user
|
||||
* (mistakenly) has issued regular writes together with native zone
|
||||
* append, we must aborts the writes as otherwise the plugged BIOs would
|
||||
* not be executed by the plug BIO work as disk_get_zone_wplug() will
|
||||
* return NULL after the plug is removed. Aborting the plugged write
|
||||
* BIOs is consistent with the fact that these writes will most likely
|
||||
* fail anyway as there is no ordering guarantees between zone append
|
||||
* operations and regular write operations.
|
||||
*/
|
||||
if (!bio_list_empty(&zwplug->bio_list)) {
|
||||
pr_warn_ratelimited("%s: zone %u: Invalid mix of zone append and regular writes\n",
|
||||
disk->disk_name, zwplug->zone_no);
|
||||
disk_zone_wplug_abort(zwplug);
|
||||
}
|
||||
disk_remove_zone_wplug(disk, zwplug);
|
||||
spin_unlock_irqrestore(&zwplug->lock, flags);
|
||||
|
||||
disk_put_zone_wplug(zwplug);
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_zone_plug_bio - Handle a zone write BIO with zone write plugging
|
||||
* @bio: The BIO being submitted
|
||||
@@ -1111,8 +1168,10 @@ bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs)
|
||||
*/
|
||||
switch (bio_op(bio)) {
|
||||
case REQ_OP_ZONE_APPEND:
|
||||
if (!bdev_emulates_zone_append(bdev))
|
||||
if (!bdev_emulates_zone_append(bdev)) {
|
||||
blk_zone_wplug_handle_native_zone_append(bio);
|
||||
return false;
|
||||
}
|
||||
fallthrough;
|
||||
case REQ_OP_WRITE:
|
||||
case REQ_OP_WRITE_ZEROES:
|
||||
@@ -1299,6 +1358,7 @@ static int disk_alloc_zone_resources(struct gendisk *disk,
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
atomic_set(&disk->nr_zone_wplugs, 0);
|
||||
disk->zone_wplugs_hash_bits =
|
||||
min(ilog2(pool_size) + 1, BLK_ZONE_WPLUG_MAX_HASH_BITS);
|
||||
|
||||
@@ -1353,6 +1413,7 @@ static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk)
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(atomic_read(&disk->nr_zone_wplugs));
|
||||
kfree(disk->zone_wplugs_hash);
|
||||
disk->zone_wplugs_hash = NULL;
|
||||
disk->zone_wplugs_hash_bits = 0;
|
||||
@@ -1570,11 +1631,12 @@ static int blk_revalidate_seq_zone(struct blk_zone *zone, unsigned int idx,
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to track the write pointer of all zones that are not
|
||||
* empty nor full. So make sure we have a zone write plug for
|
||||
* such zone if the device has a zone write plug hash table.
|
||||
* If the device needs zone append emulation, we need to track the
|
||||
* write pointer of all zones that are not empty nor full. So make sure
|
||||
* we have a zone write plug for such zone if the device has a zone
|
||||
* write plug hash table.
|
||||
*/
|
||||
if (!disk->zone_wplugs_hash)
|
||||
if (!queue_emulates_zone_append(disk->queue) || !disk->zone_wplugs_hash)
|
||||
return 0;
|
||||
|
||||
disk_zone_wplug_sync_wp_offset(disk, zone);
|
||||
|
||||
@@ -1609,8 +1609,8 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
ret = regmap_raw_write_async(regmap, reg, buf->buf,
|
||||
le32_to_cpu(region->len));
|
||||
ret = regmap_raw_write(regmap, reg, buf->buf,
|
||||
le32_to_cpu(region->len));
|
||||
if (ret != 0) {
|
||||
cs_dsp_err(dsp,
|
||||
"%s.%d: Failed to write %d bytes at %d in %s: %d\n",
|
||||
@@ -1625,12 +1625,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
regions++;
|
||||
}
|
||||
|
||||
ret = regmap_async_complete(regmap);
|
||||
if (ret != 0) {
|
||||
cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret);
|
||||
goto out_fw;
|
||||
}
|
||||
|
||||
if (pos > firmware->size)
|
||||
cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
|
||||
file, regions, pos - firmware->size);
|
||||
@@ -1638,7 +1632,6 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
|
||||
cs_dsp_debugfs_save_wmfwname(dsp, file);
|
||||
|
||||
out_fw:
|
||||
regmap_async_complete(regmap);
|
||||
cs_dsp_buf_free(&buf_list);
|
||||
|
||||
if (ret == -EOVERFLOW)
|
||||
@@ -2326,8 +2319,8 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
||||
cs_dsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
|
||||
file, blocks, le32_to_cpu(blk->len),
|
||||
reg);
|
||||
ret = regmap_raw_write_async(regmap, reg, buf->buf,
|
||||
le32_to_cpu(blk->len));
|
||||
ret = regmap_raw_write(regmap, reg, buf->buf,
|
||||
le32_to_cpu(blk->len));
|
||||
if (ret != 0) {
|
||||
cs_dsp_err(dsp,
|
||||
"%s.%d: Failed to write to %x in %s: %d\n",
|
||||
@@ -2339,10 +2332,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
||||
blocks++;
|
||||
}
|
||||
|
||||
ret = regmap_async_complete(regmap);
|
||||
if (ret != 0)
|
||||
cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret);
|
||||
|
||||
if (pos > firmware->size)
|
||||
cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
|
||||
file, blocks, pos - firmware->size);
|
||||
@@ -2350,7 +2339,6 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware
|
||||
cs_dsp_debugfs_save_binname(dsp, file);
|
||||
|
||||
out_fw:
|
||||
regmap_async_complete(regmap);
|
||||
cs_dsp_buf_free(&buf_list);
|
||||
|
||||
if (ret == -EOVERFLOW)
|
||||
@@ -2561,8 +2549,8 @@ static int cs_dsp_adsp2_enable_core(struct cs_dsp *dsp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
|
||||
ADSP2_SYS_ENA, ADSP2_SYS_ENA);
|
||||
ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
|
||||
ADSP2_SYS_ENA, ADSP2_SYS_ENA);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -103,9 +103,7 @@ void __init efi_mokvar_table_init(void)
|
||||
void *va = NULL;
|
||||
unsigned long cur_offset = 0;
|
||||
unsigned long offset_limit;
|
||||
unsigned long map_size = 0;
|
||||
unsigned long map_size_needed = 0;
|
||||
unsigned long size;
|
||||
struct efi_mokvar_table_entry *mokvar_entry;
|
||||
int err;
|
||||
|
||||
@@ -134,48 +132,34 @@ void __init efi_mokvar_table_init(void)
|
||||
*/
|
||||
err = -EINVAL;
|
||||
while (cur_offset + sizeof(*mokvar_entry) <= offset_limit) {
|
||||
mokvar_entry = va + cur_offset;
|
||||
map_size_needed = cur_offset + sizeof(*mokvar_entry);
|
||||
if (map_size_needed > map_size) {
|
||||
if (va)
|
||||
early_memunmap(va, map_size);
|
||||
/*
|
||||
* Map a little more than the fixed size entry
|
||||
* header, anticipating some data. It's safe to
|
||||
* do so as long as we stay within current memory
|
||||
* descriptor.
|
||||
*/
|
||||
map_size = min(map_size_needed + 2*EFI_PAGE_SIZE,
|
||||
offset_limit);
|
||||
va = early_memremap(efi.mokvar_table, map_size);
|
||||
if (!va) {
|
||||
pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%lu.\n",
|
||||
efi.mokvar_table, map_size);
|
||||
return;
|
||||
}
|
||||
mokvar_entry = va + cur_offset;
|
||||
if (va)
|
||||
early_memunmap(va, sizeof(*mokvar_entry));
|
||||
va = early_memremap(efi.mokvar_table + cur_offset, sizeof(*mokvar_entry));
|
||||
if (!va) {
|
||||
pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%zu.\n",
|
||||
efi.mokvar_table + cur_offset, sizeof(*mokvar_entry));
|
||||
return;
|
||||
}
|
||||
mokvar_entry = va;
|
||||
|
||||
/* Check for last sentinel entry */
|
||||
if (mokvar_entry->name[0] == '\0') {
|
||||
if (mokvar_entry->data_size != 0)
|
||||
break;
|
||||
err = 0;
|
||||
map_size_needed = cur_offset + sizeof(*mokvar_entry);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Sanity check that the name is null terminated */
|
||||
size = strnlen(mokvar_entry->name,
|
||||
sizeof(mokvar_entry->name));
|
||||
if (size >= sizeof(mokvar_entry->name))
|
||||
break;
|
||||
/* Enforce that the name is NUL terminated */
|
||||
mokvar_entry->name[sizeof(mokvar_entry->name) - 1] = '\0';
|
||||
|
||||
/* Advance to the next entry */
|
||||
cur_offset = map_size_needed + mokvar_entry->data_size;
|
||||
cur_offset += sizeof(*mokvar_entry) + mokvar_entry->data_size;
|
||||
}
|
||||
|
||||
if (va)
|
||||
early_memunmap(va, map_size);
|
||||
early_memunmap(va, sizeof(*mokvar_entry));
|
||||
if (err) {
|
||||
pr_err("EFI MOKvar config table is not valid\n");
|
||||
return;
|
||||
|
||||
@@ -1542,6 +1542,13 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
/* resizing on Dell G5 SE platforms causes problems with runtime pm */
|
||||
if ((amdgpu_runtime_pm != 0) &&
|
||||
adev->pdev->vendor == PCI_VENDOR_ID_ATI &&
|
||||
adev->pdev->device == 0x731f &&
|
||||
adev->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
|
||||
return 0;
|
||||
|
||||
/* PCI_EXT_CAP_ID_VNDR extended capability is located at 0x100 */
|
||||
if (!pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_VNDR))
|
||||
DRM_WARN("System can't access extended configuration space, please check!!\n");
|
||||
|
||||
@@ -2280,7 +2280,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo,
|
||||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
struct amdgpu_res_cursor cursor;
|
||||
u64 addr;
|
||||
int r;
|
||||
int r = 0;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -107,6 +107,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
|
||||
0x53 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT;
|
||||
|
||||
m->cp_mqd_base_addr_lo = lower_32_bits(addr);
|
||||
@@ -167,10 +169,10 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK;
|
||||
m->cp_hqd_pq_control |=
|
||||
ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
|
||||
|
||||
@@ -154,6 +154,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
|
||||
0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT;
|
||||
|
||||
m->cp_mqd_base_addr_lo = lower_32_bits(addr);
|
||||
@@ -221,10 +223,9 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK;
|
||||
m->cp_hqd_pq_control |=
|
||||
ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
|
||||
|
||||
@@ -121,6 +121,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
|
||||
0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT;
|
||||
|
||||
m->cp_mqd_base_addr_lo = lower_32_bits(addr);
|
||||
@@ -184,10 +186,9 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK;
|
||||
m->cp_hqd_pq_control |=
|
||||
ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
|
||||
|
||||
@@ -182,6 +182,9 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
||||
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
|
||||
0x53 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
|
||||
m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT;
|
||||
|
||||
m->cp_mqd_base_addr_lo = lower_32_bits(addr);
|
||||
@@ -244,7 +247,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
||||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK;
|
||||
m->cp_hqd_pq_control |= order_base_2(q->queue_size / 4) - 1;
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
|
||||
@@ -1593,75 +1593,130 @@ static bool dm_should_disable_stutter(struct pci_dev *pdev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id hpd_disconnect_quirk_table[] = {
|
||||
struct amdgpu_dm_quirks {
|
||||
bool aux_hpd_discon;
|
||||
bool support_edp0_on_dp1;
|
||||
};
|
||||
|
||||
static struct amdgpu_dm_quirks quirk_entries = {
|
||||
.aux_hpd_discon = false,
|
||||
.support_edp0_on_dp1 = false
|
||||
};
|
||||
|
||||
static int edp0_on_dp1_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
quirk_entries.support_edp0_on_dp1 = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aux_hpd_discon_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
quirk_entries.aux_hpd_discon = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id dmi_quirk_table[] = {
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3660"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3260"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3460"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower Plus 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF Plus 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro Plus 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = edp0_on_dp1_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite mt645 G8 Mobile Thin Client"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = edp0_on_dp1_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 665 16 inch G11 Notebook PC"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
/* TODO: refactor this from a fixed table to a dynamic option */
|
||||
};
|
||||
|
||||
static void retrieve_dmi_info(struct amdgpu_display_manager *dm)
|
||||
static void retrieve_dmi_info(struct amdgpu_display_manager *dm, struct dc_init_data *init_data)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
int dmi_id;
|
||||
struct drm_device *dev = dm->ddev;
|
||||
|
||||
dm->aux_hpd_discon_quirk = false;
|
||||
init_data->flags.support_edp0_on_dp1 = false;
|
||||
|
||||
dmi_id = dmi_first_match(hpd_disconnect_quirk_table);
|
||||
if (dmi_id) {
|
||||
dmi_id = dmi_check_system(dmi_quirk_table);
|
||||
|
||||
if (!dmi_id)
|
||||
return;
|
||||
|
||||
if (quirk_entries.aux_hpd_discon) {
|
||||
dm->aux_hpd_discon_quirk = true;
|
||||
DRM_INFO("aux_hpd_discon_quirk attached\n");
|
||||
drm_info(dev, "aux_hpd_discon_quirk attached\n");
|
||||
}
|
||||
if (quirk_entries.support_edp0_on_dp1) {
|
||||
init_data->flags.support_edp0_on_dp1 = true;
|
||||
drm_info(dev, "aux_hpd_discon_quirk attached\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1969,7 +2024,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0))
|
||||
init_data.num_virtual_links = 1;
|
||||
|
||||
retrieve_dmi_info(&adev->dm);
|
||||
retrieve_dmi_info(&adev->dm, &init_data);
|
||||
|
||||
if (adev->dm.bb_from_dmub)
|
||||
init_data.bb_from_dmub = adev->dm.bb_from_dmub;
|
||||
|
||||
@@ -894,6 +894,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
int i;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
@@ -920,6 +921,12 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
/* Update reference counts for HPDs */
|
||||
for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) {
|
||||
if (amdgpu_irq_get(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1))
|
||||
drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -935,6 +942,7 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
int i;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
@@ -960,4 +968,10 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
/* Update reference counts for HPDs */
|
||||
for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) {
|
||||
if (amdgpu_irq_put(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1))
|
||||
drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@ static bool link_supports_psrsu(struct dc_link *link)
|
||||
if (amdgpu_dc_debug_mask & DC_DISABLE_PSR_SU)
|
||||
return false;
|
||||
|
||||
return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub);
|
||||
/* Temporarily disable PSR-SU to avoid glitches */
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -3043,6 +3043,7 @@ static int kv_dpm_hw_init(void *handle)
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
kv_dpm_setup_asic(adev);
|
||||
ret = kv_dpm_enable(adev);
|
||||
if (ret)
|
||||
@@ -3050,6 +3051,8 @@ static int kv_dpm_hw_init(void *handle)
|
||||
else
|
||||
adev->pm.dpm_enabled = true;
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3067,32 +3070,42 @@ static int kv_dpm_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
cancel_work_sync(&adev->pm.dpm.thermal.work);
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
adev->pm.dpm_enabled = false;
|
||||
/* disable dpm */
|
||||
kv_dpm_disable(adev);
|
||||
/* reset the power state */
|
||||
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kv_dpm_resume(void *handle)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
/* asic init will reset to the boot state */
|
||||
kv_dpm_setup_asic(adev);
|
||||
ret = kv_dpm_enable(adev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
adev->pm.dpm_enabled = false;
|
||||
else
|
||||
} else {
|
||||
adev->pm.dpm_enabled = true;
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
}
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool kv_dpm_is_idle(void *handle)
|
||||
|
||||
@@ -1009,9 +1009,12 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
|
||||
enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
|
||||
int temp, size = sizeof(temp);
|
||||
|
||||
if (!adev->pm.dpm_enabled)
|
||||
return;
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
return;
|
||||
}
|
||||
if (!pp_funcs->read_sensor(adev->powerplay.pp_handle,
|
||||
AMDGPU_PP_SENSOR_GPU_TEMP,
|
||||
(void *)&temp,
|
||||
@@ -1033,4 +1036,5 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
|
||||
adev->pm.dpm.state = dpm_state;
|
||||
|
||||
amdgpu_legacy_dpm_compute_clocks(adev->powerplay.pp_handle);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
|
||||
@@ -7783,6 +7783,7 @@ static int si_dpm_hw_init(void *handle)
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
si_dpm_setup_asic(adev);
|
||||
ret = si_dpm_enable(adev);
|
||||
if (ret)
|
||||
@@ -7790,6 +7791,7 @@ static int si_dpm_hw_init(void *handle)
|
||||
else
|
||||
adev->pm.dpm_enabled = true;
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -7807,32 +7809,44 @@ static int si_dpm_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
cancel_work_sync(&adev->pm.dpm.thermal.work);
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
adev->pm.dpm_enabled = false;
|
||||
/* disable dpm */
|
||||
si_dpm_disable(adev);
|
||||
/* reset the power state */
|
||||
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si_dpm_resume(void *handle)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
/* asic init will reset to the boot state */
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
si_dpm_setup_asic(adev);
|
||||
ret = si_dpm_enable(adev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
adev->pm.dpm_enabled = false;
|
||||
else
|
||||
} else {
|
||||
adev->pm.dpm_enabled = true;
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
}
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool si_dpm_is_idle(void *handle)
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
|
||||
#define RING_CTL(base) XE_REG((base) + 0x3c)
|
||||
#define RING_CTL_SIZE(size) ((size) - PAGE_SIZE) /* in bytes -> pages */
|
||||
#define RING_CTL_SIZE(size) ((size) - PAGE_SIZE) /* in bytes -> pages */
|
||||
|
||||
#define RING_START_UDW(base) XE_REG((base) + 0x48)
|
||||
|
||||
|
||||
+390
-267
@@ -47,6 +47,11 @@ enum xe_oa_submit_deps {
|
||||
XE_OA_SUBMIT_ADD_DEPS,
|
||||
};
|
||||
|
||||
enum xe_oa_user_extn_from {
|
||||
XE_OA_USER_EXTN_FROM_OPEN,
|
||||
XE_OA_USER_EXTN_FROM_CONFIG,
|
||||
};
|
||||
|
||||
struct xe_oa_reg {
|
||||
struct xe_reg addr;
|
||||
u32 value;
|
||||
@@ -94,6 +99,17 @@ struct xe_oa_config_bo {
|
||||
struct xe_bb *bb;
|
||||
};
|
||||
|
||||
struct xe_oa_fence {
|
||||
/* @base: dma fence base */
|
||||
struct dma_fence base;
|
||||
/* @lock: lock for the fence */
|
||||
spinlock_t lock;
|
||||
/* @work: work to signal @base */
|
||||
struct delayed_work work;
|
||||
/* @cb: callback to schedule @work */
|
||||
struct dma_fence_cb cb;
|
||||
};
|
||||
|
||||
#define DRM_FMT(x) DRM_XE_OA_FMT_TYPE_##x
|
||||
|
||||
static const struct xe_oa_format oa_formats[] = {
|
||||
@@ -166,10 +182,10 @@ static struct xe_oa_config *xe_oa_get_oa_config(struct xe_oa *oa, int metrics_se
|
||||
return oa_config;
|
||||
}
|
||||
|
||||
static void free_oa_config_bo(struct xe_oa_config_bo *oa_bo)
|
||||
static void free_oa_config_bo(struct xe_oa_config_bo *oa_bo, struct dma_fence *last_fence)
|
||||
{
|
||||
xe_oa_config_put(oa_bo->oa_config);
|
||||
xe_bb_free(oa_bo->bb, NULL);
|
||||
xe_bb_free(oa_bo->bb, last_fence);
|
||||
kfree(oa_bo);
|
||||
}
|
||||
|
||||
@@ -668,7 +684,8 @@ static void xe_oa_free_configs(struct xe_oa_stream *stream)
|
||||
|
||||
xe_oa_config_put(stream->oa_config);
|
||||
llist_for_each_entry_safe(oa_bo, tmp, stream->oa_config_bos.first, node)
|
||||
free_oa_config_bo(oa_bo);
|
||||
free_oa_config_bo(oa_bo, stream->last_fence);
|
||||
dma_fence_put(stream->last_fence);
|
||||
}
|
||||
|
||||
static int xe_oa_load_with_lri(struct xe_oa_stream *stream, struct xe_oa_reg *reg_lri, u32 count)
|
||||
@@ -832,6 +849,7 @@ static void xe_oa_stream_destroy(struct xe_oa_stream *stream)
|
||||
xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(>->uc.guc.pc));
|
||||
|
||||
xe_oa_free_configs(stream);
|
||||
xe_file_put(stream->xef);
|
||||
}
|
||||
|
||||
static int xe_oa_alloc_oa_buffer(struct xe_oa_stream *stream)
|
||||
@@ -902,40 +920,113 @@ out:
|
||||
return oa_bo;
|
||||
}
|
||||
|
||||
static void xe_oa_update_last_fence(struct xe_oa_stream *stream, struct dma_fence *fence)
|
||||
{
|
||||
dma_fence_put(stream->last_fence);
|
||||
stream->last_fence = dma_fence_get(fence);
|
||||
}
|
||||
|
||||
static void xe_oa_fence_work_fn(struct work_struct *w)
|
||||
{
|
||||
struct xe_oa_fence *ofence = container_of(w, typeof(*ofence), work.work);
|
||||
|
||||
/* Signal fence to indicate new OA configuration is active */
|
||||
dma_fence_signal(&ofence->base);
|
||||
dma_fence_put(&ofence->base);
|
||||
}
|
||||
|
||||
static void xe_oa_config_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
|
||||
{
|
||||
/* Additional empirical delay needed for NOA programming after registers are written */
|
||||
#define NOA_PROGRAM_ADDITIONAL_DELAY_US 500
|
||||
|
||||
struct xe_oa_fence *ofence = container_of(cb, typeof(*ofence), cb);
|
||||
|
||||
INIT_DELAYED_WORK(&ofence->work, xe_oa_fence_work_fn);
|
||||
queue_delayed_work(system_unbound_wq, &ofence->work,
|
||||
usecs_to_jiffies(NOA_PROGRAM_ADDITIONAL_DELAY_US));
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
|
||||
static const char *xe_oa_get_driver_name(struct dma_fence *fence)
|
||||
{
|
||||
return "xe_oa";
|
||||
}
|
||||
|
||||
static const char *xe_oa_get_timeline_name(struct dma_fence *fence)
|
||||
{
|
||||
return "unbound";
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops xe_oa_fence_ops = {
|
||||
.get_driver_name = xe_oa_get_driver_name,
|
||||
.get_timeline_name = xe_oa_get_timeline_name,
|
||||
};
|
||||
|
||||
static int xe_oa_emit_oa_config(struct xe_oa_stream *stream, struct xe_oa_config *config)
|
||||
{
|
||||
#define NOA_PROGRAM_ADDITIONAL_DELAY_US 500
|
||||
struct xe_oa_config_bo *oa_bo;
|
||||
int err = 0, us = NOA_PROGRAM_ADDITIONAL_DELAY_US;
|
||||
struct xe_oa_fence *ofence;
|
||||
int i, err, num_signal = 0;
|
||||
struct dma_fence *fence;
|
||||
long timeout;
|
||||
|
||||
/* Emit OA configuration batch */
|
||||
ofence = kzalloc(sizeof(*ofence), GFP_KERNEL);
|
||||
if (!ofence) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
oa_bo = xe_oa_alloc_config_buffer(stream, config);
|
||||
if (IS_ERR(oa_bo)) {
|
||||
err = PTR_ERR(oa_bo);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Emit OA configuration batch */
|
||||
fence = xe_oa_submit_bb(stream, XE_OA_SUBMIT_ADD_DEPS, oa_bo->bb);
|
||||
if (IS_ERR(fence)) {
|
||||
err = PTR_ERR(fence);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Wait till all previous batches have executed */
|
||||
timeout = dma_fence_wait_timeout(fence, false, 5 * HZ);
|
||||
dma_fence_put(fence);
|
||||
if (timeout < 0)
|
||||
err = timeout;
|
||||
else if (!timeout)
|
||||
err = -ETIME;
|
||||
if (err)
|
||||
drm_dbg(&stream->oa->xe->drm, "dma_fence_wait_timeout err %d\n", err);
|
||||
/* Point of no return: initialize and set fence to signal */
|
||||
spin_lock_init(&ofence->lock);
|
||||
dma_fence_init(&ofence->base, &xe_oa_fence_ops, &ofence->lock, 0, 0);
|
||||
|
||||
/* Additional empirical delay needed for NOA programming after registers are written */
|
||||
usleep_range(us, 2 * us);
|
||||
for (i = 0; i < stream->num_syncs; i++) {
|
||||
if (stream->syncs[i].flags & DRM_XE_SYNC_FLAG_SIGNAL)
|
||||
num_signal++;
|
||||
xe_sync_entry_signal(&stream->syncs[i], &ofence->base);
|
||||
}
|
||||
|
||||
/* Additional dma_fence_get in case we dma_fence_wait */
|
||||
if (!num_signal)
|
||||
dma_fence_get(&ofence->base);
|
||||
|
||||
/* Update last fence too before adding callback */
|
||||
xe_oa_update_last_fence(stream, fence);
|
||||
|
||||
/* Add job fence callback to schedule work to signal ofence->base */
|
||||
err = dma_fence_add_callback(fence, &ofence->cb, xe_oa_config_cb);
|
||||
xe_gt_assert(stream->gt, !err || err == -ENOENT);
|
||||
if (err == -ENOENT)
|
||||
xe_oa_config_cb(fence, &ofence->cb);
|
||||
|
||||
/* If nothing needs to be signaled we wait synchronously */
|
||||
if (!num_signal) {
|
||||
dma_fence_wait(&ofence->base, false);
|
||||
dma_fence_put(&ofence->base);
|
||||
}
|
||||
|
||||
/* Done with syncs */
|
||||
for (i = 0; i < stream->num_syncs; i++)
|
||||
xe_sync_entry_cleanup(&stream->syncs[i]);
|
||||
kfree(stream->syncs);
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
kfree(ofence);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1006,6 +1097,262 @@ static int xe_oa_enable_metric_set(struct xe_oa_stream *stream)
|
||||
return xe_oa_emit_oa_config(stream, stream->oa_config);
|
||||
}
|
||||
|
||||
static int decode_oa_format(struct xe_oa *oa, u64 fmt, enum xe_oa_format_name *name)
|
||||
{
|
||||
u32 counter_size = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SIZE, fmt);
|
||||
u32 counter_sel = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SEL, fmt);
|
||||
u32 bc_report = FIELD_GET(DRM_XE_OA_FORMAT_MASK_BC_REPORT, fmt);
|
||||
u32 type = FIELD_GET(DRM_XE_OA_FORMAT_MASK_FMT_TYPE, fmt);
|
||||
int idx;
|
||||
|
||||
for_each_set_bit(idx, oa->format_mask, __XE_OA_FORMAT_MAX) {
|
||||
const struct xe_oa_format *f = &oa->oa_formats[idx];
|
||||
|
||||
if (counter_size == f->counter_size && bc_report == f->bc_report &&
|
||||
type == f->type && counter_sel == f->counter_select) {
|
||||
*name = idx;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_oa_unit_id(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
if (value >= oa->oa_unit_ids) {
|
||||
drm_dbg(&oa->xe->drm, "OA unit ID out of range %lld\n", value);
|
||||
return -EINVAL;
|
||||
}
|
||||
param->oa_unit_id = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_sample_oa(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->sample = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_metric_set(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->metric_set = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_oa_format(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
int ret = decode_oa_format(oa, value, ¶m->oa_format);
|
||||
|
||||
if (ret) {
|
||||
drm_dbg(&oa->xe->drm, "Unsupported OA report format %#llx\n", value);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_oa_exponent(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
#define OA_EXPONENT_MAX 31
|
||||
|
||||
if (value > OA_EXPONENT_MAX) {
|
||||
drm_dbg(&oa->xe->drm, "OA timer exponent too high (> %u)\n", OA_EXPONENT_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
param->period_exponent = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_disabled(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->disabled = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_exec_queue_id(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->exec_queue_id = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_engine_instance(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->engine_instance = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_no_preempt(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->no_preempt = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_num_syncs(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->num_syncs = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_syncs_user(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->syncs_user = u64_to_user_ptr(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_ret_inval(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
typedef int (*xe_oa_set_property_fn)(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param);
|
||||
static const xe_oa_set_property_fn xe_oa_set_property_funcs_open[] = {
|
||||
[DRM_XE_OA_PROPERTY_OA_UNIT_ID] = xe_oa_set_prop_oa_unit_id,
|
||||
[DRM_XE_OA_PROPERTY_SAMPLE_OA] = xe_oa_set_prop_sample_oa,
|
||||
[DRM_XE_OA_PROPERTY_OA_METRIC_SET] = xe_oa_set_prop_metric_set,
|
||||
[DRM_XE_OA_PROPERTY_OA_FORMAT] = xe_oa_set_prop_oa_format,
|
||||
[DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT] = xe_oa_set_prop_oa_exponent,
|
||||
[DRM_XE_OA_PROPERTY_OA_DISABLED] = xe_oa_set_prop_disabled,
|
||||
[DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID] = xe_oa_set_prop_exec_queue_id,
|
||||
[DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE] = xe_oa_set_prop_engine_instance,
|
||||
[DRM_XE_OA_PROPERTY_NO_PREEMPT] = xe_oa_set_no_preempt,
|
||||
[DRM_XE_OA_PROPERTY_NUM_SYNCS] = xe_oa_set_prop_num_syncs,
|
||||
[DRM_XE_OA_PROPERTY_SYNCS] = xe_oa_set_prop_syncs_user,
|
||||
};
|
||||
|
||||
static const xe_oa_set_property_fn xe_oa_set_property_funcs_config[] = {
|
||||
[DRM_XE_OA_PROPERTY_OA_UNIT_ID] = xe_oa_set_prop_ret_inval,
|
||||
[DRM_XE_OA_PROPERTY_SAMPLE_OA] = xe_oa_set_prop_ret_inval,
|
||||
[DRM_XE_OA_PROPERTY_OA_METRIC_SET] = xe_oa_set_prop_metric_set,
|
||||
[DRM_XE_OA_PROPERTY_OA_FORMAT] = xe_oa_set_prop_ret_inval,
|
||||
[DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT] = xe_oa_set_prop_ret_inval,
|
||||
[DRM_XE_OA_PROPERTY_OA_DISABLED] = xe_oa_set_prop_ret_inval,
|
||||
[DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID] = xe_oa_set_prop_ret_inval,
|
||||
[DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE] = xe_oa_set_prop_ret_inval,
|
||||
[DRM_XE_OA_PROPERTY_NO_PREEMPT] = xe_oa_set_prop_ret_inval,
|
||||
[DRM_XE_OA_PROPERTY_NUM_SYNCS] = xe_oa_set_prop_num_syncs,
|
||||
[DRM_XE_OA_PROPERTY_SYNCS] = xe_oa_set_prop_syncs_user,
|
||||
};
|
||||
|
||||
static int xe_oa_user_ext_set_property(struct xe_oa *oa, enum xe_oa_user_extn_from from,
|
||||
u64 extension, struct xe_oa_open_param *param)
|
||||
{
|
||||
u64 __user *address = u64_to_user_ptr(extension);
|
||||
struct drm_xe_ext_set_property ext;
|
||||
int err;
|
||||
u32 idx;
|
||||
|
||||
err = __copy_from_user(&ext, address, sizeof(ext));
|
||||
if (XE_IOCTL_DBG(oa->xe, err))
|
||||
return -EFAULT;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(xe_oa_set_property_funcs_open) !=
|
||||
ARRAY_SIZE(xe_oa_set_property_funcs_config));
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, ext.property >= ARRAY_SIZE(xe_oa_set_property_funcs_open)) ||
|
||||
XE_IOCTL_DBG(oa->xe, ext.pad))
|
||||
return -EINVAL;
|
||||
|
||||
idx = array_index_nospec(ext.property, ARRAY_SIZE(xe_oa_set_property_funcs_open));
|
||||
|
||||
if (from == XE_OA_USER_EXTN_FROM_CONFIG)
|
||||
return xe_oa_set_property_funcs_config[idx](oa, ext.value, param);
|
||||
else
|
||||
return xe_oa_set_property_funcs_open[idx](oa, ext.value, param);
|
||||
}
|
||||
|
||||
typedef int (*xe_oa_user_extension_fn)(struct xe_oa *oa, enum xe_oa_user_extn_from from,
|
||||
u64 extension, struct xe_oa_open_param *param);
|
||||
static const xe_oa_user_extension_fn xe_oa_user_extension_funcs[] = {
|
||||
[DRM_XE_OA_EXTENSION_SET_PROPERTY] = xe_oa_user_ext_set_property,
|
||||
};
|
||||
|
||||
#define MAX_USER_EXTENSIONS 16
|
||||
static int xe_oa_user_extensions(struct xe_oa *oa, enum xe_oa_user_extn_from from, u64 extension,
|
||||
int ext_number, struct xe_oa_open_param *param)
|
||||
{
|
||||
u64 __user *address = u64_to_user_ptr(extension);
|
||||
struct drm_xe_user_extension ext;
|
||||
int err;
|
||||
u32 idx;
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, ext_number >= MAX_USER_EXTENSIONS))
|
||||
return -E2BIG;
|
||||
|
||||
err = __copy_from_user(&ext, address, sizeof(ext));
|
||||
if (XE_IOCTL_DBG(oa->xe, err))
|
||||
return -EFAULT;
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, ext.pad) ||
|
||||
XE_IOCTL_DBG(oa->xe, ext.name >= ARRAY_SIZE(xe_oa_user_extension_funcs)))
|
||||
return -EINVAL;
|
||||
|
||||
idx = array_index_nospec(ext.name, ARRAY_SIZE(xe_oa_user_extension_funcs));
|
||||
err = xe_oa_user_extension_funcs[idx](oa, from, extension, param);
|
||||
if (XE_IOCTL_DBG(oa->xe, err))
|
||||
return err;
|
||||
|
||||
if (ext.next_extension)
|
||||
return xe_oa_user_extensions(oa, from, ext.next_extension, ++ext_number, param);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param)
|
||||
{
|
||||
int ret, num_syncs, num_ufence = 0;
|
||||
|
||||
if (param->num_syncs && !param->syncs_user) {
|
||||
drm_dbg(&oa->xe->drm, "num_syncs specified without sync array\n");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (param->num_syncs) {
|
||||
param->syncs = kcalloc(param->num_syncs, sizeof(*param->syncs), GFP_KERNEL);
|
||||
if (!param->syncs) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
for (num_syncs = 0; num_syncs < param->num_syncs; num_syncs++) {
|
||||
ret = xe_sync_entry_parse(oa->xe, param->xef, ¶m->syncs[num_syncs],
|
||||
¶m->syncs_user[num_syncs], 0);
|
||||
if (ret)
|
||||
goto err_syncs;
|
||||
|
||||
if (xe_sync_is_ufence(¶m->syncs[num_syncs]))
|
||||
num_ufence++;
|
||||
}
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, num_ufence > 1)) {
|
||||
ret = -EINVAL;
|
||||
goto err_syncs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_syncs:
|
||||
while (num_syncs--)
|
||||
xe_sync_entry_cleanup(¶m->syncs[num_syncs]);
|
||||
kfree(param->syncs);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void xe_oa_stream_enable(struct xe_oa_stream *stream)
|
||||
{
|
||||
stream->pollin = false;
|
||||
@@ -1099,36 +1446,38 @@ static int xe_oa_disable_locked(struct xe_oa_stream *stream)
|
||||
|
||||
static long xe_oa_config_locked(struct xe_oa_stream *stream, u64 arg)
|
||||
{
|
||||
struct drm_xe_ext_set_property ext;
|
||||
struct xe_oa_open_param param = {};
|
||||
long ret = stream->oa_config->id;
|
||||
struct xe_oa_config *config;
|
||||
int err;
|
||||
|
||||
err = __copy_from_user(&ext, u64_to_user_ptr(arg), sizeof(ext));
|
||||
if (XE_IOCTL_DBG(stream->oa->xe, err))
|
||||
return -EFAULT;
|
||||
err = xe_oa_user_extensions(stream->oa, XE_OA_USER_EXTN_FROM_CONFIG, arg, 0, ¶m);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (XE_IOCTL_DBG(stream->oa->xe, ext.pad) ||
|
||||
XE_IOCTL_DBG(stream->oa->xe, ext.base.name != DRM_XE_OA_EXTENSION_SET_PROPERTY) ||
|
||||
XE_IOCTL_DBG(stream->oa->xe, ext.base.next_extension) ||
|
||||
XE_IOCTL_DBG(stream->oa->xe, ext.property != DRM_XE_OA_PROPERTY_OA_METRIC_SET))
|
||||
return -EINVAL;
|
||||
|
||||
config = xe_oa_get_oa_config(stream->oa, ext.value);
|
||||
config = xe_oa_get_oa_config(stream->oa, param.metric_set);
|
||||
if (!config)
|
||||
return -ENODEV;
|
||||
|
||||
if (config != stream->oa_config) {
|
||||
err = xe_oa_emit_oa_config(stream, config);
|
||||
if (!err)
|
||||
config = xchg(&stream->oa_config, config);
|
||||
else
|
||||
ret = err;
|
||||
param.xef = stream->xef;
|
||||
err = xe_oa_parse_syncs(stream->oa, ¶m);
|
||||
if (err)
|
||||
goto err_config_put;
|
||||
|
||||
stream->num_syncs = param.num_syncs;
|
||||
stream->syncs = param.syncs;
|
||||
|
||||
err = xe_oa_emit_oa_config(stream, config);
|
||||
if (!err) {
|
||||
config = xchg(&stream->oa_config, config);
|
||||
drm_dbg(&stream->oa->xe->drm, "changed to oa config uuid=%s\n",
|
||||
stream->oa_config->uuid);
|
||||
}
|
||||
|
||||
err_config_put:
|
||||
xe_oa_config_put(config);
|
||||
|
||||
return ret;
|
||||
return err ?: ret;
|
||||
}
|
||||
|
||||
static long xe_oa_status_locked(struct xe_oa_stream *stream, unsigned long arg)
|
||||
@@ -1367,10 +1716,11 @@ static int xe_oa_stream_init(struct xe_oa_stream *stream,
|
||||
stream->oa_buffer.format = &stream->oa->oa_formats[param->oa_format];
|
||||
|
||||
stream->sample = param->sample;
|
||||
stream->periodic = param->period_exponent > 0;
|
||||
stream->periodic = param->period_exponent >= 0;
|
||||
stream->period_exponent = param->period_exponent;
|
||||
stream->no_preempt = param->no_preempt;
|
||||
|
||||
stream->xef = xe_file_get(param->xef);
|
||||
stream->num_syncs = param->num_syncs;
|
||||
stream->syncs = param->syncs;
|
||||
|
||||
@@ -1470,6 +1820,7 @@ err_fw_put:
|
||||
err_free_configs:
|
||||
xe_oa_free_configs(stream);
|
||||
exit:
|
||||
xe_file_put(stream->xef);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1579,27 +1930,6 @@ static bool engine_supports_oa_format(const struct xe_hw_engine *hwe, int type)
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_oa_format(struct xe_oa *oa, u64 fmt, enum xe_oa_format_name *name)
|
||||
{
|
||||
u32 counter_size = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SIZE, fmt);
|
||||
u32 counter_sel = FIELD_GET(DRM_XE_OA_FORMAT_MASK_COUNTER_SEL, fmt);
|
||||
u32 bc_report = FIELD_GET(DRM_XE_OA_FORMAT_MASK_BC_REPORT, fmt);
|
||||
u32 type = FIELD_GET(DRM_XE_OA_FORMAT_MASK_FMT_TYPE, fmt);
|
||||
int idx;
|
||||
|
||||
for_each_set_bit(idx, oa->format_mask, __XE_OA_FORMAT_MAX) {
|
||||
const struct xe_oa_format *f = &oa->oa_formats[idx];
|
||||
|
||||
if (counter_size == f->counter_size && bc_report == f->bc_report &&
|
||||
type == f->type && counter_sel == f->counter_select) {
|
||||
*name = idx;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_oa_unit_id - Return OA unit ID for a hardware engine
|
||||
* @hwe: @xe_hw_engine
|
||||
@@ -1646,214 +1976,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_oa_unit_id(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
if (value >= oa->oa_unit_ids) {
|
||||
drm_dbg(&oa->xe->drm, "OA unit ID out of range %lld\n", value);
|
||||
return -EINVAL;
|
||||
}
|
||||
param->oa_unit_id = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_sample_oa(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->sample = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_metric_set(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->metric_set = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_oa_format(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
int ret = decode_oa_format(oa, value, ¶m->oa_format);
|
||||
|
||||
if (ret) {
|
||||
drm_dbg(&oa->xe->drm, "Unsupported OA report format %#llx\n", value);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_oa_exponent(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
#define OA_EXPONENT_MAX 31
|
||||
|
||||
if (value > OA_EXPONENT_MAX) {
|
||||
drm_dbg(&oa->xe->drm, "OA timer exponent too high (> %u)\n", OA_EXPONENT_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
param->period_exponent = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_disabled(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->disabled = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_exec_queue_id(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->exec_queue_id = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_engine_instance(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->engine_instance = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_no_preempt(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->no_preempt = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_num_syncs(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->num_syncs = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_set_prop_syncs_user(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
param->syncs_user = u64_to_user_ptr(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef int (*xe_oa_set_property_fn)(struct xe_oa *oa, u64 value,
|
||||
struct xe_oa_open_param *param);
|
||||
static const xe_oa_set_property_fn xe_oa_set_property_funcs[] = {
|
||||
[DRM_XE_OA_PROPERTY_OA_UNIT_ID] = xe_oa_set_prop_oa_unit_id,
|
||||
[DRM_XE_OA_PROPERTY_SAMPLE_OA] = xe_oa_set_prop_sample_oa,
|
||||
[DRM_XE_OA_PROPERTY_OA_METRIC_SET] = xe_oa_set_prop_metric_set,
|
||||
[DRM_XE_OA_PROPERTY_OA_FORMAT] = xe_oa_set_prop_oa_format,
|
||||
[DRM_XE_OA_PROPERTY_OA_PERIOD_EXPONENT] = xe_oa_set_prop_oa_exponent,
|
||||
[DRM_XE_OA_PROPERTY_OA_DISABLED] = xe_oa_set_prop_disabled,
|
||||
[DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID] = xe_oa_set_prop_exec_queue_id,
|
||||
[DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE] = xe_oa_set_prop_engine_instance,
|
||||
[DRM_XE_OA_PROPERTY_NO_PREEMPT] = xe_oa_set_no_preempt,
|
||||
[DRM_XE_OA_PROPERTY_NUM_SYNCS] = xe_oa_set_prop_num_syncs,
|
||||
[DRM_XE_OA_PROPERTY_SYNCS] = xe_oa_set_prop_syncs_user,
|
||||
};
|
||||
|
||||
static int xe_oa_user_ext_set_property(struct xe_oa *oa, u64 extension,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
u64 __user *address = u64_to_user_ptr(extension);
|
||||
struct drm_xe_ext_set_property ext;
|
||||
int err;
|
||||
u32 idx;
|
||||
|
||||
err = __copy_from_user(&ext, address, sizeof(ext));
|
||||
if (XE_IOCTL_DBG(oa->xe, err))
|
||||
return -EFAULT;
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, ext.property >= ARRAY_SIZE(xe_oa_set_property_funcs)) ||
|
||||
XE_IOCTL_DBG(oa->xe, ext.pad))
|
||||
return -EINVAL;
|
||||
|
||||
idx = array_index_nospec(ext.property, ARRAY_SIZE(xe_oa_set_property_funcs));
|
||||
return xe_oa_set_property_funcs[idx](oa, ext.value, param);
|
||||
}
|
||||
|
||||
typedef int (*xe_oa_user_extension_fn)(struct xe_oa *oa, u64 extension,
|
||||
struct xe_oa_open_param *param);
|
||||
static const xe_oa_user_extension_fn xe_oa_user_extension_funcs[] = {
|
||||
[DRM_XE_OA_EXTENSION_SET_PROPERTY] = xe_oa_user_ext_set_property,
|
||||
};
|
||||
|
||||
#define MAX_USER_EXTENSIONS 16
|
||||
static int xe_oa_user_extensions(struct xe_oa *oa, u64 extension, int ext_number,
|
||||
struct xe_oa_open_param *param)
|
||||
{
|
||||
u64 __user *address = u64_to_user_ptr(extension);
|
||||
struct drm_xe_user_extension ext;
|
||||
int err;
|
||||
u32 idx;
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, ext_number >= MAX_USER_EXTENSIONS))
|
||||
return -E2BIG;
|
||||
|
||||
err = __copy_from_user(&ext, address, sizeof(ext));
|
||||
if (XE_IOCTL_DBG(oa->xe, err))
|
||||
return -EFAULT;
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, ext.pad) ||
|
||||
XE_IOCTL_DBG(oa->xe, ext.name >= ARRAY_SIZE(xe_oa_user_extension_funcs)))
|
||||
return -EINVAL;
|
||||
|
||||
idx = array_index_nospec(ext.name, ARRAY_SIZE(xe_oa_user_extension_funcs));
|
||||
err = xe_oa_user_extension_funcs[idx](oa, extension, param);
|
||||
if (XE_IOCTL_DBG(oa->xe, err))
|
||||
return err;
|
||||
|
||||
if (ext.next_extension)
|
||||
return xe_oa_user_extensions(oa, ext.next_extension, ++ext_number, param);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param)
|
||||
{
|
||||
int ret, num_syncs, num_ufence = 0;
|
||||
|
||||
if (param->num_syncs && !param->syncs_user) {
|
||||
drm_dbg(&oa->xe->drm, "num_syncs specified without sync array\n");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (param->num_syncs) {
|
||||
param->syncs = kcalloc(param->num_syncs, sizeof(*param->syncs), GFP_KERNEL);
|
||||
if (!param->syncs) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
for (num_syncs = 0; num_syncs < param->num_syncs; num_syncs++) {
|
||||
ret = xe_sync_entry_parse(oa->xe, param->xef, ¶m->syncs[num_syncs],
|
||||
¶m->syncs_user[num_syncs], 0);
|
||||
if (ret)
|
||||
goto err_syncs;
|
||||
|
||||
if (xe_sync_is_ufence(¶m->syncs[num_syncs]))
|
||||
num_ufence++;
|
||||
}
|
||||
|
||||
if (XE_IOCTL_DBG(oa->xe, num_ufence > 1)) {
|
||||
ret = -EINVAL;
|
||||
goto err_syncs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_syncs:
|
||||
while (num_syncs--)
|
||||
xe_sync_entry_cleanup(¶m->syncs[num_syncs]);
|
||||
kfree(param->syncs);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_oa_stream_open_ioctl - Opens an OA stream
|
||||
* @dev: @drm_device
|
||||
@@ -1880,7 +2002,8 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
|
||||
}
|
||||
|
||||
param.xef = xef;
|
||||
ret = xe_oa_user_extensions(oa, data, 0, ¶m);
|
||||
param.period_exponent = -1;
|
||||
ret = xe_oa_user_extensions(oa, XE_OA_USER_EXTN_FROM_OPEN, data, 0, ¶m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1934,7 +2057,7 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
|
||||
goto err_exec_q;
|
||||
}
|
||||
|
||||
if (param.period_exponent > 0) {
|
||||
if (param.period_exponent >= 0) {
|
||||
u64 oa_period, oa_freq_hz;
|
||||
|
||||
/* Requesting samples from OAG buffer is a privileged operation */
|
||||
|
||||
@@ -239,6 +239,12 @@ struct xe_oa_stream {
|
||||
/** @no_preempt: Whether preemption and timeslicing is disabled for stream exec_q */
|
||||
u32 no_preempt;
|
||||
|
||||
/** @xef: xe_file with which the stream was opened */
|
||||
struct xe_file *xef;
|
||||
|
||||
/** @last_fence: fence to use in stream destroy when needed */
|
||||
struct dma_fence *last_fence;
|
||||
|
||||
/** @num_syncs: size of @syncs array */
|
||||
u32 num_syncs;
|
||||
|
||||
|
||||
@@ -667,20 +667,33 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
|
||||
|
||||
/* Collect invalidated userptrs */
|
||||
spin_lock(&vm->userptr.invalidated_lock);
|
||||
xe_assert(vm->xe, list_empty(&vm->userptr.repin_list));
|
||||
list_for_each_entry_safe(uvma, next, &vm->userptr.invalidated,
|
||||
userptr.invalidate_link) {
|
||||
list_del_init(&uvma->userptr.invalidate_link);
|
||||
list_move_tail(&uvma->userptr.repin_link,
|
||||
&vm->userptr.repin_list);
|
||||
list_add_tail(&uvma->userptr.repin_link,
|
||||
&vm->userptr.repin_list);
|
||||
}
|
||||
spin_unlock(&vm->userptr.invalidated_lock);
|
||||
|
||||
/* Pin and move to temporary list */
|
||||
/* Pin and move to bind list */
|
||||
list_for_each_entry_safe(uvma, next, &vm->userptr.repin_list,
|
||||
userptr.repin_link) {
|
||||
err = xe_vma_userptr_pin_pages(uvma);
|
||||
if (err == -EFAULT) {
|
||||
list_del_init(&uvma->userptr.repin_link);
|
||||
/*
|
||||
* We might have already done the pin once already, but
|
||||
* then had to retry before the re-bind happened, due
|
||||
* some other condition in the caller, but in the
|
||||
* meantime the userptr got dinged by the notifier such
|
||||
* that we need to revalidate here, but this time we hit
|
||||
* the EFAULT. In such a case make sure we remove
|
||||
* ourselves from the rebind list to avoid going down in
|
||||
* flames.
|
||||
*/
|
||||
if (!list_empty(&uvma->vma.combined_links.rebind))
|
||||
list_del_init(&uvma->vma.combined_links.rebind);
|
||||
|
||||
/* Wait for pending binds */
|
||||
xe_vm_lock(vm, false);
|
||||
@@ -691,10 +704,10 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
|
||||
err = xe_vm_invalidate_vma(&uvma->vma);
|
||||
xe_vm_unlock(vm);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
} else {
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err)
|
||||
break;
|
||||
|
||||
list_del_init(&uvma->userptr.repin_link);
|
||||
list_move_tail(&uvma->vma.combined_links.rebind,
|
||||
@@ -702,7 +715,19 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (err) {
|
||||
down_write(&vm->userptr.notifier_lock);
|
||||
spin_lock(&vm->userptr.invalidated_lock);
|
||||
list_for_each_entry_safe(uvma, next, &vm->userptr.repin_list,
|
||||
userptr.repin_link) {
|
||||
list_del_init(&uvma->userptr.repin_link);
|
||||
list_move_tail(&uvma->userptr.invalidate_link,
|
||||
&vm->userptr.invalidated);
|
||||
}
|
||||
spin_unlock(&vm->userptr.invalidated_lock);
|
||||
up_write(&vm->userptr.notifier_lock);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1066,6 +1091,7 @@ static void xe_vma_destroy(struct xe_vma *vma, struct dma_fence *fence)
|
||||
xe_assert(vm->xe, vma->gpuva.flags & XE_VMA_DESTROYED);
|
||||
|
||||
spin_lock(&vm->userptr.invalidated_lock);
|
||||
xe_assert(vm->xe, list_empty(&to_userptr_vma(vma)->userptr.repin_link));
|
||||
list_del(&to_userptr_vma(vma)->userptr.invalidate_link);
|
||||
spin_unlock(&vm->userptr.invalidated_lock);
|
||||
} else if (!xe_vma_is_null(vma)) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* Rewritten for mainline by Binbin Zhou <zhoubinbin@loongson.cn>
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/device.h>
|
||||
@@ -26,7 +27,8 @@
|
||||
#include <linux/units.h>
|
||||
|
||||
/* I2C Registers */
|
||||
#define I2C_LS2X_PRER 0x0 /* Freq Division Register(16 bits) */
|
||||
#define I2C_LS2X_PRER_LO 0x0 /* Freq Division Low Byte Register */
|
||||
#define I2C_LS2X_PRER_HI 0x1 /* Freq Division High Byte Register */
|
||||
#define I2C_LS2X_CTR 0x2 /* Control Register */
|
||||
#define I2C_LS2X_TXR 0x3 /* Transport Data Register */
|
||||
#define I2C_LS2X_RXR 0x3 /* Receive Data Register */
|
||||
@@ -93,6 +95,7 @@ static irqreturn_t ls2x_i2c_isr(int this_irq, void *dev_id)
|
||||
*/
|
||||
static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv)
|
||||
{
|
||||
u16 val;
|
||||
struct i2c_timings *t = &priv->i2c_t;
|
||||
struct device *dev = priv->adapter.dev.parent;
|
||||
u32 acpi_speed = i2c_acpi_find_bus_speed(dev);
|
||||
@@ -104,9 +107,14 @@ static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv)
|
||||
else
|
||||
t->bus_freq_hz = LS2X_I2C_FREQ_STD;
|
||||
|
||||
/* Calculate and set i2c frequency. */
|
||||
writew(LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1,
|
||||
priv->base + I2C_LS2X_PRER);
|
||||
/*
|
||||
* According to the chip manual, we can only access the registers as bytes,
|
||||
* otherwise the high bits will be truncated.
|
||||
* So set the I2C frequency with a sequential writeb() instead of writew().
|
||||
*/
|
||||
val = LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1;
|
||||
writeb(FIELD_GET(GENMASK(7, 0), val), priv->base + I2C_LS2X_PRER_LO);
|
||||
writeb(FIELD_GET(GENMASK(15, 8), val), priv->base + I2C_LS2X_PRER_HI);
|
||||
}
|
||||
|
||||
static void ls2x_i2c_init(struct ls2x_i2c_priv *priv)
|
||||
|
||||
@@ -2319,6 +2319,13 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
/*
|
||||
* Disable the interrupt to avoid the interrupt handler being triggered
|
||||
* incorrectly by the asynchronous interrupt status since the machine
|
||||
* might do a warm reset during the last smbus/i2c transfer session.
|
||||
*/
|
||||
npcm_i2c_int_enable(bus, false);
|
||||
|
||||
ret = devm_request_irq(bus->dev, irq, npcm_i2c_bus_irq, 0,
|
||||
dev_name(bus->dev), bus);
|
||||
if (ret)
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/mwait.h>
|
||||
#include <asm/spec-ctrl.h>
|
||||
#include <asm/tsc.h>
|
||||
#include <asm/fpu/api.h>
|
||||
|
||||
#define INTEL_IDLE_VERSION "0.5.1"
|
||||
@@ -1749,6 +1750,9 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
|
||||
if (intel_idle_state_needs_timer_stop(state))
|
||||
state->flags |= CPUIDLE_FLAG_TIMER_STOP;
|
||||
|
||||
if (cx->type > ACPI_STATE_C1 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
|
||||
mark_tsc_unstable("TSC halts in idle");
|
||||
|
||||
state->enter = intel_idle;
|
||||
state->enter_s2idle = intel_idle_s2idle;
|
||||
}
|
||||
|
||||
@@ -154,6 +154,14 @@ struct bnxt_re_pacing {
|
||||
|
||||
#define BNXT_RE_GRC_FIFO_REG_BASE 0x2000
|
||||
|
||||
#define BNXT_RE_MIN_MSIX 2
|
||||
#define BNXT_RE_MAX_MSIX BNXT_MAX_ROCE_MSIX
|
||||
struct bnxt_re_nq_record {
|
||||
struct bnxt_msix_entry msix_entries[BNXT_RE_MAX_MSIX];
|
||||
struct bnxt_qplib_nq nq[BNXT_RE_MAX_MSIX];
|
||||
int num_msix;
|
||||
};
|
||||
|
||||
#define MAX_CQ_HASH_BITS (16)
|
||||
#define MAX_SRQ_HASH_BITS (16)
|
||||
struct bnxt_re_dev {
|
||||
@@ -174,24 +182,20 @@ struct bnxt_re_dev {
|
||||
unsigned int version, major, minor;
|
||||
struct bnxt_qplib_chip_ctx *chip_ctx;
|
||||
struct bnxt_en_dev *en_dev;
|
||||
int num_msix;
|
||||
|
||||
int id;
|
||||
|
||||
struct delayed_work worker;
|
||||
u8 cur_prio_map;
|
||||
|
||||
/* FP Notification Queue (CQ & SRQ) */
|
||||
struct tasklet_struct nq_task;
|
||||
|
||||
/* RCFW Channel */
|
||||
struct bnxt_qplib_rcfw rcfw;
|
||||
|
||||
/* NQ */
|
||||
struct bnxt_qplib_nq nq[BNXT_MAX_ROCE_MSIX];
|
||||
/* NQ record */
|
||||
struct bnxt_re_nq_record *nqr;
|
||||
|
||||
/* Device Resources */
|
||||
struct bnxt_qplib_dev_attr dev_attr;
|
||||
struct bnxt_qplib_dev_attr *dev_attr;
|
||||
struct bnxt_qplib_ctx qplib_ctx;
|
||||
struct bnxt_qplib_res qplib_res;
|
||||
struct bnxt_qplib_dpi dpi_privileged;
|
||||
|
||||
@@ -357,8 +357,8 @@ int bnxt_re_ib_get_hw_stats(struct ib_device *ibdev,
|
||||
goto done;
|
||||
}
|
||||
bnxt_re_copy_err_stats(rdev, stats, err_s);
|
||||
if (_is_ext_stats_supported(rdev->dev_attr.dev_cap_flags) &&
|
||||
!rdev->is_virtfn) {
|
||||
if (bnxt_ext_stats_supported(rdev->chip_ctx, rdev->dev_attr->dev_cap_flags,
|
||||
rdev->is_virtfn)) {
|
||||
rc = bnxt_re_get_ext_stat(rdev, stats);
|
||||
if (rc) {
|
||||
clear_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS,
|
||||
|
||||
@@ -118,7 +118,7 @@ static enum ib_access_flags __to_ib_access_flags(int qflags)
|
||||
static void bnxt_re_check_and_set_relaxed_ordering(struct bnxt_re_dev *rdev,
|
||||
struct bnxt_qplib_mrw *qplib_mr)
|
||||
{
|
||||
if (_is_relaxed_ordering_supported(rdev->dev_attr.dev_cap_flags2) &&
|
||||
if (_is_relaxed_ordering_supported(rdev->dev_attr->dev_cap_flags2) &&
|
||||
pcie_relaxed_ordering_enabled(rdev->en_dev->pdev))
|
||||
qplib_mr->flags |= CMDQ_REGISTER_MR_FLAGS_ENABLE_RO;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ int bnxt_re_query_device(struct ib_device *ibdev,
|
||||
struct ib_udata *udata)
|
||||
{
|
||||
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
|
||||
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
|
||||
struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr;
|
||||
|
||||
memset(ib_attr, 0, sizeof(*ib_attr));
|
||||
memcpy(&ib_attr->fw_ver, dev_attr->fw_ver,
|
||||
@@ -216,7 +216,7 @@ int bnxt_re_query_port(struct ib_device *ibdev, u32 port_num,
|
||||
struct ib_port_attr *port_attr)
|
||||
{
|
||||
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
|
||||
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
|
||||
struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr;
|
||||
int rc;
|
||||
|
||||
memset(port_attr, 0, sizeof(*port_attr));
|
||||
@@ -274,8 +274,8 @@ void bnxt_re_query_fw_str(struct ib_device *ibdev, char *str)
|
||||
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
|
||||
|
||||
snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%d.%d",
|
||||
rdev->dev_attr.fw_ver[0], rdev->dev_attr.fw_ver[1],
|
||||
rdev->dev_attr.fw_ver[2], rdev->dev_attr.fw_ver[3]);
|
||||
rdev->dev_attr->fw_ver[0], rdev->dev_attr->fw_ver[1],
|
||||
rdev->dev_attr->fw_ver[2], rdev->dev_attr->fw_ver[3]);
|
||||
}
|
||||
|
||||
int bnxt_re_query_pkey(struct ib_device *ibdev, u32 port_num,
|
||||
@@ -526,7 +526,7 @@ static int bnxt_re_create_fence_mr(struct bnxt_re_pd *pd)
|
||||
mr->qplib_mr.pd = &pd->qplib_pd;
|
||||
mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
|
||||
mr->qplib_mr.access_flags = __from_ib_access_flags(mr_access_flags);
|
||||
if (!_is_alloc_mr_unified(rdev->dev_attr.dev_cap_flags)) {
|
||||
if (!_is_alloc_mr_unified(rdev->dev_attr->dev_cap_flags)) {
|
||||
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "Failed to alloc fence-HW-MR\n");
|
||||
@@ -1001,7 +1001,7 @@ static int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp,
|
||||
rdev = qp->rdev;
|
||||
qplqp = &qp->qplib_qp;
|
||||
sq = &qplqp->sq;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
|
||||
align = sizeof(struct sq_send_hdr);
|
||||
ilsize = ALIGN(init_attr->cap.max_inline_data, align);
|
||||
@@ -1221,7 +1221,7 @@ static int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp,
|
||||
rdev = qp->rdev;
|
||||
qplqp = &qp->qplib_qp;
|
||||
rq = &qplqp->rq;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
|
||||
if (init_attr->srq) {
|
||||
struct bnxt_re_srq *srq;
|
||||
@@ -1258,7 +1258,7 @@ static void bnxt_re_adjust_gsi_rq_attr(struct bnxt_re_qp *qp)
|
||||
|
||||
rdev = qp->rdev;
|
||||
qplqp = &qp->qplib_qp;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
|
||||
if (!bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx)) {
|
||||
qplqp->rq.max_sge = dev_attr->max_qp_sges;
|
||||
@@ -1284,7 +1284,7 @@ static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp,
|
||||
rdev = qp->rdev;
|
||||
qplqp = &qp->qplib_qp;
|
||||
sq = &qplqp->sq;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
|
||||
sq->max_sge = init_attr->cap.max_send_sge;
|
||||
entries = init_attr->cap.max_send_wr;
|
||||
@@ -1337,7 +1337,7 @@ static void bnxt_re_adjust_gsi_sq_attr(struct bnxt_re_qp *qp,
|
||||
|
||||
rdev = qp->rdev;
|
||||
qplqp = &qp->qplib_qp;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
|
||||
if (!bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx)) {
|
||||
entries = bnxt_re_init_depth(init_attr->cap.max_send_wr + 1, uctx);
|
||||
@@ -1386,7 +1386,7 @@ static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
|
||||
|
||||
rdev = qp->rdev;
|
||||
qplqp = &qp->qplib_qp;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
|
||||
/* Setup misc params */
|
||||
ether_addr_copy(qplqp->smac, rdev->netdev->dev_addr);
|
||||
@@ -1556,7 +1556,7 @@ int bnxt_re_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *qp_init_attr,
|
||||
ib_pd = ib_qp->pd;
|
||||
pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
|
||||
rdev = pd->rdev;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
|
||||
|
||||
uctx = rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
|
||||
@@ -1783,7 +1783,7 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
|
||||
ib_pd = ib_srq->pd;
|
||||
pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
|
||||
rdev = pd->rdev;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
srq = container_of(ib_srq, struct bnxt_re_srq, ib_srq);
|
||||
|
||||
if (srq_init_attr->attr.max_wr >= dev_attr->max_srq_wqes) {
|
||||
@@ -1814,8 +1814,10 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
|
||||
srq->qplib_srq.wqe_size = bnxt_re_get_rwqe_size(dev_attr->max_srq_sges);
|
||||
srq->qplib_srq.threshold = srq_init_attr->attr.srq_limit;
|
||||
srq->srq_limit = srq_init_attr->attr.srq_limit;
|
||||
srq->qplib_srq.eventq_hw_ring_id = rdev->nq[0].ring_id;
|
||||
nq = &rdev->nq[0];
|
||||
srq->qplib_srq.eventq_hw_ring_id = rdev->nqr->nq[0].ring_id;
|
||||
srq->qplib_srq.sg_info.pgsize = PAGE_SIZE;
|
||||
srq->qplib_srq.sg_info.pgshft = PAGE_SHIFT;
|
||||
nq = &rdev->nqr->nq[0];
|
||||
|
||||
if (udata) {
|
||||
rc = bnxt_re_init_user_srq(rdev, pd, srq, udata);
|
||||
@@ -1987,7 +1989,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
|
||||
{
|
||||
struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
|
||||
struct bnxt_re_dev *rdev = qp->rdev;
|
||||
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
|
||||
struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr;
|
||||
enum ib_qp_state curr_qp_state, new_qp_state;
|
||||
int rc, entries;
|
||||
unsigned int flags;
|
||||
@@ -3011,7 +3013,7 @@ int bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
|
||||
struct ib_udata *udata = &attrs->driver_udata;
|
||||
struct bnxt_re_ucontext *uctx =
|
||||
rdma_udata_to_drv_context(udata, struct bnxt_re_ucontext, ib_uctx);
|
||||
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
|
||||
struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr;
|
||||
struct bnxt_qplib_chip_ctx *cctx;
|
||||
struct bnxt_qplib_nq *nq = NULL;
|
||||
unsigned int nq_alloc_cnt;
|
||||
@@ -3070,7 +3072,7 @@ int bnxt_re_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
|
||||
* used for getting the NQ index.
|
||||
*/
|
||||
nq_alloc_cnt = atomic_inc_return(&rdev->nq_alloc_cnt);
|
||||
nq = &rdev->nq[nq_alloc_cnt % (rdev->num_msix - 1)];
|
||||
nq = &rdev->nqr->nq[nq_alloc_cnt % (rdev->nqr->num_msix - 1)];
|
||||
cq->qplib_cq.max_wqe = entries;
|
||||
cq->qplib_cq.cnq_hw_ring_id = nq->ring_id;
|
||||
cq->qplib_cq.nq = nq;
|
||||
@@ -3154,7 +3156,7 @@ int bnxt_re_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
|
||||
|
||||
cq = container_of(ibcq, struct bnxt_re_cq, ib_cq);
|
||||
rdev = cq->rdev;
|
||||
dev_attr = &rdev->dev_attr;
|
||||
dev_attr = rdev->dev_attr;
|
||||
if (!ibcq->uobject) {
|
||||
ibdev_err(&rdev->ibdev, "Kernel CQ Resize not supported");
|
||||
return -EOPNOTSUPP;
|
||||
@@ -4127,7 +4129,7 @@ static struct ib_mr *__bnxt_re_user_reg_mr(struct ib_pd *ib_pd, u64 length, u64
|
||||
mr->qplib_mr.access_flags = __from_ib_access_flags(mr_access_flags);
|
||||
mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_MR;
|
||||
|
||||
if (!_is_alloc_mr_unified(rdev->dev_attr.dev_cap_flags)) {
|
||||
if (!_is_alloc_mr_unified(rdev->dev_attr->dev_cap_flags)) {
|
||||
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "Failed to allocate MR rc = %d", rc);
|
||||
@@ -4219,7 +4221,7 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata)
|
||||
struct bnxt_re_ucontext *uctx =
|
||||
container_of(ctx, struct bnxt_re_ucontext, ib_uctx);
|
||||
struct bnxt_re_dev *rdev = to_bnxt_re_dev(ibdev, ibdev);
|
||||
struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
|
||||
struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr;
|
||||
struct bnxt_re_user_mmap_entry *entry;
|
||||
struct bnxt_re_uctx_resp resp = {};
|
||||
struct bnxt_re_uctx_req ureq = {};
|
||||
|
||||
@@ -152,6 +152,10 @@ static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev)
|
||||
|
||||
if (!rdev->chip_ctx)
|
||||
return;
|
||||
|
||||
kfree(rdev->dev_attr);
|
||||
rdev->dev_attr = NULL;
|
||||
|
||||
chip_ctx = rdev->chip_ctx;
|
||||
rdev->chip_ctx = NULL;
|
||||
rdev->rcfw.res = NULL;
|
||||
@@ -165,7 +169,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
struct bnxt_qplib_chip_ctx *chip_ctx;
|
||||
struct bnxt_en_dev *en_dev;
|
||||
int rc;
|
||||
int rc = -ENOMEM;
|
||||
|
||||
en_dev = rdev->en_dev;
|
||||
|
||||
@@ -181,23 +185,30 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev)
|
||||
|
||||
rdev->qplib_res.cctx = rdev->chip_ctx;
|
||||
rdev->rcfw.res = &rdev->qplib_res;
|
||||
rdev->qplib_res.dattr = &rdev->dev_attr;
|
||||
rdev->dev_attr = kzalloc(sizeof(*rdev->dev_attr), GFP_KERNEL);
|
||||
if (!rdev->dev_attr)
|
||||
goto free_chip_ctx;
|
||||
rdev->qplib_res.dattr = rdev->dev_attr;
|
||||
rdev->qplib_res.is_vf = BNXT_EN_VF(en_dev);
|
||||
|
||||
bnxt_re_set_drv_mode(rdev);
|
||||
|
||||
bnxt_re_set_db_offset(rdev);
|
||||
rc = bnxt_qplib_map_db_bar(&rdev->qplib_res);
|
||||
if (rc) {
|
||||
kfree(rdev->chip_ctx);
|
||||
rdev->chip_ctx = NULL;
|
||||
return rc;
|
||||
}
|
||||
if (rc)
|
||||
goto free_dev_attr;
|
||||
|
||||
if (bnxt_qplib_determine_atomics(en_dev->pdev))
|
||||
ibdev_info(&rdev->ibdev,
|
||||
"platform doesn't support global atomics.");
|
||||
return 0;
|
||||
free_dev_attr:
|
||||
kfree(rdev->dev_attr);
|
||||
rdev->dev_attr = NULL;
|
||||
free_chip_ctx:
|
||||
kfree(rdev->chip_ctx);
|
||||
rdev->chip_ctx = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* SR-IOV helper functions */
|
||||
@@ -219,7 +230,7 @@ static void bnxt_re_limit_pf_res(struct bnxt_re_dev *rdev)
|
||||
struct bnxt_qplib_ctx *ctx;
|
||||
int i;
|
||||
|
||||
attr = &rdev->dev_attr;
|
||||
attr = rdev->dev_attr;
|
||||
ctx = &rdev->qplib_ctx;
|
||||
|
||||
ctx->qpc_count = min_t(u32, BNXT_RE_MAX_QPC_COUNT,
|
||||
@@ -233,7 +244,7 @@ static void bnxt_re_limit_pf_res(struct bnxt_re_dev *rdev)
|
||||
if (!bnxt_qplib_is_chip_gen_p5_p7(rdev->chip_ctx))
|
||||
for (i = 0; i < MAX_TQM_ALLOC_REQ; i++)
|
||||
rdev->qplib_ctx.tqm_ctx.qcount[i] =
|
||||
rdev->dev_attr.tqm_alloc_reqs[i];
|
||||
rdev->dev_attr->tqm_alloc_reqs[i];
|
||||
}
|
||||
|
||||
static void bnxt_re_limit_vf_res(struct bnxt_qplib_ctx *qplib_ctx, u32 num_vf)
|
||||
@@ -314,10 +325,12 @@ static void bnxt_re_stop_irq(void *handle)
|
||||
int indx;
|
||||
|
||||
rdev = en_info->rdev;
|
||||
if (!rdev)
|
||||
return;
|
||||
rcfw = &rdev->rcfw;
|
||||
|
||||
for (indx = BNXT_RE_NQ_IDX; indx < rdev->num_msix; indx++) {
|
||||
nq = &rdev->nq[indx - 1];
|
||||
for (indx = BNXT_RE_NQ_IDX; indx < rdev->nqr->num_msix; indx++) {
|
||||
nq = &rdev->nqr->nq[indx - 1];
|
||||
bnxt_qplib_nq_stop_irq(nq, false);
|
||||
}
|
||||
|
||||
@@ -334,7 +347,9 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent)
|
||||
int indx, rc;
|
||||
|
||||
rdev = en_info->rdev;
|
||||
msix_ent = rdev->en_dev->msix_entries;
|
||||
if (!rdev)
|
||||
return;
|
||||
msix_ent = rdev->nqr->msix_entries;
|
||||
rcfw = &rdev->rcfw;
|
||||
if (!ent) {
|
||||
/* Not setting the f/w timeout bit in rcfw.
|
||||
@@ -349,8 +364,8 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent)
|
||||
/* Vectors may change after restart, so update with new vectors
|
||||
* in device sctructure.
|
||||
*/
|
||||
for (indx = 0; indx < rdev->num_msix; indx++)
|
||||
rdev->en_dev->msix_entries[indx].vector = ent[indx].vector;
|
||||
for (indx = 0; indx < rdev->nqr->num_msix; indx++)
|
||||
rdev->nqr->msix_entries[indx].vector = ent[indx].vector;
|
||||
|
||||
rc = bnxt_qplib_rcfw_start_irq(rcfw, msix_ent[BNXT_RE_AEQ_IDX].vector,
|
||||
false);
|
||||
@@ -358,8 +373,8 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent)
|
||||
ibdev_warn(&rdev->ibdev, "Failed to reinit CREQ\n");
|
||||
return;
|
||||
}
|
||||
for (indx = BNXT_RE_NQ_IDX ; indx < rdev->num_msix; indx++) {
|
||||
nq = &rdev->nq[indx - 1];
|
||||
for (indx = BNXT_RE_NQ_IDX ; indx < rdev->nqr->num_msix; indx++) {
|
||||
nq = &rdev->nqr->nq[indx - 1];
|
||||
rc = bnxt_qplib_nq_start_irq(nq, indx - 1,
|
||||
msix_ent[indx].vector, false);
|
||||
if (rc) {
|
||||
@@ -943,7 +958,7 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
|
||||
|
||||
addrconf_addr_eui48((u8 *)&ibdev->node_guid, rdev->netdev->dev_addr);
|
||||
|
||||
ibdev->num_comp_vectors = rdev->num_msix - 1;
|
||||
ibdev->num_comp_vectors = rdev->nqr->num_msix - 1;
|
||||
ibdev->dev.parent = &rdev->en_dev->pdev->dev;
|
||||
ibdev->local_dma_lkey = BNXT_QPLIB_RSVD_LKEY;
|
||||
|
||||
@@ -1276,8 +1291,8 @@ static void bnxt_re_cleanup_res(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < rdev->num_msix; i++)
|
||||
bnxt_qplib_disable_nq(&rdev->nq[i - 1]);
|
||||
for (i = 1; i < rdev->nqr->num_msix; i++)
|
||||
bnxt_qplib_disable_nq(&rdev->nqr->nq[i - 1]);
|
||||
|
||||
if (rdev->qplib_res.rcfw)
|
||||
bnxt_qplib_cleanup_res(&rdev->qplib_res);
|
||||
@@ -1291,10 +1306,10 @@ static int bnxt_re_init_res(struct bnxt_re_dev *rdev)
|
||||
|
||||
bnxt_qplib_init_res(&rdev->qplib_res);
|
||||
|
||||
for (i = 1; i < rdev->num_msix ; i++) {
|
||||
db_offt = rdev->en_dev->msix_entries[i].db_offset;
|
||||
rc = bnxt_qplib_enable_nq(rdev->en_dev->pdev, &rdev->nq[i - 1],
|
||||
i - 1, rdev->en_dev->msix_entries[i].vector,
|
||||
for (i = 1; i < rdev->nqr->num_msix ; i++) {
|
||||
db_offt = rdev->nqr->msix_entries[i].db_offset;
|
||||
rc = bnxt_qplib_enable_nq(rdev->en_dev->pdev, &rdev->nqr->nq[i - 1],
|
||||
i - 1, rdev->nqr->msix_entries[i].vector,
|
||||
db_offt, &bnxt_re_cqn_handler,
|
||||
&bnxt_re_srqn_handler);
|
||||
if (rc) {
|
||||
@@ -1307,20 +1322,22 @@ static int bnxt_re_init_res(struct bnxt_re_dev *rdev)
|
||||
return 0;
|
||||
fail:
|
||||
for (i = num_vec_enabled; i >= 0; i--)
|
||||
bnxt_qplib_disable_nq(&rdev->nq[i]);
|
||||
bnxt_qplib_disable_nq(&rdev->nqr->nq[i]);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void bnxt_re_free_nq_res(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
struct bnxt_qplib_nq *nq;
|
||||
u8 type;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rdev->num_msix - 1; i++) {
|
||||
for (i = 0; i < rdev->nqr->num_msix - 1; i++) {
|
||||
type = bnxt_qplib_get_ring_type(rdev->chip_ctx);
|
||||
bnxt_re_net_ring_free(rdev, rdev->nq[i].ring_id, type);
|
||||
bnxt_qplib_free_nq(&rdev->nq[i]);
|
||||
rdev->nq[i].res = NULL;
|
||||
nq = &rdev->nqr->nq[i];
|
||||
bnxt_re_net_ring_free(rdev, nq->ring_id, type);
|
||||
bnxt_qplib_free_nq(nq);
|
||||
nq->res = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1347,12 +1364,11 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
|
||||
|
||||
/* Configure and allocate resources for qplib */
|
||||
rdev->qplib_res.rcfw = &rdev->rcfw;
|
||||
rc = bnxt_qplib_get_dev_attr(&rdev->rcfw, &rdev->dev_attr);
|
||||
rc = bnxt_qplib_get_dev_attr(&rdev->rcfw);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
rc = bnxt_qplib_alloc_res(&rdev->qplib_res, rdev->en_dev->pdev,
|
||||
rdev->netdev, &rdev->dev_attr);
|
||||
rc = bnxt_qplib_alloc_res(&rdev->qplib_res, rdev->netdev);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
@@ -1362,12 +1378,12 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
|
||||
if (rc)
|
||||
goto dealloc_res;
|
||||
|
||||
for (i = 0; i < rdev->num_msix - 1; i++) {
|
||||
for (i = 0; i < rdev->nqr->num_msix - 1; i++) {
|
||||
struct bnxt_qplib_nq *nq;
|
||||
|
||||
nq = &rdev->nq[i];
|
||||
nq = &rdev->nqr->nq[i];
|
||||
nq->hwq.max_elements = BNXT_QPLIB_NQE_MAX_CNT;
|
||||
rc = bnxt_qplib_alloc_nq(&rdev->qplib_res, &rdev->nq[i]);
|
||||
rc = bnxt_qplib_alloc_nq(&rdev->qplib_res, nq);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "Alloc Failed NQ%d rc:%#x",
|
||||
i, rc);
|
||||
@@ -1375,17 +1391,17 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
|
||||
}
|
||||
type = bnxt_qplib_get_ring_type(rdev->chip_ctx);
|
||||
rattr.dma_arr = nq->hwq.pbl[PBL_LVL_0].pg_map_arr;
|
||||
rattr.pages = nq->hwq.pbl[rdev->nq[i].hwq.level].pg_count;
|
||||
rattr.pages = nq->hwq.pbl[rdev->nqr->nq[i].hwq.level].pg_count;
|
||||
rattr.type = type;
|
||||
rattr.mode = RING_ALLOC_REQ_INT_MODE_MSIX;
|
||||
rattr.depth = BNXT_QPLIB_NQE_MAX_CNT - 1;
|
||||
rattr.lrid = rdev->en_dev->msix_entries[i + 1].ring_idx;
|
||||
rattr.lrid = rdev->nqr->msix_entries[i + 1].ring_idx;
|
||||
rc = bnxt_re_net_ring_alloc(rdev, &rattr, &nq->ring_id);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev,
|
||||
"Failed to allocate NQ fw id with rc = 0x%x",
|
||||
rc);
|
||||
bnxt_qplib_free_nq(&rdev->nq[i]);
|
||||
bnxt_qplib_free_nq(nq);
|
||||
goto free_nq;
|
||||
}
|
||||
num_vec_created++;
|
||||
@@ -1394,8 +1410,8 @@ static int bnxt_re_alloc_res(struct bnxt_re_dev *rdev)
|
||||
free_nq:
|
||||
for (i = num_vec_created - 1; i >= 0; i--) {
|
||||
type = bnxt_qplib_get_ring_type(rdev->chip_ctx);
|
||||
bnxt_re_net_ring_free(rdev, rdev->nq[i].ring_id, type);
|
||||
bnxt_qplib_free_nq(&rdev->nq[i]);
|
||||
bnxt_re_net_ring_free(rdev, rdev->nqr->nq[i].ring_id, type);
|
||||
bnxt_qplib_free_nq(&rdev->nqr->nq[i]);
|
||||
}
|
||||
bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
|
||||
&rdev->dpi_privileged);
|
||||
@@ -1584,6 +1600,21 @@ static int bnxt_re_ib_init(struct bnxt_re_dev *rdev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int bnxt_re_alloc_nqr_mem(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
rdev->nqr = kzalloc(sizeof(*rdev->nqr), GFP_KERNEL);
|
||||
if (!rdev->nqr)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnxt_re_free_nqr_mem(struct bnxt_re_dev *rdev)
|
||||
{
|
||||
kfree(rdev->nqr);
|
||||
rdev->nqr = NULL;
|
||||
}
|
||||
|
||||
static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type)
|
||||
{
|
||||
u8 type;
|
||||
@@ -1611,11 +1642,12 @@ static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type)
|
||||
bnxt_qplib_free_rcfw_channel(&rdev->rcfw);
|
||||
}
|
||||
|
||||
rdev->num_msix = 0;
|
||||
rdev->nqr->num_msix = 0;
|
||||
|
||||
if (rdev->pacing.dbr_pacing)
|
||||
bnxt_re_deinitialize_dbr_pacing(rdev);
|
||||
|
||||
bnxt_re_free_nqr_mem(rdev);
|
||||
bnxt_re_destroy_chip_ctx(rdev);
|
||||
if (op_type == BNXT_RE_COMPLETE_REMOVE) {
|
||||
if (test_and_clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags))
|
||||
@@ -1653,6 +1685,17 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
|
||||
}
|
||||
set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
|
||||
|
||||
if (rdev->en_dev->ulp_tbl->msix_requested < BNXT_RE_MIN_MSIX) {
|
||||
ibdev_err(&rdev->ibdev,
|
||||
"RoCE requires minimum 2 MSI-X vectors, but only %d reserved\n",
|
||||
rdev->en_dev->ulp_tbl->msix_requested);
|
||||
bnxt_unregister_dev(rdev->en_dev);
|
||||
clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
ibdev_dbg(&rdev->ibdev, "Got %d MSI-X vectors\n",
|
||||
rdev->en_dev->ulp_tbl->msix_requested);
|
||||
|
||||
rc = bnxt_re_setup_chip_ctx(rdev);
|
||||
if (rc) {
|
||||
bnxt_unregister_dev(rdev->en_dev);
|
||||
@@ -1661,19 +1704,20 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = bnxt_re_alloc_nqr_mem(rdev);
|
||||
if (rc) {
|
||||
bnxt_re_destroy_chip_ctx(rdev);
|
||||
bnxt_unregister_dev(rdev->en_dev);
|
||||
clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags);
|
||||
return rc;
|
||||
}
|
||||
rdev->nqr->num_msix = rdev->en_dev->ulp_tbl->msix_requested;
|
||||
memcpy(rdev->nqr->msix_entries, rdev->en_dev->msix_entries,
|
||||
sizeof(struct bnxt_msix_entry) * rdev->nqr->num_msix);
|
||||
|
||||
/* Check whether VF or PF */
|
||||
bnxt_re_get_sriov_func_type(rdev);
|
||||
|
||||
if (!rdev->en_dev->ulp_tbl->msix_requested) {
|
||||
ibdev_err(&rdev->ibdev,
|
||||
"Failed to get MSI-X vectors: %#x\n", rc);
|
||||
rc = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
ibdev_dbg(&rdev->ibdev, "Got %d MSI-X vectors\n",
|
||||
rdev->en_dev->ulp_tbl->msix_requested);
|
||||
rdev->num_msix = rdev->en_dev->ulp_tbl->msix_requested;
|
||||
|
||||
bnxt_re_query_hwrm_intf_version(rdev);
|
||||
|
||||
/* Establish RCFW Communication Channel to initialize the context
|
||||
@@ -1695,14 +1739,14 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
|
||||
rattr.type = type;
|
||||
rattr.mode = RING_ALLOC_REQ_INT_MODE_MSIX;
|
||||
rattr.depth = BNXT_QPLIB_CREQE_MAX_CNT - 1;
|
||||
rattr.lrid = rdev->en_dev->msix_entries[BNXT_RE_AEQ_IDX].ring_idx;
|
||||
rattr.lrid = rdev->nqr->msix_entries[BNXT_RE_AEQ_IDX].ring_idx;
|
||||
rc = bnxt_re_net_ring_alloc(rdev, &rattr, &creq->ring_id);
|
||||
if (rc) {
|
||||
ibdev_err(&rdev->ibdev, "Failed to allocate CREQ: %#x\n", rc);
|
||||
goto free_rcfw;
|
||||
}
|
||||
db_offt = rdev->en_dev->msix_entries[BNXT_RE_AEQ_IDX].db_offset;
|
||||
vid = rdev->en_dev->msix_entries[BNXT_RE_AEQ_IDX].vector;
|
||||
db_offt = rdev->nqr->msix_entries[BNXT_RE_AEQ_IDX].db_offset;
|
||||
vid = rdev->nqr->msix_entries[BNXT_RE_AEQ_IDX].vector;
|
||||
rc = bnxt_qplib_enable_rcfw_channel(&rdev->rcfw,
|
||||
vid, db_offt,
|
||||
&bnxt_re_aeq_handler);
|
||||
@@ -1722,7 +1766,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)
|
||||
rdev->pacing.dbr_pacing = false;
|
||||
}
|
||||
}
|
||||
rc = bnxt_qplib_get_dev_attr(&rdev->rcfw, &rdev->dev_attr);
|
||||
rc = bnxt_qplib_get_dev_attr(&rdev->rcfw);
|
||||
if (rc)
|
||||
goto disable_rcfw;
|
||||
|
||||
@@ -2047,6 +2091,7 @@ static int bnxt_re_suspend(struct auxiliary_device *adev, pm_message_t state)
|
||||
ibdev_info(&rdev->ibdev, "%s: L2 driver notified to stop en_state 0x%lx",
|
||||
__func__, en_dev->en_state);
|
||||
bnxt_re_remove_device(rdev, BNXT_RE_PRE_RECOVERY_REMOVE, adev);
|
||||
bnxt_re_update_en_info_rdev(NULL, en_info, adev);
|
||||
mutex_unlock(&bnxt_re_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -876,14 +876,13 @@ void bnxt_qplib_free_res(struct bnxt_qplib_res *res)
|
||||
bnxt_qplib_free_dpi_tbl(res, &res->dpi_tbl);
|
||||
}
|
||||
|
||||
int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct pci_dev *pdev,
|
||||
struct net_device *netdev,
|
||||
struct bnxt_qplib_dev_attr *dev_attr)
|
||||
int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct net_device *netdev)
|
||||
{
|
||||
struct bnxt_qplib_dev_attr *dev_attr;
|
||||
int rc;
|
||||
|
||||
res->pdev = pdev;
|
||||
res->netdev = netdev;
|
||||
dev_attr = res->dattr;
|
||||
|
||||
rc = bnxt_qplib_alloc_sgid_tbl(res, &res->sgid_tbl, dev_attr->max_sgid);
|
||||
if (rc)
|
||||
|
||||
@@ -421,9 +421,7 @@ int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
|
||||
void bnxt_qplib_cleanup_res(struct bnxt_qplib_res *res);
|
||||
int bnxt_qplib_init_res(struct bnxt_qplib_res *res);
|
||||
void bnxt_qplib_free_res(struct bnxt_qplib_res *res);
|
||||
int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct pci_dev *pdev,
|
||||
struct net_device *netdev,
|
||||
struct bnxt_qplib_dev_attr *dev_attr);
|
||||
int bnxt_qplib_alloc_res(struct bnxt_qplib_res *res, struct net_device *netdev);
|
||||
void bnxt_qplib_free_ctx(struct bnxt_qplib_res *res,
|
||||
struct bnxt_qplib_ctx *ctx);
|
||||
int bnxt_qplib_alloc_ctx(struct bnxt_qplib_res *res,
|
||||
@@ -546,6 +544,14 @@ static inline bool _is_ext_stats_supported(u16 dev_cap_flags)
|
||||
CREQ_QUERY_FUNC_RESP_SB_EXT_STATS;
|
||||
}
|
||||
|
||||
static inline int bnxt_ext_stats_supported(struct bnxt_qplib_chip_ctx *ctx,
|
||||
u16 flags, bool virtfn)
|
||||
{
|
||||
/* ext stats supported if cap flag is set AND is a PF OR a Thor2 VF */
|
||||
return (_is_ext_stats_supported(flags) &&
|
||||
((virtfn && bnxt_qplib_is_chip_gen_p7(ctx)) || (!virtfn)));
|
||||
}
|
||||
|
||||
static inline bool _is_hw_retx_supported(u16 dev_cap_flags)
|
||||
{
|
||||
return dev_cap_flags &
|
||||
|
||||
@@ -88,9 +88,9 @@ static void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw,
|
||||
fw_ver[3] = resp.fw_rsvd;
|
||||
}
|
||||
|
||||
int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
|
||||
struct bnxt_qplib_dev_attr *attr)
|
||||
int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw)
|
||||
{
|
||||
struct bnxt_qplib_dev_attr *attr = rcfw->res->dattr;
|
||||
struct creq_query_func_resp resp = {};
|
||||
struct bnxt_qplib_cmdqmsg msg = {};
|
||||
struct creq_query_func_resp_sb *sb;
|
||||
|
||||
@@ -325,8 +325,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
|
||||
int bnxt_qplib_update_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
|
||||
struct bnxt_qplib_gid *gid, u16 gid_idx,
|
||||
const u8 *smac);
|
||||
int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
|
||||
struct bnxt_qplib_dev_attr *attr);
|
||||
int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw);
|
||||
int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res,
|
||||
struct bnxt_qplib_rcfw *rcfw,
|
||||
struct bnxt_qplib_ctx *ctx);
|
||||
|
||||
@@ -1286,10 +1286,8 @@ static u32 hns_roce_cmdq_tx_timeout(u16 opcode, u32 tx_timeout)
|
||||
return tx_timeout;
|
||||
}
|
||||
|
||||
static void hns_roce_wait_csq_done(struct hns_roce_dev *hr_dev, u16 opcode)
|
||||
static void hns_roce_wait_csq_done(struct hns_roce_dev *hr_dev, u32 tx_timeout)
|
||||
{
|
||||
struct hns_roce_v2_priv *priv = hr_dev->priv;
|
||||
u32 tx_timeout = hns_roce_cmdq_tx_timeout(opcode, priv->cmq.tx_timeout);
|
||||
u32 timeout = 0;
|
||||
|
||||
do {
|
||||
@@ -1299,8 +1297,9 @@ static void hns_roce_wait_csq_done(struct hns_roce_dev *hr_dev, u16 opcode)
|
||||
} while (++timeout < tx_timeout);
|
||||
}
|
||||
|
||||
static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmq_desc *desc, int num)
|
||||
static int __hns_roce_cmq_send_one(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmq_desc *desc,
|
||||
int num, u32 tx_timeout)
|
||||
{
|
||||
struct hns_roce_v2_priv *priv = hr_dev->priv;
|
||||
struct hns_roce_v2_cmq_ring *csq = &priv->cmq.csq;
|
||||
@@ -1309,8 +1308,6 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&csq->lock);
|
||||
|
||||
tail = csq->head;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
@@ -1324,22 +1321,17 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
|
||||
|
||||
atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_CMDS_CNT]);
|
||||
|
||||
hns_roce_wait_csq_done(hr_dev, le16_to_cpu(desc->opcode));
|
||||
hns_roce_wait_csq_done(hr_dev, tx_timeout);
|
||||
if (hns_roce_cmq_csq_done(hr_dev)) {
|
||||
ret = 0;
|
||||
for (i = 0; i < num; i++) {
|
||||
/* check the result of hardware write back */
|
||||
desc[i] = csq->desc[tail++];
|
||||
desc_ret = le16_to_cpu(csq->desc[tail++].retval);
|
||||
if (tail == csq->desc_num)
|
||||
tail = 0;
|
||||
|
||||
desc_ret = le16_to_cpu(desc[i].retval);
|
||||
if (likely(desc_ret == CMD_EXEC_SUCCESS))
|
||||
continue;
|
||||
|
||||
dev_err_ratelimited(hr_dev->dev,
|
||||
"Cmdq IO error, opcode = 0x%x, return = 0x%x.\n",
|
||||
desc->opcode, desc_ret);
|
||||
ret = hns_roce_cmd_err_convert_errno(desc_ret);
|
||||
}
|
||||
} else {
|
||||
@@ -1354,14 +1346,54 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&csq->lock);
|
||||
|
||||
if (ret)
|
||||
atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_CMDS_ERR_CNT]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmq_desc *desc, int num)
|
||||
{
|
||||
struct hns_roce_v2_priv *priv = hr_dev->priv;
|
||||
struct hns_roce_v2_cmq_ring *csq = &priv->cmq.csq;
|
||||
u16 opcode = le16_to_cpu(desc->opcode);
|
||||
u32 tx_timeout = hns_roce_cmdq_tx_timeout(opcode, priv->cmq.tx_timeout);
|
||||
u8 try_cnt = HNS_ROCE_OPC_POST_MB_TRY_CNT;
|
||||
u32 rsv_tail;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
while (try_cnt) {
|
||||
try_cnt--;
|
||||
|
||||
spin_lock_bh(&csq->lock);
|
||||
rsv_tail = csq->head;
|
||||
ret = __hns_roce_cmq_send_one(hr_dev, desc, num, tx_timeout);
|
||||
if (opcode == HNS_ROCE_OPC_POST_MB && ret == -ETIME &&
|
||||
try_cnt) {
|
||||
spin_unlock_bh(&csq->lock);
|
||||
mdelay(HNS_ROCE_OPC_POST_MB_RETRY_GAP_MSEC);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
desc[i] = csq->desc[rsv_tail++];
|
||||
if (rsv_tail == csq->desc_num)
|
||||
rsv_tail = 0;
|
||||
}
|
||||
spin_unlock_bh(&csq->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
dev_err_ratelimited(hr_dev->dev,
|
||||
"Cmdq IO error, opcode = 0x%x, return = %d.\n",
|
||||
opcode, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns_roce_cmq_send(struct hns_roce_dev *hr_dev,
|
||||
struct hns_roce_cmq_desc *desc, int num)
|
||||
{
|
||||
|
||||
@@ -230,6 +230,8 @@ enum hns_roce_opcode_type {
|
||||
};
|
||||
|
||||
#define HNS_ROCE_OPC_POST_MB_TIMEOUT 35000
|
||||
#define HNS_ROCE_OPC_POST_MB_TRY_CNT 8
|
||||
#define HNS_ROCE_OPC_POST_MB_RETRY_GAP_MSEC 5
|
||||
struct hns_roce_cmdq_tx_timeout_map {
|
||||
u16 opcode;
|
||||
u32 tx_timeout;
|
||||
|
||||
@@ -174,7 +174,7 @@ static int mana_gd_allocate_doorbell_page(struct gdma_context *gc,
|
||||
|
||||
req.resource_type = GDMA_RESOURCE_DOORBELL_PAGE;
|
||||
req.num_resources = 1;
|
||||
req.alignment = 1;
|
||||
req.alignment = PAGE_SIZE / MANA_PAGE_SIZE;
|
||||
|
||||
/* Have GDMA start searching from 0 */
|
||||
req.allocated_resources = 0;
|
||||
|
||||
@@ -67,7 +67,8 @@ static void create_ib_ah(struct mlx5_ib_dev *dev, struct mlx5_ib_ah *ah,
|
||||
ah->av.tclass = grh->traffic_class;
|
||||
}
|
||||
|
||||
ah->av.stat_rate_sl = (rdma_ah_get_static_rate(ah_attr) << 4);
|
||||
ah->av.stat_rate_sl =
|
||||
(mlx5r_ib_rate(dev, rdma_ah_get_static_rate(ah_attr)) << 4);
|
||||
|
||||
if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
|
||||
if (init_attr->xmit_slave)
|
||||
|
||||
@@ -546,6 +546,7 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
|
||||
struct ib_qp *qp)
|
||||
{
|
||||
struct mlx5_ib_dev *dev = to_mdev(qp->device);
|
||||
bool new = false;
|
||||
int err;
|
||||
|
||||
if (!counter->id) {
|
||||
@@ -560,6 +561,7 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
|
||||
return err;
|
||||
counter->id =
|
||||
MLX5_GET(alloc_q_counter_out, out, counter_set_id);
|
||||
new = true;
|
||||
}
|
||||
|
||||
err = mlx5_ib_qp_set_counter(qp, counter);
|
||||
@@ -569,8 +571,10 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
|
||||
return 0;
|
||||
|
||||
fail_set_counter:
|
||||
mlx5_ib_counter_dealloc(counter);
|
||||
counter->id = 0;
|
||||
if (new) {
|
||||
mlx5_ib_counter_dealloc(counter);
|
||||
counter->id = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1550,7 +1550,7 @@ static void mlx5_ib_dmabuf_invalidate_cb(struct dma_buf_attachment *attach)
|
||||
|
||||
dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv);
|
||||
|
||||
if (!umem_dmabuf->sgt)
|
||||
if (!umem_dmabuf->sgt || !mr)
|
||||
return;
|
||||
|
||||
mlx5r_umr_update_mr_pas(mr, MLX5_IB_UPD_XLT_ZAP);
|
||||
@@ -1935,7 +1935,8 @@ err:
|
||||
static void
|
||||
mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
|
||||
{
|
||||
if (!mr->umem && !mr->data_direct && mr->descs) {
|
||||
if (!mr->umem && !mr->data_direct &&
|
||||
mr->ibmr.type != IB_MR_TYPE_DM && mr->descs) {
|
||||
struct ib_device *device = mr->ibmr.device;
|
||||
int size = mr->max_descs * mr->desc_size;
|
||||
struct mlx5_ib_dev *dev = to_mdev(device);
|
||||
@@ -2022,11 +2023,16 @@ static int mlx5_revoke_mr(struct mlx5_ib_mr *mr)
|
||||
struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device);
|
||||
struct mlx5_cache_ent *ent = mr->mmkey.cache_ent;
|
||||
bool is_odp = is_odp_mr(mr);
|
||||
bool is_odp_dma_buf = is_dmabuf_mr(mr) &&
|
||||
!to_ib_umem_dmabuf(mr->umem)->pinned;
|
||||
int ret = 0;
|
||||
|
||||
if (is_odp)
|
||||
mutex_lock(&to_ib_umem_odp(mr->umem)->umem_mutex);
|
||||
|
||||
if (is_odp_dma_buf)
|
||||
dma_resv_lock(to_ib_umem_dmabuf(mr->umem)->attach->dmabuf->resv, NULL);
|
||||
|
||||
if (mr->mmkey.cacheable && !mlx5r_umr_revoke_mr(mr) && !cache_ent_find_and_store(dev, mr)) {
|
||||
ent = mr->mmkey.cache_ent;
|
||||
/* upon storing to a clean temp entry - schedule its cleanup */
|
||||
@@ -2054,6 +2060,12 @@ out:
|
||||
mutex_unlock(&to_ib_umem_odp(mr->umem)->umem_mutex);
|
||||
}
|
||||
|
||||
if (is_odp_dma_buf) {
|
||||
if (!ret)
|
||||
to_ib_umem_dmabuf(mr->umem)->private = NULL;
|
||||
dma_resv_unlock(to_ib_umem_dmabuf(mr->umem)->attach->dmabuf->resv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -242,6 +242,7 @@ static void destroy_unused_implicit_child_mr(struct mlx5_ib_mr *mr)
|
||||
if (__xa_cmpxchg(&imr->implicit_children, idx, mr, NULL, GFP_KERNEL) !=
|
||||
mr) {
|
||||
xa_unlock(&imr->implicit_children);
|
||||
mlx5r_deref_odp_mkey(&imr->mmkey);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3420,11 +3420,11 @@ static int ib_to_mlx5_rate_map(u8 rate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ib_rate_to_mlx5(struct mlx5_ib_dev *dev, u8 rate)
|
||||
int mlx5r_ib_rate(struct mlx5_ib_dev *dev, u8 rate)
|
||||
{
|
||||
u32 stat_rate_support;
|
||||
|
||||
if (rate == IB_RATE_PORT_CURRENT)
|
||||
if (rate == IB_RATE_PORT_CURRENT || rate == IB_RATE_800_GBPS)
|
||||
return 0;
|
||||
|
||||
if (rate < IB_RATE_2_5_GBPS || rate > IB_RATE_800_GBPS)
|
||||
@@ -3569,7 +3569,7 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
|
||||
sizeof(grh->dgid.raw));
|
||||
}
|
||||
|
||||
err = ib_rate_to_mlx5(dev, rdma_ah_get_static_rate(ah));
|
||||
err = mlx5r_ib_rate(dev, rdma_ah_get_static_rate(ah));
|
||||
if (err < 0)
|
||||
return err;
|
||||
MLX5_SET(ads, path, stat_rate, err);
|
||||
@@ -4547,6 +4547,8 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
|
||||
set_id = mlx5_ib_get_counters_id(dev, attr->port_num - 1);
|
||||
MLX5_SET(dctc, dctc, counter_set_id, set_id);
|
||||
|
||||
qp->port = attr->port_num;
|
||||
} else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
|
||||
struct mlx5_ib_modify_qp_resp resp = {};
|
||||
u32 out[MLX5_ST_SZ_DW(create_dct_out)] = {};
|
||||
@@ -5033,7 +5035,7 @@ static int mlx5_ib_dct_query_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *mqp,
|
||||
}
|
||||
|
||||
if (qp_attr_mask & IB_QP_PORT)
|
||||
qp_attr->port_num = MLX5_GET(dctc, dctc, port);
|
||||
qp_attr->port_num = mqp->port;
|
||||
if (qp_attr_mask & IB_QP_MIN_RNR_TIMER)
|
||||
qp_attr->min_rnr_timer = MLX5_GET(dctc, dctc, min_rnr_nak);
|
||||
if (qp_attr_mask & IB_QP_AV) {
|
||||
|
||||
@@ -56,4 +56,5 @@ int mlx5_core_xrcd_dealloc(struct mlx5_ib_dev *dev, u32 xrcdn);
|
||||
int mlx5_ib_qp_set_counter(struct ib_qp *qp, struct rdma_counter *counter);
|
||||
int mlx5_ib_qp_event_init(void);
|
||||
void mlx5_ib_qp_event_cleanup(void);
|
||||
int mlx5r_ib_rate(struct mlx5_ib_dev *dev, u8 rate);
|
||||
#endif /* _MLX5_IB_QP_H */
|
||||
|
||||
@@ -231,30 +231,6 @@ void mlx5r_umr_cleanup(struct mlx5_ib_dev *dev)
|
||||
ib_dealloc_pd(dev->umrc.pd);
|
||||
}
|
||||
|
||||
static int mlx5r_umr_recover(struct mlx5_ib_dev *dev)
|
||||
{
|
||||
struct umr_common *umrc = &dev->umrc;
|
||||
struct ib_qp_attr attr;
|
||||
int err;
|
||||
|
||||
attr.qp_state = IB_QPS_RESET;
|
||||
err = ib_modify_qp(umrc->qp, &attr, IB_QP_STATE);
|
||||
if (err) {
|
||||
mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = mlx5r_umr_qp_rst2rts(dev, umrc->qp);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
umrc->state = MLX5_UMR_STATE_ACTIVE;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
umrc->state = MLX5_UMR_STATE_ERR;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5r_umr_post_send(struct ib_qp *ibqp, u32 mkey, struct ib_cqe *cqe,
|
||||
struct mlx5r_umr_wqe *wqe, bool with_data)
|
||||
@@ -302,6 +278,61 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5r_umr_recover(struct mlx5_ib_dev *dev, u32 mkey,
|
||||
struct mlx5r_umr_context *umr_context,
|
||||
struct mlx5r_umr_wqe *wqe, bool with_data)
|
||||
{
|
||||
struct umr_common *umrc = &dev->umrc;
|
||||
struct ib_qp_attr attr;
|
||||
int err;
|
||||
|
||||
mutex_lock(&umrc->lock);
|
||||
/* Preventing any further WRs to be sent now */
|
||||
if (umrc->state != MLX5_UMR_STATE_RECOVER) {
|
||||
mlx5_ib_warn(dev, "UMR recovery encountered an unexpected state=%d\n",
|
||||
umrc->state);
|
||||
umrc->state = MLX5_UMR_STATE_RECOVER;
|
||||
}
|
||||
mutex_unlock(&umrc->lock);
|
||||
|
||||
/* Sending a final/barrier WR (the failed one) and wait for its completion.
|
||||
* This will ensure that all the previous WRs got a completion before
|
||||
* we set the QP state to RESET.
|
||||
*/
|
||||
err = mlx5r_umr_post_send(umrc->qp, mkey, &umr_context->cqe, wqe,
|
||||
with_data);
|
||||
if (err) {
|
||||
mlx5_ib_warn(dev, "UMR recovery post send failed, err %d\n", err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Since the QP is in an error state, it will only receive
|
||||
* IB_WC_WR_FLUSH_ERR. However, as it serves only as a barrier
|
||||
* we don't care about its status.
|
||||
*/
|
||||
wait_for_completion(&umr_context->done);
|
||||
|
||||
attr.qp_state = IB_QPS_RESET;
|
||||
err = ib_modify_qp(umrc->qp, &attr, IB_QP_STATE);
|
||||
if (err) {
|
||||
mlx5_ib_warn(dev, "Couldn't modify UMR QP to RESET, err=%d\n", err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = mlx5r_umr_qp_rst2rts(dev, umrc->qp);
|
||||
if (err) {
|
||||
mlx5_ib_warn(dev, "Couldn't modify UMR QP to RTS, err=%d\n", err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
umrc->state = MLX5_UMR_STATE_ACTIVE;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
umrc->state = MLX5_UMR_STATE_ERR;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5r_umr_done(struct ib_cq *cq, struct ib_wc *wc)
|
||||
{
|
||||
struct mlx5_ib_umr_context *context =
|
||||
@@ -366,9 +397,7 @@ static int mlx5r_umr_post_send_wait(struct mlx5_ib_dev *dev, u32 mkey,
|
||||
mlx5_ib_warn(dev,
|
||||
"reg umr failed (%u). Trying to recover and resubmit the flushed WQEs, mkey = %u\n",
|
||||
umr_context.status, mkey);
|
||||
mutex_lock(&umrc->lock);
|
||||
err = mlx5r_umr_recover(dev);
|
||||
mutex_unlock(&umrc->lock);
|
||||
err = mlx5r_umr_recover(dev, mkey, &umr_context, wqe, with_data);
|
||||
if (err)
|
||||
mlx5_ib_warn(dev, "couldn't recover UMR, err %d\n",
|
||||
err);
|
||||
|
||||
@@ -2056,6 +2056,7 @@ int enable_drhd_fault_handling(unsigned int cpu)
|
||||
/*
|
||||
* Enable fault control interrupt.
|
||||
*/
|
||||
guard(rwsem_read)(&dmar_global_lock);
|
||||
for_each_iommu(iommu, drhd) {
|
||||
u32 fault_status;
|
||||
int ret;
|
||||
|
||||
@@ -3307,7 +3307,14 @@ int __init intel_iommu_init(void)
|
||||
iommu_device_sysfs_add(&iommu->iommu, NULL,
|
||||
intel_iommu_groups,
|
||||
"%s", iommu->name);
|
||||
/*
|
||||
* The iommu device probe is protected by the iommu_probe_device_lock.
|
||||
* Release the dmar_global_lock before entering the device probe path
|
||||
* to avoid unnecessary lock order splat.
|
||||
*/
|
||||
up_read(&dmar_global_lock);
|
||||
iommu_device_register(&iommu->iommu, &intel_iommu_ops, NULL);
|
||||
down_read(&dmar_global_lock);
|
||||
|
||||
iommu_pmu_register(iommu);
|
||||
}
|
||||
@@ -4547,9 +4554,6 @@ static int context_setup_pass_through_cb(struct pci_dev *pdev, u16 alias, void *
|
||||
{
|
||||
struct device *dev = data;
|
||||
|
||||
if (dev != &pdev->dev)
|
||||
return 0;
|
||||
|
||||
return context_setup_pass_through(dev, PCI_BUS_NUM(alias), alias & 0xff);
|
||||
}
|
||||
|
||||
|
||||
@@ -3790,10 +3790,6 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
|
||||
break;
|
||||
|
||||
case STATUSTYPE_TABLE: {
|
||||
__u64 watermark_percentage = (__u64)(ic->journal_entries - ic->free_sectors_threshold) * 100;
|
||||
|
||||
watermark_percentage += ic->journal_entries / 2;
|
||||
do_div(watermark_percentage, ic->journal_entries);
|
||||
arg_count = 3;
|
||||
arg_count += !!ic->meta_dev;
|
||||
arg_count += ic->sectors_per_block != 1;
|
||||
@@ -3826,6 +3822,10 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type,
|
||||
DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
|
||||
DMEMIT(" buffer_sectors:%u", 1U << ic->log2_buffer_sectors);
|
||||
if (ic->mode == 'J') {
|
||||
__u64 watermark_percentage = (__u64)(ic->journal_entries - ic->free_sectors_threshold) * 100;
|
||||
|
||||
watermark_percentage += ic->journal_entries / 2;
|
||||
do_div(watermark_percentage, ic->journal_entries);
|
||||
DMEMIT(" journal_watermark:%u", (unsigned int)watermark_percentage);
|
||||
DMEMIT(" commit_time:%u", ic->autocommit_msec);
|
||||
}
|
||||
|
||||
@@ -2178,6 +2178,7 @@ static int initialize_index(struct vdo *vdo, struct hash_zones *zones)
|
||||
|
||||
vdo_set_dedupe_index_timeout_interval(vdo_dedupe_index_timeout_interval);
|
||||
vdo_set_dedupe_index_min_timer_interval(vdo_dedupe_index_min_timer_interval);
|
||||
spin_lock_init(&zones->lock);
|
||||
|
||||
/*
|
||||
* Since we will save up the timeouts that would have been reported but were ratelimited,
|
||||
|
||||
@@ -43,4 +43,10 @@ config NET_DSA_REALTEK_RTL8366RB
|
||||
help
|
||||
Select to enable support for Realtek RTL8366RB.
|
||||
|
||||
config NET_DSA_REALTEK_RTL8366RB_LEDS
|
||||
bool "Support RTL8366RB LED control"
|
||||
depends on (LEDS_CLASS=y || LEDS_CLASS=NET_DSA_REALTEK_RTL8366RB)
|
||||
depends on NET_DSA_REALTEK_RTL8366RB
|
||||
default NET_DSA_REALTEK_RTL8366RB
|
||||
|
||||
endif
|
||||
|
||||
@@ -12,4 +12,7 @@ endif
|
||||
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
|
||||
rtl8366-objs := rtl8366-core.o rtl8366rb.o
|
||||
ifdef CONFIG_NET_DSA_REALTEK_RTL8366RB_LEDS
|
||||
rtl8366-objs += rtl8366rb-leds.o
|
||||
endif
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_RTL8365MB) += rtl8365mb.o
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <net/dsa.h>
|
||||
#include "rtl83xx.h"
|
||||
#include "rtl8366rb.h"
|
||||
|
||||
static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port)
|
||||
{
|
||||
switch (led_group) {
|
||||
case 0:
|
||||
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
case 1:
|
||||
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
case 2:
|
||||
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
case 3:
|
||||
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int rb8366rb_get_port_led(struct rtl8366rb_led *led)
|
||||
{
|
||||
struct realtek_priv *priv = led->priv;
|
||||
u8 led_group = led->led_group;
|
||||
u8 port_num = led->port_num;
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
ret = regmap_read(priv->map, RTL8366RB_LED_X_X_CTRL_REG(led_group),
|
||||
&val);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "error reading LED on port %d group %d\n",
|
||||
led_group, port_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return !!(val & rtl8366rb_led_group_port_mask(led_group, port_num));
|
||||
}
|
||||
|
||||
static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable)
|
||||
{
|
||||
struct realtek_priv *priv = led->priv;
|
||||
u8 led_group = led->led_group;
|
||||
u8 port_num = led->port_num;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(priv->map,
|
||||
RTL8366RB_LED_X_X_CTRL_REG(led_group),
|
||||
rtl8366rb_led_group_port_mask(led_group,
|
||||
port_num),
|
||||
enable ? 0xffff : 0);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "error updating LED on port %d group %d\n",
|
||||
led_group, port_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Change the LED group to manual controlled LEDs if required */
|
||||
ret = rb8366rb_set_ledgroup_mode(priv, led_group,
|
||||
RTL8366RB_LEDGROUP_FORCE);
|
||||
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "error updating LED GROUP group %d\n",
|
||||
led_group);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct rtl8366rb_led *led = container_of(ldev, struct rtl8366rb_led,
|
||||
cdev);
|
||||
|
||||
return rb8366rb_set_port_led(led, brightness == LED_ON);
|
||||
}
|
||||
|
||||
static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp,
|
||||
struct fwnode_handle *led_fwnode)
|
||||
{
|
||||
struct rtl8366rb *rb = priv->chip_data;
|
||||
struct led_init_data init_data = { };
|
||||
enum led_default_state state;
|
||||
struct rtl8366rb_led *led;
|
||||
u32 led_group;
|
||||
int ret;
|
||||
|
||||
ret = fwnode_property_read_u32(led_fwnode, "reg", &led_group);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (led_group >= RTL8366RB_NUM_LEDGROUPS) {
|
||||
dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
|
||||
led_group, dp->index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
led = &rb->leds[dp->index][led_group];
|
||||
led->port_num = dp->index;
|
||||
led->led_group = led_group;
|
||||
led->priv = priv;
|
||||
|
||||
state = led_init_default_state_get(led_fwnode);
|
||||
switch (state) {
|
||||
case LEDS_DEFSTATE_ON:
|
||||
led->cdev.brightness = 1;
|
||||
rb8366rb_set_port_led(led, 1);
|
||||
break;
|
||||
case LEDS_DEFSTATE_KEEP:
|
||||
led->cdev.brightness =
|
||||
rb8366rb_get_port_led(led);
|
||||
break;
|
||||
case LEDS_DEFSTATE_OFF:
|
||||
default:
|
||||
led->cdev.brightness = 0;
|
||||
rb8366rb_set_port_led(led, 0);
|
||||
}
|
||||
|
||||
led->cdev.max_brightness = 1;
|
||||
led->cdev.brightness_set_blocking =
|
||||
rtl8366rb_cled_brightness_set_blocking;
|
||||
init_data.fwnode = led_fwnode;
|
||||
init_data.devname_mandatory = true;
|
||||
|
||||
init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d",
|
||||
dp->ds->index, dp->index, led_group);
|
||||
if (!init_data.devicename)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data);
|
||||
if (ret) {
|
||||
dev_warn(priv->dev, "Failed to init LED %d for port %d",
|
||||
led_group, dp->index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtl8366rb_setup_leds(struct realtek_priv *priv)
|
||||
{
|
||||
struct dsa_switch *ds = &priv->ds;
|
||||
struct device_node *leds_np;
|
||||
struct dsa_port *dp;
|
||||
int ret = 0;
|
||||
|
||||
dsa_switch_for_each_port(dp, ds) {
|
||||
if (!dp->dn)
|
||||
continue;
|
||||
|
||||
leds_np = of_get_child_by_name(dp->dn, "leds");
|
||||
if (!leds_np) {
|
||||
dev_dbg(priv->dev, "No leds defined for port %d",
|
||||
dp->index);
|
||||
continue;
|
||||
}
|
||||
|
||||
for_each_child_of_node_scoped(leds_np, led_np) {
|
||||
ret = rtl8366rb_setup_led(priv, dp,
|
||||
of_fwnode_handle(led_np));
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
of_node_put(leds_np);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -26,11 +26,7 @@
|
||||
#include "realtek-smi.h"
|
||||
#include "realtek-mdio.h"
|
||||
#include "rtl83xx.h"
|
||||
|
||||
#define RTL8366RB_PORT_NUM_CPU 5
|
||||
#define RTL8366RB_NUM_PORTS 6
|
||||
#define RTL8366RB_PHY_NO_MAX 4
|
||||
#define RTL8366RB_PHY_ADDR_MAX 31
|
||||
#include "rtl8366rb.h"
|
||||
|
||||
/* Switch Global Configuration register */
|
||||
#define RTL8366RB_SGCR 0x0000
|
||||
@@ -175,39 +171,6 @@
|
||||
*/
|
||||
#define RTL8366RB_VLAN_INGRESS_CTRL2_REG 0x037f
|
||||
|
||||
/* LED control registers */
|
||||
/* The LED blink rate is global; it is used by all triggers in all groups. */
|
||||
#define RTL8366RB_LED_BLINKRATE_REG 0x0430
|
||||
#define RTL8366RB_LED_BLINKRATE_MASK 0x0007
|
||||
#define RTL8366RB_LED_BLINKRATE_28MS 0x0000
|
||||
#define RTL8366RB_LED_BLINKRATE_56MS 0x0001
|
||||
#define RTL8366RB_LED_BLINKRATE_84MS 0x0002
|
||||
#define RTL8366RB_LED_BLINKRATE_111MS 0x0003
|
||||
#define RTL8366RB_LED_BLINKRATE_222MS 0x0004
|
||||
#define RTL8366RB_LED_BLINKRATE_446MS 0x0005
|
||||
|
||||
/* LED trigger event for each group */
|
||||
#define RTL8366RB_LED_CTRL_REG 0x0431
|
||||
#define RTL8366RB_LED_CTRL_OFFSET(led_group) \
|
||||
(4 * (led_group))
|
||||
#define RTL8366RB_LED_CTRL_MASK(led_group) \
|
||||
(0xf << RTL8366RB_LED_CTRL_OFFSET(led_group))
|
||||
|
||||
/* The RTL8366RB_LED_X_X registers are used to manually set the LED state only
|
||||
* when the corresponding LED group in RTL8366RB_LED_CTRL_REG is
|
||||
* RTL8366RB_LEDGROUP_FORCE. Otherwise, it is ignored.
|
||||
*/
|
||||
#define RTL8366RB_LED_0_1_CTRL_REG 0x0432
|
||||
#define RTL8366RB_LED_2_3_CTRL_REG 0x0433
|
||||
#define RTL8366RB_LED_X_X_CTRL_REG(led_group) \
|
||||
((led_group) <= 1 ? \
|
||||
RTL8366RB_LED_0_1_CTRL_REG : \
|
||||
RTL8366RB_LED_2_3_CTRL_REG)
|
||||
#define RTL8366RB_LED_0_X_CTRL_MASK GENMASK(5, 0)
|
||||
#define RTL8366RB_LED_X_1_CTRL_MASK GENMASK(11, 6)
|
||||
#define RTL8366RB_LED_2_X_CTRL_MASK GENMASK(5, 0)
|
||||
#define RTL8366RB_LED_X_3_CTRL_MASK GENMASK(11, 6)
|
||||
|
||||
#define RTL8366RB_MIB_COUNT 33
|
||||
#define RTL8366RB_GLOBAL_MIB_COUNT 1
|
||||
#define RTL8366RB_MIB_COUNTER_PORT_OFFSET 0x0050
|
||||
@@ -243,7 +206,6 @@
|
||||
#define RTL8366RB_PORT_STATUS_AN_MASK 0x0080
|
||||
|
||||
#define RTL8366RB_NUM_VLANS 16
|
||||
#define RTL8366RB_NUM_LEDGROUPS 4
|
||||
#define RTL8366RB_NUM_VIDS 4096
|
||||
#define RTL8366RB_PRIORITYMAX 7
|
||||
#define RTL8366RB_NUM_FIDS 8
|
||||
@@ -350,46 +312,6 @@
|
||||
#define RTL8366RB_GREEN_FEATURE_TX BIT(0)
|
||||
#define RTL8366RB_GREEN_FEATURE_RX BIT(2)
|
||||
|
||||
enum rtl8366_ledgroup_mode {
|
||||
RTL8366RB_LEDGROUP_OFF = 0x0,
|
||||
RTL8366RB_LEDGROUP_DUP_COL = 0x1,
|
||||
RTL8366RB_LEDGROUP_LINK_ACT = 0x2,
|
||||
RTL8366RB_LEDGROUP_SPD1000 = 0x3,
|
||||
RTL8366RB_LEDGROUP_SPD100 = 0x4,
|
||||
RTL8366RB_LEDGROUP_SPD10 = 0x5,
|
||||
RTL8366RB_LEDGROUP_SPD1000_ACT = 0x6,
|
||||
RTL8366RB_LEDGROUP_SPD100_ACT = 0x7,
|
||||
RTL8366RB_LEDGROUP_SPD10_ACT = 0x8,
|
||||
RTL8366RB_LEDGROUP_SPD100_10_ACT = 0x9,
|
||||
RTL8366RB_LEDGROUP_FIBER = 0xa,
|
||||
RTL8366RB_LEDGROUP_AN_FAULT = 0xb,
|
||||
RTL8366RB_LEDGROUP_LINK_RX = 0xc,
|
||||
RTL8366RB_LEDGROUP_LINK_TX = 0xd,
|
||||
RTL8366RB_LEDGROUP_MASTER = 0xe,
|
||||
RTL8366RB_LEDGROUP_FORCE = 0xf,
|
||||
|
||||
__RTL8366RB_LEDGROUP_MODE_MAX
|
||||
};
|
||||
|
||||
struct rtl8366rb_led {
|
||||
u8 port_num;
|
||||
u8 led_group;
|
||||
struct realtek_priv *priv;
|
||||
struct led_classdev cdev;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rtl8366rb - RTL8366RB-specific data
|
||||
* @max_mtu: per-port max MTU setting
|
||||
* @pvid_enabled: if PVID is set for respective port
|
||||
* @leds: per-port and per-ledgroup led info
|
||||
*/
|
||||
struct rtl8366rb {
|
||||
unsigned int max_mtu[RTL8366RB_NUM_PORTS];
|
||||
bool pvid_enabled[RTL8366RB_NUM_PORTS];
|
||||
struct rtl8366rb_led leds[RTL8366RB_NUM_PORTS][RTL8366RB_NUM_LEDGROUPS];
|
||||
};
|
||||
|
||||
static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = {
|
||||
{ 0, 0, 4, "IfInOctets" },
|
||||
{ 0, 4, 4, "EtherStatsOctets" },
|
||||
@@ -830,9 +752,10 @@ static int rtl8366rb_jam_table(const struct rtl8366rb_jam_tbl_entry *jam_table,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rb8366rb_set_ledgroup_mode(struct realtek_priv *priv,
|
||||
u8 led_group,
|
||||
enum rtl8366_ledgroup_mode mode)
|
||||
/* This code is used also with LEDs disabled */
|
||||
int rb8366rb_set_ledgroup_mode(struct realtek_priv *priv,
|
||||
u8 led_group,
|
||||
enum rtl8366_ledgroup_mode mode)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
@@ -849,144 +772,7 @@ static int rb8366rb_set_ledgroup_mode(struct realtek_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port)
|
||||
{
|
||||
switch (led_group) {
|
||||
case 0:
|
||||
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
case 1:
|
||||
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
case 2:
|
||||
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
case 3:
|
||||
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int rb8366rb_get_port_led(struct rtl8366rb_led *led)
|
||||
{
|
||||
struct realtek_priv *priv = led->priv;
|
||||
u8 led_group = led->led_group;
|
||||
u8 port_num = led->port_num;
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
ret = regmap_read(priv->map, RTL8366RB_LED_X_X_CTRL_REG(led_group),
|
||||
&val);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "error reading LED on port %d group %d\n",
|
||||
led_group, port_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return !!(val & rtl8366rb_led_group_port_mask(led_group, port_num));
|
||||
}
|
||||
|
||||
static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable)
|
||||
{
|
||||
struct realtek_priv *priv = led->priv;
|
||||
u8 led_group = led->led_group;
|
||||
u8 port_num = led->port_num;
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(priv->map,
|
||||
RTL8366RB_LED_X_X_CTRL_REG(led_group),
|
||||
rtl8366rb_led_group_port_mask(led_group,
|
||||
port_num),
|
||||
enable ? 0xffff : 0);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "error updating LED on port %d group %d\n",
|
||||
led_group, port_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Change the LED group to manual controlled LEDs if required */
|
||||
ret = rb8366rb_set_ledgroup_mode(priv, led_group,
|
||||
RTL8366RB_LEDGROUP_FORCE);
|
||||
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "error updating LED GROUP group %d\n",
|
||||
led_group);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
struct rtl8366rb_led *led = container_of(ldev, struct rtl8366rb_led,
|
||||
cdev);
|
||||
|
||||
return rb8366rb_set_port_led(led, brightness == LED_ON);
|
||||
}
|
||||
|
||||
static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp,
|
||||
struct fwnode_handle *led_fwnode)
|
||||
{
|
||||
struct rtl8366rb *rb = priv->chip_data;
|
||||
struct led_init_data init_data = { };
|
||||
enum led_default_state state;
|
||||
struct rtl8366rb_led *led;
|
||||
u32 led_group;
|
||||
int ret;
|
||||
|
||||
ret = fwnode_property_read_u32(led_fwnode, "reg", &led_group);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (led_group >= RTL8366RB_NUM_LEDGROUPS) {
|
||||
dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
|
||||
led_group, dp->index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
led = &rb->leds[dp->index][led_group];
|
||||
led->port_num = dp->index;
|
||||
led->led_group = led_group;
|
||||
led->priv = priv;
|
||||
|
||||
state = led_init_default_state_get(led_fwnode);
|
||||
switch (state) {
|
||||
case LEDS_DEFSTATE_ON:
|
||||
led->cdev.brightness = 1;
|
||||
rb8366rb_set_port_led(led, 1);
|
||||
break;
|
||||
case LEDS_DEFSTATE_KEEP:
|
||||
led->cdev.brightness =
|
||||
rb8366rb_get_port_led(led);
|
||||
break;
|
||||
case LEDS_DEFSTATE_OFF:
|
||||
default:
|
||||
led->cdev.brightness = 0;
|
||||
rb8366rb_set_port_led(led, 0);
|
||||
}
|
||||
|
||||
led->cdev.max_brightness = 1;
|
||||
led->cdev.brightness_set_blocking =
|
||||
rtl8366rb_cled_brightness_set_blocking;
|
||||
init_data.fwnode = led_fwnode;
|
||||
init_data.devname_mandatory = true;
|
||||
|
||||
init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d",
|
||||
dp->ds->index, dp->index, led_group);
|
||||
if (!init_data.devicename)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data);
|
||||
if (ret) {
|
||||
dev_warn(priv->dev, "Failed to init LED %d for port %d",
|
||||
led_group, dp->index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This code is used also with LEDs disabled */
|
||||
static int rtl8366rb_setup_all_leds_off(struct realtek_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -1007,38 +793,6 @@ static int rtl8366rb_setup_all_leds_off(struct realtek_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl8366rb_setup_leds(struct realtek_priv *priv)
|
||||
{
|
||||
struct dsa_switch *ds = &priv->ds;
|
||||
struct device_node *leds_np;
|
||||
struct dsa_port *dp;
|
||||
int ret = 0;
|
||||
|
||||
dsa_switch_for_each_port(dp, ds) {
|
||||
if (!dp->dn)
|
||||
continue;
|
||||
|
||||
leds_np = of_get_child_by_name(dp->dn, "leds");
|
||||
if (!leds_np) {
|
||||
dev_dbg(priv->dev, "No leds defined for port %d",
|
||||
dp->index);
|
||||
continue;
|
||||
}
|
||||
|
||||
for_each_child_of_node_scoped(leds_np, led_np) {
|
||||
ret = rtl8366rb_setup_led(priv, dp,
|
||||
of_fwnode_handle(led_np));
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
of_node_put(leds_np);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8366rb_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct realtek_priv *priv = ds->priv;
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
#ifndef _RTL8366RB_H
|
||||
#define _RTL8366RB_H
|
||||
|
||||
#include "realtek.h"
|
||||
|
||||
#define RTL8366RB_PORT_NUM_CPU 5
|
||||
#define RTL8366RB_NUM_PORTS 6
|
||||
#define RTL8366RB_PHY_NO_MAX 4
|
||||
#define RTL8366RB_NUM_LEDGROUPS 4
|
||||
#define RTL8366RB_PHY_ADDR_MAX 31
|
||||
|
||||
/* LED control registers */
|
||||
/* The LED blink rate is global; it is used by all triggers in all groups. */
|
||||
#define RTL8366RB_LED_BLINKRATE_REG 0x0430
|
||||
#define RTL8366RB_LED_BLINKRATE_MASK 0x0007
|
||||
#define RTL8366RB_LED_BLINKRATE_28MS 0x0000
|
||||
#define RTL8366RB_LED_BLINKRATE_56MS 0x0001
|
||||
#define RTL8366RB_LED_BLINKRATE_84MS 0x0002
|
||||
#define RTL8366RB_LED_BLINKRATE_111MS 0x0003
|
||||
#define RTL8366RB_LED_BLINKRATE_222MS 0x0004
|
||||
#define RTL8366RB_LED_BLINKRATE_446MS 0x0005
|
||||
|
||||
/* LED trigger event for each group */
|
||||
#define RTL8366RB_LED_CTRL_REG 0x0431
|
||||
#define RTL8366RB_LED_CTRL_OFFSET(led_group) \
|
||||
(4 * (led_group))
|
||||
#define RTL8366RB_LED_CTRL_MASK(led_group) \
|
||||
(0xf << RTL8366RB_LED_CTRL_OFFSET(led_group))
|
||||
|
||||
/* The RTL8366RB_LED_X_X registers are used to manually set the LED state only
|
||||
* when the corresponding LED group in RTL8366RB_LED_CTRL_REG is
|
||||
* RTL8366RB_LEDGROUP_FORCE. Otherwise, it is ignored.
|
||||
*/
|
||||
#define RTL8366RB_LED_0_1_CTRL_REG 0x0432
|
||||
#define RTL8366RB_LED_2_3_CTRL_REG 0x0433
|
||||
#define RTL8366RB_LED_X_X_CTRL_REG(led_group) \
|
||||
((led_group) <= 1 ? \
|
||||
RTL8366RB_LED_0_1_CTRL_REG : \
|
||||
RTL8366RB_LED_2_3_CTRL_REG)
|
||||
#define RTL8366RB_LED_0_X_CTRL_MASK GENMASK(5, 0)
|
||||
#define RTL8366RB_LED_X_1_CTRL_MASK GENMASK(11, 6)
|
||||
#define RTL8366RB_LED_2_X_CTRL_MASK GENMASK(5, 0)
|
||||
#define RTL8366RB_LED_X_3_CTRL_MASK GENMASK(11, 6)
|
||||
|
||||
enum rtl8366_ledgroup_mode {
|
||||
RTL8366RB_LEDGROUP_OFF = 0x0,
|
||||
RTL8366RB_LEDGROUP_DUP_COL = 0x1,
|
||||
RTL8366RB_LEDGROUP_LINK_ACT = 0x2,
|
||||
RTL8366RB_LEDGROUP_SPD1000 = 0x3,
|
||||
RTL8366RB_LEDGROUP_SPD100 = 0x4,
|
||||
RTL8366RB_LEDGROUP_SPD10 = 0x5,
|
||||
RTL8366RB_LEDGROUP_SPD1000_ACT = 0x6,
|
||||
RTL8366RB_LEDGROUP_SPD100_ACT = 0x7,
|
||||
RTL8366RB_LEDGROUP_SPD10_ACT = 0x8,
|
||||
RTL8366RB_LEDGROUP_SPD100_10_ACT = 0x9,
|
||||
RTL8366RB_LEDGROUP_FIBER = 0xa,
|
||||
RTL8366RB_LEDGROUP_AN_FAULT = 0xb,
|
||||
RTL8366RB_LEDGROUP_LINK_RX = 0xc,
|
||||
RTL8366RB_LEDGROUP_LINK_TX = 0xd,
|
||||
RTL8366RB_LEDGROUP_MASTER = 0xe,
|
||||
RTL8366RB_LEDGROUP_FORCE = 0xf,
|
||||
|
||||
__RTL8366RB_LEDGROUP_MODE_MAX
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB_LEDS)
|
||||
|
||||
struct rtl8366rb_led {
|
||||
u8 port_num;
|
||||
u8 led_group;
|
||||
struct realtek_priv *priv;
|
||||
struct led_classdev cdev;
|
||||
};
|
||||
|
||||
int rtl8366rb_setup_leds(struct realtek_priv *priv);
|
||||
|
||||
#else
|
||||
|
||||
static inline int rtl8366rb_setup_leds(struct realtek_priv *priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_LEDS_CLASS) */
|
||||
|
||||
/**
|
||||
* struct rtl8366rb - RTL8366RB-specific data
|
||||
* @max_mtu: per-port max MTU setting
|
||||
* @pvid_enabled: if PVID is set for respective port
|
||||
* @leds: per-port and per-ledgroup led info
|
||||
*/
|
||||
struct rtl8366rb {
|
||||
unsigned int max_mtu[RTL8366RB_NUM_PORTS];
|
||||
bool pvid_enabled[RTL8366RB_NUM_PORTS];
|
||||
#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB_LEDS)
|
||||
struct rtl8366rb_led leds[RTL8366RB_NUM_PORTS][RTL8366RB_NUM_LEDGROUPS];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This code is used also with LEDs disabled */
|
||||
int rb8366rb_set_ledgroup_mode(struct realtek_priv *priv,
|
||||
u8 led_group,
|
||||
enum rtl8366_ledgroup_mode mode);
|
||||
|
||||
#endif /* _RTL8366RB_H */
|
||||
@@ -1279,6 +1279,8 @@ struct macb {
|
||||
struct clk *rx_clk;
|
||||
struct clk *tsu_clk;
|
||||
struct net_device *dev;
|
||||
/* Protects hw_stats and ethtool_stats */
|
||||
spinlock_t stats_lock;
|
||||
union {
|
||||
struct macb_stats macb;
|
||||
struct gem_stats gem;
|
||||
|
||||
@@ -1992,10 +1992,12 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
|
||||
|
||||
if (status & MACB_BIT(ISR_ROVR)) {
|
||||
/* We missed at least one packet */
|
||||
spin_lock(&bp->stats_lock);
|
||||
if (macb_is_gem(bp))
|
||||
bp->hw_stats.gem.rx_overruns++;
|
||||
else
|
||||
bp->hw_stats.macb.rx_overruns++;
|
||||
spin_unlock(&bp->stats_lock);
|
||||
|
||||
if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
|
||||
queue_writel(queue, ISR, MACB_BIT(ISR_ROVR));
|
||||
@@ -3116,6 +3118,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
|
||||
if (!netif_running(bp->dev))
|
||||
return nstat;
|
||||
|
||||
spin_lock_irq(&bp->stats_lock);
|
||||
gem_update_stats(bp);
|
||||
|
||||
nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors +
|
||||
@@ -3145,6 +3148,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
|
||||
nstat->tx_aborted_errors = hwstat->tx_excessive_collisions;
|
||||
nstat->tx_carrier_errors = hwstat->tx_carrier_sense_errors;
|
||||
nstat->tx_fifo_errors = hwstat->tx_underrun;
|
||||
spin_unlock_irq(&bp->stats_lock);
|
||||
|
||||
return nstat;
|
||||
}
|
||||
@@ -3152,12 +3156,13 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
|
||||
static void gem_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct macb *bp;
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
|
||||
bp = netdev_priv(dev);
|
||||
spin_lock_irq(&bp->stats_lock);
|
||||
gem_update_stats(bp);
|
||||
memcpy(data, &bp->ethtool_stats, sizeof(u64)
|
||||
* (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES));
|
||||
spin_unlock_irq(&bp->stats_lock);
|
||||
}
|
||||
|
||||
static int gem_get_sset_count(struct net_device *dev, int sset)
|
||||
@@ -3207,6 +3212,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
|
||||
return gem_get_stats(bp);
|
||||
|
||||
/* read stats from hardware */
|
||||
spin_lock_irq(&bp->stats_lock);
|
||||
macb_update_stats(bp);
|
||||
|
||||
/* Convert HW stats into netdevice stats */
|
||||
@@ -3240,6 +3246,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
|
||||
nstat->tx_carrier_errors = hwstat->tx_carrier_errors;
|
||||
nstat->tx_fifo_errors = hwstat->tx_underruns;
|
||||
/* Don't know about heartbeat or window errors... */
|
||||
spin_unlock_irq(&bp->stats_lock);
|
||||
|
||||
return nstat;
|
||||
}
|
||||
@@ -5110,6 +5117,7 @@ static int macb_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
spin_lock_init(&bp->lock);
|
||||
spin_lock_init(&bp->stats_lock);
|
||||
|
||||
/* setup capabilities */
|
||||
macb_configure_caps(bp, macb_config);
|
||||
|
||||
@@ -145,6 +145,24 @@ static int enetc_ptp_parse(struct sk_buff *skb, u8 *udp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* enetc_unwind_tx_frame() - Unwind the DMA mappings of a multi-buffer Tx frame
|
||||
* @tx_ring: Pointer to the Tx ring on which the buffer descriptors are located
|
||||
* @count: Number of Tx buffer descriptors which need to be unmapped
|
||||
* @i: Index of the last successfully mapped Tx buffer descriptor
|
||||
*/
|
||||
static void enetc_unwind_tx_frame(struct enetc_bdr *tx_ring, int count, int i)
|
||||
{
|
||||
while (count--) {
|
||||
struct enetc_tx_swbd *tx_swbd = &tx_ring->tx_swbd[i];
|
||||
|
||||
enetc_free_tx_frame(tx_ring, tx_swbd);
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
{
|
||||
bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false;
|
||||
@@ -235,9 +253,11 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (do_onestep_tstamp) {
|
||||
u32 lo, hi, val;
|
||||
u64 sec, nsec;
|
||||
__be32 new_sec_l, new_nsec;
|
||||
u32 lo, hi, nsec, val;
|
||||
__be16 new_sec_h;
|
||||
u8 *data;
|
||||
u64 sec;
|
||||
|
||||
lo = enetc_rd_hot(hw, ENETC_SICTR0);
|
||||
hi = enetc_rd_hot(hw, ENETC_SICTR1);
|
||||
@@ -251,13 +271,38 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
/* Update originTimestamp field of Sync packet
|
||||
* - 48 bits seconds field
|
||||
* - 32 bits nanseconds field
|
||||
*
|
||||
* In addition, the UDP checksum needs to be updated
|
||||
* by software after updating originTimestamp field,
|
||||
* otherwise the hardware will calculate the wrong
|
||||
* checksum when updating the correction field and
|
||||
* update it to the packet.
|
||||
*/
|
||||
data = skb_mac_header(skb);
|
||||
*(__be16 *)(data + offset2) =
|
||||
htons((sec >> 32) & 0xffff);
|
||||
*(__be32 *)(data + offset2 + 2) =
|
||||
htonl(sec & 0xffffffff);
|
||||
*(__be32 *)(data + offset2 + 6) = htonl(nsec);
|
||||
new_sec_h = htons((sec >> 32) & 0xffff);
|
||||
new_sec_l = htonl(sec & 0xffffffff);
|
||||
new_nsec = htonl(nsec);
|
||||
if (udp) {
|
||||
struct udphdr *uh = udp_hdr(skb);
|
||||
__be32 old_sec_l, old_nsec;
|
||||
__be16 old_sec_h;
|
||||
|
||||
old_sec_h = *(__be16 *)(data + offset2);
|
||||
inet_proto_csum_replace2(&uh->check, skb, old_sec_h,
|
||||
new_sec_h, false);
|
||||
|
||||
old_sec_l = *(__be32 *)(data + offset2 + 2);
|
||||
inet_proto_csum_replace4(&uh->check, skb, old_sec_l,
|
||||
new_sec_l, false);
|
||||
|
||||
old_nsec = *(__be32 *)(data + offset2 + 6);
|
||||
inet_proto_csum_replace4(&uh->check, skb, old_nsec,
|
||||
new_nsec, false);
|
||||
}
|
||||
|
||||
*(__be16 *)(data + offset2) = new_sec_h;
|
||||
*(__be32 *)(data + offset2 + 2) = new_sec_l;
|
||||
*(__be32 *)(data + offset2 + 6) = new_nsec;
|
||||
|
||||
/* Configure single-step register */
|
||||
val = ENETC_PM0_SINGLE_STEP_EN;
|
||||
@@ -328,25 +373,20 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
dma_err:
|
||||
dev_err(tx_ring->dev, "DMA map error");
|
||||
|
||||
do {
|
||||
tx_swbd = &tx_ring->tx_swbd[i];
|
||||
enetc_free_tx_frame(tx_ring, tx_swbd);
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
} while (count--);
|
||||
enetc_unwind_tx_frame(tx_ring, count, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
struct enetc_tx_swbd *tx_swbd,
|
||||
union enetc_tx_bd *txbd, int *i, int hdr_len,
|
||||
int data_len)
|
||||
static int enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
struct enetc_tx_swbd *tx_swbd,
|
||||
union enetc_tx_bd *txbd, int *i, int hdr_len,
|
||||
int data_len)
|
||||
{
|
||||
union enetc_tx_bd txbd_tmp;
|
||||
u8 flags = 0, e_flags = 0;
|
||||
dma_addr_t addr;
|
||||
int count = 1;
|
||||
|
||||
enetc_clear_tx_bd(&txbd_tmp);
|
||||
addr = tx_ring->tso_headers_dma + *i * TSO_HEADER_SIZE;
|
||||
@@ -389,7 +429,10 @@ static void enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
/* Write the BD */
|
||||
txbd_tmp.ext.e_flags = e_flags;
|
||||
*txbd = txbd_tmp;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int enetc_map_tx_tso_data(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
@@ -521,9 +564,9 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
|
||||
|
||||
/* compute the csum over the L4 header */
|
||||
csum = enetc_tso_hdr_csum(&tso, skb, hdr, hdr_len, &pos);
|
||||
enetc_map_tx_tso_hdr(tx_ring, skb, tx_swbd, txbd, &i, hdr_len, data_len);
|
||||
count += enetc_map_tx_tso_hdr(tx_ring, skb, tx_swbd, txbd,
|
||||
&i, hdr_len, data_len);
|
||||
bd_data_num = 0;
|
||||
count++;
|
||||
|
||||
while (data_len > 0) {
|
||||
int size;
|
||||
@@ -547,8 +590,13 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
|
||||
err = enetc_map_tx_tso_data(tx_ring, skb, tx_swbd, txbd,
|
||||
tso.data, size,
|
||||
size == data_len);
|
||||
if (err)
|
||||
if (err) {
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
|
||||
goto err_map_data;
|
||||
}
|
||||
|
||||
data_len -= size;
|
||||
count++;
|
||||
@@ -577,13 +625,7 @@ err_map_data:
|
||||
dev_err(tx_ring->dev, "DMA map error");
|
||||
|
||||
err_chained_bd:
|
||||
do {
|
||||
tx_swbd = &tx_ring->tx_swbd[i];
|
||||
enetc_free_tx_frame(tx_ring, tx_swbd);
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
} while (count--);
|
||||
enetc_unwind_tx_frame(tx_ring, count, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1623,7 +1665,7 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
|
||||
enetc_xdp_drop(rx_ring, orig_i, i);
|
||||
tx_ring->stats.xdp_tx_drops++;
|
||||
} else {
|
||||
tx_ring->stats.xdp_tx += xdp_tx_bd_cnt;
|
||||
tx_ring->stats.xdp_tx++;
|
||||
rx_ring->xdp.xdp_tx_in_flight += xdp_tx_bd_cnt;
|
||||
xdp_tx_frm_cnt++;
|
||||
/* The XDP_TX enqueue was successful, so we
|
||||
@@ -2929,6 +2971,9 @@ static int enetc_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr)
|
||||
new_offloads |= ENETC_F_TX_TSTAMP;
|
||||
break;
|
||||
case HWTSTAMP_TX_ONESTEP_SYNC:
|
||||
if (!enetc_si_is_pf(priv->si))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
new_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
|
||||
new_offloads |= ENETC_F_TX_ONESTEP_SYNC_TSTAMP;
|
||||
break;
|
||||
|
||||
@@ -843,6 +843,7 @@ static int enetc_set_coalesce(struct net_device *ndev,
|
||||
static int enetc_get_ts_info(struct net_device *ndev,
|
||||
struct kernel_ethtool_ts_info *info)
|
||||
{
|
||||
struct enetc_ndev_priv *priv = netdev_priv(ndev);
|
||||
int *phc_idx;
|
||||
|
||||
phc_idx = symbol_get(enetc_phc_index);
|
||||
@@ -863,8 +864,10 @@ static int enetc_get_ts_info(struct net_device *ndev,
|
||||
SOF_TIMESTAMPING_TX_SOFTWARE;
|
||||
|
||||
info->tx_types = (1 << HWTSTAMP_TX_OFF) |
|
||||
(1 << HWTSTAMP_TX_ON) |
|
||||
(1 << HWTSTAMP_TX_ONESTEP_SYNC);
|
||||
(1 << HWTSTAMP_TX_ON);
|
||||
|
||||
if (enetc_si_is_pf(priv->si))
|
||||
info->tx_types |= (1 << HWTSTAMP_TX_ONESTEP_SYNC);
|
||||
|
||||
info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
|
||||
(1 << HWTSTAMP_FILTER_ALL);
|
||||
|
||||
@@ -207,6 +207,7 @@ enum ice_feature {
|
||||
ICE_F_GNSS,
|
||||
ICE_F_ROCE_LAG,
|
||||
ICE_F_SRIOV_LAG,
|
||||
ICE_F_MBX_LIMIT,
|
||||
ICE_F_MAX
|
||||
};
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
|
||||
if (ice_vsi_add_vlan_zero(uplink_vsi))
|
||||
goto err_vlan_zero;
|
||||
|
||||
if (ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, true,
|
||||
ICE_FLTR_RX))
|
||||
if (ice_set_dflt_vsi(uplink_vsi))
|
||||
goto err_def_rx;
|
||||
|
||||
if (ice_cfg_dflt_vsi(uplink_vsi->port_info, uplink_vsi->idx, true,
|
||||
|
||||
@@ -539,5 +539,8 @@
|
||||
#define E830_PRTMAC_CL01_QNT_THR_CL0_M GENMASK(15, 0)
|
||||
#define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4))
|
||||
#define VFINT_DYN_CTLN_CLEARPBA_M BIT(1)
|
||||
#define E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH 0x00234000
|
||||
#define E830_MBX_VF_DEC_TRIG(_VF) (0x00233800 + (_VF) * 4)
|
||||
#define E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(_VF) (0x00233000 + (_VF) * 4)
|
||||
|
||||
#endif /* _ICE_HW_AUTOGEN_H_ */
|
||||
|
||||
@@ -3880,6 +3880,9 @@ void ice_init_feature_support(struct ice_pf *pf)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pf->hw.mac_type == ICE_MAC_E830)
|
||||
ice_set_feature_support(pf, ICE_F_MBX_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1546,12 +1546,20 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type)
|
||||
ice_vf_lan_overflow_event(pf, &event);
|
||||
break;
|
||||
case ice_mbx_opc_send_msg_to_pf:
|
||||
data.num_msg_proc = i;
|
||||
data.num_pending_arq = pending;
|
||||
data.max_num_msgs_mbx = hw->mailboxq.num_rq_entries;
|
||||
data.async_watermark_val = ICE_MBX_OVERFLOW_WATERMARK;
|
||||
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT)) {
|
||||
ice_vc_process_vf_msg(pf, &event, NULL);
|
||||
ice_mbx_vf_dec_trig_e830(hw, &event);
|
||||
} else {
|
||||
u16 val = hw->mailboxq.num_rq_entries;
|
||||
|
||||
ice_vc_process_vf_msg(pf, &event, &data);
|
||||
data.max_num_msgs_mbx = val;
|
||||
val = ICE_MBX_OVERFLOW_WATERMARK;
|
||||
data.async_watermark_val = val;
|
||||
data.num_msg_proc = i;
|
||||
data.num_pending_arq = pending;
|
||||
|
||||
ice_vc_process_vf_msg(pf, &event, &data);
|
||||
}
|
||||
break;
|
||||
case ice_aqc_opc_fw_logs_event:
|
||||
ice_get_fwlog_data(pf, &event);
|
||||
@@ -4082,7 +4090,11 @@ static int ice_init_pf(struct ice_pf *pf)
|
||||
|
||||
mutex_init(&pf->vfs.table_lock);
|
||||
hash_init(pf->vfs.table);
|
||||
ice_mbx_init_snapshot(&pf->hw);
|
||||
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
|
||||
wr32(&pf->hw, E830_MBX_PF_IN_FLIGHT_VF_MSGS_THRESH,
|
||||
ICE_MBX_OVERFLOW_WATERMARK);
|
||||
else
|
||||
ice_mbx_init_snapshot(&pf->hw);
|
||||
|
||||
xa_init(&pf->dyn_ports);
|
||||
xa_init(&pf->sf_nums);
|
||||
|
||||
@@ -36,6 +36,7 @@ static void ice_free_vf_entries(struct ice_pf *pf)
|
||||
|
||||
hash_for_each_safe(vfs->table, bkt, tmp, vf, entry) {
|
||||
hash_del_rcu(&vf->entry);
|
||||
ice_deinitialize_vf_entry(vf);
|
||||
ice_put_vf(vf);
|
||||
}
|
||||
}
|
||||
@@ -193,9 +194,6 @@ void ice_free_vfs(struct ice_pf *pf)
|
||||
wr32(hw, GLGEN_VFLRSTAT(reg_idx), BIT(bit_idx));
|
||||
}
|
||||
|
||||
/* clear malicious info since the VF is getting released */
|
||||
list_del(&vf->mbx_info.list_entry);
|
||||
|
||||
mutex_unlock(&vf->cfg_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -716,6 +716,23 @@ ice_vf_clear_vsi_promisc(struct ice_vf *vf, struct ice_vsi *vsi, u8 promisc_m)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_reset_vf_mbx_cnt - reset VF mailbox message count
|
||||
* @vf: pointer to the VF structure
|
||||
*
|
||||
* This function clears the VF mailbox message count, and should be called on
|
||||
* VF reset.
|
||||
*/
|
||||
static void ice_reset_vf_mbx_cnt(struct ice_vf *vf)
|
||||
{
|
||||
struct ice_pf *pf = vf->pf;
|
||||
|
||||
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
|
||||
ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id);
|
||||
else
|
||||
ice_mbx_clear_malvf(&vf->mbx_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_reset_all_vfs - reset all allocated VFs in one go
|
||||
* @pf: pointer to the PF structure
|
||||
@@ -742,7 +759,7 @@ void ice_reset_all_vfs(struct ice_pf *pf)
|
||||
|
||||
/* clear all malicious info if the VFs are getting reset */
|
||||
ice_for_each_vf(pf, bkt, vf)
|
||||
ice_mbx_clear_malvf(&vf->mbx_info);
|
||||
ice_reset_vf_mbx_cnt(vf);
|
||||
|
||||
/* If VFs have been disabled, there is no need to reset */
|
||||
if (test_and_set_bit(ICE_VF_DIS, pf->state)) {
|
||||
@@ -958,7 +975,7 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
|
||||
ice_eswitch_update_repr(&vf->repr_id, vsi);
|
||||
|
||||
/* if the VF has been reset allow it to come up again */
|
||||
ice_mbx_clear_malvf(&vf->mbx_info);
|
||||
ice_reset_vf_mbx_cnt(vf);
|
||||
|
||||
out_unlock:
|
||||
if (lag && lag->bonded && lag->primary &&
|
||||
@@ -1011,11 +1028,22 @@ void ice_initialize_vf_entry(struct ice_vf *vf)
|
||||
ice_vf_fdir_init(vf);
|
||||
|
||||
/* Initialize mailbox info for this VF */
|
||||
ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info);
|
||||
if (ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
|
||||
ice_mbx_vf_clear_cnt_e830(&pf->hw, vf->vf_id);
|
||||
else
|
||||
ice_mbx_init_vf_info(&pf->hw, &vf->mbx_info);
|
||||
|
||||
mutex_init(&vf->cfg_lock);
|
||||
}
|
||||
|
||||
void ice_deinitialize_vf_entry(struct ice_vf *vf)
|
||||
{
|
||||
struct ice_pf *pf = vf->pf;
|
||||
|
||||
if (!ice_is_feature_supported(pf, ICE_F_MBX_LIMIT))
|
||||
list_del(&vf->mbx_info.list_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_dis_vf_qs - Disable the VF queues
|
||||
* @vf: pointer to the VF structure
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#endif
|
||||
|
||||
void ice_initialize_vf_entry(struct ice_vf *vf);
|
||||
void ice_deinitialize_vf_entry(struct ice_vf *vf);
|
||||
void ice_dis_vf_qs(struct ice_vf *vf);
|
||||
int ice_check_vf_init(struct ice_vf *vf);
|
||||
enum virtchnl_status_code ice_err_to_virt_err(int err);
|
||||
|
||||
@@ -210,6 +210,38 @@ ice_mbx_detect_malvf(struct ice_hw *hw, struct ice_mbx_vf_info *vf_info,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_mbx_vf_dec_trig_e830 - Decrements the VF mailbox queue counter
|
||||
* @hw: pointer to the HW struct
|
||||
* @event: pointer to the control queue receive event
|
||||
*
|
||||
* This function triggers to decrement the counter
|
||||
* MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT when the driver replenishes
|
||||
* the buffers at the PF mailbox queue.
|
||||
*/
|
||||
void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
|
||||
const struct ice_rq_event_info *event)
|
||||
{
|
||||
u16 vfid = le16_to_cpu(event->desc.retval);
|
||||
|
||||
wr32(hw, E830_MBX_VF_DEC_TRIG(vfid), 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_mbx_vf_clear_cnt_e830 - Clear the VF mailbox queue count
|
||||
* @hw: pointer to the HW struct
|
||||
* @vf_id: VF ID in the PF space
|
||||
*
|
||||
* This function clears the counter MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT, and should
|
||||
* be called when a VF is created and on VF reset.
|
||||
*/
|
||||
void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id)
|
||||
{
|
||||
u32 reg = rd32(hw, E830_MBX_VF_IN_FLIGHT_MSGS_AT_PF_CNT(vf_id));
|
||||
|
||||
wr32(hw, E830_MBX_VF_DEC_TRIG(vf_id), reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_mbx_vf_state_handler - Handle states of the overflow algorithm
|
||||
* @hw: pointer to the HW struct
|
||||
|
||||
@@ -19,6 +19,9 @@ ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
|
||||
u8 *msg, u16 msglen, struct ice_sq_cd *cd);
|
||||
|
||||
u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed);
|
||||
void ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
|
||||
const struct ice_rq_event_info *event);
|
||||
void ice_mbx_vf_clear_cnt_e830(const struct ice_hw *hw, u16 vf_id);
|
||||
int
|
||||
ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data,
|
||||
struct ice_mbx_vf_info *vf_info, bool *report_malvf);
|
||||
@@ -47,5 +50,11 @@ static inline void ice_mbx_init_snapshot(struct ice_hw *hw)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ice_mbx_vf_dec_trig_e830(const struct ice_hw *hw,
|
||||
const struct ice_rq_event_info *event)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PCI_IOV */
|
||||
#endif /* _ICE_VF_MBX_H_ */
|
||||
|
||||
@@ -4008,8 +4008,10 @@ ice_is_malicious_vf(struct ice_vf *vf, struct ice_mbx_data *mbxdata)
|
||||
* @event: pointer to the AQ event
|
||||
* @mbxdata: information used to detect VF attempting mailbox overflow
|
||||
*
|
||||
* called from the common asq/arq handler to
|
||||
* process request from VF
|
||||
* Called from the common asq/arq handler to process request from VF. When this
|
||||
* flow is used for devices with hardware VF to PF message queue overflow
|
||||
* support (ICE_F_MBX_LIMIT) mbxdata is set to NULL and ice_is_malicious_vf
|
||||
* check is skipped.
|
||||
*/
|
||||
void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
|
||||
struct ice_mbx_data *mbxdata)
|
||||
@@ -4035,7 +4037,7 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
|
||||
mutex_lock(&vf->cfg_lock);
|
||||
|
||||
/* Check if the VF is trying to overflow the mailbox */
|
||||
if (ice_is_malicious_vf(vf, mbxdata))
|
||||
if (mbxdata && ice_is_malicious_vf(vf, mbxdata))
|
||||
goto finish;
|
||||
|
||||
/* Check if VF is disabled. */
|
||||
|
||||
@@ -3013,7 +3013,6 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
|
||||
skb_shinfo(skb)->gso_size = rsc_seg_len;
|
||||
|
||||
skb_reset_network_header(skb);
|
||||
len = skb->len - skb_transport_offset(skb);
|
||||
|
||||
if (ipv4) {
|
||||
struct iphdr *ipv4h = ip_hdr(skb);
|
||||
@@ -3022,6 +3021,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
|
||||
|
||||
/* Reset and set transport header offset in skb */
|
||||
skb_set_transport_header(skb, sizeof(struct iphdr));
|
||||
len = skb->len - skb_transport_offset(skb);
|
||||
|
||||
/* Compute the TCP pseudo header checksum*/
|
||||
tcp_hdr(skb)->check =
|
||||
@@ -3031,6 +3031,7 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb,
|
||||
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
|
||||
skb_set_transport_header(skb, sizeof(struct ipv6hdr));
|
||||
len = skb->len - skb_transport_offset(skb);
|
||||
tcp_hdr(skb)->check =
|
||||
~tcp_v6_check(len, &ipv6h->saddr, &ipv6h->daddr, 0);
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ static const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = {
|
||||
MVPP2_PRS_RI_VLAN_MASK),
|
||||
/* Non IP flow, with vlan tag */
|
||||
MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_TAG,
|
||||
MVPP22_CLS_HEK_OPT_VLAN,
|
||||
MVPP22_CLS_HEK_TAGGED,
|
||||
0, 0),
|
||||
};
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ irq_pool_alloc(struct mlx5_core_dev *dev, int start, int size, char *name,
|
||||
pool->min_threshold = min_threshold * MLX5_EQ_REFS_PER_IRQ;
|
||||
pool->max_threshold = max_threshold * MLX5_EQ_REFS_PER_IRQ;
|
||||
mlx5_core_dbg(dev, "pool->name = %s, pool->size = %d, pool->start = %d",
|
||||
name, size, start);
|
||||
name ? name : "mlx5_pcif_pool", size, start);
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
||||
@@ -516,6 +516,19 @@ static int loongson_dwmac_acpi_config(struct pci_dev *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Loongson's DWMAC device may take nearly two seconds to complete DMA reset */
|
||||
static int loongson_dwmac_fix_reset(void *priv, void __iomem *ioaddr)
|
||||
{
|
||||
u32 value = readl(ioaddr + DMA_BUS_MODE);
|
||||
|
||||
value |= DMA_BUS_MODE_SFT_RESET;
|
||||
writel(value, ioaddr + DMA_BUS_MODE);
|
||||
|
||||
return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
|
||||
!(value & DMA_BUS_MODE_SFT_RESET),
|
||||
10000, 2000000);
|
||||
}
|
||||
|
||||
static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct plat_stmmacenet_data *plat;
|
||||
@@ -566,6 +579,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
|
||||
|
||||
plat->bsp_priv = ld;
|
||||
plat->setup = loongson_dwmac_setup;
|
||||
plat->fix_soc_reset = loongson_dwmac_fix_reset;
|
||||
ld->dev = &pdev->dev;
|
||||
ld->loongson_id = readl(res.addr + GMAC_VERSION) & 0xff;
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ config TI_K3_AM65_CPSW_NUSS
|
||||
select NET_DEVLINK
|
||||
select TI_DAVINCI_MDIO
|
||||
select PHYLINK
|
||||
select PAGE_POOL
|
||||
select TI_K3_CPPI_DESC_POOL
|
||||
imply PHY_TI_GMII_SEL
|
||||
depends on TI_K3_AM65_CPTS || !TI_K3_AM65_CPTS
|
||||
|
||||
@@ -474,26 +474,7 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
|
||||
static int icss_iep_perout_enable(struct icss_iep *iep,
|
||||
struct ptp_perout_request *req, int on)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&iep->ptp_clk_mutex);
|
||||
|
||||
if (iep->pps_enabled) {
|
||||
ret = -EBUSY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (iep->perout_enabled == !!on)
|
||||
goto exit;
|
||||
|
||||
ret = icss_iep_perout_enable_hw(iep, req, on);
|
||||
if (!ret)
|
||||
iep->perout_enabled = !!on;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&iep->ptp_clk_mutex);
|
||||
|
||||
return ret;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void icss_iep_cap_cmp_work(struct work_struct *work)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include <net/inet_dscp.h>
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ipvlan.h"
|
||||
|
||||
@@ -415,20 +416,25 @@ struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
|
||||
|
||||
static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb)
|
||||
{
|
||||
const struct iphdr *ip4h = ip_hdr(skb);
|
||||
struct net_device *dev = skb->dev;
|
||||
struct net *net = dev_net(dev);
|
||||
struct rtable *rt;
|
||||
int err, ret = NET_XMIT_DROP;
|
||||
const struct iphdr *ip4h;
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4 = {
|
||||
.flowi4_oif = dev->ifindex,
|
||||
.flowi4_tos = ip4h->tos & INET_DSCP_MASK,
|
||||
.flowi4_flags = FLOWI_FLAG_ANYSRC,
|
||||
.flowi4_mark = skb->mark,
|
||||
.daddr = ip4h->daddr,
|
||||
.saddr = ip4h->saddr,
|
||||
};
|
||||
|
||||
if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
|
||||
goto err;
|
||||
|
||||
ip4h = ip_hdr(skb);
|
||||
fl4.daddr = ip4h->daddr;
|
||||
fl4.saddr = ip4h->saddr;
|
||||
fl4.flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h));
|
||||
|
||||
rt = ip_route_output_flow(net, &fl4, NULL);
|
||||
if (IS_ERR(rt))
|
||||
goto err;
|
||||
@@ -487,6 +493,12 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
||||
struct net_device *dev = skb->dev;
|
||||
int err, ret = NET_XMIT_DROP;
|
||||
|
||||
if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) {
|
||||
DEV_STATS_INC(dev, tx_errors);
|
||||
kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
err = ipvlan_route_v6_outbound(dev, skb);
|
||||
if (unlikely(err)) {
|
||||
DEV_STATS_INC(dev, tx_errors);
|
||||
|
||||
@@ -244,8 +244,22 @@ static netdev_tx_t blackhole_netdev_xmit(struct sk_buff *skb,
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static int blackhole_neigh_output(struct neighbour *n, struct sk_buff *skb)
|
||||
{
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blackhole_neigh_construct(struct net_device *dev,
|
||||
struct neighbour *n)
|
||||
{
|
||||
n->output = blackhole_neigh_output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops blackhole_netdev_ops = {
|
||||
.ndo_start_xmit = blackhole_netdev_xmit,
|
||||
.ndo_neigh_construct = blackhole_neigh_construct,
|
||||
};
|
||||
|
||||
/* This is a dst-dummy device used specifically for invalidated
|
||||
|
||||
@@ -774,7 +774,7 @@ static int qca807x_config_init(struct phy_device *phydev)
|
||||
control_dac &= ~QCA807X_CONTROL_DAC_MASK;
|
||||
if (!priv->dac_full_amplitude)
|
||||
control_dac |= QCA807X_CONTROL_DAC_DSP_AMPLITUDE;
|
||||
if (!priv->dac_full_amplitude)
|
||||
if (!priv->dac_full_bias_current)
|
||||
control_dac |= QCA807X_CONTROL_DAC_DSP_BIAS_CURRENT;
|
||||
if (!priv->dac_disable_bias_current_tweak)
|
||||
control_dac |= QCA807X_CONTROL_DAC_BIAS_CURRENT_TWEAK;
|
||||
|
||||
@@ -179,9 +179,7 @@ static int genelink_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
{
|
||||
dev->hard_mtu = GL_RCV_BUF_SIZE;
|
||||
dev->net->hard_header_len += 4;
|
||||
dev->in = usb_rcvbulkpipe(dev->udev, dev->driver_info->in);
|
||||
dev->out = usb_sndbulkpipe(dev->udev, dev->driver_info->out);
|
||||
return 0;
|
||||
return usbnet_get_endpoints(dev, intf);
|
||||
}
|
||||
|
||||
static const struct driver_info genelink_info = {
|
||||
|
||||
@@ -125,6 +125,7 @@ config PHY_ROCKCHIP_USBDP
|
||||
depends on ARCH_ROCKCHIP && OF
|
||||
depends on TYPEC
|
||||
select GENERIC_PHY
|
||||
select USB_COMMON
|
||||
help
|
||||
Enable this to support the Rockchip USB3.0/DP combo PHY with
|
||||
Samsung IP block. This is required for USB3 support on RK3588.
|
||||
|
||||
@@ -309,7 +309,10 @@ static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy
|
||||
|
||||
priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
|
||||
|
||||
priv->phy_rst = devm_reset_control_get(dev, "phy");
|
||||
priv->phy_rst = devm_reset_control_get_exclusive(dev, "phy");
|
||||
/* fallback to old behaviour */
|
||||
if (PTR_ERR(priv->phy_rst) == -ENOENT)
|
||||
priv->phy_rst = devm_reset_control_array_get_exclusive(dev);
|
||||
if (IS_ERR(priv->phy_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
|
||||
|
||||
|
||||
@@ -488,9 +488,9 @@ exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
|
||||
reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
|
||||
|
||||
/* FSEL settings corresponding to reference clock */
|
||||
reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
|
||||
PHYCLKRST_MPLL_MULTIPLIER_MASK |
|
||||
PHYCLKRST_SSC_REFCLKSEL_MASK;
|
||||
reg &= ~(PHYCLKRST_FSEL_PIPE_MASK |
|
||||
PHYCLKRST_MPLL_MULTIPLIER_MASK |
|
||||
PHYCLKRST_SSC_REFCLKSEL_MASK);
|
||||
switch (phy_drd->extrefclk) {
|
||||
case EXYNOS5_FSEL_50MHZ:
|
||||
reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
|
||||
@@ -532,9 +532,9 @@ exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
|
||||
reg &= ~PHYCLKRST_REFCLKSEL_MASK;
|
||||
reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
|
||||
|
||||
reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
|
||||
PHYCLKRST_MPLL_MULTIPLIER_MASK |
|
||||
PHYCLKRST_SSC_REFCLKSEL_MASK;
|
||||
reg &= ~(PHYCLKRST_FSEL_UTMI_MASK |
|
||||
PHYCLKRST_MPLL_MULTIPLIER_MASK |
|
||||
PHYCLKRST_SSC_REFCLKSEL_MASK);
|
||||
reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
|
||||
|
||||
return reg;
|
||||
@@ -1296,14 +1296,17 @@ static int exynos5_usbdrd_gs101_phy_exit(struct phy *phy)
|
||||
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
|
||||
int ret;
|
||||
|
||||
if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) {
|
||||
ret = exynos850_usbdrd_phy_exit(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
exynos5_usbdrd_phy_isol(inst, true);
|
||||
|
||||
if (inst->phy_cfg->id != EXYNOS5_DRDPHY_UTMI)
|
||||
return 0;
|
||||
|
||||
ret = exynos850_usbdrd_phy_exit(phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
exynos5_usbdrd_phy_isol(inst, true);
|
||||
return regulator_bulk_disable(phy_drd->drv_data->n_regulators,
|
||||
phy_drd->regulators);
|
||||
}
|
||||
|
||||
@@ -928,6 +928,7 @@ static int tegra186_utmi_phy_init(struct phy *phy)
|
||||
unsigned int index = lane->index;
|
||||
struct device *dev = padctl->dev;
|
||||
int err;
|
||||
u32 reg;
|
||||
|
||||
port = tegra_xusb_find_usb2_port(padctl, index);
|
||||
if (!port) {
|
||||
@@ -935,6 +936,16 @@ static int tegra186_utmi_phy_init(struct phy *phy)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (port->mode == USB_DR_MODE_OTG ||
|
||||
port->mode == USB_DR_MODE_PERIPHERAL) {
|
||||
/* reset VBUS&ID OVERRIDE */
|
||||
reg = padctl_readl(padctl, USB2_VBUS_ID);
|
||||
reg &= ~VBUS_OVERRIDE;
|
||||
reg &= ~ID_OVERRIDE(~0);
|
||||
reg |= ID_OVERRIDE_FLOATING;
|
||||
padctl_writel(padctl, reg, USB2_VBUS_ID);
|
||||
}
|
||||
|
||||
if (port->supply && port->mode == USB_DR_MODE_HOST) {
|
||||
err = regulator_enable(port->supply);
|
||||
if (err) {
|
||||
|
||||
@@ -1659,13 +1659,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
|
||||
if (in_flight)
|
||||
__set_bit(SCMD_STATE_INFLIGHT, &cmd->state);
|
||||
|
||||
/*
|
||||
* Only clear the driver-private command data if the LLD does not supply
|
||||
* a function to initialize that data.
|
||||
*/
|
||||
if (!shost->hostt->init_cmd_priv)
|
||||
memset(cmd + 1, 0, shost->hostt->cmd_size);
|
||||
|
||||
cmd->prot_op = SCSI_PROT_NORMAL;
|
||||
if (blk_rq_bytes(req))
|
||||
cmd->sc_data_direction = rq_dma_dir(req);
|
||||
@@ -1832,6 +1825,13 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
if (!scsi_host_queue_ready(q, shost, sdev, cmd))
|
||||
goto out_dec_target_busy;
|
||||
|
||||
/*
|
||||
* Only clear the driver-private command data if the LLD does not supply
|
||||
* a function to initialize that data.
|
||||
*/
|
||||
if (shost->hostt->cmd_size && !shost->hostt->init_cmd_priv)
|
||||
memset(cmd + 1, 0, shost->hostt->cmd_size);
|
||||
|
||||
if (!(req->rq_flags & RQF_DONTPREP)) {
|
||||
ret = scsi_prepare_cmd(req);
|
||||
if (ret != BLK_STS_OK)
|
||||
|
||||
@@ -67,6 +67,7 @@ static void bang_bang_control(struct thermal_zone_device *tz,
|
||||
const struct thermal_trip *trip,
|
||||
bool crossed_up)
|
||||
{
|
||||
const struct thermal_trip_desc *td = trip_to_trip_desc(trip);
|
||||
struct thermal_instance *instance;
|
||||
|
||||
lockdep_assert_held(&tz->lock);
|
||||
@@ -75,10 +76,8 @@ static void bang_bang_control(struct thermal_zone_device *tz,
|
||||
thermal_zone_trip_id(tz, trip), trip->temperature,
|
||||
tz->temperature, trip->hysteresis);
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
if (instance->trip == trip)
|
||||
bang_bang_set_instance_target(instance, crossed_up);
|
||||
}
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node)
|
||||
bang_bang_set_instance_target(instance, crossed_up);
|
||||
}
|
||||
|
||||
static void bang_bang_manage(struct thermal_zone_device *tz)
|
||||
@@ -104,8 +103,8 @@ static void bang_bang_manage(struct thermal_zone_device *tz)
|
||||
* to the thermal zone temperature and the trip point threshold.
|
||||
*/
|
||||
turn_on = tz->temperature >= td->threshold;
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
if (!instance->initialized && instance->trip == trip)
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
if (!instance->initialized)
|
||||
bang_bang_set_instance_target(instance, turn_on);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ static int get_trip_level(struct thermal_zone_device *tz)
|
||||
/**
|
||||
* fair_share_throttle - throttles devices associated with the given zone
|
||||
* @tz: thermal_zone_device
|
||||
* @trip: trip point
|
||||
* @td: trip point descriptor
|
||||
* @trip_level: number of trips crossed by the zone temperature
|
||||
*
|
||||
* Throttling Logic: This uses three parameters to calculate the new
|
||||
@@ -61,29 +61,23 @@ static int get_trip_level(struct thermal_zone_device *tz)
|
||||
* new_state of cooling device = P3 * P2 * P1
|
||||
*/
|
||||
static void fair_share_throttle(struct thermal_zone_device *tz,
|
||||
const struct thermal_trip *trip,
|
||||
const struct thermal_trip_desc *td,
|
||||
int trip_level)
|
||||
{
|
||||
struct thermal_instance *instance;
|
||||
int total_weight = 0;
|
||||
int nr_instances = 0;
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
if (instance->trip != trip)
|
||||
continue;
|
||||
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
total_weight += instance->weight;
|
||||
nr_instances++;
|
||||
}
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
struct thermal_cooling_device *cdev = instance->cdev;
|
||||
u64 dividend;
|
||||
u32 divisor;
|
||||
|
||||
if (instance->trip != trip)
|
||||
continue;
|
||||
|
||||
dividend = trip_level;
|
||||
dividend *= cdev->max_state;
|
||||
divisor = tz->num_trips;
|
||||
@@ -116,7 +110,7 @@ static void fair_share_manage(struct thermal_zone_device *tz)
|
||||
trip->type == THERMAL_TRIP_HOT)
|
||||
continue;
|
||||
|
||||
fair_share_throttle(tz, trip, trip_level);
|
||||
fair_share_throttle(tz, td, trip_level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,11 +97,9 @@ struct power_allocator_params {
|
||||
struct power_actor *power;
|
||||
};
|
||||
|
||||
static bool power_actor_is_valid(struct power_allocator_params *params,
|
||||
struct thermal_instance *instance)
|
||||
static bool power_actor_is_valid(struct thermal_instance *instance)
|
||||
{
|
||||
return (instance->trip == params->trip_max &&
|
||||
cdev_is_power_actor(instance->cdev));
|
||||
return cdev_is_power_actor(instance->cdev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,13 +116,14 @@ static bool power_actor_is_valid(struct power_allocator_params *params,
|
||||
static u32 estimate_sustainable_power(struct thermal_zone_device *tz)
|
||||
{
|
||||
struct power_allocator_params *params = tz->governor_data;
|
||||
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct thermal_instance *instance;
|
||||
u32 sustainable_power = 0;
|
||||
u32 min_power;
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
if (!power_actor_is_valid(params, instance))
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
if (!power_actor_is_valid(instance))
|
||||
continue;
|
||||
|
||||
cdev = instance->cdev;
|
||||
@@ -364,7 +363,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors,
|
||||
|
||||
for (i = 0; i < num_actors; i++) {
|
||||
struct power_actor *pa = &power[i];
|
||||
u64 req_range = (u64)pa->req_power * power_range;
|
||||
u64 req_range = (u64)pa->weighted_req_power * power_range;
|
||||
|
||||
pa->granted_power = DIV_ROUND_CLOSEST_ULL(req_range,
|
||||
total_req_power);
|
||||
@@ -400,6 +399,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors,
|
||||
static void allocate_power(struct thermal_zone_device *tz, int control_temp)
|
||||
{
|
||||
struct power_allocator_params *params = tz->governor_data;
|
||||
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
|
||||
unsigned int num_actors = params->num_actors;
|
||||
struct power_actor *power = params->power;
|
||||
struct thermal_cooling_device *cdev;
|
||||
@@ -417,10 +417,10 @@ static void allocate_power(struct thermal_zone_device *tz, int control_temp)
|
||||
/* Clean all buffers for new power estimations */
|
||||
memset(power, 0, params->buffer_size);
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
struct power_actor *pa = &power[i];
|
||||
|
||||
if (!power_actor_is_valid(params, instance))
|
||||
if (!power_actor_is_valid(instance))
|
||||
continue;
|
||||
|
||||
cdev = instance->cdev;
|
||||
@@ -454,10 +454,10 @@ static void allocate_power(struct thermal_zone_device *tz, int control_temp)
|
||||
power_range);
|
||||
|
||||
i = 0;
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
struct power_actor *pa = &power[i];
|
||||
|
||||
if (!power_actor_is_valid(params, instance))
|
||||
if (!power_actor_is_valid(instance))
|
||||
continue;
|
||||
|
||||
power_actor_set_power(instance->cdev, instance,
|
||||
@@ -538,12 +538,13 @@ static void reset_pid_controller(struct power_allocator_params *params)
|
||||
static void allow_maximum_power(struct thermal_zone_device *tz)
|
||||
{
|
||||
struct power_allocator_params *params = tz->governor_data;
|
||||
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct thermal_instance *instance;
|
||||
u32 req_power;
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
if (!power_actor_is_valid(params, instance))
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
if (!power_actor_is_valid(instance))
|
||||
continue;
|
||||
|
||||
cdev = instance->cdev;
|
||||
@@ -581,13 +582,16 @@ static void allow_maximum_power(struct thermal_zone_device *tz)
|
||||
static int check_power_actors(struct thermal_zone_device *tz,
|
||||
struct power_allocator_params *params)
|
||||
{
|
||||
const struct thermal_trip_desc *td;
|
||||
struct thermal_instance *instance;
|
||||
int ret = 0;
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
if (instance->trip != params->trip_max)
|
||||
continue;
|
||||
if (!params->trip_max)
|
||||
return 0;
|
||||
|
||||
td = trip_to_trip_desc(params->trip_max);
|
||||
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
if (!cdev_is_power_actor(instance->cdev)) {
|
||||
dev_warn(&tz->device, "power_allocator: %s is not a power actor\n",
|
||||
instance->cdev->type);
|
||||
@@ -631,30 +635,43 @@ clean_state:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void power_allocator_update_weight(struct power_allocator_params *params)
|
||||
{
|
||||
const struct thermal_trip_desc *td;
|
||||
struct thermal_instance *instance;
|
||||
|
||||
if (!params->trip_max)
|
||||
return;
|
||||
|
||||
td = trip_to_trip_desc(params->trip_max);
|
||||
|
||||
params->total_weight = 0;
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node)
|
||||
if (power_actor_is_valid(instance))
|
||||
params->total_weight += instance->weight;
|
||||
}
|
||||
|
||||
static void power_allocator_update_tz(struct thermal_zone_device *tz,
|
||||
enum thermal_notify_event reason)
|
||||
{
|
||||
struct power_allocator_params *params = tz->governor_data;
|
||||
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
|
||||
struct thermal_instance *instance;
|
||||
int num_actors = 0;
|
||||
|
||||
switch (reason) {
|
||||
case THERMAL_TZ_BIND_CDEV:
|
||||
case THERMAL_TZ_UNBIND_CDEV:
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node)
|
||||
if (power_actor_is_valid(params, instance))
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node)
|
||||
if (power_actor_is_valid(instance))
|
||||
num_actors++;
|
||||
|
||||
if (num_actors == params->num_actors)
|
||||
return;
|
||||
if (num_actors != params->num_actors)
|
||||
allocate_actors_buffer(params, num_actors);
|
||||
|
||||
allocate_actors_buffer(params, num_actors);
|
||||
break;
|
||||
fallthrough;
|
||||
case THERMAL_INSTANCE_WEIGHT_CHANGED:
|
||||
params->total_weight = 0;
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node)
|
||||
if (power_actor_is_valid(params, instance))
|
||||
params->total_weight += instance->weight;
|
||||
power_allocator_update_weight(params);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -720,6 +737,8 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
|
||||
|
||||
tz->governor_data = params;
|
||||
|
||||
power_allocator_update_weight(params);
|
||||
|
||||
return 0;
|
||||
|
||||
free_params:
|
||||
|
||||
@@ -66,9 +66,10 @@ static unsigned long get_target_state(struct thermal_instance *instance,
|
||||
}
|
||||
|
||||
static void thermal_zone_trip_update(struct thermal_zone_device *tz,
|
||||
const struct thermal_trip *trip,
|
||||
const struct thermal_trip_desc *td,
|
||||
int trip_threshold)
|
||||
{
|
||||
const struct thermal_trip *trip = &td->trip;
|
||||
enum thermal_trend trend = get_tz_trend(tz, trip);
|
||||
int trip_id = thermal_zone_trip_id(tz, trip);
|
||||
struct thermal_instance *instance;
|
||||
@@ -82,12 +83,9 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
|
||||
dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
|
||||
trip_id, trip->type, trip_threshold, trend, throttle);
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
|
||||
int old_target;
|
||||
|
||||
if (instance->trip != trip)
|
||||
continue;
|
||||
|
||||
old_target = instance->target;
|
||||
instance->target = get_target_state(instance, trend, throttle);
|
||||
|
||||
@@ -127,11 +125,13 @@ static void step_wise_manage(struct thermal_zone_device *tz)
|
||||
trip->type == THERMAL_TRIP_HOT)
|
||||
continue;
|
||||
|
||||
thermal_zone_trip_update(tz, trip, td->threshold);
|
||||
thermal_zone_trip_update(tz, td, td->threshold);
|
||||
}
|
||||
|
||||
list_for_each_entry(instance, &tz->thermal_instances, tz_node)
|
||||
thermal_cdev_update(instance->cdev);
|
||||
for_each_trip_desc(tz, td) {
|
||||
list_for_each_entry(instance, &td->thermal_instances, trip_node)
|
||||
thermal_cdev_update(instance->cdev);
|
||||
}
|
||||
}
|
||||
|
||||
static struct thermal_governor thermal_gov_step_wise = {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user