Merge 6.12.18 into android16-6.12

GKI (arm64) relevant 37 out of 149 changes, affecting 60 files +390/-338
  659bfea591 scsi: ufs: core: Fix ufshcd_is_ufs_dev_busy() and ufshcd_eh_timed_out() [1 file, +4/-4]
  3594aad97e ovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up [1 file, +1/-1]
  a3ae6a60ba SUNRPC: Prevent looping due to rpc_signal_task() races [3 files, +2/-6]
  b5038504da scsi: core: Clear driver private data when retrying request [1 file, +7/-7]
  465a814323 scsi: ufs: core: Set default runtime/system PM levels before ufshcd_hba_init() [1 file, +15/-15]
  ee5d6cb5cc ALSA: usb-audio: Avoid dropping MIDI events at closing multiple ports [1 file, +1/-1]
  5c9921f1da Bluetooth: L2CAP: Fix L2CAP_ECRED_CONN_RSP response [1 file, +7/-2]
  f22df335b2 net: loopback: Avoid sending IP packets without an Ethernet header [1 file, +14/-0]
  915d64a78f net: set the minimum for net_hotdata.netdev_budget_usecs [1 file, +2/-1]
  db8b2a613d ipv4: Convert icmp_route_lookup() to dscp_t. [1 file, +9/-10]
  97c455c3c2 ipv4: Convert ip_route_input() to dscp_t. [6 files, +18/-9]
  8ffd0390fc ipvs: Always clear ipvs_property flag in skb_scrub_packet() [1 file, +1/-1]
  c417b1e4d8 tcp: devmem: don't write truncated dmabuf CMSGs to userspace [3 files, +22/-16]
  33d782e38d tcp: Defer ts_recent changes until req is owned [1 file, +4/-6]
  902d576296 net: Clear old fragment checksum value in napi_reuse_skb [1 file, +1/-0]
  806437d047 thermal: gov_power_allocator: Fix incorrect calculation in divvy_up_power() [1 file, +1/-1]
  7d582eb6e4 perf/core: Order the PMU list to fix warning about unordered pmu_ctx_list [1 file, +9/-2]
  13cca2b73e uprobes: Reject the shared zeropage in uprobe_write_opcode() [1 file, +5/-0]
  07a82c78d8 thermal: of: Simplify thermal_of_should_bind with scoped for each OF child [1 file, +2/-3]
  e11df3bffd thermal/of: Fix cdev lookup in thermal_of_should_bind() [1 file, +29/-21]
  19cd2dc4d4 thermal: core: Move lists of thermal instances to trip descriptors [7 files, +62/-64]
  27a144c3be thermal: gov_power_allocator: Update total_weight on bind and cdev updates [1 file, +22/-8]
  546c19eb69 io_uring/net: save msg_control for compat [1 file, +3/-1]
  8cc451444c unreachable: Unify [2 files, +7/-15]
  2cfd0e5084 objtool: Remove annotate_{,un}reachable() [2 files, +2/-68]
  a00e900c9b objtool: Fix C jump table annotations for Clang [3 files, +6/-5]
  435d2964af tracing: Fix bad hist from corrupting named_triggers list [1 file, +15/-15]
  8e31d9fb2f ALSA: usb-audio: Re-add sample rate quirk for Pioneer DJM-900NXS2 [1 file, +1/-0]
  b9de147b2c KVM: arm64: Ensure a VMID is allocated before programming VTTBR_EL2 [3 files, +14/-21]
  a2475ccad6 perf/core: Add RCU read lock protection to perf_iterate_ctx() [1 file, +2/-1]
  322cb23e24 perf/core: Fix low freq setting via IOC_PERIOD [1 file, +9/-8]
  8f6369c3cd arm64/mm: Fix Boot panic on Ampere Altra [1 file, +1/-6]
  2f572c42bb block: Remove zone write plugs when handling native zone append writes [2 files, +73/-10]
  29b6d5ad3e rcuref: Plug slowpath race in rcuref_put() [2 files, +8/-6]
  0362847c52 sched/core: Prevent rescheduling when interrupts are disabled [1 file, +1/-1]
  59455f968c scsi: ufs: core: bsg: Fix crash when arpmb command fails [1 file, +4/-2]
  72cbaf8b41 thermal: 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:
Greg Kroah-Hartman
2025-03-10 13:05:08 +00:00
172 changed files with 2930 additions and 1402 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 12
SUBLEVEL = 17
SUBLEVEL = 18
EXTRAVERSION =
NAME = Baby Opossum Posse
+1 -1
View File
@@ -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
View File
@@ -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();
+3 -8
View File
@@ -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;
}
/*
+1 -1
View File
@@ -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();
+6 -6
View File
@@ -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;
}
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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))
-6
View File
@@ -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;
+6 -5
View File
@@ -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;
+12 -3
View File
@@ -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;
}
+1
View File
@@ -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
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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 */
+192 -91
View File
@@ -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:
+444
View 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,
}
},
};
-2
View File
@@ -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
View File
@@ -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);
+6 -18
View File
@@ -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;
+13 -29
View File
@@ -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");
+1 -1
View File
@@ -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;
}
/*
+19 -6
View File
@@ -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);
}
+20 -6
View File
@@ -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)
-1
View File
@@ -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
View File
@@ -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(&gt->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, &param->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, &param->syncs[num_syncs],
&param->syncs_user[num_syncs], 0);
if (ret)
goto err_syncs;
if (xe_sync_is_ufence(&param->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(&param->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, &param);
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, &param);
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, &param->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, &param->syncs[num_syncs],
&param->syncs_user[num_syncs], 0);
if (ret)
goto err_syncs;
if (xe_sync_is_ufence(&param->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(&param->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, &param);
param.period_exponent = -1;
ret = xe_oa_user_extensions(oa, XE_OA_USER_EXTN_FROM_OPEN, data, 0, &param);
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 */
+6
View File
@@ -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;
+33 -7
View File
@@ -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)) {
+12 -4
View File
@@ -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)
+7
View File
@@ -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)
+4
View File
@@ -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;
}
+11 -7
View File
@@ -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;
+2 -2
View File
@@ -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,
+24 -22
View File
@@ -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 = {};
+99 -54
View File
@@ -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;
+3 -4
View File
@@ -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)
+9 -3
View File
@@ -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 &
+2 -2
View File
@@ -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;
+1 -2
View File
@@ -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);
+48 -16
View File
@@ -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;
+1 -1
View File
@@ -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;
+2 -1
View File
@@ -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)
+6 -2
View File
@@ -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;
}
+14 -2
View File
@@ -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;
}
+1
View File
@@ -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;
}
+6 -4
View File
@@ -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) {
+1
View File
@@ -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 */
+56 -27
View File
@@ -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);
+1
View File
@@ -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;
+7 -3
View File
@@ -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);
}
+4 -4
View File
@@ -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);
}
+1
View File
@@ -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,
+6
View File
@@ -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
+3
View File
@@ -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
+177
View File
@@ -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;
}
+6 -252
View File
@@ -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;
+107
View File
@@ -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 */
+2
View File
@@ -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;
+10 -2
View File
@@ -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);
+74 -29
View File
@@ -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);
+1
View File
@@ -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
};
+1 -2
View File
@@ -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_ */
+3
View File
@@ -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);
}
/**
+18 -6
View File
@@ -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);
+1 -3
View File
@@ -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);
}
+31 -3
View File
@@ -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. */
+2 -1
View File
@@ -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;
+1
View File
@@ -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
+1 -20
View File
@@ -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)
+17 -5
View File
@@ -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);
+14
View File
@@ -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
+1 -1
View File
@@ -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;
+1 -3
View File
@@ -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 = {
+1
View File
@@ -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");
+14 -11
View File
@@ -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);
}
+11
View File
@@ -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) {
+7 -7
View File
@@ -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)
+5 -6
View File
@@ -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);
}
}
+5 -11
View File
@@ -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);
}
}
+45 -26
View File
@@ -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:
+8 -8
View File
@@ -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