Merge 6.12.7 into android16-6.12
GKI (arm64) relevant 43 out of 161 changes, affecting 62 files +519/-4605dbe6816c4sched/fair: Fix NEXT_BUDDY [1 file, +2/-5]0ee98301f1sched/fair: Fix sched_can_stop_tick() for fair tasks [1 file, +1/-1]0653fa6ee0erofs: fix PSI memstall accounting [1 file, +2/-2]bdd68033d1sched/dlserver: Fix dlserver double enqueue [3 files, +18/-2]baedaacee1sched/dlserver: Fix dlserver time accounting [1 file, +9/-6]910798ecd3erofs: add erofs_sb_free() helper [1 file, +19/-17]3e0d81efcberofs: use `struct erofs_device_info` for the primary device [4 files, +22/-31]f067d3f69derofs: reference `struct erofs_device_info` for erofs_map_dev [4 files, +15/-23]3042448109erofs: use buffered I/O for file-backed mounts by default [3 files, +21/-10]d924c8afe6netdev: fix repeated netlink messages in queue dump [1 file, +4/-7]b38e858ab0netdev: fix repeated netlink messages in queue stats [1 file, +2/-2]57ed6505banetdev-genl: avoid empty messages in queue dump [1 file, +2/-2]aa9e573145net: mdiobus: fix an OF node reference leak [1 file, +10/-3]20bf32f482irqchip/gic-v3: Work around insecure GIC integrations [1 file, +16/-1]ea78f77f78KVM: arm64: Do not allow ID_AA64MMFR0_EL1.ASIDbits to be overridden [1 file, +2/-1]4f393ea1e2net: tun: fix tun_napi_alloc_frags() [1 file, +1/-1]97701315e3block: Revert "block: Fix potential deadlock while freezing queue and acquiring sysfs_lock" [3 files, +23/-26]7ccad1ee83xhci: Turn NEC specific quirk for handling Stop Endpoint errors generic [1 file, +0/-2]47c8b6cf1ddrm/modes: Avoid divide by zero harder in drm_mode_vrefresh() [1 file, +7/-4]c8395bfcd0dma-buf: Fix __dma_buf_debugfs_list_del argument for !CONFIG_DEBUG_FS [1 file, +1/-1]b5792c162dblock: avoid to reuse `hctx` not removed from cpuhp callback list [1 file, +10/-1]1828714c09trace/ring-buffer: Do not use TP_printk() formatting for boot mapped buffers [1 file, +9/-0]6d91e90cfczram: refuse to use zero sized block device as backing device [1 file, +6/-0]6fb92e9a52zram: fix uninitialized ZRAM not releasing backing device [1 file, +4/-5]ad7c9f1f43vmalloc: fix accounting with i915 [1 file, +4/-2]4234ca9884mm/page_alloc: don't call pfn_to_page() on possibly non-existent PFN in split_large_buddy() [1 file, +4/-2]ec12f30fe5ring-buffer: Fix overflow in __rb_map_vma [1 file, +5/-1]9667c91464alloc_tag: fix set_codetag_empty() when !CONFIG_MEM_ALLOC_PROFILING_DEBUG [1 file, +6/-1]3985cd3047tracing: Fix test_event_printk() to process entire print argument [1 file, +53/-29]71a613ceactracing: Add missing helper functions in event pointer dereference check [1 file, +19/-2]683eccacc0tracing: Add "%s" check in test_event_printk() [1 file, +89/-15]d3e73fe7catracing: Check "%s" dereference via the field and not the TP_printk format [5 files, +88/-217]06eb089489io_uring: Fix registered ring file refcount leak [2 files, +2/-3]4f95a2186bio_uring: check if iowq is killed before queuing [1 file, +5/-1]2976661ed4of/irq: Fix interrupt-map cell length check in of_irq_parse_imap_parent() [1 file, +1/-0]e30e72844cof/irq: Fix using uninitialized variable @addr_len in API of_irq_parse_one() [1 file, +1/-0]e0d9c581acof: property: fw_devlink: Do not use interrupt-parent directly [1 file, +0/-2]501d686391of: address: Preserve the flags portion on 1:1 dma-ranges mapping [1 file, +2/-1]c62318587cof: Fix error path in of_parse_phandle_with_args_map() [1 file, +10/-5]adc4b70fb6of: Fix refcount leakage for OF node returned by __of_get_dma_parent() [1 file, +1/-1]a095090b70mm: shmem: fix ShmemHugePages at swapout [1 file, +12/-10]a086c8d7f2mm: convert partially_mapped set/clear operations to be atomic [2 files, +6/-14]2d129beb8depoll: Add synchronous wakeup support for ep_poll_callback [2 files, +5/-1] Changes in 6.12.7 net: sched: fix ordering of qlen adjustment net: stmmac: fix TSO DMA API usage causing oops firmware: arm_scmi: Fix i.MX build dependency firmware: arm_ffa: Fix the race around setting ffa_dev->properties RISC-V: KVM: Fix csr_write -> csr_set for HVIEN PMU overflow bit sched/fair: Fix NEXT_BUDDY sched/fair: Fix sched_can_stop_tick() for fair tasks sched/eevdf: More PELT vs DELAYED_DEQUEUE p2sb: Factor out p2sb_read_from_cache() p2sb: Introduce the global flag p2sb_hidden_by_bios p2sb: Move P2SB hide and unhide code to p2sb_scan_and_cache() p2sb: Do not scan and remove the P2SB device when it is unhidden i2c: pnx: Fix timeout in wait functions s390/ipl: Fix never less than zero warning erofs: fix PSI memstall accounting sched/dlserver: Fix dlserver double enqueue sched/dlserver: Fix dlserver time accounting s390/mm: Consider KMSAN modules metadata for paging levels erofs: add erofs_sb_free() helper erofs: use `struct erofs_device_info` for the primary device erofs: reference `struct erofs_device_info` for erofs_map_dev erofs: use buffered I/O for file-backed mounts by default xfs: sb_spino_align is not verified xfs: fix sparse inode limits on runt AG xfs: fix off-by-one error in fsmap's end_daddr usage xfs: fix sb_spino_align checks for large fsblock sizes xfs: fix zero byte checking in the superblock scrubber tools: hv: change permissions of NetworkManager configuration file cxl/pci: Fix potential bogus return value upon successful probing cxl/region: Fix region creation for greater than x2 switches net/smc: protect link down work from execute after lgr freed net/smc: check sndbuf_space again after NOSPACE flag is set in smc_poll net/smc: check iparea_offset and ipv6_prefixes_cnt when receiving proposal msg net/smc: check v2_ext_offset/eid_cnt/ism_gid_cnt when receiving proposal msg net/smc: check smcd_v2_ext_offset when receiving proposal msg net/smc: check return value of sock_recvmsg when draining clc data net: mscc: ocelot: fix incorrect IFH SRC_PORT field in ocelot_ifh_set_basic() netdevsim: prevent bad user input in nsim_dev_health_break_write() tools/net/ynl: fix sub-message key lookup for nested attributes ionic: Fix netdev notifier unregister on failure ionic: no double destroy workqueue ionic: use ee->offset when returning sprom data net: renesas: rswitch: rework ts tags management ksmbd: count all requests in req_running counter ksmbd: fix broken transfers when exceeding max simultaneous operations netdev: fix repeated netlink messages in queue dump netdev: fix repeated netlink messages in queue stats team: Fix feature exposure when no ports are present net: hinic: Fix cleanup in create_rxqs/txqs() net: ethernet: oa_tc6: fix infinite loop error when tx credits becomes 0 net: ethernet: oa_tc6: fix tx skb race condition between reference pointers net: ethernet: bgmac-platform: fix an OF node reference leak net: netdevsim: fix nsim_pp_hold_write() can: m_can: set init flag earlier in probe can: m_can: fix missed interrupts with m_can_pci ipvs: Fix clamp() of ip_vs_conn_tab on small memory systems netfilter: ipset: Fix for recursive locking warning selftests: openvswitch: fix tcpdump execution net: dsa: restore dsa_software_vlan_untag() ability to operate on VLAN-untagged traffic netdev-genl: avoid empty messages in queue dump psample: adjust size if rate_as_probability is set net: mdiobus: fix an OF node reference leak mmc: sdhci-tegra: Remove SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC quirk mmc: mtk-sd: disable wakeup in .remove() and in the error path of .probe() irqchip/gic-v3: Work around insecure GIC integrations EDAC/amd64: Simplify ECC check on unified memory controllers KVM: arm64: Do not allow ID_AA64MMFR0_EL1.ASIDbits to be overridden KVM: x86: Cache CPUID.0xD XSTATE offsets+sizes during module init net: tun: fix tun_napi_alloc_frags() chelsio/chtls: prevent potential integer overflow on 32bit net: mctp: handle skb cleanup on sock_queue failures block: Revert "block: Fix potential deadlock while freezing queue and acquiring sysfs_lock" i2c: riic: Always round-up when calculating bus period efivarfs: Fix error on non-existent file hexagon: Disable constant extender optimization for LLVM prior to 19.1.0 USB: serial: option: add TCL IK512 MBIM & ECM USB: serial: option: add MeiG Smart SLM770A USB: serial: option: add Netprisma LCUK54 modules for WWAN Ready USB: serial: option: add MediaTek T7XX compositions USB: serial: option: add Telit FE910C04 rmnet compositions xhci: Turn NEC specific quirk for handling Stop Endpoint errors generic thunderbolt: Add support for Intel Panther Lake-M/P thunderbolt: Improve redrive mode handling thunderbolt: Don't display nvm_version unless upgrade supported drm/display: use ERR_PTR on DP tunnel manager creation fail drm/amd: Update strapping for NBIO 2.5.0 drm/modes: Avoid divide by zero harder in drm_mode_vrefresh() drm/amdgpu: fix amdgpu_coredump drm/amdgpu: Handle NULL bo->tbo.resource (again) in amdgpu_vm_bo_update udmabuf: udmabuf_create pin folio codestyle cleanup udmabuf: fix memory leak on last export_udmabuf() error path dma-buf: Fix __dma_buf_debugfs_list_del argument for !CONFIG_DEBUG_FS drm/panel: himax-hx83102: Add a check to prevent NULL pointer dereference drm/panel: novatek-nt35950: fix return value check in nt35950_probe() drm/panel: st7701: Add prepare_prev_first flag to drm_panel drm/panel: synaptics-r63353: Fix regulator unbalance i915/guc: Reset engine utilization buffer before registration i915/guc: Ensure busyness counter increases motonically i915/guc: Accumulate active runtime on gt reset drm/amdgpu: don't access invalid sched hwmon: (tmp513) Fix interpretation of values of Shunt Voltage and Limit Registers hwmon: (tmp513) Fix Current Register value interpretation hwmon: (tmp513) Fix interpretation of values of Temperature Result and Limit Registers block: avoid to reuse `hctx` not removed from cpuhp callback list trace/ring-buffer: Do not use TP_printk() formatting for boot mapped buffers drm/amdgpu/nbio7.11: fix IP version check drm/amdgpu/nbio7.7: fix IP version check drm/amdgpu/smu14.0.2: fix IP version check zram: refuse to use zero sized block device as backing device zram: fix uninitialized ZRAM not releasing backing device vmalloc: fix accounting with i915 mm/page_alloc: don't call pfn_to_page() on possibly non-existent PFN in split_large_buddy() ring-buffer: Fix overflow in __rb_map_vma alloc_tag: fix set_codetag_empty() when !CONFIG_MEM_ALLOC_PROFILING_DEBUG btrfs: split bios to the fs sector size boundary btrfs: fix improper generation check in snapshot delete btrfs: tree-checker: reject inline extent items with 0 ref count s390/mm: Fix DirectMap accounting drm/amdgpu/nbio7.0: fix IP version check drm/amdgpu/gfx12: fix IP version check drm/amdgpu/mmhub4.1: fix IP version check fgraph: Still initialize idle shadow stacks when starting Drivers: hv: util: Avoid accessing a ringbuffer not initialized yet tools: hv: Fix a complier warning in the fcopy uio daemon x86/hyperv: Fix hv tsc page based sched_clock for hibernation KVM: x86: Play nice with protected guests in complete_hypercall_exit() smb: client: fix TCP timers deadlock after rmmod accel/ivpu: Fix general protection fault in ivpu_bo_list() accel/ivpu: Fix WARN in ivpu_ipc_send_receive_internal() tracing: Fix test_event_printk() to process entire print argument tracing: Add missing helper functions in event pointer dereference check tracing: Add "%s" check in test_event_printk() tracing: Check "%s" dereference via the field and not the TP_printk format selftests/memfd: run sysctl tests when PID namespace support is enabled selftests/bpf: Use asm constraint "m" for LoongArch io_uring: Fix registered ring file refcount leak io_uring: check if iowq is killed before queuing NFS/pnfs: Fix a live lock between recalled layouts and layoutget KVM: SVM: Allow guest writes to set MSR_AMD64_DE_CFG bits of/irq: Fix interrupt-map cell length check in of_irq_parse_imap_parent() of/irq: Fix using uninitialized variable @addr_len in API of_irq_parse_one() ocfs2: fix the space leak in LA when releasing LA nilfs2: fix buffer head leaks in calls to truncate_inode_pages() nilfs2: prevent use of deleted inode udmabuf: fix racy memfd sealing check udmabuf: also check for F_SEAL_FUTURE_WRITE of: property: fw_devlink: Do not use interrupt-parent directly of: address: Preserve the flags portion on 1:1 dma-ranges mapping of: Fix error path in of_parse_phandle_with_args_map() of: Fix refcount leakage for OF node returned by __of_get_dma_parent() ceph: give up on paths longer than PATH_MAX ceph: validate snapdirname option length when mounting ceph: improve error handling and short/overflow-read logic in __ceph_sync_read() ceph: fix memory leaks in __ceph_sync_read() ceph: fix memory leak in ceph_direct_read_write() mm: use aligned address in clear_gigantic_page() mm: use aligned address in copy_user_gigantic_page() mm: shmem: fix ShmemHugePages at swapout mm: convert partially_mapped set/clear operations to be atomic epoll: Add synchronous wakeup support for ep_poll_callback Linux 6.12.7 Change-Id: I139753dbdf8a7e4c9a1d0381d0f14830965acd1a Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 12
|
||||
SUBLEVEL = 6
|
||||
SUBLEVEL = 7
|
||||
EXTRAVERSION =
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
|
||||
@@ -2351,7 +2351,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
||||
ID_WRITABLE(ID_AA64MMFR0_EL1, ~(ID_AA64MMFR0_EL1_RES0 |
|
||||
ID_AA64MMFR0_EL1_TGRAN4_2 |
|
||||
ID_AA64MMFR0_EL1_TGRAN64_2 |
|
||||
ID_AA64MMFR0_EL1_TGRAN16_2)),
|
||||
ID_AA64MMFR0_EL1_TGRAN16_2 |
|
||||
ID_AA64MMFR0_EL1_ASIDBITS)),
|
||||
ID_WRITABLE(ID_AA64MMFR1_EL1, ~(ID_AA64MMFR1_EL1_RES0 |
|
||||
ID_AA64MMFR1_EL1_HCX |
|
||||
ID_AA64MMFR1_EL1_TWED |
|
||||
|
||||
@@ -32,3 +32,9 @@ KBUILD_LDFLAGS += $(ldflags-y)
|
||||
TIR_NAME := r19
|
||||
KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__
|
||||
KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME)
|
||||
|
||||
# Disable HexagonConstExtenders pass for LLVM versions prior to 19.1.0
|
||||
# https://github.com/llvm/llvm-project/issues/99714
|
||||
ifneq ($(call clang-min-version, 190100),y)
|
||||
KBUILD_CFLAGS += -mllvm -hexagon-cext=false
|
||||
endif
|
||||
|
||||
@@ -552,7 +552,7 @@ void kvm_riscv_aia_enable(void)
|
||||
csr_set(CSR_HIE, BIT(IRQ_S_GEXT));
|
||||
/* Enable IRQ filtering for overflow interrupt only if sscofpmf is present */
|
||||
if (__riscv_isa_extension_available(NULL, RISCV_ISA_EXT_SSCOFPMF))
|
||||
csr_write(CSR_HVIEN, BIT(IRQ_PMU_OVF));
|
||||
csr_set(CSR_HVIEN, BIT(IRQ_PMU_OVF));
|
||||
}
|
||||
|
||||
void kvm_riscv_aia_disable(void)
|
||||
|
||||
@@ -231,6 +231,8 @@ static unsigned long get_vmem_size(unsigned long identity_size,
|
||||
vsize = round_up(SZ_2G + max_mappable, rte_size) +
|
||||
round_up(vmemmap_size, rte_size) +
|
||||
FIXMAP_SIZE + MODULES_LEN + KASLR_LEN;
|
||||
if (IS_ENABLED(CONFIG_KMSAN))
|
||||
vsize += MODULES_LEN * 2;
|
||||
return size_add(vsize, vmalloc_size);
|
||||
}
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ static void pgtable_pte_populate(pmd_t *pmd, unsigned long addr, unsigned long e
|
||||
pages++;
|
||||
}
|
||||
}
|
||||
if (mode == POPULATE_DIRECT)
|
||||
if (mode == POPULATE_IDENTITY)
|
||||
update_page_count(PG_DIRECT_MAP_4K, pages);
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ static void pgtable_pmd_populate(pud_t *pud, unsigned long addr, unsigned long e
|
||||
}
|
||||
pgtable_pte_populate(pmd, addr, next, mode);
|
||||
}
|
||||
if (mode == POPULATE_DIRECT)
|
||||
if (mode == POPULATE_IDENTITY)
|
||||
update_page_count(PG_DIRECT_MAP_1M, pages);
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ static void pgtable_pud_populate(p4d_t *p4d, unsigned long addr, unsigned long e
|
||||
}
|
||||
pgtable_pmd_populate(pud, addr, next, mode);
|
||||
}
|
||||
if (mode == POPULATE_DIRECT)
|
||||
if (mode == POPULATE_IDENTITY)
|
||||
update_page_count(PG_DIRECT_MAP_2G, pages);
|
||||
}
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
|
||||
if (len >= sizeof(_value)) \
|
||||
return -E2BIG; \
|
||||
len = strscpy(_value, buf, sizeof(_value)); \
|
||||
if (len < 0) \
|
||||
if ((ssize_t)len < 0) \
|
||||
return len; \
|
||||
strim(_value); \
|
||||
return len; \
|
||||
|
||||
@@ -223,6 +223,63 @@ static void hv_machine_crash_shutdown(struct pt_regs *regs)
|
||||
hyperv_cleanup();
|
||||
}
|
||||
#endif /* CONFIG_CRASH_DUMP */
|
||||
|
||||
static u64 hv_ref_counter_at_suspend;
|
||||
static void (*old_save_sched_clock_state)(void);
|
||||
static void (*old_restore_sched_clock_state)(void);
|
||||
|
||||
/*
|
||||
* Hyper-V clock counter resets during hibernation. Save and restore clock
|
||||
* offset during suspend/resume, while also considering the time passed
|
||||
* before suspend. This is to make sure that sched_clock using hv tsc page
|
||||
* based clocksource, proceeds from where it left off during suspend and
|
||||
* it shows correct time for the timestamps of kernel messages after resume.
|
||||
*/
|
||||
static void save_hv_clock_tsc_state(void)
|
||||
{
|
||||
hv_ref_counter_at_suspend = hv_read_reference_counter();
|
||||
}
|
||||
|
||||
static void restore_hv_clock_tsc_state(void)
|
||||
{
|
||||
/*
|
||||
* Adjust the offsets used by hv tsc clocksource to
|
||||
* account for the time spent before hibernation.
|
||||
* adjusted value = reference counter (time) at suspend
|
||||
* - reference counter (time) now.
|
||||
*/
|
||||
hv_adj_sched_clock_offset(hv_ref_counter_at_suspend - hv_read_reference_counter());
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to override save_sched_clock_state and restore_sched_clock_state
|
||||
* functions of x86_platform. The Hyper-V clock counter is reset during
|
||||
* suspend-resume and the offset used to measure time needs to be
|
||||
* corrected, post resume.
|
||||
*/
|
||||
static void hv_save_sched_clock_state(void)
|
||||
{
|
||||
old_save_sched_clock_state();
|
||||
save_hv_clock_tsc_state();
|
||||
}
|
||||
|
||||
static void hv_restore_sched_clock_state(void)
|
||||
{
|
||||
restore_hv_clock_tsc_state();
|
||||
old_restore_sched_clock_state();
|
||||
}
|
||||
|
||||
static void __init x86_setup_ops_for_tsc_pg_clock(void)
|
||||
{
|
||||
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
|
||||
return;
|
||||
|
||||
old_save_sched_clock_state = x86_platform.save_sched_clock_state;
|
||||
x86_platform.save_sched_clock_state = hv_save_sched_clock_state;
|
||||
|
||||
old_restore_sched_clock_state = x86_platform.restore_sched_clock_state;
|
||||
x86_platform.restore_sched_clock_state = hv_restore_sched_clock_state;
|
||||
}
|
||||
#endif /* CONFIG_HYPERV */
|
||||
|
||||
static uint32_t __init ms_hyperv_platform(void)
|
||||
@@ -579,6 +636,7 @@ static void __init ms_hyperv_init_platform(void)
|
||||
|
||||
/* Register Hyper-V specific clocksource */
|
||||
hv_init_clocksource();
|
||||
x86_setup_ops_for_tsc_pg_clock();
|
||||
hv_vtl_init_platform();
|
||||
#endif
|
||||
/*
|
||||
|
||||
+26
-5
@@ -36,6 +36,26 @@
|
||||
u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
|
||||
EXPORT_SYMBOL_GPL(kvm_cpu_caps);
|
||||
|
||||
struct cpuid_xstate_sizes {
|
||||
u32 eax;
|
||||
u32 ebx;
|
||||
u32 ecx;
|
||||
};
|
||||
|
||||
static struct cpuid_xstate_sizes xstate_sizes[XFEATURE_MAX] __ro_after_init;
|
||||
|
||||
void __init kvm_init_xstate_sizes(void)
|
||||
{
|
||||
u32 ign;
|
||||
int i;
|
||||
|
||||
for (i = XFEATURE_YMM; i < ARRAY_SIZE(xstate_sizes); i++) {
|
||||
struct cpuid_xstate_sizes *xs = &xstate_sizes[i];
|
||||
|
||||
cpuid_count(0xD, i, &xs->eax, &xs->ebx, &xs->ecx, &ign);
|
||||
}
|
||||
}
|
||||
|
||||
u32 xstate_required_size(u64 xstate_bv, bool compacted)
|
||||
{
|
||||
int feature_bit = 0;
|
||||
@@ -44,14 +64,15 @@ u32 xstate_required_size(u64 xstate_bv, bool compacted)
|
||||
xstate_bv &= XFEATURE_MASK_EXTEND;
|
||||
while (xstate_bv) {
|
||||
if (xstate_bv & 0x1) {
|
||||
u32 eax, ebx, ecx, edx, offset;
|
||||
cpuid_count(0xD, feature_bit, &eax, &ebx, &ecx, &edx);
|
||||
struct cpuid_xstate_sizes *xs = &xstate_sizes[feature_bit];
|
||||
u32 offset;
|
||||
|
||||
/* ECX[1]: 64B alignment in compacted form */
|
||||
if (compacted)
|
||||
offset = (ecx & 0x2) ? ALIGN(ret, 64) : ret;
|
||||
offset = (xs->ecx & 0x2) ? ALIGN(ret, 64) : ret;
|
||||
else
|
||||
offset = ebx;
|
||||
ret = max(ret, offset + eax);
|
||||
offset = xs->ebx;
|
||||
ret = max(ret, offset + xs->eax);
|
||||
}
|
||||
|
||||
xstate_bv >>= 1;
|
||||
|
||||
@@ -32,6 +32,7 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
|
||||
bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
|
||||
u32 *ecx, u32 *edx, bool exact_only);
|
||||
|
||||
void __init kvm_init_xstate_sizes(void);
|
||||
u32 xstate_required_size(u64 xstate_bv, bool compacted);
|
||||
|
||||
int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
|
||||
|
||||
@@ -3199,15 +3199,6 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
||||
if (data & ~supported_de_cfg)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Don't let the guest change the host-programmed value. The
|
||||
* MSR is very model specific, i.e. contains multiple bits that
|
||||
* are completely unknown to KVM, and the one bit known to KVM
|
||||
* is simply a reflection of hardware capabilities.
|
||||
*/
|
||||
if (!msr->host_initiated && data != svm->msr_decfg)
|
||||
return 1;
|
||||
|
||||
svm->msr_decfg = data;
|
||||
break;
|
||||
}
|
||||
|
||||
+3
-1
@@ -9991,7 +9991,7 @@ static int complete_hypercall_exit(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
u64 ret = vcpu->run->hypercall.ret;
|
||||
|
||||
if (!is_64_bit_mode(vcpu))
|
||||
if (!is_64_bit_hypercall(vcpu))
|
||||
ret = (u32)ret;
|
||||
kvm_rax_write(vcpu, ret);
|
||||
++vcpu->stat.hypercalls;
|
||||
@@ -14010,6 +14010,8 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_rmp_fault);
|
||||
|
||||
static int __init kvm_x86_init(void)
|
||||
{
|
||||
kvm_init_xstate_sizes();
|
||||
|
||||
kvm_mmu_x86_module_init();
|
||||
mitigate_smt_rsb &= boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible();
|
||||
return 0;
|
||||
|
||||
+10
-6
@@ -275,13 +275,15 @@ void blk_mq_sysfs_unregister_hctxs(struct request_queue *q)
|
||||
struct blk_mq_hw_ctx *hctx;
|
||||
unsigned long i;
|
||||
|
||||
lockdep_assert_held(&q->sysfs_dir_lock);
|
||||
|
||||
mutex_lock(&q->sysfs_dir_lock);
|
||||
if (!q->mq_sysfs_init_done)
|
||||
return;
|
||||
goto unlock;
|
||||
|
||||
queue_for_each_hw_ctx(q, hctx, i)
|
||||
blk_mq_unregister_hctx(hctx);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&q->sysfs_dir_lock);
|
||||
}
|
||||
|
||||
int blk_mq_sysfs_register_hctxs(struct request_queue *q)
|
||||
@@ -290,10 +292,9 @@ int blk_mq_sysfs_register_hctxs(struct request_queue *q)
|
||||
unsigned long i;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&q->sysfs_dir_lock);
|
||||
|
||||
mutex_lock(&q->sysfs_dir_lock);
|
||||
if (!q->mq_sysfs_init_done)
|
||||
return ret;
|
||||
goto unlock;
|
||||
|
||||
queue_for_each_hw_ctx(q, hctx, i) {
|
||||
ret = blk_mq_register_hctx(hctx);
|
||||
@@ -301,5 +302,8 @@ int blk_mq_sysfs_register_hctxs(struct request_queue *q)
|
||||
break;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&q->sysfs_dir_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+21
-19
@@ -4421,6 +4421,15 @@ struct gendisk *blk_mq_alloc_disk_for_queue(struct request_queue *q,
|
||||
}
|
||||
EXPORT_SYMBOL(blk_mq_alloc_disk_for_queue);
|
||||
|
||||
/*
|
||||
* Only hctx removed from cpuhp list can be reused
|
||||
*/
|
||||
static bool blk_mq_hctx_is_reusable(struct blk_mq_hw_ctx *hctx)
|
||||
{
|
||||
return hlist_unhashed(&hctx->cpuhp_online) &&
|
||||
hlist_unhashed(&hctx->cpuhp_dead);
|
||||
}
|
||||
|
||||
static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
|
||||
struct blk_mq_tag_set *set, struct request_queue *q,
|
||||
int hctx_idx, int node)
|
||||
@@ -4430,7 +4439,7 @@ static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
|
||||
/* reuse dead hctx first */
|
||||
spin_lock(&q->unused_hctx_lock);
|
||||
list_for_each_entry(tmp, &q->unused_hctx_list, hctx_list) {
|
||||
if (tmp->numa_node == node) {
|
||||
if (tmp->numa_node == node && blk_mq_hctx_is_reusable(tmp)) {
|
||||
hctx = tmp;
|
||||
break;
|
||||
}
|
||||
@@ -4462,8 +4471,7 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
|
||||
unsigned long i, j;
|
||||
|
||||
/* protect against switching io scheduler */
|
||||
lockdep_assert_held(&q->sysfs_lock);
|
||||
|
||||
mutex_lock(&q->sysfs_lock);
|
||||
for (i = 0; i < set->nr_hw_queues; i++) {
|
||||
int old_node;
|
||||
int node = blk_mq_get_hctx_node(set, i);
|
||||
@@ -4496,6 +4504,7 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
|
||||
|
||||
xa_for_each_start(&q->hctx_table, j, hctx, j)
|
||||
blk_mq_exit_hctx(q, set, hctx, j);
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
|
||||
/* unregister cpuhp callbacks for exited hctxs */
|
||||
blk_mq_remove_hw_queues_cpuhp(q);
|
||||
@@ -4527,14 +4536,10 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
|
||||
|
||||
xa_init(&q->hctx_table);
|
||||
|
||||
mutex_lock(&q->sysfs_lock);
|
||||
|
||||
blk_mq_realloc_hw_ctxs(set, q);
|
||||
if (!q->nr_hw_queues)
|
||||
goto err_hctxs;
|
||||
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
|
||||
INIT_WORK(&q->timeout_work, blk_mq_timeout_work);
|
||||
blk_queue_rq_timeout(q, set->timeout ? set->timeout : 30 * HZ);
|
||||
|
||||
@@ -4553,7 +4558,6 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
|
||||
return 0;
|
||||
|
||||
err_hctxs:
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
blk_mq_release(q);
|
||||
err_exit:
|
||||
q->mq_ops = NULL;
|
||||
@@ -4934,12 +4938,12 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
|
||||
return false;
|
||||
|
||||
/* q->elevator needs protection from ->sysfs_lock */
|
||||
lockdep_assert_held(&q->sysfs_lock);
|
||||
mutex_lock(&q->sysfs_lock);
|
||||
|
||||
/* the check has to be done with holding sysfs_lock */
|
||||
if (!q->elevator) {
|
||||
kfree(qe);
|
||||
goto out;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&qe->node);
|
||||
@@ -4949,7 +4953,9 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
|
||||
__elevator_get(qe->type);
|
||||
list_add(&qe->node, head);
|
||||
elevator_disable(q);
|
||||
out:
|
||||
unlock:
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4978,9 +4984,11 @@ static void blk_mq_elv_switch_back(struct list_head *head,
|
||||
list_del(&qe->node);
|
||||
kfree(qe);
|
||||
|
||||
mutex_lock(&q->sysfs_lock);
|
||||
elevator_switch(q, t);
|
||||
/* drop the reference acquired in blk_mq_elv_switch_none */
|
||||
elevator_put(t);
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
}
|
||||
|
||||
static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
|
||||
@@ -5000,11 +5008,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
|
||||
if (set->nr_maps == 1 && nr_hw_queues == set->nr_hw_queues)
|
||||
return;
|
||||
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list) {
|
||||
mutex_lock(&q->sysfs_dir_lock);
|
||||
mutex_lock(&q->sysfs_lock);
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list)
|
||||
blk_mq_freeze_queue(q);
|
||||
}
|
||||
/*
|
||||
* Switch IO scheduler to 'none', cleaning up the data associated
|
||||
* with the previous scheduler. We will switch back once we are done
|
||||
@@ -5060,11 +5065,8 @@ switch_back:
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list)
|
||||
blk_mq_elv_switch_back(&head, q);
|
||||
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list) {
|
||||
list_for_each_entry(q, &set->tag_list, tag_set_list)
|
||||
blk_mq_unfreeze_queue(q);
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
mutex_unlock(&q->sysfs_dir_lock);
|
||||
}
|
||||
|
||||
/* Free the excess tags when nr_hw_queues shrink. */
|
||||
for (i = set->nr_hw_queues; i < prev_nr_hw_queues; i++)
|
||||
|
||||
+2
-2
@@ -690,11 +690,11 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||
return res;
|
||||
}
|
||||
|
||||
mutex_lock(&q->sysfs_lock);
|
||||
blk_mq_freeze_queue(q);
|
||||
mutex_lock(&q->sysfs_lock);
|
||||
res = entry->store(disk, page, length);
|
||||
blk_mq_unfreeze_queue(q);
|
||||
mutex_unlock(&q->sysfs_lock);
|
||||
blk_mq_unfreeze_queue(q);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -406,7 +406,7 @@ static void ivpu_bo_print_info(struct ivpu_bo *bo, struct drm_printer *p)
|
||||
mutex_lock(&bo->lock);
|
||||
|
||||
drm_printf(p, "%-9p %-3u 0x%-12llx %-10lu 0x%-8x %-4u",
|
||||
bo, bo->ctx->id, bo->vpu_addr, bo->base.base.size,
|
||||
bo, bo->ctx ? bo->ctx->id : 0, bo->vpu_addr, bo->base.base.size,
|
||||
bo->flags, kref_read(&bo->base.base.refcount));
|
||||
|
||||
if (bo->base.pages)
|
||||
|
||||
@@ -364,6 +364,7 @@ void ivpu_pm_init(struct ivpu_device *vdev)
|
||||
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, delay);
|
||||
pm_runtime_set_active(dev);
|
||||
|
||||
ivpu_dbg(vdev, PM, "Autosuspend delay = %d\n", delay);
|
||||
}
|
||||
@@ -378,7 +379,6 @@ void ivpu_pm_enable(struct ivpu_device *vdev)
|
||||
{
|
||||
struct device *dev = vdev->drm.dev;
|
||||
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_allow(dev);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
|
||||
@@ -524,6 +524,12 @@ static ssize_t backing_dev_store(struct device *dev,
|
||||
}
|
||||
|
||||
nr_pages = i_size_read(inode) >> PAGE_SHIFT;
|
||||
/* Refuse to use zero sized device (also prevents self reference) */
|
||||
if (!nr_pages) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bitmap_sz = BITS_TO_LONGS(nr_pages) * sizeof(long);
|
||||
bitmap = kvzalloc(bitmap_sz, GFP_KERNEL);
|
||||
if (!bitmap) {
|
||||
@@ -1319,12 +1325,16 @@ static void zram_meta_free(struct zram *zram, u64 disksize)
|
||||
size_t num_pages = disksize >> PAGE_SHIFT;
|
||||
size_t index;
|
||||
|
||||
if (!zram->table)
|
||||
return;
|
||||
|
||||
/* Free all pages that are still in this zram device */
|
||||
for (index = 0; index < num_pages; index++)
|
||||
zram_free_page(zram, index);
|
||||
|
||||
zs_destroy_pool(zram->mem_pool);
|
||||
vfree(zram->table);
|
||||
zram->table = NULL;
|
||||
}
|
||||
|
||||
static bool zram_meta_alloc(struct zram *zram, u64 disksize)
|
||||
@@ -2165,11 +2175,6 @@ static void zram_reset_device(struct zram *zram)
|
||||
|
||||
zram->limit_pages = 0;
|
||||
|
||||
if (!init_done(zram)) {
|
||||
up_write(&zram->init_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
set_capacity_and_notify(zram->disk, 0);
|
||||
part_stat_set_all(zram->disk->part0, 0);
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
#include <asm/mshyperv.h>
|
||||
|
||||
static struct clock_event_device __percpu *hv_clock_event;
|
||||
static u64 hv_sched_clock_offset __ro_after_init;
|
||||
/* Note: offset can hold negative values after hibernation. */
|
||||
static u64 hv_sched_clock_offset __read_mostly;
|
||||
|
||||
/*
|
||||
* If false, we're using the old mechanism for stimer0 interrupts
|
||||
@@ -470,6 +471,17 @@ static void resume_hv_clock_tsc(struct clocksource *arg)
|
||||
hv_set_msr(HV_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called during resume from hibernation, from overridden
|
||||
* x86_platform.restore_sched_clock_state routine. This is to adjust offsets
|
||||
* used to calculate time for hv tsc page based sched_clock, to account for
|
||||
* time spent before hibernation.
|
||||
*/
|
||||
void hv_adj_sched_clock_offset(u64 offset)
|
||||
{
|
||||
hv_sched_clock_offset -= offset;
|
||||
}
|
||||
|
||||
#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK
|
||||
static int hv_cs_enable(struct clocksource *cs)
|
||||
{
|
||||
|
||||
@@ -1295,6 +1295,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
|
||||
struct cxl_region_params *p = &cxlr->params;
|
||||
struct cxl_decoder *cxld = cxl_rr->decoder;
|
||||
struct cxl_switch_decoder *cxlsd;
|
||||
struct cxl_port *iter = port;
|
||||
u16 eig, peig;
|
||||
u8 eiw, peiw;
|
||||
|
||||
@@ -1311,16 +1312,26 @@ static int cxl_port_setup_targets(struct cxl_port *port,
|
||||
|
||||
cxlsd = to_cxl_switch_decoder(&cxld->dev);
|
||||
if (cxl_rr->nr_targets_set) {
|
||||
int i, distance;
|
||||
int i, distance = 1;
|
||||
struct cxl_region_ref *cxl_rr_iter;
|
||||
|
||||
/*
|
||||
* Passthrough decoders impose no distance requirements between
|
||||
* peers
|
||||
* The "distance" between peer downstream ports represents which
|
||||
* endpoint positions in the region interleave a given port can
|
||||
* host.
|
||||
*
|
||||
* For example, at the root of a hierarchy the distance is
|
||||
* always 1 as every index targets a different host-bridge. At
|
||||
* each subsequent switch level those ports map every Nth region
|
||||
* position where N is the width of the switch == distance.
|
||||
*/
|
||||
if (cxl_rr->nr_targets == 1)
|
||||
distance = 0;
|
||||
else
|
||||
distance = p->nr_targets / cxl_rr->nr_targets;
|
||||
do {
|
||||
cxl_rr_iter = cxl_rr_load(iter, cxlr);
|
||||
distance *= cxl_rr_iter->nr_targets;
|
||||
iter = to_cxl_port(iter->dev.parent);
|
||||
} while (!is_cxl_root(iter));
|
||||
distance *= cxlrd->cxlsd.cxld.interleave_ways;
|
||||
|
||||
for (i = 0; i < cxl_rr->nr_targets_set; i++)
|
||||
if (ep->dport == cxlsd->target[i]) {
|
||||
rc = check_last_peer(cxled, ep, cxl_rr,
|
||||
|
||||
+1
-2
@@ -942,8 +942,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = cxl_pci_ras_unmask(pdev);
|
||||
if (rc)
|
||||
if (cxl_pci_ras_unmask(pdev))
|
||||
dev_dbg(&pdev->dev, "No RAS reporting unmasked\n");
|
||||
|
||||
pci_save_state(pdev);
|
||||
|
||||
+103
-77
@@ -256,15 +256,12 @@ static const struct dma_buf_ops udmabuf_ops = {
|
||||
};
|
||||
|
||||
#define SEALS_WANTED (F_SEAL_SHRINK)
|
||||
#define SEALS_DENIED (F_SEAL_WRITE)
|
||||
#define SEALS_DENIED (F_SEAL_WRITE|F_SEAL_FUTURE_WRITE)
|
||||
|
||||
static int check_memfd_seals(struct file *memfd)
|
||||
{
|
||||
int seals;
|
||||
|
||||
if (!memfd)
|
||||
return -EBADFD;
|
||||
|
||||
if (!shmem_file(memfd) && !is_file_hugepages(memfd))
|
||||
return -EBADFD;
|
||||
|
||||
@@ -279,12 +276,10 @@ static int check_memfd_seals(struct file *memfd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int export_udmabuf(struct udmabuf *ubuf,
|
||||
struct miscdevice *device,
|
||||
u32 flags)
|
||||
static struct dma_buf *export_udmabuf(struct udmabuf *ubuf,
|
||||
struct miscdevice *device)
|
||||
{
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
struct dma_buf *buf;
|
||||
|
||||
ubuf->device = device;
|
||||
exp_info.ops = &udmabuf_ops;
|
||||
@@ -292,24 +287,72 @@ static int export_udmabuf(struct udmabuf *ubuf,
|
||||
exp_info.priv = ubuf;
|
||||
exp_info.flags = O_RDWR;
|
||||
|
||||
buf = dma_buf_export(&exp_info);
|
||||
if (IS_ERR(buf))
|
||||
return PTR_ERR(buf);
|
||||
return dma_buf_export(&exp_info);
|
||||
}
|
||||
|
||||
return dma_buf_fd(buf, flags);
|
||||
static long udmabuf_pin_folios(struct udmabuf *ubuf, struct file *memfd,
|
||||
loff_t start, loff_t size)
|
||||
{
|
||||
pgoff_t pgoff, pgcnt, upgcnt = ubuf->pagecount;
|
||||
struct folio **folios = NULL;
|
||||
u32 cur_folio, cur_pgcnt;
|
||||
long nr_folios;
|
||||
long ret = 0;
|
||||
loff_t end;
|
||||
|
||||
pgcnt = size >> PAGE_SHIFT;
|
||||
folios = kvmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL);
|
||||
if (!folios)
|
||||
return -ENOMEM;
|
||||
|
||||
end = start + (pgcnt << PAGE_SHIFT) - 1;
|
||||
nr_folios = memfd_pin_folios(memfd, start, end, folios, pgcnt, &pgoff);
|
||||
if (nr_folios <= 0) {
|
||||
ret = nr_folios ? nr_folios : -EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
cur_pgcnt = 0;
|
||||
for (cur_folio = 0; cur_folio < nr_folios; ++cur_folio) {
|
||||
pgoff_t subpgoff = pgoff;
|
||||
size_t fsize = folio_size(folios[cur_folio]);
|
||||
|
||||
ret = add_to_unpin_list(&ubuf->unpin_list, folios[cur_folio]);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
|
||||
for (; subpgoff < fsize; subpgoff += PAGE_SIZE) {
|
||||
ubuf->folios[upgcnt] = folios[cur_folio];
|
||||
ubuf->offsets[upgcnt] = subpgoff;
|
||||
++upgcnt;
|
||||
|
||||
if (++cur_pgcnt >= pgcnt)
|
||||
goto end;
|
||||
}
|
||||
|
||||
/**
|
||||
* In a given range, only the first subpage of the first folio
|
||||
* has an offset, that is returned by memfd_pin_folios().
|
||||
* The first subpages of other folios (in the range) have an
|
||||
* offset of 0.
|
||||
*/
|
||||
pgoff = 0;
|
||||
}
|
||||
end:
|
||||
ubuf->pagecount = upgcnt;
|
||||
kvfree(folios);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long udmabuf_create(struct miscdevice *device,
|
||||
struct udmabuf_create_list *head,
|
||||
struct udmabuf_create_item *list)
|
||||
{
|
||||
pgoff_t pgoff, pgcnt, pglimit, pgbuf = 0;
|
||||
long nr_folios, ret = -EINVAL;
|
||||
struct file *memfd = NULL;
|
||||
struct folio **folios;
|
||||
pgoff_t pgcnt = 0, pglimit;
|
||||
struct udmabuf *ubuf;
|
||||
u32 i, j, k, flags;
|
||||
loff_t end;
|
||||
struct dma_buf *dmabuf;
|
||||
long ret = -EINVAL;
|
||||
u32 i, flags;
|
||||
|
||||
ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
|
||||
if (!ubuf)
|
||||
@@ -318,93 +361,76 @@ static long udmabuf_create(struct miscdevice *device,
|
||||
INIT_LIST_HEAD(&ubuf->unpin_list);
|
||||
pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT;
|
||||
for (i = 0; i < head->count; i++) {
|
||||
if (!IS_ALIGNED(list[i].offset, PAGE_SIZE))
|
||||
if (!PAGE_ALIGNED(list[i].offset))
|
||||
goto err;
|
||||
if (!IS_ALIGNED(list[i].size, PAGE_SIZE))
|
||||
if (!PAGE_ALIGNED(list[i].size))
|
||||
goto err;
|
||||
ubuf->pagecount += list[i].size >> PAGE_SHIFT;
|
||||
if (ubuf->pagecount > pglimit)
|
||||
|
||||
pgcnt += list[i].size >> PAGE_SHIFT;
|
||||
if (pgcnt > pglimit)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ubuf->pagecount)
|
||||
if (!pgcnt)
|
||||
goto err;
|
||||
|
||||
ubuf->folios = kvmalloc_array(ubuf->pagecount, sizeof(*ubuf->folios),
|
||||
GFP_KERNEL);
|
||||
ubuf->folios = kvmalloc_array(pgcnt, sizeof(*ubuf->folios), GFP_KERNEL);
|
||||
if (!ubuf->folios) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
ubuf->offsets = kvcalloc(ubuf->pagecount, sizeof(*ubuf->offsets),
|
||||
GFP_KERNEL);
|
||||
|
||||
ubuf->offsets = kvcalloc(pgcnt, sizeof(*ubuf->offsets), GFP_KERNEL);
|
||||
if (!ubuf->offsets) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pgbuf = 0;
|
||||
for (i = 0; i < head->count; i++) {
|
||||
memfd = fget(list[i].memfd);
|
||||
struct file *memfd = fget(list[i].memfd);
|
||||
|
||||
if (!memfd) {
|
||||
ret = -EBADFD;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the inode lock to protect against concurrent
|
||||
* memfd_add_seals(), which takes this lock in write mode.
|
||||
*/
|
||||
inode_lock_shared(file_inode(memfd));
|
||||
ret = check_memfd_seals(memfd);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
pgcnt = list[i].size >> PAGE_SHIFT;
|
||||
folios = kvmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL);
|
||||
if (!folios) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
end = list[i].offset + (pgcnt << PAGE_SHIFT) - 1;
|
||||
ret = memfd_pin_folios(memfd, list[i].offset, end,
|
||||
folios, pgcnt, &pgoff);
|
||||
if (ret <= 0) {
|
||||
kvfree(folios);
|
||||
if (!ret)
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
nr_folios = ret;
|
||||
pgoff >>= PAGE_SHIFT;
|
||||
for (j = 0, k = 0; j < pgcnt; j++) {
|
||||
ubuf->folios[pgbuf] = folios[k];
|
||||
ubuf->offsets[pgbuf] = pgoff << PAGE_SHIFT;
|
||||
|
||||
if (j == 0 || ubuf->folios[pgbuf-1] != folios[k]) {
|
||||
ret = add_to_unpin_list(&ubuf->unpin_list,
|
||||
folios[k]);
|
||||
if (ret < 0) {
|
||||
kfree(folios);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
pgbuf++;
|
||||
if (++pgoff == folio_nr_pages(folios[k])) {
|
||||
pgoff = 0;
|
||||
if (++k == nr_folios)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
kvfree(folios);
|
||||
ret = udmabuf_pin_folios(ubuf, memfd, list[i].offset,
|
||||
list[i].size);
|
||||
out_unlock:
|
||||
inode_unlock_shared(file_inode(memfd));
|
||||
fput(memfd);
|
||||
memfd = NULL;
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
flags = head->flags & UDMABUF_FLAGS_CLOEXEC ? O_CLOEXEC : 0;
|
||||
ret = export_udmabuf(ubuf, device, flags);
|
||||
if (ret < 0)
|
||||
dmabuf = export_udmabuf(ubuf, device);
|
||||
if (IS_ERR(dmabuf)) {
|
||||
ret = PTR_ERR(dmabuf);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Ownership of ubuf is held by the dmabuf from here.
|
||||
* If the following dma_buf_fd() fails, dma_buf_put() cleans up both the
|
||||
* dmabuf and the ubuf (through udmabuf_ops.release).
|
||||
*/
|
||||
|
||||
ret = dma_buf_fd(dmabuf, flags);
|
||||
if (ret < 0)
|
||||
dma_buf_put(dmabuf);
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (memfd)
|
||||
fput(memfd);
|
||||
unpin_all_folios(&ubuf->unpin_list);
|
||||
kvfree(ubuf->offsets);
|
||||
kvfree(ubuf->folios);
|
||||
|
||||
+10
-22
@@ -3362,36 +3362,24 @@ static bool dct_ecc_enabled(struct amd64_pvt *pvt)
|
||||
|
||||
static bool umc_ecc_enabled(struct amd64_pvt *pvt)
|
||||
{
|
||||
u8 umc_en_mask = 0, ecc_en_mask = 0;
|
||||
u16 nid = pvt->mc_node_id;
|
||||
struct amd64_umc *umc;
|
||||
u8 ecc_en = 0, i;
|
||||
bool ecc_en = false;
|
||||
int i;
|
||||
|
||||
/* Check whether at least one UMC is enabled: */
|
||||
for_each_umc(i) {
|
||||
umc = &pvt->umc[i];
|
||||
|
||||
/* Only check enabled UMCs. */
|
||||
if (!(umc->sdp_ctrl & UMC_SDP_INIT))
|
||||
continue;
|
||||
|
||||
umc_en_mask |= BIT(i);
|
||||
|
||||
if (umc->umc_cap_hi & UMC_ECC_ENABLED)
|
||||
ecc_en_mask |= BIT(i);
|
||||
if (umc->sdp_ctrl & UMC_SDP_INIT &&
|
||||
umc->umc_cap_hi & UMC_ECC_ENABLED) {
|
||||
ecc_en = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether at least one UMC is enabled: */
|
||||
if (umc_en_mask)
|
||||
ecc_en = umc_en_mask == ecc_en_mask;
|
||||
else
|
||||
edac_dbg(0, "Node %d: No enabled UMCs.\n", nid);
|
||||
edac_dbg(3, "Node %d: DRAM ECC %s.\n", pvt->mc_node_id, (ecc_en ? "enabled" : "disabled"));
|
||||
|
||||
edac_dbg(3, "Node %d: DRAM ECC %s.\n", nid, (ecc_en ? "enabled" : "disabled"));
|
||||
|
||||
if (!ecc_en)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
return ecc_en;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
||||
@@ -187,13 +187,18 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev)
|
||||
return valid;
|
||||
}
|
||||
|
||||
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
|
||||
const struct ffa_ops *ops)
|
||||
struct ffa_device *
|
||||
ffa_device_register(const struct ffa_partition_info *part_info,
|
||||
const struct ffa_ops *ops)
|
||||
{
|
||||
int id, ret;
|
||||
uuid_t uuid;
|
||||
struct device *dev;
|
||||
struct ffa_device *ffa_dev;
|
||||
|
||||
if (!part_info)
|
||||
return NULL;
|
||||
|
||||
id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL);
|
||||
if (id < 0)
|
||||
return NULL;
|
||||
@@ -210,9 +215,11 @@ struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
|
||||
dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
|
||||
|
||||
ffa_dev->id = id;
|
||||
ffa_dev->vm_id = vm_id;
|
||||
ffa_dev->vm_id = part_info->id;
|
||||
ffa_dev->properties = part_info->properties;
|
||||
ffa_dev->ops = ops;
|
||||
uuid_copy(&ffa_dev->uuid, uuid);
|
||||
import_uuid(&uuid, (u8 *)part_info->uuid);
|
||||
uuid_copy(&ffa_dev->uuid, &uuid);
|
||||
|
||||
ret = device_register(&ffa_dev->dev);
|
||||
if (ret) {
|
||||
|
||||
@@ -1387,7 +1387,6 @@ static struct notifier_block ffa_bus_nb = {
|
||||
static int ffa_setup_partitions(void)
|
||||
{
|
||||
int count, idx, ret;
|
||||
uuid_t uuid;
|
||||
struct ffa_device *ffa_dev;
|
||||
struct ffa_dev_part_info *info;
|
||||
struct ffa_partition_info *pbuf, *tpbuf;
|
||||
@@ -1406,23 +1405,19 @@ static int ffa_setup_partitions(void)
|
||||
|
||||
xa_init(&drv_info->partition_info);
|
||||
for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
|
||||
import_uuid(&uuid, (u8 *)tpbuf->uuid);
|
||||
|
||||
/* Note that if the UUID will be uuid_null, that will require
|
||||
* ffa_bus_notifier() to find the UUID of this partition id
|
||||
* with help of ffa_device_match_uuid(). FF-A v1.1 and above
|
||||
* provides UUID here for each partition as part of the
|
||||
* discovery API and the same is passed.
|
||||
*/
|
||||
ffa_dev = ffa_device_register(&uuid, tpbuf->id, &ffa_drv_ops);
|
||||
ffa_dev = ffa_device_register(tpbuf, &ffa_drv_ops);
|
||||
if (!ffa_dev) {
|
||||
pr_err("%s: failed to register partition ID 0x%x\n",
|
||||
__func__, tpbuf->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ffa_dev->properties = tpbuf->properties;
|
||||
|
||||
if (drv_info->version > FFA_VERSION_1_0 &&
|
||||
!(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC))
|
||||
ffa_mode_32bit_set(ffa_dev);
|
||||
|
||||
@@ -15,6 +15,7 @@ config IMX_SCMI_BBM_EXT
|
||||
config IMX_SCMI_MISC_EXT
|
||||
tristate "i.MX SCMI MISC EXTENSION"
|
||||
depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
|
||||
depends on IMX_SCMI_MISC_DRV
|
||||
default y if ARCH_MXC
|
||||
help
|
||||
This enables i.MX System MISC control logic such as gpio expander
|
||||
|
||||
@@ -25,7 +25,6 @@ config IMX_SCU
|
||||
|
||||
config IMX_SCMI_MISC_DRV
|
||||
tristate "IMX SCMI MISC Protocol driver"
|
||||
depends on IMX_SCMI_MISC_EXT || COMPILE_TEST
|
||||
default y if ARCH_MXC
|
||||
help
|
||||
The System Controller Management Interface firmware (SCMI FW) is
|
||||
|
||||
@@ -345,11 +345,10 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
||||
coredump->skip_vram_check = skip_vram_check;
|
||||
coredump->reset_vram_lost = vram_lost;
|
||||
|
||||
if (job && job->vm) {
|
||||
struct amdgpu_vm *vm = job->vm;
|
||||
if (job && job->pasid) {
|
||||
struct amdgpu_task_info *ti;
|
||||
|
||||
ti = amdgpu_vm_get_task_info_vm(vm);
|
||||
ti = amdgpu_vm_get_task_info_pasid(adev, job->pasid);
|
||||
if (ti) {
|
||||
coredump->reset_task_info = *ti;
|
||||
amdgpu_vm_put_task_info(ti);
|
||||
|
||||
@@ -253,7 +253,6 @@ void amdgpu_job_set_resources(struct amdgpu_job *job, struct amdgpu_bo *gds,
|
||||
|
||||
void amdgpu_job_free_resources(struct amdgpu_job *job)
|
||||
{
|
||||
struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched);
|
||||
struct dma_fence *f;
|
||||
unsigned i;
|
||||
|
||||
@@ -266,7 +265,7 @@ void amdgpu_job_free_resources(struct amdgpu_job *job)
|
||||
f = NULL;
|
||||
|
||||
for (i = 0; i < job->num_ibs; ++i)
|
||||
amdgpu_ib_free(ring->adev, &job->ibs[i], f);
|
||||
amdgpu_ib_free(NULL, &job->ibs[i], f);
|
||||
}
|
||||
|
||||
static void amdgpu_job_free_cb(struct drm_sched_job *s_job)
|
||||
|
||||
@@ -1260,10 +1260,9 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
|
||||
* next command submission.
|
||||
*/
|
||||
if (amdgpu_vm_is_bo_always_valid(vm, bo)) {
|
||||
uint32_t mem_type = bo->tbo.resource->mem_type;
|
||||
|
||||
if (!(bo->preferred_domains &
|
||||
amdgpu_mem_type_to_domain(mem_type)))
|
||||
if (bo->tbo.resource &&
|
||||
!(bo->preferred_domains &
|
||||
amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type)))
|
||||
amdgpu_vm_bo_evicted(&bo_va->base);
|
||||
else
|
||||
amdgpu_vm_bo_idle(&bo_va->base);
|
||||
|
||||
@@ -4105,7 +4105,7 @@ static int gfx_v12_0_set_clockgating_state(void *handle,
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
switch (adev->ip_versions[GC_HWIP][0]) {
|
||||
switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
gfx_v12_0_update_gfx_clock_gating(adev,
|
||||
|
||||
@@ -108,7 +108,7 @@ mmhub_v4_1_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
|
||||
dev_err(adev->dev,
|
||||
"MMVM_L2_PROTECTION_FAULT_STATUS_LO32:0x%08X\n",
|
||||
status);
|
||||
switch (adev->ip_versions[MMHUB_HWIP][0]) {
|
||||
switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
|
||||
case IP_VERSION(4, 1, 0):
|
||||
mmhub_cid = mmhub_client_ids_v4_1_0[cid][rw];
|
||||
break;
|
||||
|
||||
@@ -271,8 +271,19 @@ const struct nbio_hdp_flush_reg nbio_v7_0_hdp_flush_reg = {
|
||||
.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__SDMA1_MASK,
|
||||
};
|
||||
|
||||
#define regRCC_DEV0_EPF6_STRAP4 0xd304
|
||||
#define regRCC_DEV0_EPF6_STRAP4_BASE_IDX 5
|
||||
|
||||
static void nbio_v7_0_init_registers(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
|
||||
case IP_VERSION(2, 5, 0):
|
||||
data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF6_STRAP4) & ~BIT(23);
|
||||
WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF6_STRAP4, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define MMIO_REG_HOLE_OFFSET (0x80000 - PAGE_SIZE)
|
||||
|
||||
@@ -275,7 +275,7 @@ static void nbio_v7_11_init_registers(struct amdgpu_device *adev)
|
||||
if (def != data)
|
||||
WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, data);
|
||||
|
||||
switch (adev->ip_versions[NBIO_HWIP][0]) {
|
||||
switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
|
||||
case IP_VERSION(7, 11, 0):
|
||||
case IP_VERSION(7, 11, 1):
|
||||
case IP_VERSION(7, 11, 2):
|
||||
|
||||
@@ -247,7 +247,7 @@ static void nbio_v7_7_init_registers(struct amdgpu_device *adev)
|
||||
if (def != data)
|
||||
WREG32_SOC15(NBIO, 0, regBIF0_PCIE_MST_CTRL_3, data);
|
||||
|
||||
switch (adev->ip_versions[NBIO_HWIP][0]) {
|
||||
switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
|
||||
case IP_VERSION(7, 7, 0):
|
||||
data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4) & ~BIT(23);
|
||||
WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4, data);
|
||||
|
||||
@@ -2108,7 +2108,7 @@ static int smu_v14_0_2_enable_gfx_features(struct smu_context *smu)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
|
||||
if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(14, 0, 2))
|
||||
if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 2))
|
||||
return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnableAllSmuFeatures,
|
||||
FEATURE_PWR_GFX, NULL);
|
||||
else
|
||||
|
||||
@@ -1896,8 +1896,8 @@ static void destroy_mgr(struct drm_dp_tunnel_mgr *mgr)
|
||||
*
|
||||
* Creates a DP tunnel manager for @dev.
|
||||
*
|
||||
* Returns a pointer to the tunnel manager if created successfully or NULL in
|
||||
* case of an error.
|
||||
* Returns a pointer to the tunnel manager if created successfully or error
|
||||
* pointer in case of failure.
|
||||
*/
|
||||
struct drm_dp_tunnel_mgr *
|
||||
drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)
|
||||
@@ -1907,7 +1907,7 @@ drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)
|
||||
|
||||
mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
|
||||
if (!mgr)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
mgr->dev = dev;
|
||||
init_waitqueue_head(&mgr->bw_req_queue);
|
||||
@@ -1916,7 +1916,7 @@ drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)
|
||||
if (!mgr->groups) {
|
||||
kfree(mgr);
|
||||
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
|
||||
@@ -1927,7 +1927,7 @@ drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)
|
||||
if (!init_group(mgr, &mgr->groups[i])) {
|
||||
destroy_mgr(mgr);
|
||||
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
mgr->group_count++;
|
||||
|
||||
@@ -1287,14 +1287,11 @@ EXPORT_SYMBOL(drm_mode_set_name);
|
||||
*/
|
||||
int drm_mode_vrefresh(const struct drm_display_mode *mode)
|
||||
{
|
||||
unsigned int num, den;
|
||||
unsigned int num = 1, den = 1;
|
||||
|
||||
if (mode->htotal == 0 || mode->vtotal == 0)
|
||||
return 0;
|
||||
|
||||
num = mode->clock;
|
||||
den = mode->htotal * mode->vtotal;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
num *= 2;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
@@ -1302,6 +1299,12 @@ int drm_mode_vrefresh(const struct drm_display_mode *mode)
|
||||
if (mode->vscan > 1)
|
||||
den *= mode->vscan;
|
||||
|
||||
if (check_mul_overflow(mode->clock, num, &num))
|
||||
return 0;
|
||||
|
||||
if (check_mul_overflow(mode->htotal * mode->vtotal, den, &den))
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_vrefresh);
|
||||
|
||||
@@ -343,6 +343,11 @@ struct intel_engine_guc_stats {
|
||||
* @start_gt_clk: GT clock time of last idle to active transition.
|
||||
*/
|
||||
u64 start_gt_clk;
|
||||
|
||||
/**
|
||||
* @total: The last value of total returned
|
||||
*/
|
||||
u64 total;
|
||||
};
|
||||
|
||||
union intel_engine_tlb_inv_reg {
|
||||
|
||||
@@ -1243,6 +1243,21 @@ static void __get_engine_usage_record(struct intel_engine_cs *engine,
|
||||
} while (++i < 6);
|
||||
}
|
||||
|
||||
static void __set_engine_usage_record(struct intel_engine_cs *engine,
|
||||
u32 last_in, u32 id, u32 total)
|
||||
{
|
||||
struct iosys_map rec_map = intel_guc_engine_usage_record_map(engine);
|
||||
|
||||
#define record_write(map_, field_, val_) \
|
||||
iosys_map_wr_field(map_, 0, struct guc_engine_usage_record, field_, val_)
|
||||
|
||||
record_write(&rec_map, last_switch_in_stamp, last_in);
|
||||
record_write(&rec_map, current_context_index, id);
|
||||
record_write(&rec_map, total_runtime, total);
|
||||
|
||||
#undef record_write
|
||||
}
|
||||
|
||||
static void guc_update_engine_gt_clks(struct intel_engine_cs *engine)
|
||||
{
|
||||
struct intel_engine_guc_stats *stats = &engine->stats.guc;
|
||||
@@ -1363,9 +1378,12 @@ static ktime_t guc_engine_busyness(struct intel_engine_cs *engine, ktime_t *now)
|
||||
total += intel_gt_clock_interval_to_ns(gt, clk);
|
||||
}
|
||||
|
||||
if (total > stats->total)
|
||||
stats->total = total;
|
||||
|
||||
spin_unlock_irqrestore(&guc->timestamp.lock, flags);
|
||||
|
||||
return ns_to_ktime(total);
|
||||
return ns_to_ktime(stats->total);
|
||||
}
|
||||
|
||||
static void guc_enable_busyness_worker(struct intel_guc *guc)
|
||||
@@ -1431,8 +1449,21 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc)
|
||||
|
||||
guc_update_pm_timestamp(guc, &unused);
|
||||
for_each_engine(engine, gt, id) {
|
||||
struct intel_engine_guc_stats *stats = &engine->stats.guc;
|
||||
|
||||
guc_update_engine_gt_clks(engine);
|
||||
engine->stats.guc.prev_total = 0;
|
||||
|
||||
/*
|
||||
* If resetting a running context, accumulate the active
|
||||
* time as well since there will be no context switch.
|
||||
*/
|
||||
if (stats->running) {
|
||||
u64 clk = guc->timestamp.gt_stamp - stats->start_gt_clk;
|
||||
|
||||
stats->total_gt_clks += clk;
|
||||
}
|
||||
stats->prev_total = 0;
|
||||
stats->running = 0;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&guc->timestamp.lock, flags);
|
||||
@@ -1543,6 +1574,9 @@ err_trylock:
|
||||
|
||||
static int guc_action_enable_usage_stats(struct intel_guc *guc)
|
||||
{
|
||||
struct intel_gt *gt = guc_to_gt(guc);
|
||||
struct intel_engine_cs *engine;
|
||||
enum intel_engine_id id;
|
||||
u32 offset = intel_guc_engine_usage_offset(guc);
|
||||
u32 action[] = {
|
||||
INTEL_GUC_ACTION_SET_ENG_UTIL_BUFF,
|
||||
@@ -1550,6 +1584,9 @@ static int guc_action_enable_usage_stats(struct intel_guc *guc)
|
||||
0,
|
||||
};
|
||||
|
||||
for_each_engine(engine, gt, id)
|
||||
__set_engine_usage_record(engine, 0, 0xffffffff, 0);
|
||||
|
||||
return intel_guc_send(guc, action, ARRAY_SIZE(action));
|
||||
}
|
||||
|
||||
|
||||
@@ -565,6 +565,8 @@ static int hx83102_get_modes(struct drm_panel *panel,
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, m);
|
||||
if (!mode)
|
||||
return -ENOMEM;
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
@@ -481,9 +481,9 @@ static int nt35950_probe(struct mipi_dsi_device *dsi)
|
||||
return dev_err_probe(dev, -EPROBE_DEFER, "Cannot get secondary DSI host\n");
|
||||
|
||||
nt->dsi[1] = mipi_dsi_device_register_full(dsi_r_host, info);
|
||||
if (!nt->dsi[1]) {
|
||||
if (IS_ERR(nt->dsi[1])) {
|
||||
dev_err(dev, "Cannot get secondary DSI node\n");
|
||||
return -ENODEV;
|
||||
return PTR_ERR(nt->dsi[1]);
|
||||
}
|
||||
num_dsis++;
|
||||
}
|
||||
|
||||
@@ -1177,6 +1177,7 @@ static int st7701_probe(struct device *dev, int connector_type)
|
||||
return dev_err_probe(dev, ret, "Failed to get orientation\n");
|
||||
|
||||
drm_panel_init(&st7701->panel, dev, &st7701_funcs, connector_type);
|
||||
st7701->panel.prepare_prev_first = true;
|
||||
|
||||
/**
|
||||
* Once sleep out has been issued, ST7701 IC required to wait 120ms
|
||||
|
||||
@@ -325,7 +325,7 @@ static void r63353_panel_shutdown(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
r63353_panel_unprepare(&rpanel->base);
|
||||
drm_panel_unprepare(&rpanel->base);
|
||||
}
|
||||
|
||||
static const struct r63353_desc sharp_ls068b3sx02_data = {
|
||||
|
||||
@@ -767,6 +767,12 @@ hv_kvp_init(struct hv_util_service *srv)
|
||||
*/
|
||||
kvp_transaction.state = HVUTIL_DEVICE_INIT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hv_kvp_init_transport(void)
|
||||
{
|
||||
hvt = hvutil_transport_init(kvp_devname, CN_KVP_IDX, CN_KVP_VAL,
|
||||
kvp_on_msg, kvp_on_reset);
|
||||
if (!hvt)
|
||||
|
||||
@@ -388,6 +388,12 @@ hv_vss_init(struct hv_util_service *srv)
|
||||
*/
|
||||
vss_transaction.state = HVUTIL_DEVICE_INIT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hv_vss_init_transport(void)
|
||||
{
|
||||
hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL,
|
||||
vss_on_msg, vss_on_reset);
|
||||
if (!hvt) {
|
||||
|
||||
@@ -141,6 +141,7 @@ static struct hv_util_service util_heartbeat = {
|
||||
static struct hv_util_service util_kvp = {
|
||||
.util_cb = hv_kvp_onchannelcallback,
|
||||
.util_init = hv_kvp_init,
|
||||
.util_init_transport = hv_kvp_init_transport,
|
||||
.util_pre_suspend = hv_kvp_pre_suspend,
|
||||
.util_pre_resume = hv_kvp_pre_resume,
|
||||
.util_deinit = hv_kvp_deinit,
|
||||
@@ -149,6 +150,7 @@ static struct hv_util_service util_kvp = {
|
||||
static struct hv_util_service util_vss = {
|
||||
.util_cb = hv_vss_onchannelcallback,
|
||||
.util_init = hv_vss_init,
|
||||
.util_init_transport = hv_vss_init_transport,
|
||||
.util_pre_suspend = hv_vss_pre_suspend,
|
||||
.util_pre_resume = hv_vss_pre_resume,
|
||||
.util_deinit = hv_vss_deinit,
|
||||
@@ -613,6 +615,13 @@ static int util_probe(struct hv_device *dev,
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (srv->util_init_transport) {
|
||||
ret = srv->util_init_transport();
|
||||
if (ret) {
|
||||
vmbus_close(dev->channel);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
@@ -370,12 +370,14 @@ void vmbus_on_event(unsigned long data);
|
||||
void vmbus_on_msg_dpc(unsigned long data);
|
||||
|
||||
int hv_kvp_init(struct hv_util_service *srv);
|
||||
int hv_kvp_init_transport(void);
|
||||
void hv_kvp_deinit(void);
|
||||
int hv_kvp_pre_suspend(void);
|
||||
int hv_kvp_pre_resume(void);
|
||||
void hv_kvp_onchannelcallback(void *context);
|
||||
|
||||
int hv_vss_init(struct hv_util_service *srv);
|
||||
int hv_vss_init_transport(void);
|
||||
void hv_vss_deinit(void);
|
||||
int hv_vss_pre_suspend(void);
|
||||
int hv_vss_pre_resume(void);
|
||||
|
||||
@@ -182,7 +182,7 @@ struct tmp51x_data {
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
// Set the shift based on the gain 8=4, 4=3, 2=2, 1=1
|
||||
// Set the shift based on the gain: 8 -> 1, 4 -> 2, 2 -> 3, 1 -> 4
|
||||
static inline u8 tmp51x_get_pga_shift(struct tmp51x_data *data)
|
||||
{
|
||||
return 5 - ffs(data->pga_gain);
|
||||
@@ -204,7 +204,9 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
|
||||
* 2's complement number shifted by one to four depending
|
||||
* on the pga gain setting. 1lsb = 10uV
|
||||
*/
|
||||
*val = sign_extend32(regval, 17 - tmp51x_get_pga_shift(data));
|
||||
*val = sign_extend32(regval,
|
||||
reg == TMP51X_SHUNT_CURRENT_RESULT ?
|
||||
16 - tmp51x_get_pga_shift(data) : 15);
|
||||
*val = DIV_ROUND_CLOSEST(*val * 10 * MILLI, data->shunt_uohms);
|
||||
break;
|
||||
case TMP51X_BUS_VOLTAGE_RESULT:
|
||||
@@ -220,7 +222,7 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
|
||||
break;
|
||||
case TMP51X_BUS_CURRENT_RESULT:
|
||||
// Current = (ShuntVoltage * CalibrationRegister) / 4096
|
||||
*val = sign_extend32(regval, 16) * data->curr_lsb_ua;
|
||||
*val = sign_extend32(regval, 15) * (long)data->curr_lsb_ua;
|
||||
*val = DIV_ROUND_CLOSEST(*val, MILLI);
|
||||
break;
|
||||
case TMP51X_LOCAL_TEMP_RESULT:
|
||||
@@ -232,7 +234,7 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
|
||||
case TMP51X_REMOTE_TEMP_LIMIT_2:
|
||||
case TMP513_REMOTE_TEMP_LIMIT_3:
|
||||
// 1lsb = 0.0625 degrees centigrade
|
||||
*val = sign_extend32(regval, 16) >> TMP51X_TEMP_SHIFT;
|
||||
*val = sign_extend32(regval, 15) >> TMP51X_TEMP_SHIFT;
|
||||
*val = DIV_ROUND_CLOSEST(*val * 625, 10);
|
||||
break;
|
||||
case TMP51X_N_FACTOR_AND_HYST_1:
|
||||
|
||||
@@ -95,7 +95,7 @@ enum {
|
||||
|
||||
static inline int wait_timeout(struct i2c_pnx_algo_data *data)
|
||||
{
|
||||
long timeout = data->timeout;
|
||||
long timeout = jiffies_to_msecs(data->timeout);
|
||||
while (timeout > 0 &&
|
||||
(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
|
||||
mdelay(1);
|
||||
@@ -106,7 +106,7 @@ static inline int wait_timeout(struct i2c_pnx_algo_data *data)
|
||||
|
||||
static inline int wait_reset(struct i2c_pnx_algo_data *data)
|
||||
{
|
||||
long timeout = data->timeout;
|
||||
long timeout = jiffies_to_msecs(data->timeout);
|
||||
while (timeout > 0 &&
|
||||
(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
|
||||
mdelay(1);
|
||||
|
||||
@@ -352,7 +352,7 @@ static int riic_init_hw(struct riic_dev *riic)
|
||||
if (brl <= (0x1F + 3))
|
||||
break;
|
||||
|
||||
total_ticks /= 2;
|
||||
total_ticks = DIV_ROUND_UP(total_ticks, 2);
|
||||
rate /= 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,22 @@ static bool cpus_have_group0 __ro_after_init;
|
||||
|
||||
static void __init gic_prio_init(void)
|
||||
{
|
||||
cpus_have_security_disabled = gic_dist_security_disabled();
|
||||
bool ds;
|
||||
|
||||
ds = gic_dist_security_disabled();
|
||||
if (!ds) {
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(gic_data.dist_base + GICD_CTLR);
|
||||
val |= GICD_CTLR_DS;
|
||||
writel_relaxed(val, gic_data.dist_base + GICD_CTLR);
|
||||
|
||||
ds = gic_dist_security_disabled();
|
||||
if (ds)
|
||||
pr_warn("Broken GIC integration, security disabled");
|
||||
}
|
||||
|
||||
cpus_have_security_disabled = ds;
|
||||
cpus_have_group0 = gic_has_group0();
|
||||
|
||||
/*
|
||||
|
||||
@@ -2924,6 +2924,7 @@ release_clk:
|
||||
msdc_gate_clock(host);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
release_mem:
|
||||
device_init_wakeup(&pdev->dev, false);
|
||||
if (host->dma.gpd)
|
||||
dma_free_coherent(&pdev->dev,
|
||||
2 * sizeof(struct mt_gpdma_desc),
|
||||
@@ -2957,6 +2958,7 @@ static void msdc_drv_remove(struct platform_device *pdev)
|
||||
host->dma.gpd, host->dma.gpd_addr);
|
||||
dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc),
|
||||
host->dma.bd, host->dma.bd_addr);
|
||||
device_init_wakeup(&pdev->dev, false);
|
||||
}
|
||||
|
||||
static void msdc_save_reg(struct msdc_host *host)
|
||||
|
||||
@@ -1525,7 +1525,6 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
|
||||
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
|
||||
SDHCI_QUIRK_SINGLE_POWER_WRITE |
|
||||
SDHCI_QUIRK_NO_HISPD_BIT |
|
||||
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
|
||||
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
|
||||
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
|
||||
SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER,
|
||||
|
||||
@@ -1220,20 +1220,32 @@ static void m_can_coalescing_update(struct m_can_classdev *cdev, u32 ir)
|
||||
static int m_can_interrupt_handler(struct m_can_classdev *cdev)
|
||||
{
|
||||
struct net_device *dev = cdev->net;
|
||||
u32 ir;
|
||||
u32 ir = 0, ir_read;
|
||||
int ret;
|
||||
|
||||
if (pm_runtime_suspended(cdev->dev))
|
||||
return IRQ_NONE;
|
||||
|
||||
ir = m_can_read(cdev, M_CAN_IR);
|
||||
/* The m_can controller signals its interrupt status as a level, but
|
||||
* depending in the integration the CPU may interpret the signal as
|
||||
* edge-triggered (for example with m_can_pci). For these
|
||||
* edge-triggered integrations, we must observe that IR is 0 at least
|
||||
* once to be sure that the next interrupt will generate an edge.
|
||||
*/
|
||||
while ((ir_read = m_can_read(cdev, M_CAN_IR)) != 0) {
|
||||
ir |= ir_read;
|
||||
|
||||
/* ACK all irqs */
|
||||
m_can_write(cdev, M_CAN_IR, ir);
|
||||
|
||||
if (!cdev->irq_edge_triggered)
|
||||
break;
|
||||
}
|
||||
|
||||
m_can_coalescing_update(cdev, ir);
|
||||
if (!ir)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* ACK all irqs */
|
||||
m_can_write(cdev, M_CAN_IR, ir);
|
||||
|
||||
if (cdev->ops->clear_interrupts)
|
||||
cdev->ops->clear_interrupts(cdev);
|
||||
|
||||
@@ -1695,6 +1707,14 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Write the INIT bit, in case no hardware reset has happened before
|
||||
* the probe (for example, it was observed that the Intel Elkhart Lake
|
||||
* SoCs do not properly reset the CAN controllers on reboot)
|
||||
*/
|
||||
err = m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!cdev->is_peripheral)
|
||||
netif_napi_add(dev, &cdev->napi, m_can_poll);
|
||||
|
||||
@@ -1746,11 +1766,7 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Forcing standby mode should be redundant, as the chip should be in
|
||||
* standby after a reset. Write the INIT bit anyways, should the chip
|
||||
* be configured by previous stage.
|
||||
*/
|
||||
return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void m_can_stop(struct net_device *dev)
|
||||
|
||||
@@ -99,6 +99,7 @@ struct m_can_classdev {
|
||||
int pm_clock_support;
|
||||
int pm_wake_source;
|
||||
int is_peripheral;
|
||||
bool irq_edge_triggered;
|
||||
|
||||
// Cached M_CAN_IE register content
|
||||
u32 active_interrupts;
|
||||
|
||||
@@ -127,6 +127,7 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
|
||||
mcan_class->pm_clock_support = 1;
|
||||
mcan_class->pm_wake_source = 0;
|
||||
mcan_class->can.clock.freq = id->driver_data;
|
||||
mcan_class->irq_edge_triggered = true;
|
||||
mcan_class->ops = &m_can_pci_ops;
|
||||
|
||||
pci_set_drvdata(pci, mcan_class);
|
||||
|
||||
@@ -171,6 +171,7 @@ static int platform_phy_connect(struct bgmac *bgmac)
|
||||
static int bgmac_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *phy_node;
|
||||
struct bgmac *bgmac;
|
||||
struct resource *regs;
|
||||
int ret;
|
||||
@@ -236,7 +237,9 @@ static int bgmac_probe(struct platform_device *pdev)
|
||||
bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
|
||||
bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
|
||||
bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
|
||||
if (of_parse_phandle(np, "phy-handle", 0)) {
|
||||
phy_node = of_parse_phandle(np, "phy-handle", 0);
|
||||
if (phy_node) {
|
||||
of_node_put(phy_node);
|
||||
bgmac->phy_connect = platform_phy_connect;
|
||||
} else {
|
||||
bgmac->phy_connect = bgmac_phy_connect_direct;
|
||||
|
||||
@@ -346,8 +346,9 @@ static struct sk_buff *copy_gl_to_skb_pkt(const struct pkt_gl *gl,
|
||||
* driver. Once driver synthesizes cpl_pass_accpet_req the skb will go
|
||||
* through the regular cpl_pass_accept_req processing in TOM.
|
||||
*/
|
||||
skb = alloc_skb(gl->tot_len + sizeof(struct cpl_pass_accept_req)
|
||||
- pktshift, GFP_ATOMIC);
|
||||
skb = alloc_skb(size_add(gl->tot_len,
|
||||
sizeof(struct cpl_pass_accept_req)) -
|
||||
pktshift, GFP_ATOMIC);
|
||||
if (unlikely(!skb))
|
||||
return NULL;
|
||||
__skb_put(skb, gl->tot_len + sizeof(struct cpl_pass_accept_req)
|
||||
|
||||
@@ -172,6 +172,7 @@ err_init_txq:
|
||||
hinic_sq_dbgfs_uninit(nic_dev);
|
||||
|
||||
devm_kfree(&netdev->dev, nic_dev->txqs);
|
||||
nic_dev->txqs = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -268,6 +269,7 @@ err_init_rxq:
|
||||
hinic_rq_dbgfs_uninit(nic_dev);
|
||||
|
||||
devm_kfree(&netdev->dev, nic_dev->rxqs);
|
||||
nic_dev->rxqs = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -1432,7 +1432,7 @@ void ocelot_ifh_set_basic(void *ifh, struct ocelot *ocelot, int port,
|
||||
|
||||
memset(ifh, 0, OCELOT_TAG_LEN);
|
||||
ocelot_ifh_set_bypass(ifh, 1);
|
||||
ocelot_ifh_set_src(ifh, BIT_ULL(ocelot->num_phys_ports));
|
||||
ocelot_ifh_set_src(ifh, ocelot->num_phys_ports);
|
||||
ocelot_ifh_set_dest(ifh, BIT_ULL(port));
|
||||
ocelot_ifh_set_qos_class(ifh, qos_class);
|
||||
ocelot_ifh_set_tag_type(ifh, tag_type);
|
||||
|
||||
@@ -113,6 +113,7 @@ struct oa_tc6 {
|
||||
struct mii_bus *mdiobus;
|
||||
struct spi_device *spi;
|
||||
struct mutex spi_ctrl_lock; /* Protects spi control transfer */
|
||||
spinlock_t tx_skb_lock; /* Protects tx skb handling */
|
||||
void *spi_ctrl_tx_buf;
|
||||
void *spi_ctrl_rx_buf;
|
||||
void *spi_data_tx_buf;
|
||||
@@ -1004,8 +1005,10 @@ static u16 oa_tc6_prepare_spi_tx_buf_for_tx_skbs(struct oa_tc6 *tc6)
|
||||
for (used_tx_credits = 0; used_tx_credits < tc6->tx_credits;
|
||||
used_tx_credits++) {
|
||||
if (!tc6->ongoing_tx_skb) {
|
||||
spin_lock_bh(&tc6->tx_skb_lock);
|
||||
tc6->ongoing_tx_skb = tc6->waiting_tx_skb;
|
||||
tc6->waiting_tx_skb = NULL;
|
||||
spin_unlock_bh(&tc6->tx_skb_lock);
|
||||
}
|
||||
if (!tc6->ongoing_tx_skb)
|
||||
break;
|
||||
@@ -1111,8 +1114,9 @@ static int oa_tc6_spi_thread_handler(void *data)
|
||||
/* This kthread will be waken up if there is a tx skb or mac-phy
|
||||
* interrupt to perform spi transfer with tx chunks.
|
||||
*/
|
||||
wait_event_interruptible(tc6->spi_wq, tc6->waiting_tx_skb ||
|
||||
tc6->int_flag ||
|
||||
wait_event_interruptible(tc6->spi_wq, tc6->int_flag ||
|
||||
(tc6->waiting_tx_skb &&
|
||||
tc6->tx_credits) ||
|
||||
kthread_should_stop());
|
||||
|
||||
if (kthread_should_stop())
|
||||
@@ -1209,7 +1213,9 @@ netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb)
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
spin_lock_bh(&tc6->tx_skb_lock);
|
||||
tc6->waiting_tx_skb = skb;
|
||||
spin_unlock_bh(&tc6->tx_skb_lock);
|
||||
|
||||
/* Wake spi kthread to perform spi transfer */
|
||||
wake_up_interruptible(&tc6->spi_wq);
|
||||
@@ -1239,6 +1245,7 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct net_device *netdev)
|
||||
tc6->netdev = netdev;
|
||||
SET_NETDEV_DEV(netdev, &spi->dev);
|
||||
mutex_init(&tc6->spi_ctrl_lock);
|
||||
spin_lock_init(&tc6->tx_skb_lock);
|
||||
|
||||
/* Set the SPI controller to pump at realtime priority */
|
||||
tc6->spi->rt = true;
|
||||
|
||||
@@ -277,7 +277,10 @@ void ionic_dev_teardown(struct ionic *ionic)
|
||||
idev->phy_cmb_pages = 0;
|
||||
idev->cmb_npages = 0;
|
||||
|
||||
destroy_workqueue(ionic->wq);
|
||||
if (ionic->wq) {
|
||||
destroy_workqueue(ionic->wq);
|
||||
ionic->wq = NULL;
|
||||
}
|
||||
mutex_destroy(&idev->cmb_inuse_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -961,8 +961,8 @@ static int ionic_get_module_eeprom(struct net_device *netdev,
|
||||
len = min_t(u32, sizeof(xcvr->sprom), ee->len);
|
||||
|
||||
do {
|
||||
memcpy(data, xcvr->sprom, len);
|
||||
memcpy(tbuf, xcvr->sprom, len);
|
||||
memcpy(data, &xcvr->sprom[ee->offset], len);
|
||||
memcpy(tbuf, &xcvr->sprom[ee->offset], len);
|
||||
|
||||
/* Let's make sure we got a consistent copy */
|
||||
if (!memcmp(data, tbuf, len))
|
||||
|
||||
@@ -3869,8 +3869,8 @@ int ionic_lif_register(struct ionic_lif *lif)
|
||||
/* only register LIF0 for now */
|
||||
err = register_netdev(lif->netdev);
|
||||
if (err) {
|
||||
dev_err(lif->ionic->dev, "Cannot register net device, aborting\n");
|
||||
ionic_lif_unregister_phc(lif);
|
||||
dev_err(lif->ionic->dev, "Cannot register net device: %d, aborting\n", err);
|
||||
ionic_lif_unregister(lif);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -547,7 +547,6 @@ static int rswitch_gwca_ts_queue_alloc(struct rswitch_private *priv)
|
||||
desc = &gq->ts_ring[gq->ring_size];
|
||||
desc->desc.die_dt = DT_LINKFIX;
|
||||
rswitch_desc_set_dptr(&desc->desc, gq->ring_dma);
|
||||
INIT_LIST_HEAD(&priv->gwca.ts_info_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1003,9 +1002,10 @@ static int rswitch_gwca_request_irqs(struct rswitch_private *priv)
|
||||
static void rswitch_ts(struct rswitch_private *priv)
|
||||
{
|
||||
struct rswitch_gwca_queue *gq = &priv->gwca.ts_queue;
|
||||
struct rswitch_gwca_ts_info *ts_info, *ts_info2;
|
||||
struct skb_shared_hwtstamps shhwtstamps;
|
||||
struct rswitch_ts_desc *desc;
|
||||
struct rswitch_device *rdev;
|
||||
struct sk_buff *ts_skb;
|
||||
struct timespec64 ts;
|
||||
unsigned int num;
|
||||
u32 tag, port;
|
||||
@@ -1015,23 +1015,28 @@ static void rswitch_ts(struct rswitch_private *priv)
|
||||
dma_rmb();
|
||||
|
||||
port = TS_DESC_DPN(__le32_to_cpu(desc->desc.dptrl));
|
||||
if (unlikely(port >= RSWITCH_NUM_PORTS))
|
||||
goto next;
|
||||
rdev = priv->rdev[port];
|
||||
|
||||
tag = TS_DESC_TSUN(__le32_to_cpu(desc->desc.dptrl));
|
||||
if (unlikely(tag >= TS_TAGS_PER_PORT))
|
||||
goto next;
|
||||
ts_skb = xchg(&rdev->ts_skb[tag], NULL);
|
||||
smp_mb(); /* order rdev->ts_skb[] read before bitmap update */
|
||||
clear_bit(tag, rdev->ts_skb_used);
|
||||
|
||||
list_for_each_entry_safe(ts_info, ts_info2, &priv->gwca.ts_info_list, list) {
|
||||
if (!(ts_info->port == port && ts_info->tag == tag))
|
||||
continue;
|
||||
if (unlikely(!ts_skb))
|
||||
goto next;
|
||||
|
||||
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
|
||||
ts.tv_sec = __le32_to_cpu(desc->ts_sec);
|
||||
ts.tv_nsec = __le32_to_cpu(desc->ts_nsec & cpu_to_le32(0x3fffffff));
|
||||
shhwtstamps.hwtstamp = timespec64_to_ktime(ts);
|
||||
skb_tstamp_tx(ts_info->skb, &shhwtstamps);
|
||||
dev_consume_skb_irq(ts_info->skb);
|
||||
list_del(&ts_info->list);
|
||||
kfree(ts_info);
|
||||
break;
|
||||
}
|
||||
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
|
||||
ts.tv_sec = __le32_to_cpu(desc->ts_sec);
|
||||
ts.tv_nsec = __le32_to_cpu(desc->ts_nsec & cpu_to_le32(0x3fffffff));
|
||||
shhwtstamps.hwtstamp = timespec64_to_ktime(ts);
|
||||
skb_tstamp_tx(ts_skb, &shhwtstamps);
|
||||
dev_consume_skb_irq(ts_skb);
|
||||
|
||||
next:
|
||||
gq->cur = rswitch_next_queue_index(gq, true, 1);
|
||||
desc = &gq->ts_ring[gq->cur];
|
||||
}
|
||||
@@ -1576,8 +1581,9 @@ static int rswitch_open(struct net_device *ndev)
|
||||
static int rswitch_stop(struct net_device *ndev)
|
||||
{
|
||||
struct rswitch_device *rdev = netdev_priv(ndev);
|
||||
struct rswitch_gwca_ts_info *ts_info, *ts_info2;
|
||||
struct sk_buff *ts_skb;
|
||||
unsigned long flags;
|
||||
unsigned int tag;
|
||||
|
||||
netif_tx_stop_all_queues(ndev);
|
||||
|
||||
@@ -1594,12 +1600,13 @@ static int rswitch_stop(struct net_device *ndev)
|
||||
if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
|
||||
iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID);
|
||||
|
||||
list_for_each_entry_safe(ts_info, ts_info2, &rdev->priv->gwca.ts_info_list, list) {
|
||||
if (ts_info->port != rdev->port)
|
||||
continue;
|
||||
dev_kfree_skb_irq(ts_info->skb);
|
||||
list_del(&ts_info->list);
|
||||
kfree(ts_info);
|
||||
for (tag = find_first_bit(rdev->ts_skb_used, TS_TAGS_PER_PORT);
|
||||
tag < TS_TAGS_PER_PORT;
|
||||
tag = find_next_bit(rdev->ts_skb_used, TS_TAGS_PER_PORT, tag + 1)) {
|
||||
ts_skb = xchg(&rdev->ts_skb[tag], NULL);
|
||||
clear_bit(tag, rdev->ts_skb_used);
|
||||
if (ts_skb)
|
||||
dev_kfree_skb(ts_skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1612,20 +1619,17 @@ static bool rswitch_ext_desc_set_info1(struct rswitch_device *rdev,
|
||||
desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) |
|
||||
INFO1_IPV(GWCA_IPV_NUM) | INFO1_FMT);
|
||||
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
|
||||
struct rswitch_gwca_ts_info *ts_info;
|
||||
unsigned int tag;
|
||||
|
||||
ts_info = kzalloc(sizeof(*ts_info), GFP_ATOMIC);
|
||||
if (!ts_info)
|
||||
tag = find_first_zero_bit(rdev->ts_skb_used, TS_TAGS_PER_PORT);
|
||||
if (tag == TS_TAGS_PER_PORT)
|
||||
return false;
|
||||
smp_mb(); /* order bitmap read before rdev->ts_skb[] write */
|
||||
rdev->ts_skb[tag] = skb_get(skb);
|
||||
set_bit(tag, rdev->ts_skb_used);
|
||||
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
|
||||
rdev->ts_tag++;
|
||||
desc->info1 |= cpu_to_le64(INFO1_TSUN(rdev->ts_tag) | INFO1_TXC);
|
||||
|
||||
ts_info->skb = skb_get(skb);
|
||||
ts_info->port = rdev->port;
|
||||
ts_info->tag = rdev->ts_tag;
|
||||
list_add_tail(&ts_info->list, &rdev->priv->gwca.ts_info_list);
|
||||
desc->info1 |= cpu_to_le64(INFO1_TSUN(tag) | INFO1_TXC);
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
}
|
||||
|
||||
@@ -972,14 +972,6 @@ struct rswitch_gwca_queue {
|
||||
};
|
||||
};
|
||||
|
||||
struct rswitch_gwca_ts_info {
|
||||
struct sk_buff *skb;
|
||||
struct list_head list;
|
||||
|
||||
int port;
|
||||
u8 tag;
|
||||
};
|
||||
|
||||
#define RSWITCH_NUM_IRQ_REGS (RSWITCH_MAX_NUM_QUEUES / BITS_PER_TYPE(u32))
|
||||
struct rswitch_gwca {
|
||||
unsigned int index;
|
||||
@@ -989,7 +981,6 @@ struct rswitch_gwca {
|
||||
struct rswitch_gwca_queue *queues;
|
||||
int num_queues;
|
||||
struct rswitch_gwca_queue ts_queue;
|
||||
struct list_head ts_info_list;
|
||||
DECLARE_BITMAP(used, RSWITCH_MAX_NUM_QUEUES);
|
||||
u32 tx_irq_bits[RSWITCH_NUM_IRQ_REGS];
|
||||
u32 rx_irq_bits[RSWITCH_NUM_IRQ_REGS];
|
||||
@@ -997,6 +988,7 @@ struct rswitch_gwca {
|
||||
};
|
||||
|
||||
#define NUM_QUEUES_PER_NDEV 2
|
||||
#define TS_TAGS_PER_PORT 256
|
||||
struct rswitch_device {
|
||||
struct rswitch_private *priv;
|
||||
struct net_device *ndev;
|
||||
@@ -1004,7 +996,8 @@ struct rswitch_device {
|
||||
void __iomem *addr;
|
||||
struct rswitch_gwca_queue *tx_queue;
|
||||
struct rswitch_gwca_queue *rx_queue;
|
||||
u8 ts_tag;
|
||||
struct sk_buff *ts_skb[TS_TAGS_PER_PORT];
|
||||
DECLARE_BITMAP(ts_skb_used, TS_TAGS_PER_PORT);
|
||||
bool disabled;
|
||||
|
||||
int port;
|
||||
|
||||
@@ -4220,8 +4220,8 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
struct stmmac_txq_stats *txq_stats;
|
||||
struct stmmac_tx_queue *tx_q;
|
||||
u32 pay_len, mss, queue;
|
||||
dma_addr_t tso_des, des;
|
||||
u8 proto_hdr_len, hdr;
|
||||
dma_addr_t des;
|
||||
bool set_ic;
|
||||
int i;
|
||||
|
||||
@@ -4317,14 +4317,15 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
/* If needed take extra descriptors to fill the remaining payload */
|
||||
tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE;
|
||||
tso_des = des;
|
||||
} else {
|
||||
stmmac_set_desc_addr(priv, first, des);
|
||||
tmp_pay_len = pay_len;
|
||||
des += proto_hdr_len;
|
||||
tso_des = des + proto_hdr_len;
|
||||
pay_len = 0;
|
||||
}
|
||||
|
||||
stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);
|
||||
stmmac_tso_allocator(priv, tso_des, tmp_pay_len, (nfrags == 0), queue);
|
||||
|
||||
/* In case two or more DMA transmit descriptors are allocated for this
|
||||
* non-paged SKB data, the DMA buffer address should be saved to
|
||||
|
||||
@@ -40,6 +40,7 @@ fwnode_find_pse_control(struct fwnode_handle *fwnode)
|
||||
static struct mii_timestamper *
|
||||
fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct mii_timestamper *mii_ts;
|
||||
struct of_phandle_args arg;
|
||||
int err;
|
||||
|
||||
@@ -53,10 +54,16 @@ fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
|
||||
else if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (arg.args_count != 1)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (arg.args_count != 1) {
|
||||
mii_ts = ERR_PTR(-EINVAL);
|
||||
goto put_node;
|
||||
}
|
||||
|
||||
return register_mii_timestamper(arg.np, arg.args[0]);
|
||||
mii_ts = register_mii_timestamper(arg.np, arg.args[0]);
|
||||
|
||||
put_node:
|
||||
of_node_put(arg.np);
|
||||
return mii_ts;
|
||||
}
|
||||
|
||||
int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
|
||||
|
||||
@@ -149,6 +149,8 @@ static ssize_t nsim_dev_health_break_write(struct file *file,
|
||||
char *break_msg;
|
||||
int err;
|
||||
|
||||
if (count == 0 || count > PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
break_msg = memdup_user_nul(data, count);
|
||||
if (IS_ERR(break_msg))
|
||||
return PTR_ERR(break_msg);
|
||||
|
||||
@@ -596,10 +596,10 @@ nsim_pp_hold_write(struct file *file, const char __user *data,
|
||||
page_pool_put_full_page(ns->page->pp, ns->page, false);
|
||||
ns->page = NULL;
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
exit:
|
||||
return count;
|
||||
rtnl_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations nsim_pp_hold_fops = {
|
||||
|
||||
@@ -998,9 +998,13 @@ static void __team_compute_features(struct team *team)
|
||||
unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
|
||||
IFF_XMIT_DST_RELEASE_PERM;
|
||||
|
||||
vlan_features = netdev_base_features(vlan_features);
|
||||
|
||||
rcu_read_lock();
|
||||
if (list_empty(&team->port_list))
|
||||
goto done;
|
||||
|
||||
vlan_features = netdev_base_features(vlan_features);
|
||||
enc_features = netdev_base_features(enc_features);
|
||||
|
||||
list_for_each_entry_rcu(port, &team->port_list, list) {
|
||||
vlan_features = netdev_increment_features(vlan_features,
|
||||
port->dev->vlan_features,
|
||||
@@ -1010,11 +1014,11 @@ static void __team_compute_features(struct team *team)
|
||||
port->dev->hw_enc_features,
|
||||
TEAM_ENC_FEATURES);
|
||||
|
||||
|
||||
dst_release_flag &= port->dev->priv_flags;
|
||||
if (port->dev->hard_header_len > max_hard_header_len)
|
||||
max_hard_header_len = port->dev->hard_header_len;
|
||||
}
|
||||
done:
|
||||
rcu_read_unlock();
|
||||
|
||||
team->dev->vlan_features = vlan_features;
|
||||
|
||||
+1
-1
@@ -1481,7 +1481,7 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile,
|
||||
skb->truesize += skb->data_len;
|
||||
|
||||
for (i = 1; i < it->nr_segs; i++) {
|
||||
const struct iovec *iov = iter_iov(it);
|
||||
const struct iovec *iov = iter_iov(it) + i;
|
||||
size_t fragsz = iov->iov_len;
|
||||
struct page *page;
|
||||
void *frag;
|
||||
|
||||
@@ -455,7 +455,8 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
|
||||
}
|
||||
if (ranges == NULL || rlen == 0) {
|
||||
offset = of_read_number(addr, na);
|
||||
memset(addr, 0, pna * 4);
|
||||
/* set address to zero, pass flags through */
|
||||
memset(addr + pbus->flag_cells, 0, (pna - pbus->flag_cells) * 4);
|
||||
pr_debug("empty ranges; 1:1 translation\n");
|
||||
goto finish;
|
||||
}
|
||||
@@ -615,7 +616,7 @@ struct device_node *__of_get_dma_parent(const struct device_node *np)
|
||||
if (ret < 0)
|
||||
return of_get_parent(np);
|
||||
|
||||
return of_node_get(args.np);
|
||||
return args.np;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+10
-5
@@ -1455,8 +1455,10 @@ int of_parse_phandle_with_args_map(const struct device_node *np,
|
||||
map_len--;
|
||||
|
||||
/* Check if not found */
|
||||
if (!new)
|
||||
if (!new) {
|
||||
ret = -EINVAL;
|
||||
goto put;
|
||||
}
|
||||
|
||||
if (!of_device_is_available(new))
|
||||
match = 0;
|
||||
@@ -1466,17 +1468,20 @@ int of_parse_phandle_with_args_map(const struct device_node *np,
|
||||
goto put;
|
||||
|
||||
/* Check for malformed properties */
|
||||
if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
|
||||
goto put;
|
||||
if (map_len < new_size)
|
||||
if (WARN_ON(new_size > MAX_PHANDLE_ARGS) ||
|
||||
map_len < new_size) {
|
||||
ret = -EINVAL;
|
||||
goto put;
|
||||
}
|
||||
|
||||
/* Move forward by new node's #<list>-cells amount */
|
||||
map += new_size;
|
||||
map_len -= new_size;
|
||||
}
|
||||
if (!match)
|
||||
if (!match) {
|
||||
ret = -ENOENT;
|
||||
goto put;
|
||||
}
|
||||
|
||||
/* Get the <list>-map-pass-thru property (optional) */
|
||||
pass = of_get_property(cur, pass_name, NULL);
|
||||
|
||||
@@ -111,6 +111,7 @@ const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_ph
|
||||
else
|
||||
np = of_find_node_by_phandle(be32_to_cpup(imap));
|
||||
imap++;
|
||||
len--;
|
||||
|
||||
/* Check if not found */
|
||||
if (!np) {
|
||||
@@ -354,6 +355,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
|
||||
return of_irq_parse_oldworld(device, index, out_irq);
|
||||
|
||||
/* Get the reg property (if any) */
|
||||
addr_len = 0;
|
||||
addr = of_get_property(device, "reg", &addr_len);
|
||||
|
||||
/* Prevent out-of-bounds read in case of longer interrupt parent address size */
|
||||
|
||||
@@ -1213,7 +1213,6 @@ DEFINE_SIMPLE_PROP(iommus, "iommus", "#iommu-cells")
|
||||
DEFINE_SIMPLE_PROP(mboxes, "mboxes", "#mbox-cells")
|
||||
DEFINE_SIMPLE_PROP(io_channels, "io-channels", "#io-channel-cells")
|
||||
DEFINE_SIMPLE_PROP(io_backends, "io-backends", "#io-backend-cells")
|
||||
DEFINE_SIMPLE_PROP(interrupt_parent, "interrupt-parent", NULL)
|
||||
DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells")
|
||||
DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells")
|
||||
DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells")
|
||||
@@ -1359,7 +1358,6 @@ static const struct supplier_bindings of_supplier_bindings[] = {
|
||||
{ .parse_prop = parse_mboxes, },
|
||||
{ .parse_prop = parse_io_channels, },
|
||||
{ .parse_prop = parse_io_backends, },
|
||||
{ .parse_prop = parse_interrupt_parent, },
|
||||
{ .parse_prop = parse_dmas, .optional = true, },
|
||||
{ .parse_prop = parse_power_domains, },
|
||||
{ .parse_prop = parse_hwlocks, },
|
||||
|
||||
+56
-23
@@ -42,6 +42,7 @@ struct p2sb_res_cache {
|
||||
};
|
||||
|
||||
static struct p2sb_res_cache p2sb_resources[NR_P2SB_RES_CACHE];
|
||||
static bool p2sb_hidden_by_bios;
|
||||
|
||||
static void p2sb_get_devfn(unsigned int *devfn)
|
||||
{
|
||||
@@ -96,6 +97,12 @@ static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn)
|
||||
|
||||
static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn)
|
||||
{
|
||||
/*
|
||||
* The BIOS prevents the P2SB device from being enumerated by the PCI
|
||||
* subsystem, so we need to unhide and hide it back to lookup the BAR.
|
||||
*/
|
||||
pci_bus_write_config_dword(bus, devfn, P2SBC, 0);
|
||||
|
||||
/* Scan the P2SB device and cache its BAR0 */
|
||||
p2sb_scan_and_cache_devfn(bus, devfn);
|
||||
|
||||
@@ -103,6 +110,8 @@ static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn)
|
||||
if (devfn == P2SB_DEVFN_GOLDMONT)
|
||||
p2sb_scan_and_cache_devfn(bus, SPI_DEVFN_GOLDMONT);
|
||||
|
||||
pci_bus_write_config_dword(bus, devfn, P2SBC, P2SBC_HIDE);
|
||||
|
||||
if (!p2sb_valid_resource(&p2sb_resources[PCI_FUNC(devfn)].res))
|
||||
return -ENOENT;
|
||||
|
||||
@@ -128,7 +137,7 @@ static int p2sb_cache_resources(void)
|
||||
u32 value = P2SBC_HIDE;
|
||||
struct pci_bus *bus;
|
||||
u16 class;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/* Get devfn for P2SB device itself */
|
||||
p2sb_get_devfn(&devfn_p2sb);
|
||||
@@ -151,26 +160,57 @@ static int p2sb_cache_resources(void)
|
||||
*/
|
||||
pci_lock_rescan_remove();
|
||||
|
||||
/*
|
||||
* The BIOS prevents the P2SB device from being enumerated by the PCI
|
||||
* subsystem, so we need to unhide and hide it back to lookup the BAR.
|
||||
* Unhide the P2SB device here, if needed.
|
||||
*/
|
||||
pci_bus_read_config_dword(bus, devfn_p2sb, P2SBC, &value);
|
||||
if (value & P2SBC_HIDE)
|
||||
pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, 0);
|
||||
p2sb_hidden_by_bios = value & P2SBC_HIDE;
|
||||
|
||||
ret = p2sb_scan_and_cache(bus, devfn_p2sb);
|
||||
|
||||
/* Hide the P2SB device, if it was hidden */
|
||||
if (value & P2SBC_HIDE)
|
||||
pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, P2SBC_HIDE);
|
||||
/*
|
||||
* If the BIOS does not hide the P2SB device then its resources
|
||||
* are accesilble. Cache them only if the P2SB device is hidden.
|
||||
*/
|
||||
if (p2sb_hidden_by_bios)
|
||||
ret = p2sb_scan_and_cache(bus, devfn_p2sb);
|
||||
|
||||
pci_unlock_rescan_remove();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int p2sb_read_from_cache(struct pci_bus *bus, unsigned int devfn,
|
||||
struct resource *mem)
|
||||
{
|
||||
struct p2sb_res_cache *cache = &p2sb_resources[PCI_FUNC(devfn)];
|
||||
|
||||
if (cache->bus_dev_id != bus->dev.id)
|
||||
return -ENODEV;
|
||||
|
||||
if (!p2sb_valid_resource(&cache->res))
|
||||
return -ENOENT;
|
||||
|
||||
memcpy(mem, &cache->res, sizeof(*mem));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p2sb_read_from_dev(struct pci_bus *bus, unsigned int devfn,
|
||||
struct resource *mem)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
int ret = 0;
|
||||
|
||||
pdev = pci_get_slot(bus, devfn);
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
if (p2sb_valid_resource(pci_resource_n(pdev, 0)))
|
||||
p2sb_read_bar0(pdev, mem);
|
||||
else
|
||||
ret = -ENOENT;
|
||||
|
||||
pci_dev_put(pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* p2sb_bar - Get Primary to Sideband (P2SB) bridge device BAR
|
||||
* @bus: PCI bus to communicate with
|
||||
@@ -187,8 +227,6 @@ static int p2sb_cache_resources(void)
|
||||
*/
|
||||
int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
|
||||
{
|
||||
struct p2sb_res_cache *cache;
|
||||
|
||||
bus = p2sb_get_bus(bus);
|
||||
if (!bus)
|
||||
return -ENODEV;
|
||||
@@ -196,15 +234,10 @@ int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
|
||||
if (!devfn)
|
||||
p2sb_get_devfn(&devfn);
|
||||
|
||||
cache = &p2sb_resources[PCI_FUNC(devfn)];
|
||||
if (cache->bus_dev_id != bus->dev.id)
|
||||
return -ENODEV;
|
||||
if (p2sb_hidden_by_bios)
|
||||
return p2sb_read_from_cache(bus, devfn, mem);
|
||||
|
||||
if (!p2sb_valid_resource(&cache->res))
|
||||
return -ENOENT;
|
||||
|
||||
memcpy(mem, &cache->res, sizeof(*mem));
|
||||
return 0;
|
||||
return p2sb_read_from_dev(bus, devfn, mem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(p2sb_bar);
|
||||
|
||||
|
||||
@@ -1520,6 +1520,14 @@ static struct pci_device_id nhi_ids[] = {
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_LNL_NHI1),
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI0),
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI1),
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI0),
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI1),
|
||||
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) },
|
||||
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) },
|
||||
|
||||
|
||||
@@ -92,6 +92,10 @@ extern const struct tb_nhi_ops icl_nhi_ops;
|
||||
#define PCI_DEVICE_ID_INTEL_RPL_NHI1 0xa76d
|
||||
#define PCI_DEVICE_ID_INTEL_LNL_NHI0 0xa833
|
||||
#define PCI_DEVICE_ID_INTEL_LNL_NHI1 0xa834
|
||||
#define PCI_DEVICE_ID_INTEL_PTL_M_NHI0 0xe333
|
||||
#define PCI_DEVICE_ID_INTEL_PTL_M_NHI1 0xe334
|
||||
#define PCI_DEVICE_ID_INTEL_PTL_P_NHI0 0xe433
|
||||
#define PCI_DEVICE_ID_INTEL_PTL_P_NHI1 0xe434
|
||||
|
||||
#define PCI_CLASS_SERIAL_USB_USB4 0x0c0340
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt)
|
||||
|
||||
err_nvm:
|
||||
dev_dbg(&rt->dev, "NVM upgrade disabled\n");
|
||||
rt->no_nvm_upgrade = true;
|
||||
if (!IS_ERR(nvm))
|
||||
tb_nvm_free(nvm);
|
||||
|
||||
@@ -182,8 +183,6 @@ static ssize_t nvm_authenticate_show(struct device *dev,
|
||||
|
||||
if (!rt->nvm)
|
||||
ret = -EAGAIN;
|
||||
else if (rt->no_nvm_upgrade)
|
||||
ret = -EOPNOTSUPP;
|
||||
else
|
||||
ret = sysfs_emit(buf, "%#x\n", rt->auth_status);
|
||||
|
||||
@@ -323,8 +322,6 @@ static ssize_t nvm_version_show(struct device *dev,
|
||||
|
||||
if (!rt->nvm)
|
||||
ret = -EAGAIN;
|
||||
else if (rt->no_nvm_upgrade)
|
||||
ret = -EOPNOTSUPP;
|
||||
else
|
||||
ret = sysfs_emit(buf, "%x.%x\n", rt->nvm->major, rt->nvm->minor);
|
||||
|
||||
@@ -342,6 +339,19 @@ static ssize_t vendor_show(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR_RO(vendor);
|
||||
|
||||
static umode_t retimer_is_visible(struct kobject *kobj, struct attribute *attr,
|
||||
int n)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct tb_retimer *rt = tb_to_retimer(dev);
|
||||
|
||||
if (attr == &dev_attr_nvm_authenticate.attr ||
|
||||
attr == &dev_attr_nvm_version.attr)
|
||||
return rt->no_nvm_upgrade ? 0 : attr->mode;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
static struct attribute *retimer_attrs[] = {
|
||||
&dev_attr_device.attr,
|
||||
&dev_attr_nvm_authenticate.attr,
|
||||
@@ -351,6 +361,7 @@ static struct attribute *retimer_attrs[] = {
|
||||
};
|
||||
|
||||
static const struct attribute_group retimer_group = {
|
||||
.is_visible = retimer_is_visible,
|
||||
.attrs = retimer_attrs,
|
||||
};
|
||||
|
||||
|
||||
@@ -2059,6 +2059,37 @@ static void tb_exit_redrive(struct tb_port *port)
|
||||
}
|
||||
}
|
||||
|
||||
static void tb_switch_enter_redrive(struct tb_switch *sw)
|
||||
{
|
||||
struct tb_port *port;
|
||||
|
||||
tb_switch_for_each_port(sw, port)
|
||||
tb_enter_redrive(port);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called during system and runtime suspend to forcefully exit redrive
|
||||
* mode without querying whether the resource is available.
|
||||
*/
|
||||
static void tb_switch_exit_redrive(struct tb_switch *sw)
|
||||
{
|
||||
struct tb_port *port;
|
||||
|
||||
if (!(sw->quirks & QUIRK_KEEP_POWER_IN_DP_REDRIVE))
|
||||
return;
|
||||
|
||||
tb_switch_for_each_port(sw, port) {
|
||||
if (!tb_port_is_dpin(port))
|
||||
continue;
|
||||
|
||||
if (port->redrive) {
|
||||
port->redrive = false;
|
||||
pm_runtime_put(&sw->dev);
|
||||
tb_port_dbg(port, "exit redrive mode\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tb_dp_resource_unavailable(struct tb *tb, struct tb_port *port)
|
||||
{
|
||||
struct tb_port *in, *out;
|
||||
@@ -2909,6 +2940,7 @@ static int tb_start(struct tb *tb, bool reset)
|
||||
tb_create_usb3_tunnels(tb->root_switch);
|
||||
/* Add DP IN resources for the root switch */
|
||||
tb_add_dp_resources(tb->root_switch);
|
||||
tb_switch_enter_redrive(tb->root_switch);
|
||||
/* Make the discovered switches available to the userspace */
|
||||
device_for_each_child(&tb->root_switch->dev, NULL,
|
||||
tb_scan_finalize_switch);
|
||||
@@ -2924,6 +2956,7 @@ static int tb_suspend_noirq(struct tb *tb)
|
||||
|
||||
tb_dbg(tb, "suspending...\n");
|
||||
tb_disconnect_and_release_dp(tb);
|
||||
tb_switch_exit_redrive(tb->root_switch);
|
||||
tb_switch_suspend(tb->root_switch, false);
|
||||
tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */
|
||||
tb_dbg(tb, "suspend finished\n");
|
||||
@@ -3016,6 +3049,7 @@ static int tb_resume_noirq(struct tb *tb)
|
||||
tb_dbg(tb, "tunnels restarted, sleeping for 100ms\n");
|
||||
msleep(100);
|
||||
}
|
||||
tb_switch_enter_redrive(tb->root_switch);
|
||||
/* Allow tb_handle_hotplug to progress events */
|
||||
tcm->hotplug_active = true;
|
||||
tb_dbg(tb, "resume finished\n");
|
||||
@@ -3079,6 +3113,12 @@ static int tb_runtime_suspend(struct tb *tb)
|
||||
struct tb_cm *tcm = tb_priv(tb);
|
||||
|
||||
mutex_lock(&tb->lock);
|
||||
/*
|
||||
* The below call only releases DP resources to allow exiting and
|
||||
* re-entering redrive mode.
|
||||
*/
|
||||
tb_disconnect_and_release_dp(tb);
|
||||
tb_switch_exit_redrive(tb->root_switch);
|
||||
tb_switch_suspend(tb->root_switch, true);
|
||||
tcm->hotplug_active = false;
|
||||
mutex_unlock(&tb->lock);
|
||||
@@ -3110,6 +3150,7 @@ static int tb_runtime_resume(struct tb *tb)
|
||||
tb_restore_children(tb->root_switch);
|
||||
list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
|
||||
tb_tunnel_restart(tunnel);
|
||||
tb_switch_enter_redrive(tb->root_switch);
|
||||
tcm->hotplug_active = true;
|
||||
mutex_unlock(&tb->lock);
|
||||
|
||||
|
||||
@@ -1192,8 +1192,6 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
|
||||
* Keep retrying until the EP starts and stops again, on
|
||||
* chips where this is known to help. Wait for 100ms.
|
||||
*/
|
||||
if (!(xhci->quirks & XHCI_NEC_HOST))
|
||||
break;
|
||||
if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100)))
|
||||
break;
|
||||
fallthrough;
|
||||
|
||||
@@ -625,6 +625,8 @@ static void option_instat_callback(struct urb *urb);
|
||||
#define MEIGSMART_PRODUCT_SRM825L 0x4d22
|
||||
/* MeiG Smart SLM320 based on UNISOC UIS8910 */
|
||||
#define MEIGSMART_PRODUCT_SLM320 0x4d41
|
||||
/* MeiG Smart SLM770A based on ASR1803 */
|
||||
#define MEIGSMART_PRODUCT_SLM770A 0x4d57
|
||||
|
||||
/* Device flags */
|
||||
|
||||
@@ -1395,6 +1397,12 @@ static const struct usb_device_id option_ids[] = {
|
||||
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */
|
||||
.driver_info = NCTRL(3) | RSVD(4) | RSVD(5) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c0, 0xff), /* Telit FE910C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c4, 0xff), /* Telit FE910C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(3) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */
|
||||
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
|
||||
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
|
||||
@@ -2247,6 +2255,8 @@ static const struct usb_device_id option_ids[] = {
|
||||
.driver_info = NCTRL(2) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x7127, 0xff, 0x00, 0x00),
|
||||
.driver_info = NCTRL(2) | NCTRL(3) | NCTRL(4) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x7129, 0xff, 0x00, 0x00), /* MediaTek T7XX */
|
||||
.driver_info = NCTRL(2) | NCTRL(3) | NCTRL(4) },
|
||||
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
|
||||
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MPL200),
|
||||
.driver_info = RSVD(1) | RSVD(4) },
|
||||
@@ -2375,6 +2385,18 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Golbal EDU */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010a, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WRD for WWAN Ready */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010a, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010a, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010b, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for WWAN Ready */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010b, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010b, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010c, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WRD for WWAN Ready */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010c, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010c, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010d, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for WWAN Ready */
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010d, 0xff, 0x00, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010d, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
|
||||
@@ -2382,9 +2404,14 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM770A, 0xff, 0, 0) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) },
|
||||
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */
|
||||
.driver_info = NCTRL(1) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */
|
||||
.driver_info = NCTRL(3) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||
|
||||
+8
-2
@@ -649,8 +649,14 @@ static u64 btrfs_append_map_length(struct btrfs_bio *bbio, u64 map_length)
|
||||
map_length = min(map_length, bbio->fs_info->max_zone_append_size);
|
||||
sector_offset = bio_split_rw_at(&bbio->bio, &bbio->fs_info->limits,
|
||||
&nr_segs, map_length);
|
||||
if (sector_offset)
|
||||
return sector_offset << SECTOR_SHIFT;
|
||||
if (sector_offset) {
|
||||
/*
|
||||
* bio_split_rw_at() could split at a size smaller than our
|
||||
* sectorsize and thus cause unaligned I/Os. Fix that by
|
||||
* always rounding down to the nearest boundary.
|
||||
*/
|
||||
return ALIGN_DOWN(sector_offset << SECTOR_SHIFT, bbio->fs_info->sectorsize);
|
||||
}
|
||||
return map_length;
|
||||
}
|
||||
|
||||
|
||||
@@ -370,6 +370,25 @@ static inline void btrfs_set_root_last_trans(struct btrfs_root *root, u64 transi
|
||||
WRITE_ONCE(root->last_trans, transid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the generation this root started with.
|
||||
*
|
||||
* Every normal root that is created with root->root_key.offset set to it's
|
||||
* originating generation. If it is a snapshot it is the generation when the
|
||||
* snapshot was created.
|
||||
*
|
||||
* However for TREE_RELOC roots root_key.offset is the objectid of the owning
|
||||
* tree root. Thankfully we copy the root item of the owning tree root, which
|
||||
* has it's last_snapshot set to what we would have root_key.offset set to, so
|
||||
* return that if this is a TREE_RELOC root.
|
||||
*/
|
||||
static inline u64 btrfs_root_origin_generation(const struct btrfs_root *root)
|
||||
{
|
||||
if (btrfs_root_id(root) == BTRFS_TREE_RELOC_OBJECTID)
|
||||
return btrfs_root_last_snapshot(&root->root_item);
|
||||
return root->root_key.offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure that conveys information about an extent that is going to replace
|
||||
* all the extents in a file range.
|
||||
|
||||
@@ -5308,7 +5308,7 @@ static bool visit_node_for_delete(struct btrfs_root *root, struct walk_control *
|
||||
* reference to it.
|
||||
*/
|
||||
generation = btrfs_node_ptr_generation(eb, slot);
|
||||
if (!wc->update_ref || generation <= root->root_key.offset)
|
||||
if (!wc->update_ref || generation <= btrfs_root_origin_generation(root))
|
||||
return false;
|
||||
|
||||
/*
|
||||
@@ -5363,7 +5363,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
|
||||
goto reada;
|
||||
|
||||
if (wc->stage == UPDATE_BACKREF &&
|
||||
generation <= root->root_key.offset)
|
||||
generation <= btrfs_root_origin_generation(root))
|
||||
continue;
|
||||
|
||||
/* We don't lock the tree block, it's OK to be racy here */
|
||||
@@ -5706,7 +5706,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
|
||||
* for the subtree
|
||||
*/
|
||||
if (wc->stage == UPDATE_BACKREF &&
|
||||
generation <= root->root_key.offset) {
|
||||
generation <= btrfs_root_origin_generation(root)) {
|
||||
wc->lookup_info = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+26
-1
@@ -1527,6 +1527,11 @@ static int check_extent_item(struct extent_buffer *leaf,
|
||||
dref_offset, fs_info->sectorsize);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (unlikely(btrfs_extent_data_ref_count(leaf, dref) == 0)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid data ref count, should have non-zero value");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
inline_refs += btrfs_extent_data_ref_count(leaf, dref);
|
||||
break;
|
||||
/* Contains parent bytenr and ref count */
|
||||
@@ -1539,6 +1544,11 @@ static int check_extent_item(struct extent_buffer *leaf,
|
||||
inline_offset, fs_info->sectorsize);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (unlikely(btrfs_shared_data_ref_count(leaf, sref) == 0)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid shared data ref count, should have non-zero value");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
inline_refs += btrfs_shared_data_ref_count(leaf, sref);
|
||||
break;
|
||||
case BTRFS_EXTENT_OWNER_REF_KEY:
|
||||
@@ -1611,8 +1621,18 @@ static int check_simple_keyed_refs(struct extent_buffer *leaf,
|
||||
{
|
||||
u32 expect_item_size = 0;
|
||||
|
||||
if (key->type == BTRFS_SHARED_DATA_REF_KEY)
|
||||
if (key->type == BTRFS_SHARED_DATA_REF_KEY) {
|
||||
struct btrfs_shared_data_ref *sref;
|
||||
|
||||
sref = btrfs_item_ptr(leaf, slot, struct btrfs_shared_data_ref);
|
||||
if (unlikely(btrfs_shared_data_ref_count(leaf, sref) == 0)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid shared data backref count, should have non-zero value");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
expect_item_size = sizeof(struct btrfs_shared_data_ref);
|
||||
}
|
||||
|
||||
if (unlikely(btrfs_item_size(leaf, slot) != expect_item_size)) {
|
||||
generic_err(leaf, slot,
|
||||
@@ -1689,6 +1709,11 @@ static int check_extent_data_ref(struct extent_buffer *leaf,
|
||||
offset, leaf->fs_info->sectorsize);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (unlikely(btrfs_extent_data_ref_count(leaf, dref) == 0)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid extent data backref count, should have non-zero value");
|
||||
return -EUCLEAN;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+38
-39
@@ -1066,7 +1066,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
|
||||
if (ceph_inode_is_shutdown(inode))
|
||||
return -EIO;
|
||||
|
||||
if (!len)
|
||||
if (!len || !i_size)
|
||||
return 0;
|
||||
/*
|
||||
* flush any page cache pages in this range. this
|
||||
@@ -1086,7 +1086,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
|
||||
int num_pages;
|
||||
size_t page_off;
|
||||
bool more;
|
||||
int idx;
|
||||
int idx = 0;
|
||||
size_t left;
|
||||
struct ceph_osd_req_op *op;
|
||||
u64 read_off = off;
|
||||
@@ -1116,6 +1116,16 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
|
||||
len = read_off + read_len - off;
|
||||
more = len < iov_iter_count(to);
|
||||
|
||||
op = &req->r_ops[0];
|
||||
if (sparse) {
|
||||
extent_cnt = __ceph_sparse_read_ext_count(inode, read_len);
|
||||
ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
|
||||
if (ret) {
|
||||
ceph_osdc_put_request(req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
num_pages = calc_pages_for(read_off, read_len);
|
||||
page_off = offset_in_page(off);
|
||||
pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL);
|
||||
@@ -1127,17 +1137,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
|
||||
|
||||
osd_req_op_extent_osd_data_pages(req, 0, pages, read_len,
|
||||
offset_in_page(read_off),
|
||||
false, false);
|
||||
|
||||
op = &req->r_ops[0];
|
||||
if (sparse) {
|
||||
extent_cnt = __ceph_sparse_read_ext_count(inode, read_len);
|
||||
ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
|
||||
if (ret) {
|
||||
ceph_osdc_put_request(req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
false, true);
|
||||
|
||||
ceph_osdc_start_request(osdc, req);
|
||||
ret = ceph_osdc_wait_request(osdc, req);
|
||||
@@ -1160,7 +1160,14 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
|
||||
else if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
|
||||
if (ret > 0 && IS_ENCRYPTED(inode)) {
|
||||
if (ret < 0) {
|
||||
ceph_osdc_put_request(req);
|
||||
if (ret == -EBLOCKLISTED)
|
||||
fsc->blocklisted = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_ENCRYPTED(inode)) {
|
||||
int fret;
|
||||
|
||||
fret = ceph_fscrypt_decrypt_extents(inode, pages,
|
||||
@@ -1186,10 +1193,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
|
||||
ret = min_t(ssize_t, fret, len);
|
||||
}
|
||||
|
||||
ceph_osdc_put_request(req);
|
||||
|
||||
/* Short read but not EOF? Zero out the remainder. */
|
||||
if (ret >= 0 && ret < len && (off + ret < i_size)) {
|
||||
if (ret < len && (off + ret < i_size)) {
|
||||
int zlen = min(len - ret, i_size - off - ret);
|
||||
int zoff = page_off + ret;
|
||||
|
||||
@@ -1199,13 +1204,11 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
|
||||
ret += zlen;
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
if (ret <= 0)
|
||||
left = 0;
|
||||
else if (off + ret > i_size)
|
||||
left = i_size - off;
|
||||
if (off + ret > i_size)
|
||||
left = (i_size > off) ? i_size - off : 0;
|
||||
else
|
||||
left = ret;
|
||||
|
||||
while (left > 0) {
|
||||
size_t plen, copied;
|
||||
|
||||
@@ -1221,13 +1224,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
|
||||
break;
|
||||
}
|
||||
}
|
||||
ceph_release_page_vector(pages, num_pages);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret == -EBLOCKLISTED)
|
||||
fsc->blocklisted = true;
|
||||
break;
|
||||
}
|
||||
ceph_osdc_put_request(req);
|
||||
|
||||
if (off >= i_size || !more)
|
||||
break;
|
||||
@@ -1553,6 +1551,16 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
|
||||
break;
|
||||
}
|
||||
|
||||
op = &req->r_ops[0];
|
||||
if (sparse) {
|
||||
extent_cnt = __ceph_sparse_read_ext_count(inode, size);
|
||||
ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
|
||||
if (ret) {
|
||||
ceph_osdc_put_request(req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len = iter_get_bvecs_alloc(iter, size, &bvecs, &num_pages);
|
||||
if (len < 0) {
|
||||
ceph_osdc_put_request(req);
|
||||
@@ -1562,6 +1570,8 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
|
||||
if (len != size)
|
||||
osd_req_op_extent_update(req, 0, len);
|
||||
|
||||
osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len);
|
||||
|
||||
/*
|
||||
* To simplify error handling, allow AIO when IO within i_size
|
||||
* or IO can be satisfied by single OSD request.
|
||||
@@ -1593,17 +1603,6 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
|
||||
req->r_mtime = mtime;
|
||||
}
|
||||
|
||||
osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len);
|
||||
op = &req->r_ops[0];
|
||||
if (sparse) {
|
||||
extent_cnt = __ceph_sparse_read_ext_count(inode, size);
|
||||
ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
|
||||
if (ret) {
|
||||
ceph_osdc_put_request(req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (aio_req) {
|
||||
aio_req->total_len += len;
|
||||
aio_req->num_reqs++;
|
||||
|
||||
@@ -2808,12 +2808,11 @@ retry:
|
||||
|
||||
if (pos < 0) {
|
||||
/*
|
||||
* A rename didn't occur, but somehow we didn't end up where
|
||||
* we thought we would. Throw a warning and try again.
|
||||
* The path is longer than PATH_MAX and this function
|
||||
* cannot ever succeed. Creating paths that long is
|
||||
* possible with Ceph, but Linux cannot use them.
|
||||
*/
|
||||
pr_warn_client(cl, "did not end path lookup where expected (pos = %d)\n",
|
||||
pos);
|
||||
goto retry;
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
}
|
||||
|
||||
*pbase = base;
|
||||
|
||||
@@ -431,6 +431,8 @@ static int ceph_parse_mount_param(struct fs_context *fc,
|
||||
|
||||
switch (token) {
|
||||
case Opt_snapdirname:
|
||||
if (strlen(param->string) > NAME_MAX)
|
||||
return invalfc(fc, "snapdirname too long");
|
||||
kfree(fsopt->snapdir_name);
|
||||
fsopt->snapdir_name = param->string;
|
||||
param->string = NULL;
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ struct inode *efivarfs_get_inode(struct super_block *sb,
|
||||
*
|
||||
* VariableName-12345678-1234-1234-1234-1234567891bc
|
||||
*/
|
||||
bool efivarfs_valid_name(const char *str, int len)
|
||||
static bool efivarfs_valid_name(const char *str, int len)
|
||||
{
|
||||
const char *s = str + len - EFI_VARIABLE_GUID_LEN;
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
|
||||
|
||||
extern const struct file_operations efivarfs_file_operations;
|
||||
extern const struct inode_operations efivarfs_dir_inode_operations;
|
||||
extern bool efivarfs_valid_name(const char *str, int len);
|
||||
extern struct inode *efivarfs_get_inode(struct super_block *sb,
|
||||
const struct inode *dir, int mode, dev_t dev,
|
||||
bool is_removable);
|
||||
|
||||
@@ -144,9 +144,6 @@ static int efivarfs_d_hash(const struct dentry *dentry, struct qstr *qstr)
|
||||
const unsigned char *s = qstr->name;
|
||||
unsigned int len = qstr->len;
|
||||
|
||||
if (!efivarfs_valid_name(s, len))
|
||||
return -EINVAL;
|
||||
|
||||
while (len-- > EFI_VARIABLE_GUID_LEN)
|
||||
hash = partial_name_hash(*s++, hash);
|
||||
|
||||
|
||||
+13
-23
@@ -63,10 +63,10 @@ void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb)
|
||||
|
||||
buf->file = NULL;
|
||||
if (erofs_is_fileio_mode(sbi)) {
|
||||
buf->file = sbi->fdev; /* some fs like FUSE needs it */
|
||||
buf->file = sbi->dif0.file; /* some fs like FUSE needs it */
|
||||
buf->mapping = buf->file->f_mapping;
|
||||
} else if (erofs_is_fscache_mode(sb))
|
||||
buf->mapping = sbi->s_fscache->inode->i_mapping;
|
||||
buf->mapping = sbi->dif0.fscache->inode->i_mapping;
|
||||
else
|
||||
buf->mapping = sb->s_bdev->bd_mapping;
|
||||
}
|
||||
@@ -186,19 +186,13 @@ out:
|
||||
}
|
||||
|
||||
static void erofs_fill_from_devinfo(struct erofs_map_dev *map,
|
||||
struct erofs_device_info *dif)
|
||||
struct super_block *sb, struct erofs_device_info *dif)
|
||||
{
|
||||
map->m_sb = sb;
|
||||
map->m_dif = dif;
|
||||
map->m_bdev = NULL;
|
||||
map->m_fp = NULL;
|
||||
if (dif->file) {
|
||||
if (S_ISBLK(file_inode(dif->file)->i_mode))
|
||||
map->m_bdev = file_bdev(dif->file);
|
||||
else
|
||||
map->m_fp = dif->file;
|
||||
}
|
||||
map->m_daxdev = dif->dax_dev;
|
||||
map->m_dax_part_off = dif->dax_part_off;
|
||||
map->m_fscache = dif->fscache;
|
||||
if (dif->file && S_ISBLK(file_inode(dif->file)->i_mode))
|
||||
map->m_bdev = file_bdev(dif->file);
|
||||
}
|
||||
|
||||
int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
|
||||
@@ -208,12 +202,8 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
|
||||
erofs_off_t startoff, length;
|
||||
int id;
|
||||
|
||||
map->m_bdev = sb->s_bdev;
|
||||
map->m_daxdev = EROFS_SB(sb)->dax_dev;
|
||||
map->m_dax_part_off = EROFS_SB(sb)->dax_part_off;
|
||||
map->m_fscache = EROFS_SB(sb)->s_fscache;
|
||||
map->m_fp = EROFS_SB(sb)->fdev;
|
||||
|
||||
erofs_fill_from_devinfo(map, sb, &EROFS_SB(sb)->dif0);
|
||||
map->m_bdev = sb->s_bdev; /* use s_bdev for the primary device */
|
||||
if (map->m_deviceid) {
|
||||
down_read(&devs->rwsem);
|
||||
dif = idr_find(&devs->tree, map->m_deviceid - 1);
|
||||
@@ -226,7 +216,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
|
||||
up_read(&devs->rwsem);
|
||||
return 0;
|
||||
}
|
||||
erofs_fill_from_devinfo(map, dif);
|
||||
erofs_fill_from_devinfo(map, sb, dif);
|
||||
up_read(&devs->rwsem);
|
||||
} else if (devs->extra_devices && !devs->flatdev) {
|
||||
down_read(&devs->rwsem);
|
||||
@@ -239,7 +229,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
|
||||
if (map->m_pa >= startoff &&
|
||||
map->m_pa < startoff + length) {
|
||||
map->m_pa -= startoff;
|
||||
erofs_fill_from_devinfo(map, dif);
|
||||
erofs_fill_from_devinfo(map, sb, dif);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -309,7 +299,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
|
||||
|
||||
iomap->offset = map.m_la;
|
||||
if (flags & IOMAP_DAX)
|
||||
iomap->dax_dev = mdev.m_daxdev;
|
||||
iomap->dax_dev = mdev.m_dif->dax_dev;
|
||||
else
|
||||
iomap->bdev = mdev.m_bdev;
|
||||
iomap->length = map.m_llen;
|
||||
@@ -338,7 +328,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
|
||||
iomap->type = IOMAP_MAPPED;
|
||||
iomap->addr = mdev.m_pa;
|
||||
if (flags & IOMAP_DAX)
|
||||
iomap->addr += mdev.m_dax_part_off;
|
||||
iomap->addr += mdev.m_dif->dax_part_off;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+6
-3
@@ -9,6 +9,7 @@ struct erofs_fileio_rq {
|
||||
struct bio_vec bvecs[BIO_MAX_VECS];
|
||||
struct bio bio;
|
||||
struct kiocb iocb;
|
||||
struct super_block *sb;
|
||||
};
|
||||
|
||||
struct erofs_fileio {
|
||||
@@ -52,8 +53,9 @@ static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq)
|
||||
rq->iocb.ki_pos = rq->bio.bi_iter.bi_sector << SECTOR_SHIFT;
|
||||
rq->iocb.ki_ioprio = get_current_ioprio();
|
||||
rq->iocb.ki_complete = erofs_fileio_ki_complete;
|
||||
rq->iocb.ki_flags = (rq->iocb.ki_filp->f_mode & FMODE_CAN_ODIRECT) ?
|
||||
IOCB_DIRECT : 0;
|
||||
if (test_opt(&EROFS_SB(rq->sb)->opt, DIRECT_IO) &&
|
||||
rq->iocb.ki_filp->f_mode & FMODE_CAN_ODIRECT)
|
||||
rq->iocb.ki_flags = IOCB_DIRECT;
|
||||
iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt,
|
||||
rq->bio.bi_iter.bi_size);
|
||||
ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter);
|
||||
@@ -67,7 +69,8 @@ static struct erofs_fileio_rq *erofs_fileio_rq_alloc(struct erofs_map_dev *mdev)
|
||||
GFP_KERNEL | __GFP_NOFAIL);
|
||||
|
||||
bio_init(&rq->bio, NULL, rq->bvecs, BIO_MAX_VECS, REQ_OP_READ);
|
||||
rq->iocb.ki_filp = mdev->m_fp;
|
||||
rq->iocb.ki_filp = mdev->m_dif->file;
|
||||
rq->sb = mdev->m_sb;
|
||||
return rq;
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -198,7 +198,7 @@ struct bio *erofs_fscache_bio_alloc(struct erofs_map_dev *mdev)
|
||||
|
||||
io = kmalloc(sizeof(*io), GFP_KERNEL | __GFP_NOFAIL);
|
||||
bio_init(&io->bio, NULL, io->bvecs, BIO_MAX_VECS, REQ_OP_READ);
|
||||
io->io.private = mdev->m_fscache->cookie;
|
||||
io->io.private = mdev->m_dif->fscache->cookie;
|
||||
io->io.end_io = erofs_fscache_bio_endio;
|
||||
refcount_set(&io->io.ref, 1);
|
||||
return &io->bio;
|
||||
@@ -316,7 +316,7 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_rq *req)
|
||||
if (!io)
|
||||
return -ENOMEM;
|
||||
iov_iter_xarray(&io->iter, ITER_DEST, &mapping->i_pages, pos, count);
|
||||
ret = erofs_fscache_read_io_async(mdev.m_fscache->cookie,
|
||||
ret = erofs_fscache_read_io_async(mdev.m_dif->fscache->cookie,
|
||||
mdev.m_pa + (pos - map.m_la), io);
|
||||
erofs_fscache_req_io_put(io);
|
||||
|
||||
@@ -657,7 +657,7 @@ int erofs_fscache_register_fs(struct super_block *sb)
|
||||
if (IS_ERR(fscache))
|
||||
return PTR_ERR(fscache);
|
||||
|
||||
sbi->s_fscache = fscache;
|
||||
sbi->dif0.fscache = fscache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -665,14 +665,14 @@ void erofs_fscache_unregister_fs(struct super_block *sb)
|
||||
{
|
||||
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
||||
|
||||
erofs_fscache_unregister_cookie(sbi->s_fscache);
|
||||
erofs_fscache_unregister_cookie(sbi->dif0.fscache);
|
||||
|
||||
if (sbi->domain)
|
||||
erofs_fscache_domain_put(sbi->domain);
|
||||
else
|
||||
fscache_relinquish_volume(sbi->volume, NULL, false);
|
||||
|
||||
sbi->s_fscache = NULL;
|
||||
sbi->dif0.fscache = NULL;
|
||||
sbi->volume = NULL;
|
||||
sbi->domain = NULL;
|
||||
}
|
||||
|
||||
+5
-10
@@ -113,6 +113,7 @@ struct erofs_xattr_prefix_item {
|
||||
};
|
||||
|
||||
struct erofs_sb_info {
|
||||
struct erofs_device_info dif0;
|
||||
struct erofs_mount_opts opt; /* options */
|
||||
#ifdef CONFIG_EROFS_FS_ZIP
|
||||
/* list for all registered superblocks, mainly for shrinker */
|
||||
@@ -130,13 +131,9 @@ struct erofs_sb_info {
|
||||
|
||||
struct erofs_sb_lz4_info lz4;
|
||||
#endif /* CONFIG_EROFS_FS_ZIP */
|
||||
struct file *fdev;
|
||||
struct inode *packed_inode;
|
||||
struct erofs_dev_context *devs;
|
||||
struct dax_device *dax_dev;
|
||||
u64 dax_part_off;
|
||||
u64 total_blocks;
|
||||
u32 primarydevice_blocks;
|
||||
|
||||
u32 meta_blkaddr;
|
||||
#ifdef CONFIG_EROFS_FS_XATTR
|
||||
@@ -172,7 +169,6 @@ struct erofs_sb_info {
|
||||
|
||||
/* fscache support */
|
||||
struct fscache_volume *volume;
|
||||
struct erofs_fscache *s_fscache;
|
||||
struct erofs_domain *domain;
|
||||
char *fsid;
|
||||
char *domain_id;
|
||||
@@ -186,6 +182,7 @@ struct erofs_sb_info {
|
||||
#define EROFS_MOUNT_POSIX_ACL 0x00000020
|
||||
#define EROFS_MOUNT_DAX_ALWAYS 0x00000040
|
||||
#define EROFS_MOUNT_DAX_NEVER 0x00000080
|
||||
#define EROFS_MOUNT_DIRECT_IO 0x00000100
|
||||
|
||||
#define clear_opt(opt, option) ((opt)->mount_opt &= ~EROFS_MOUNT_##option)
|
||||
#define set_opt(opt, option) ((opt)->mount_opt |= EROFS_MOUNT_##option)
|
||||
@@ -193,7 +190,7 @@ struct erofs_sb_info {
|
||||
|
||||
static inline bool erofs_is_fileio_mode(struct erofs_sb_info *sbi)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && sbi->fdev;
|
||||
return IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && sbi->dif0.file;
|
||||
}
|
||||
|
||||
static inline bool erofs_is_fscache_mode(struct super_block *sb)
|
||||
@@ -370,11 +367,9 @@ enum {
|
||||
};
|
||||
|
||||
struct erofs_map_dev {
|
||||
struct erofs_fscache *m_fscache;
|
||||
struct super_block *m_sb;
|
||||
struct erofs_device_info *m_dif;
|
||||
struct block_device *m_bdev;
|
||||
struct dax_device *m_daxdev;
|
||||
struct file *m_fp;
|
||||
u64 m_dax_part_off;
|
||||
|
||||
erofs_off_t m_pa;
|
||||
unsigned int m_deviceid;
|
||||
|
||||
+44
-36
@@ -218,7 +218,7 @@ static int erofs_scan_devices(struct super_block *sb,
|
||||
struct erofs_device_info *dif;
|
||||
int id, err = 0;
|
||||
|
||||
sbi->total_blocks = sbi->primarydevice_blocks;
|
||||
sbi->total_blocks = sbi->dif0.blocks;
|
||||
if (!erofs_sb_has_device_table(sbi))
|
||||
ondisk_extradevs = 0;
|
||||
else
|
||||
@@ -322,7 +322,7 @@ static int erofs_read_superblock(struct super_block *sb)
|
||||
sbi->sb_size);
|
||||
goto out;
|
||||
}
|
||||
sbi->primarydevice_blocks = le32_to_cpu(dsb->blocks);
|
||||
sbi->dif0.blocks = le32_to_cpu(dsb->blocks);
|
||||
sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr);
|
||||
#ifdef CONFIG_EROFS_FS_XATTR
|
||||
sbi->xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr);
|
||||
@@ -379,14 +379,8 @@ static void erofs_default_options(struct erofs_sb_info *sbi)
|
||||
}
|
||||
|
||||
enum {
|
||||
Opt_user_xattr,
|
||||
Opt_acl,
|
||||
Opt_cache_strategy,
|
||||
Opt_dax,
|
||||
Opt_dax_enum,
|
||||
Opt_device,
|
||||
Opt_fsid,
|
||||
Opt_domain_id,
|
||||
Opt_user_xattr, Opt_acl, Opt_cache_strategy, Opt_dax, Opt_dax_enum,
|
||||
Opt_device, Opt_fsid, Opt_domain_id, Opt_directio,
|
||||
Opt_err
|
||||
};
|
||||
|
||||
@@ -413,6 +407,7 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = {
|
||||
fsparam_string("device", Opt_device),
|
||||
fsparam_string("fsid", Opt_fsid),
|
||||
fsparam_string("domain_id", Opt_domain_id),
|
||||
fsparam_flag_no("directio", Opt_directio),
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -526,6 +521,16 @@ static int erofs_fc_parse_param(struct fs_context *fc,
|
||||
errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name);
|
||||
break;
|
||||
#endif
|
||||
case Opt_directio:
|
||||
#ifdef CONFIG_EROFS_FS_BACKED_BY_FILE
|
||||
if (result.boolean)
|
||||
set_opt(&sbi->opt, DIRECT_IO);
|
||||
else
|
||||
clear_opt(&sbi->opt, DIRECT_IO);
|
||||
#else
|
||||
errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -ENOPARAM;
|
||||
}
|
||||
@@ -617,9 +622,8 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sbi->dax_dev = fs_dax_get_by_bdev(sb->s_bdev,
|
||||
&sbi->dax_part_off,
|
||||
NULL, NULL);
|
||||
sbi->dif0.dax_dev = fs_dax_get_by_bdev(sb->s_bdev,
|
||||
&sbi->dif0.dax_part_off, NULL, NULL);
|
||||
}
|
||||
|
||||
err = erofs_read_superblock(sb);
|
||||
@@ -642,7 +646,7 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
}
|
||||
|
||||
if (test_opt(&sbi->opt, DAX_ALWAYS)) {
|
||||
if (!sbi->dax_dev) {
|
||||
if (!sbi->dif0.dax_dev) {
|
||||
errorfc(fc, "DAX unsupported by block device. Turning off DAX.");
|
||||
clear_opt(&sbi->opt, DAX_ALWAYS);
|
||||
} else if (sbi->blkszbits != PAGE_SHIFT) {
|
||||
@@ -718,16 +722,18 @@ static int erofs_fc_get_tree(struct fs_context *fc)
|
||||
GET_TREE_BDEV_QUIET_LOOKUP : 0);
|
||||
#ifdef CONFIG_EROFS_FS_BACKED_BY_FILE
|
||||
if (ret == -ENOTBLK) {
|
||||
struct file *file;
|
||||
|
||||
if (!fc->source)
|
||||
return invalf(fc, "No source specified");
|
||||
sbi->fdev = filp_open(fc->source, O_RDONLY | O_LARGEFILE, 0);
|
||||
if (IS_ERR(sbi->fdev))
|
||||
return PTR_ERR(sbi->fdev);
|
||||
file = filp_open(fc->source, O_RDONLY | O_LARGEFILE, 0);
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
sbi->dif0.file = file;
|
||||
|
||||
if (S_ISREG(file_inode(sbi->fdev)->i_mode) &&
|
||||
sbi->fdev->f_mapping->a_ops->read_folio)
|
||||
if (S_ISREG(file_inode(sbi->dif0.file)->i_mode) &&
|
||||
sbi->dif0.file->f_mapping->a_ops->read_folio)
|
||||
return get_tree_nodev(fc, erofs_fc_fill_super);
|
||||
fput(sbi->fdev);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
@@ -778,17 +784,22 @@ static void erofs_free_dev_context(struct erofs_dev_context *devs)
|
||||
kfree(devs);
|
||||
}
|
||||
|
||||
static void erofs_sb_free(struct erofs_sb_info *sbi)
|
||||
{
|
||||
erofs_free_dev_context(sbi->devs);
|
||||
kfree(sbi->fsid);
|
||||
kfree(sbi->domain_id);
|
||||
if (sbi->dif0.file)
|
||||
fput(sbi->dif0.file);
|
||||
kfree(sbi);
|
||||
}
|
||||
|
||||
static void erofs_fc_free(struct fs_context *fc)
|
||||
{
|
||||
struct erofs_sb_info *sbi = fc->s_fs_info;
|
||||
|
||||
if (!sbi)
|
||||
return;
|
||||
|
||||
erofs_free_dev_context(sbi->devs);
|
||||
kfree(sbi->fsid);
|
||||
kfree(sbi->domain_id);
|
||||
kfree(sbi);
|
||||
if (sbi) /* free here if an error occurs before transferring to sb */
|
||||
erofs_sb_free(sbi);
|
||||
}
|
||||
|
||||
static const struct fs_context_operations erofs_context_ops = {
|
||||
@@ -824,19 +835,14 @@ static void erofs_kill_sb(struct super_block *sb)
|
||||
{
|
||||
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
||||
|
||||
if ((IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid) || sbi->fdev)
|
||||
if ((IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid) ||
|
||||
sbi->dif0.file)
|
||||
kill_anon_super(sb);
|
||||
else
|
||||
kill_block_super(sb);
|
||||
|
||||
erofs_free_dev_context(sbi->devs);
|
||||
fs_put_dax(sbi->dax_dev, NULL);
|
||||
fs_put_dax(sbi->dif0.dax_dev, NULL);
|
||||
erofs_fscache_unregister_fs(sb);
|
||||
kfree(sbi->fsid);
|
||||
kfree(sbi->domain_id);
|
||||
if (sbi->fdev)
|
||||
fput(sbi->fdev);
|
||||
kfree(sbi);
|
||||
erofs_sb_free(sbi);
|
||||
sb->s_fs_info = NULL;
|
||||
}
|
||||
|
||||
@@ -962,6 +968,8 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root)
|
||||
seq_puts(seq, ",dax=always");
|
||||
if (test_opt(opt, DAX_NEVER))
|
||||
seq_puts(seq, ",dax=never");
|
||||
if (erofs_is_fileio_mode(sbi) && test_opt(opt, DIRECT_IO))
|
||||
seq_puts(seq, ",directio");
|
||||
#ifdef CONFIG_EROFS_FS_ONDEMAND
|
||||
if (sbi->fsid)
|
||||
seq_printf(seq, ",fsid=%s", sbi->fsid);
|
||||
|
||||
+2
-2
@@ -1679,9 +1679,9 @@ drain_io:
|
||||
erofs_fscache_submit_bio(bio);
|
||||
else
|
||||
submit_bio(bio);
|
||||
if (memstall)
|
||||
psi_memstall_leave(&pflags);
|
||||
}
|
||||
if (memstall)
|
||||
psi_memstall_leave(&pflags);
|
||||
|
||||
/*
|
||||
* although background is preferred, no one is pending for submission.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user