Merge 5.15.82 into android14-5.15

Changes in 5.15.82
	arm64: mte: Avoid setting PG_mte_tagged if no tags cleared or restored
	drm/i915: Create a dummy object for gen6 ppgtt
	drm/i915/gt: Use i915_vm_put on ppgtt_create error paths
	erofs: fix order >= MAX_ORDER warning due to crafted negative i_size
	btrfs: sink iterator parameter to btrfs_ioctl_logical_to_ino
	btrfs: free btrfs_path before copying inodes to userspace
	spi: spi-imx: Fix spi_bus_clk if requested clock is higher than input clock
	btrfs: move QUOTA_ENABLED check to rescan_should_stop from btrfs_qgroup_rescan_worker
	btrfs: qgroup: fix sleep from invalid context bug in btrfs_qgroup_inherit()
	drm/display/dp_mst: Fix drm_dp_mst_add_affected_dsc_crtcs() return code
	drm/amdgpu: update drm_display_info correctly when the edid is read
	drm/amdgpu: Partially revert "drm/amdgpu: update drm_display_info correctly when the edid is read"
	iio: health: afe4403: Fix oob read in afe4403_read_raw
	iio: health: afe4404: Fix oob read in afe4404_[read|write]_raw
	iio: light: rpr0521: add missing Kconfig dependencies
	bpf, perf: Use subprog name when reporting subprog ksymbol
	scripts/faddr2line: Fix regression in name resolution on ppc64le
	ARM: at91: rm9200: fix usb device clock id
	libbpf: Handle size overflow for ringbuf mmap
	hwmon: (ltc2947) fix temperature scaling
	hwmon: (ina3221) Fix shunt sum critical calculation
	hwmon: (i5500_temp) fix missing pci_disable_device()
	hwmon: (ibmpex) Fix possible UAF when ibmpex_register_bmc() fails
	bpf: Do not copy spin lock field from user in bpf_selem_alloc
	nvmem: rmem: Fix return value check in rmem_read()
	of: property: decrement node refcount in of_fwnode_get_reference_args()
	ixgbevf: Fix resource leak in ixgbevf_init_module()
	i40e: Fix error handling in i40e_init_module()
	fm10k: Fix error handling in fm10k_init_module()
	iavf: remove redundant ret variable
	iavf: Fix error handling in iavf_init_module()
	e100: Fix possible use after free in e100_xmit_prepare
	net/mlx5: DR, Rename list field in matcher struct to list_node
	net/mlx5: DR, Fix uninitialized var warning
	net/mlx5: Fix uninitialized variable bug in outlen_write()
	net/mlx5e: Fix use-after-free when reverting termination table
	can: sja1000_isa: sja1000_isa_probe(): add missing free_sja1000dev()
	can: cc770: cc770_isa_probe(): add missing free_cc770dev()
	can: etas_es58x: es58x_init_netdev(): free netdev when register_candev()
	can: m_can: pci: add missing m_can_class_free_dev() in probe/remove methods
	can: m_can: Add check for devm_clk_get
	qlcnic: fix sleep-in-atomic-context bugs caused by msleep
	aquantia: Do not purge addresses when setting the number of rings
	wifi: cfg80211: fix buffer overflow in elem comparison
	wifi: cfg80211: don't allow multi-BSSID in S1G
	wifi: mac8021: fix possible oob access in ieee80211_get_rate_duration
	net: phy: fix null-ptr-deref while probe() failed
	net: ethernet: ti: am65-cpsw: fix error handling in am65_cpsw_nuss_probe()
	net: net_netdev: Fix error handling in ntb_netdev_init_module()
	net/9p: Fix a potential socket leak in p9_socket_open
	net: ethernet: nixge: fix NULL dereference
	net: wwan: iosm: fix kernel test robot reported error
	net: wwan: iosm: fix dma_alloc_coherent incompatible pointer type
	dsa: lan9303: Correct stat name
	tipc: re-fetch skb cb after tipc_msg_validate
	net: hsr: Fix potential use-after-free
	net: mdiobus: fix unbalanced node reference count
	afs: Fix fileserver probe RTT handling
	net: tun: Fix use-after-free in tun_detach()
	packet: do not set TP_STATUS_CSUM_VALID on CHECKSUM_COMPLETE
	sctp: fix memory leak in sctp_stream_outq_migrate()
	net: ethernet: renesas: ravb: Fix promiscuous mode after system resumed
	hwmon: (coretemp) Check for null before removing sysfs attrs
	hwmon: (coretemp) fix pci device refcount leak in nv1a_ram_new()
	riscv: vdso: fix section overlapping under some conditions
	riscv: mm: Proper page permissions after initmem free
	ALSA: dice: fix regression for Lexicon I-ONIX FW810S
	error-injection: Add prompt for function error injection
	tools/vm/slabinfo-gnuplot: use "grep -E" instead of "egrep"
	nilfs2: fix NULL pointer dereference in nilfs_palloc_commit_free_entry()
	x86/bugs: Make sure MSR_SPEC_CTRL is updated properly upon resume from S3
	pinctrl: intel: Save and restore pins in "direct IRQ" mode
	v4l2: don't fall back to follow_pfn() if pin_user_pages_fast() fails
	net: stmmac: Set MAC's flow control register to reflect current settings
	mmc: mmc_test: Fix removal of debugfs file
	mmc: core: Fix ambiguous TRIM and DISCARD arg
	mmc: sdhci-esdhc-imx: correct CQHCI exit halt state check
	mmc: sdhci-sprd: Fix no reset data and command after voltage switch
	mmc: sdhci: Fix voltage switch delay
	drm/amdgpu: temporarily disable broken Clang builds due to blown stack-frame
	drm/amdgpu: enable Vangogh VCN indirect sram mode
	drm/i915: Fix negative value passed as remaining time
	drm/i915: Never return 0 if not all requests retired
	tracing/osnoise: Fix duration type
	tracing: Fix race where histograms can be called before the event
	tracing: Free buffers when a used dynamic event is removed
	io_uring: update res mask in io_poll_check_events
	io_uring: fix tw losing poll events
	io_uring: cmpxchg for poll arm refs release
	io_uring: make poll refs more robust
	io_uring/poll: fix poll_refs race with cancelation
	KVM: x86/mmu: Fix race condition in direct_page_fault
	ASoC: ops: Fix bounds check for _sx controls
	pinctrl: single: Fix potential division by zero
	riscv: Sync efi page table's kernel mappings before switching
	riscv: fix race when vmap stack overflow
	riscv: kexec: Fixup irq controller broken in kexec crash path
	nvme: fix SRCU protection of nvme_ns_head list
	iommu/vt-d: Fix PCI device refcount leak in has_external_pci()
	iommu/vt-d: Fix PCI device refcount leak in dmar_dev_scope_init()
	mm: __isolate_lru_page_prepare() in isolate_migratepages_block()
	mm: migrate: fix THP's mapcount on isolation
	parisc: Increase FRAME_WARN to 2048 bytes on parisc
	Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is enabled
	selftests: net: add delete nexthop route warning test
	selftests: net: fix nexthop warning cleanup double ip typo
	ipv4: Handle attempt to delete multipath route when fib_info contains an nh reference
	ipv4: Fix route deletion when nexthop info is not specified
	serial: stm32: Factor out GPIO RTS toggling into separate function
	serial: stm32: Use TC interrupt to deassert GPIO RTS in RS485 mode
	serial: stm32: Deassert Transmit Enable on ->rs485_config()
	i2c: npcm7xx: Fix error handling in npcm_i2c_init()
	i2c: imx: Only DMA messages with I2C_M_DMA_SAFE flag set
	ACPI: HMAT: remove unnecessary variable initialization
	ACPI: HMAT: Fix initiator registration for single-initiator systems
	Revert "clocksource/drivers/riscv: Events are stopped during CPU suspend"
	char: tpm: Protect tpm_pm_suspend with locks
	Input: raydium_ts_i2c - fix memory leak in raydium_i2c_send()
	ipc/sem: Fix dangling sem_array access in semtimedop race
	proc: avoid integer type confusion in get_proc_long
	proc: proc_skip_spaces() shouldn't think it is working on C strings
	Linux 5.15.82

Change-Id: I1631261fcfd321674c546c41628bb3283e02f1a5
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2022-12-08 16:43:35 +00:00
132 changed files with 1054 additions and 560 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 5 VERSION = 5
PATCHLEVEL = 15 PATCHLEVEL = 15
SUBLEVEL = 81 SUBLEVEL = 82
EXTRAVERSION = EXTRAVERSION =
NAME = Trick or Treat NAME = Trick or Treat

View File

@@ -660,7 +660,7 @@
compatible = "atmel,at91rm9200-udc"; compatible = "atmel,at91rm9200-udc";
reg = <0xfffb0000 0x4000>; reg = <0xfffb0000 0x4000>;
interrupts = <11 IRQ_TYPE_LEVEL_HIGH 2>; interrupts = <11 IRQ_TYPE_LEVEL_HIGH 2>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 11>, <&pmc PMC_TYPE_SYSTEM 2>; clocks = <&pmc PMC_TYPE_PERIPHERAL 11>, <&pmc PMC_TYPE_SYSTEM 1>;
clock-names = "pclk", "hclk"; clock-names = "pclk", "hclk";
status = "disabled"; status = "disabled";
}; };

View File

@@ -56,6 +56,11 @@ static void mte_sync_page_tags(struct page *page, pte_t old_pte,
* the new page->flags are visible before the tags were updated. * the new page->flags are visible before the tags were updated.
*/ */
smp_wmb(); smp_wmb();
/*
* Test PG_mte_tagged again in case it was racing with another
* set_pte_at().
*/
if (!test_and_set_bit(PG_mte_tagged, &page->flags))
mte_clear_page_tags(page_address(page)); mte_clear_page_tags(page_address(page));
} }
@@ -72,7 +77,7 @@ void mte_sync_tags(pte_t old_pte, pte_t pte)
/* if PG_mte_tagged is set, tags have already been initialised */ /* if PG_mte_tagged is set, tags have already been initialised */
for (i = 0; i < nr_pages; i++, page++) { for (i = 0; i < nr_pages; i++, page++) {
if (!test_and_set_bit(PG_mte_tagged, &page->flags)) if (!test_bit(PG_mte_tagged, &page->flags))
mte_sync_page_tags(page, old_pte, check_swap, mte_sync_page_tags(page, old_pte, check_swap,
pte_is_tagged); pte_is_tagged);
} }

View File

@@ -62,6 +62,11 @@ bool mte_restore_tags(swp_entry_t entry, struct page *page)
* the new page->flags are visible before the tags were updated. * the new page->flags are visible before the tags were updated.
*/ */
smp_wmb(); smp_wmb();
/*
* Test PG_mte_tagged again in case it was racing with another
* set_pte_at().
*/
if (!test_and_set_bit(PG_mte_tagged, &page->flags))
mte_restore_page_tags(page_address(page), tags); mte_restore_page_tags(page_address(page), tags);
return true; return true;

View File

@@ -23,6 +23,7 @@
#define REG_L __REG_SEL(ld, lw) #define REG_L __REG_SEL(ld, lw)
#define REG_S __REG_SEL(sd, sw) #define REG_S __REG_SEL(sd, sw)
#define REG_SC __REG_SEL(sc.d, sc.w) #define REG_SC __REG_SEL(sc.d, sc.w)
#define REG_AMOSWAP_AQ __REG_SEL(amoswap.d.aq, amoswap.w.aq)
#define REG_ASM __REG_SEL(.dword, .word) #define REG_ASM __REG_SEL(.dword, .word)
#define SZREG __REG_SEL(8, 4) #define SZREG __REG_SEL(8, 4)
#define LGREG __REG_SEL(3, 2) #define LGREG __REG_SEL(3, 2)

View File

@@ -10,6 +10,7 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/pgalloc.h>
#ifdef CONFIG_EFI #ifdef CONFIG_EFI
extern void efi_init(void); extern void efi_init(void);
@@ -20,7 +21,10 @@ extern void efi_init(void);
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md); int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
#define arch_efi_call_virt_setup() efi_virtmap_load() #define arch_efi_call_virt_setup() ({ \
sync_kernel_mappings(efi_mm.pgd); \
efi_virtmap_load(); \
})
#define arch_efi_call_virt_teardown() efi_virtmap_unload() #define arch_efi_call_virt_teardown() efi_virtmap_unload()
#define arch_efi_call_virt(p, f, args...) p->f(args) #define arch_efi_call_virt(p, f, args...) p->f(args)

View File

@@ -38,6 +38,13 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
} }
#endif /* __PAGETABLE_PMD_FOLDED */ #endif /* __PAGETABLE_PMD_FOLDED */
static inline void sync_kernel_mappings(pgd_t *pgd)
{
memcpy(pgd + USER_PTRS_PER_PGD,
init_mm.pgd + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
static inline pgd_t *pgd_alloc(struct mm_struct *mm) static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{ {
pgd_t *pgd; pgd_t *pgd;
@@ -46,9 +53,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
if (likely(pgd != NULL)) { if (likely(pgd != NULL)) {
memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
/* Copy kernel mappings */ /* Copy kernel mappings */
memcpy(pgd + USER_PTRS_PER_PGD, sync_kernel_mappings(pgd);
init_mm.pgd + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
} }
return pgd; return pgd;
} }

View File

@@ -387,6 +387,19 @@ handle_syscall_trace_exit:
#ifdef CONFIG_VMAP_STACK #ifdef CONFIG_VMAP_STACK
handle_kernel_stack_overflow: handle_kernel_stack_overflow:
/*
* Takes the psuedo-spinlock for the shadow stack, in case multiple
* harts are concurrently overflowing their kernel stacks. We could
* store any value here, but since we're overflowing the kernel stack
* already we only have SP to use as a scratch register. So we just
* swap in the address of the spinlock, as that's definately non-zero.
*
* Pairs with a store_release in handle_bad_stack().
*/
1: la sp, spin_shadow_stack
REG_AMOSWAP_AQ sp, sp, (sp)
bnez sp, 1b
la sp, shadow_stack la sp, shadow_stack
addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE addi sp, sp, SHADOW_OVERFLOW_STACK_SIZE

View File

@@ -15,6 +15,8 @@
#include <linux/compiler.h> /* For unreachable() */ #include <linux/compiler.h> /* For unreachable() */
#include <linux/cpu.h> /* For cpu_down() */ #include <linux/cpu.h> /* For cpu_down() */
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
/* /*
* kexec_image_info - Print received image details * kexec_image_info - Print received image details
@@ -154,6 +156,37 @@ void crash_smp_send_stop(void)
cpus_stopped = 1; cpus_stopped = 1;
} }
static void machine_kexec_mask_interrupts(void)
{
unsigned int i;
struct irq_desc *desc;
for_each_irq_desc(i, desc) {
struct irq_chip *chip;
int ret;
chip = irq_desc_get_chip(desc);
if (!chip)
continue;
/*
* First try to remove the active state. If this
* fails, try to EOI the interrupt.
*/
ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
if (ret && irqd_irq_inprogress(&desc->irq_data) &&
chip->irq_eoi)
chip->irq_eoi(&desc->irq_data);
if (chip->irq_mask)
chip->irq_mask(&desc->irq_data);
if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
chip->irq_disable(&desc->irq_data);
}
}
/* /*
* machine_crash_shutdown - Prepare to kexec after a kernel crash * machine_crash_shutdown - Prepare to kexec after a kernel crash
* *
@@ -169,6 +202,8 @@ machine_crash_shutdown(struct pt_regs *regs)
crash_smp_send_stop(); crash_smp_send_stop();
crash_save_cpu(regs, smp_processor_id()); crash_save_cpu(regs, smp_processor_id());
machine_kexec_mask_interrupts();
pr_info("Starting crashdump kernel...\n"); pr_info("Starting crashdump kernel...\n");
} }

View File

@@ -331,10 +331,11 @@ subsys_initcall(topology_init);
void free_initmem(void) void free_initmem(void)
{ {
if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) {
set_kernel_memory(lm_alias(__init_begin), lm_alias(__init_end), set_kernel_memory(lm_alias(__init_begin), lm_alias(__init_end), set_memory_rw_nx);
IS_ENABLED(CONFIG_64BIT) ? if (IS_ENABLED(CONFIG_64BIT))
set_memory_rw : set_memory_rw_nx); set_kernel_memory(__init_begin, __init_end, set_memory_nx);
}
free_initmem_default(POISON_FREE_INITMEM); free_initmem_default(POISON_FREE_INITMEM);
} }

View File

@@ -218,11 +218,29 @@ asmlinkage unsigned long get_overflow_stack(void)
OVERFLOW_STACK_SIZE; OVERFLOW_STACK_SIZE;
} }
/*
* A pseudo spinlock to protect the shadow stack from being used by multiple
* harts concurrently. This isn't a real spinlock because the lock side must
* be taken without a valid stack and only a single register, it's only taken
* while in the process of panicing anyway so the performance and error
* checking a proper spinlock gives us doesn't matter.
*/
unsigned long spin_shadow_stack;
asmlinkage void handle_bad_stack(struct pt_regs *regs) asmlinkage void handle_bad_stack(struct pt_regs *regs)
{ {
unsigned long tsk_stk = (unsigned long)current->stack; unsigned long tsk_stk = (unsigned long)current->stack;
unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack); unsigned long ovf_stk = (unsigned long)this_cpu_ptr(overflow_stack);
/*
* We're done with the shadow stack by this point, as we're on the
* overflow stack. Tell any other concurrent overflowing harts that
* they can proceed with panicing by releasing the pseudo-spinlock.
*
* This pairs with an amoswap.aq in handle_kernel_stack_overflow.
*/
smp_store_release(&spin_shadow_stack, 0);
console_verbose(); console_verbose();
pr_emerg("Insufficient stack space to handle exception!\n"); pr_emerg("Insufficient stack space to handle exception!\n");

View File

@@ -17,6 +17,7 @@ vdso-syms += flush_icache
obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o obj-vdso = $(patsubst %, %.o, $(vdso-syms)) note.o
ccflags-y := -fno-stack-protector ccflags-y := -fno-stack-protector
ccflags-y += -DDISABLE_BRANCH_PROFILING
ifneq ($(c-gettimeofday-y),) ifneq ($(c-gettimeofday-y),)
CFLAGS_vgettimeofday.o += -fPIC -include $(c-gettimeofday-y) CFLAGS_vgettimeofday.o += -fPIC -include $(c-gettimeofday-y)

View File

@@ -310,7 +310,7 @@ static inline void indirect_branch_prediction_barrier(void)
/* The Intel SPEC CTRL MSR base value cache */ /* The Intel SPEC CTRL MSR base value cache */
extern u64 x86_spec_ctrl_base; extern u64 x86_spec_ctrl_base;
DECLARE_PER_CPU(u64, x86_spec_ctrl_current); DECLARE_PER_CPU(u64, x86_spec_ctrl_current);
extern void write_spec_ctrl_current(u64 val, bool force); extern void update_spec_ctrl_cond(u64 val);
extern u64 spec_ctrl_current(void); extern u64 spec_ctrl_current(void);
/* /*

View File

@@ -60,11 +60,18 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_current);
static DEFINE_MUTEX(spec_ctrl_mutex); static DEFINE_MUTEX(spec_ctrl_mutex);
/* Update SPEC_CTRL MSR and its cached copy unconditionally */
static void update_spec_ctrl(u64 val)
{
this_cpu_write(x86_spec_ctrl_current, val);
wrmsrl(MSR_IA32_SPEC_CTRL, val);
}
/* /*
* Keep track of the SPEC_CTRL MSR value for the current task, which may differ * Keep track of the SPEC_CTRL MSR value for the current task, which may differ
* from x86_spec_ctrl_base due to STIBP/SSB in __speculation_ctrl_update(). * from x86_spec_ctrl_base due to STIBP/SSB in __speculation_ctrl_update().
*/ */
void write_spec_ctrl_current(u64 val, bool force) void update_spec_ctrl_cond(u64 val)
{ {
if (this_cpu_read(x86_spec_ctrl_current) == val) if (this_cpu_read(x86_spec_ctrl_current) == val)
return; return;
@@ -75,7 +82,7 @@ void write_spec_ctrl_current(u64 val, bool force)
* When KERNEL_IBRS this MSR is written on return-to-user, unless * When KERNEL_IBRS this MSR is written on return-to-user, unless
* forced the update can be delayed until that time. * forced the update can be delayed until that time.
*/ */
if (force || !cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS)) if (!cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS))
wrmsrl(MSR_IA32_SPEC_CTRL, val); wrmsrl(MSR_IA32_SPEC_CTRL, val);
} }
@@ -1328,7 +1335,7 @@ static void __init spec_ctrl_disable_kernel_rrsba(void)
if (ia32_cap & ARCH_CAP_RRSBA) { if (ia32_cap & ARCH_CAP_RRSBA) {
x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S; x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
write_spec_ctrl_current(x86_spec_ctrl_base, true); update_spec_ctrl(x86_spec_ctrl_base);
} }
} }
@@ -1450,7 +1457,7 @@ static void __init spectre_v2_select_mitigation(void)
if (spectre_v2_in_ibrs_mode(mode)) { if (spectre_v2_in_ibrs_mode(mode)) {
x86_spec_ctrl_base |= SPEC_CTRL_IBRS; x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
write_spec_ctrl_current(x86_spec_ctrl_base, true); update_spec_ctrl(x86_spec_ctrl_base);
} }
switch (mode) { switch (mode) {
@@ -1564,7 +1571,7 @@ static void __init spectre_v2_select_mitigation(void)
static void update_stibp_msr(void * __unused) static void update_stibp_msr(void * __unused)
{ {
u64 val = spec_ctrl_current() | (x86_spec_ctrl_base & SPEC_CTRL_STIBP); u64 val = spec_ctrl_current() | (x86_spec_ctrl_base & SPEC_CTRL_STIBP);
write_spec_ctrl_current(val, true); update_spec_ctrl(val);
} }
/* Update x86_spec_ctrl_base in case SMT state changed. */ /* Update x86_spec_ctrl_base in case SMT state changed. */
@@ -1797,7 +1804,7 @@ static enum ssb_mitigation __init __ssb_select_mitigation(void)
x86_amd_ssb_disable(); x86_amd_ssb_disable();
} else { } else {
x86_spec_ctrl_base |= SPEC_CTRL_SSBD; x86_spec_ctrl_base |= SPEC_CTRL_SSBD;
write_spec_ctrl_current(x86_spec_ctrl_base, true); update_spec_ctrl(x86_spec_ctrl_base);
} }
} }
@@ -2048,7 +2055,7 @@ int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
void x86_spec_ctrl_setup_ap(void) void x86_spec_ctrl_setup_ap(void)
{ {
if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL)) if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL))
write_spec_ctrl_current(x86_spec_ctrl_base, true); update_spec_ctrl(x86_spec_ctrl_base);
if (ssb_mode == SPEC_STORE_BYPASS_DISABLE) if (ssb_mode == SPEC_STORE_BYPASS_DISABLE)
x86_amd_ssb_disable(); x86_amd_ssb_disable();

View File

@@ -584,7 +584,7 @@ static __always_inline void __speculation_ctrl_update(unsigned long tifp,
} }
if (updmsr) if (updmsr)
write_spec_ctrl_current(msr, false); update_spec_ctrl_cond(msr);
} }
static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk) static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)

View File

@@ -2369,6 +2369,7 @@ static bool __kvm_mmu_prepare_zap_page(struct kvm *kvm,
{ {
bool list_unstable; bool list_unstable;
lockdep_assert_held_write(&kvm->mmu_lock);
trace_kvm_mmu_prepare_zap_page(sp); trace_kvm_mmu_prepare_zap_page(sp);
++kvm->stat.mmu_shadow_zapped; ++kvm->stat.mmu_shadow_zapped;
*nr_zapped = mmu_zap_unsync_children(kvm, sp, invalid_list); *nr_zapped = mmu_zap_unsync_children(kvm, sp, invalid_list);
@@ -4019,16 +4020,17 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
if (!is_noslot_pfn(pfn) && mmu_notifier_retry_hva(vcpu->kvm, mmu_seq, hva)) if (!is_noslot_pfn(pfn) && mmu_notifier_retry_hva(vcpu->kvm, mmu_seq, hva))
goto out_unlock; goto out_unlock;
if (is_tdp_mmu_fault) {
r = kvm_tdp_mmu_map(vcpu, gpa, error_code, map_writable, max_level,
pfn, prefault);
} else {
r = make_mmu_pages_available(vcpu); r = make_mmu_pages_available(vcpu);
if (r) if (r)
goto out_unlock; goto out_unlock;
if (is_tdp_mmu_fault)
r = kvm_tdp_mmu_map(vcpu, gpa, error_code, map_writable, max_level,
pfn, prefault);
else
r = __direct_map(vcpu, gpa, error_code, map_writable, max_level, pfn, r = __direct_map(vcpu, gpa, error_code, map_writable, max_level, pfn,
prefault, is_tdp); prefault, is_tdp);
}
out_unlock: out_unlock:
if (is_tdp_mmu_fault) if (is_tdp_mmu_fault)

View File

@@ -563,17 +563,26 @@ static int initiator_cmp(void *priv, const struct list_head *a,
{ {
struct memory_initiator *ia; struct memory_initiator *ia;
struct memory_initiator *ib; struct memory_initiator *ib;
unsigned long *p_nodes = priv;
ia = list_entry(a, struct memory_initiator, node); ia = list_entry(a, struct memory_initiator, node);
ib = list_entry(b, struct memory_initiator, node); ib = list_entry(b, struct memory_initiator, node);
set_bit(ia->processor_pxm, p_nodes);
set_bit(ib->processor_pxm, p_nodes);
return ia->processor_pxm - ib->processor_pxm; return ia->processor_pxm - ib->processor_pxm;
} }
static int initiators_to_nodemask(unsigned long *p_nodes)
{
struct memory_initiator *initiator;
if (list_empty(&initiators))
return -ENXIO;
list_for_each_entry(initiator, &initiators, node)
set_bit(initiator->processor_pxm, p_nodes);
return 0;
}
static void hmat_register_target_initiators(struct memory_target *target) static void hmat_register_target_initiators(struct memory_target *target)
{ {
static DECLARE_BITMAP(p_nodes, MAX_NUMNODES); static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
@@ -610,7 +619,10 @@ static void hmat_register_target_initiators(struct memory_target *target)
* initiators. * initiators.
*/ */
bitmap_zero(p_nodes, MAX_NUMNODES); bitmap_zero(p_nodes, MAX_NUMNODES);
list_sort(p_nodes, &initiators, initiator_cmp); list_sort(NULL, &initiators, initiator_cmp);
if (initiators_to_nodemask(p_nodes) < 0)
return;
if (!access0done) { if (!access0done) {
for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) { for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
loc = localities_types[i]; loc = localities_types[i];
@@ -644,8 +656,9 @@ static void hmat_register_target_initiators(struct memory_target *target)
/* Access 1 ignores Generic Initiators */ /* Access 1 ignores Generic Initiators */
bitmap_zero(p_nodes, MAX_NUMNODES); bitmap_zero(p_nodes, MAX_NUMNODES);
list_sort(p_nodes, &initiators, initiator_cmp); if (initiators_to_nodemask(p_nodes) < 0)
best = 0; return;
for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) { for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
loc = localities_types[i]; loc = localities_types[i];
if (!loc) if (!loc)

View File

@@ -401,13 +401,14 @@ int tpm_pm_suspend(struct device *dev)
!pm_suspend_via_firmware()) !pm_suspend_via_firmware())
goto suspended; goto suspended;
if (!tpm_chip_start(chip)) { rc = tpm_try_get_ops(chip);
if (!rc) {
if (chip->flags & TPM_CHIP_FLAG_TPM2) if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_STATE); tpm2_shutdown(chip, TPM2_SU_STATE);
else else
rc = tpm1_pm_suspend(chip, tpm_suspend_pcr); rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
tpm_chip_stop(chip); tpm_put_ops(chip);
} }
suspended: suspended:

View File

@@ -40,7 +40,7 @@ static const struct clk_pll_characteristics rm9200_pll_characteristics = {
}; };
static const struct sck at91rm9200_systemck[] = { static const struct sck at91rm9200_systemck[] = {
{ .n = "udpck", .p = "usbck", .id = 2 }, { .n = "udpck", .p = "usbck", .id = 1 },
{ .n = "uhpck", .p = "usbck", .id = 4 }, { .n = "uhpck", .p = "usbck", .id = 4 },
{ .n = "pck0", .p = "prog0", .id = 8 }, { .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 }, { .n = "pck1", .p = "prog1", .id = 9 },

View File

@@ -32,7 +32,7 @@ static int riscv_clock_next_event(unsigned long delta,
static unsigned int riscv_clock_event_irq; static unsigned int riscv_clock_event_irq;
static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = { static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = {
.name = "riscv_timer_clockevent", .name = "riscv_timer_clockevent",
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP, .features = CLOCK_EVT_FEAT_ONESHOT,
.rating = 100, .rating = 100,
.set_next_event = riscv_clock_next_event, .set_next_event = riscv_clock_next_event,
}; };

View File

@@ -315,8 +315,10 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector)
if (!amdgpu_connector->edid) { if (!amdgpu_connector->edid) {
/* some laptops provide a hardcoded edid in rom for LCDs */ /* some laptops provide a hardcoded edid in rom for LCDs */
if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) || if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
(connector->connector_type == DRM_MODE_CONNECTOR_eDP))) (connector->connector_type == DRM_MODE_CONNECTOR_eDP))) {
amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev); amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
drm_connector_update_edid_property(connector, amdgpu_connector->edid);
}
} }
} }

View File

@@ -149,6 +149,9 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
break; break;
case CHIP_VANGOGH: case CHIP_VANGOGH:
fw_name = FIRMWARE_VANGOGH; fw_name = FIRMWARE_VANGOGH;
if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
(adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
adev->vcn.indirect_sram = true;
break; break;
case CHIP_DIMGREY_CAVEFISH: case CHIP_DIMGREY_CAVEFISH:
fw_name = FIRMWARE_DIMGREY_CAVEFISH; fw_name = FIRMWARE_DIMGREY_CAVEFISH;

View File

@@ -5,6 +5,7 @@ menu "Display Engine Configuration"
config DRM_AMD_DC config DRM_AMD_DC
bool "AMD DC - Enable new display engine" bool "AMD DC - Enable new display engine"
default y default y
depends on BROKEN || !CC_IS_CLANG || X86_64 || SPARC64 || ARM64
select SND_HDA_COMPONENT if SND_HDA_CORE select SND_HDA_COMPONENT if SND_HDA_CORE
select DRM_AMD_DC_DCN if (X86 || PPC64) && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS) select DRM_AMD_DC_DCN if (X86 || PPC64) && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS)
help help
@@ -12,6 +13,12 @@ config DRM_AMD_DC
support for AMDGPU. This adds required support for Vega and support for AMDGPU. This adds required support for Vega and
Raven ASICs. Raven ASICs.
calculate_bandwidth() is presently broken on all !(X86_64 || SPARC64 || ARM64)
architectures built with Clang (all released versions), whereby the stack
frame gets blown up to well over 5k. This would cause an immediate kernel
panic on most architectures. We'll revert this when the following bug report
has been resolved: https://github.com/llvm/llvm-project/issues/41896.
config DRM_AMD_DC_DCN config DRM_AMD_DC_DCN
def_bool n def_bool n
help help

View File

@@ -2997,13 +2997,12 @@ void amdgpu_dm_update_connector_after_detect(
aconnector->edid = aconnector->edid =
(struct edid *)sink->dc_edid.raw_edid; (struct edid *)sink->dc_edid.raw_edid;
drm_connector_update_edid_property(connector,
aconnector->edid);
if (aconnector->dc_link->aux_mode) if (aconnector->dc_link->aux_mode)
drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux, drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
aconnector->edid); aconnector->edid);
} }
drm_connector_update_edid_property(connector, aconnector->edid);
amdgpu_dm_update_freesync_caps(connector, aconnector->edid); amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
update_connector_ext_caps(aconnector); update_connector_ext_caps(aconnector);
} else { } else {

View File

@@ -5285,7 +5285,7 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm
mst_state = drm_atomic_get_mst_topology_state(state, mgr); mst_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(mst_state)) if (IS_ERR(mst_state))
return -EINVAL; return PTR_ERR(mst_state);
list_for_each_entry(pos, &mst_state->vcpis, next) { list_for_each_entry(pos, &mst_state->vcpis, next) {

View File

@@ -143,23 +143,9 @@ static const struct drm_i915_gem_object_ops i915_gem_object_internal_ops = {
.put_pages = i915_gem_object_put_pages_internal, .put_pages = i915_gem_object_put_pages_internal,
}; };
/**
* i915_gem_object_create_internal: create an object with volatile pages
* @i915: the i915 device
* @size: the size in bytes of backing storage to allocate for the object
*
* Creates a new object that wraps some internal memory for private use.
* This object is not backed by swappable storage, and as such its contents
* are volatile and only valid whilst pinned. If the object is reaped by the
* shrinker, its pages and data will be discarded. Equally, it is not a full
* GEM object and so not valid for access from userspace. This makes it useful
* for hardware interfaces like ringbuffers (which are pinned from the time
* the request is written to the time the hardware stops accessing it), but
* not for contexts (which need to be preserved when not active for later
* reuse). Note that it is not cleared upon allocation.
*/
struct drm_i915_gem_object * struct drm_i915_gem_object *
i915_gem_object_create_internal(struct drm_i915_private *i915, __i915_gem_object_create_internal(struct drm_i915_private *i915,
const struct drm_i915_gem_object_ops *ops,
phys_addr_t size) phys_addr_t size)
{ {
static struct lock_class_key lock_class; static struct lock_class_key lock_class;
@@ -177,7 +163,7 @@ i915_gem_object_create_internal(struct drm_i915_private *i915,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
drm_gem_private_object_init(&i915->drm, &obj->base, size); drm_gem_private_object_init(&i915->drm, &obj->base, size);
i915_gem_object_init(obj, &i915_gem_object_internal_ops, &lock_class, 0); i915_gem_object_init(obj, ops, &lock_class, 0);
obj->mem_flags |= I915_BO_FLAG_STRUCT_PAGE; obj->mem_flags |= I915_BO_FLAG_STRUCT_PAGE;
/* /*
@@ -197,3 +183,25 @@ i915_gem_object_create_internal(struct drm_i915_private *i915,
return obj; return obj;
} }
/**
* i915_gem_object_create_internal: create an object with volatile pages
* @i915: the i915 device
* @size: the size in bytes of backing storage to allocate for the object
*
* Creates a new object that wraps some internal memory for private use.
* This object is not backed by swappable storage, and as such its contents
* are volatile and only valid whilst pinned. If the object is reaped by the
* shrinker, its pages and data will be discarded. Equally, it is not a full
* GEM object and so not valid for access from userspace. This makes it useful
* for hardware interfaces like ringbuffers (which are pinned from the time
* the request is written to the time the hardware stops accessing it), but
* not for contexts (which need to be preserved when not active for later
* reuse). Note that it is not cleared upon allocation.
*/
struct drm_i915_gem_object *
i915_gem_object_create_internal(struct drm_i915_private *i915,
phys_addr_t size)
{
return __i915_gem_object_create_internal(i915, &i915_gem_object_internal_ops, size);
}

View File

@@ -244,6 +244,7 @@ err_scratch1:
i915_gem_object_put(vm->scratch[1]); i915_gem_object_put(vm->scratch[1]);
err_scratch0: err_scratch0:
i915_gem_object_put(vm->scratch[0]); i915_gem_object_put(vm->scratch[0]);
vm->scratch[0] = NULL;
return ret; return ret;
} }
@@ -262,15 +263,13 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
{ {
struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm));
__i915_vma_put(ppgtt->vma);
gen6_ppgtt_free_pd(ppgtt); gen6_ppgtt_free_pd(ppgtt);
free_scratch(vm); free_scratch(vm);
mutex_destroy(&ppgtt->flush); if (ppgtt->base.pd)
mutex_destroy(&ppgtt->pin_mutex);
free_pd(&ppgtt->base.vm, ppgtt->base.pd); free_pd(&ppgtt->base.vm, ppgtt->base.pd);
mutex_destroy(&ppgtt->flush);
} }
static int pd_vma_set_pages(struct i915_vma *vma) static int pd_vma_set_pages(struct i915_vma *vma)
@@ -331,37 +330,6 @@ static const struct i915_vma_ops pd_vma_ops = {
.unbind_vma = pd_vma_unbind, .unbind_vma = pd_vma_unbind,
}; };
static struct i915_vma *pd_vma_create(struct gen6_ppgtt *ppgtt, int size)
{
struct i915_ggtt *ggtt = ppgtt->base.vm.gt->ggtt;
struct i915_vma *vma;
GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_PAGE_SIZE));
GEM_BUG_ON(size > ggtt->vm.total);
vma = i915_vma_alloc();
if (!vma)
return ERR_PTR(-ENOMEM);
i915_active_init(&vma->active, NULL, NULL, 0);
kref_init(&vma->ref);
mutex_init(&vma->pages_mutex);
vma->vm = i915_vm_get(&ggtt->vm);
vma->ops = &pd_vma_ops;
vma->private = ppgtt;
vma->size = size;
vma->fence_size = size;
atomic_set(&vma->flags, I915_VMA_GGTT);
vma->ggtt_view.type = I915_GGTT_VIEW_ROTATED; /* prevent fencing */
INIT_LIST_HEAD(&vma->obj_link);
INIT_LIST_HEAD(&vma->closed_link);
return vma;
}
int gen6_ppgtt_pin(struct i915_ppgtt *base, struct i915_gem_ww_ctx *ww) int gen6_ppgtt_pin(struct i915_ppgtt *base, struct i915_gem_ww_ctx *ww)
{ {
struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base); struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base);
@@ -378,24 +346,85 @@ int gen6_ppgtt_pin(struct i915_ppgtt *base, struct i915_gem_ww_ctx *ww)
if (atomic_add_unless(&ppgtt->pin_count, 1, 0)) if (atomic_add_unless(&ppgtt->pin_count, 1, 0))
return 0; return 0;
if (mutex_lock_interruptible(&ppgtt->pin_mutex)) /* grab the ppgtt resv to pin the object */
return -EINTR; err = i915_vm_lock_objects(&ppgtt->base.vm, ww);
if (err)
return err;
/* /*
* PPGTT PDEs reside in the GGTT and consists of 512 entries. The * PPGTT PDEs reside in the GGTT and consists of 512 entries. The
* allocator works in address space sizes, so it's multiplied by page * allocator works in address space sizes, so it's multiplied by page
* size. We allocate at the top of the GTT to avoid fragmentation. * size. We allocate at the top of the GTT to avoid fragmentation.
*/ */
err = 0; if (!atomic_read(&ppgtt->pin_count)) {
if (!atomic_read(&ppgtt->pin_count))
err = i915_ggtt_pin(ppgtt->vma, ww, GEN6_PD_ALIGN, PIN_HIGH); err = i915_ggtt_pin(ppgtt->vma, ww, GEN6_PD_ALIGN, PIN_HIGH);
GEM_BUG_ON(ppgtt->vma->fence);
clear_bit(I915_VMA_CAN_FENCE_BIT, __i915_vma_flags(ppgtt->vma));
}
if (!err) if (!err)
atomic_inc(&ppgtt->pin_count); atomic_inc(&ppgtt->pin_count);
mutex_unlock(&ppgtt->pin_mutex);
return err; return err;
} }
static int pd_dummy_obj_get_pages(struct drm_i915_gem_object *obj)
{
obj->mm.pages = ZERO_SIZE_PTR;
return 0;
}
static void pd_dummy_obj_put_pages(struct drm_i915_gem_object *obj,
struct sg_table *pages)
{
}
static const struct drm_i915_gem_object_ops pd_dummy_obj_ops = {
.name = "pd_dummy_obj",
.get_pages = pd_dummy_obj_get_pages,
.put_pages = pd_dummy_obj_put_pages,
};
static struct i915_page_directory *
gen6_alloc_top_pd(struct gen6_ppgtt *ppgtt)
{
struct i915_ggtt * const ggtt = ppgtt->base.vm.gt->ggtt;
struct i915_page_directory *pd;
int err;
pd = __alloc_pd(I915_PDES);
if (unlikely(!pd))
return ERR_PTR(-ENOMEM);
pd->pt.base = __i915_gem_object_create_internal(ppgtt->base.vm.gt->i915,
&pd_dummy_obj_ops,
I915_PDES * SZ_4K);
if (IS_ERR(pd->pt.base)) {
err = PTR_ERR(pd->pt.base);
pd->pt.base = NULL;
goto err_pd;
}
pd->pt.base->base.resv = i915_vm_resv_get(&ppgtt->base.vm);
pd->pt.base->shares_resv_from = &ppgtt->base.vm;
ppgtt->vma = i915_vma_instance(pd->pt.base, &ggtt->vm, NULL);
if (IS_ERR(ppgtt->vma)) {
err = PTR_ERR(ppgtt->vma);
ppgtt->vma = NULL;
goto err_pd;
}
/* The dummy object we create is special, override ops.. */
ppgtt->vma->ops = &pd_vma_ops;
ppgtt->vma->private = ppgtt;
return pd;
err_pd:
free_pd(&ppgtt->base.vm, pd);
return ERR_PTR(err);
}
void gen6_ppgtt_unpin(struct i915_ppgtt *base) void gen6_ppgtt_unpin(struct i915_ppgtt *base)
{ {
struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base); struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base);
@@ -427,7 +456,6 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
mutex_init(&ppgtt->flush); mutex_init(&ppgtt->flush);
mutex_init(&ppgtt->pin_mutex);
ppgtt_init(&ppgtt->base, gt); ppgtt_init(&ppgtt->base, gt);
ppgtt->base.vm.pd_shift = ilog2(SZ_4K * SZ_4K / sizeof(gen6_pte_t)); ppgtt->base.vm.pd_shift = ilog2(SZ_4K * SZ_4K / sizeof(gen6_pte_t));
@@ -442,30 +470,19 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt)
ppgtt->base.vm.alloc_pt_dma = alloc_pt_dma; ppgtt->base.vm.alloc_pt_dma = alloc_pt_dma;
ppgtt->base.vm.pte_encode = ggtt->vm.pte_encode; ppgtt->base.vm.pte_encode = ggtt->vm.pte_encode;
ppgtt->base.pd = __alloc_pd(I915_PDES);
if (!ppgtt->base.pd) {
err = -ENOMEM;
goto err_free;
}
err = gen6_ppgtt_init_scratch(ppgtt); err = gen6_ppgtt_init_scratch(ppgtt);
if (err) if (err)
goto err_pd; goto err_put;
ppgtt->vma = pd_vma_create(ppgtt, GEN6_PD_SIZE); ppgtt->base.pd = gen6_alloc_top_pd(ppgtt);
if (IS_ERR(ppgtt->vma)) { if (IS_ERR(ppgtt->base.pd)) {
err = PTR_ERR(ppgtt->vma); err = PTR_ERR(ppgtt->base.pd);
goto err_scratch; goto err_put;
} }
return &ppgtt->base; return &ppgtt->base;
err_scratch: err_put:
free_scratch(&ppgtt->base.vm); i915_vm_put(&ppgtt->base.vm);
err_pd:
free_pd(&ppgtt->base.vm, ppgtt->base.pd);
err_free:
mutex_destroy(&ppgtt->pin_mutex);
kfree(ppgtt);
return ERR_PTR(err); return ERR_PTR(err);
} }

View File

@@ -19,7 +19,6 @@ struct gen6_ppgtt {
u32 pp_dir; u32 pp_dir;
atomic_t pin_count; atomic_t pin_count;
struct mutex pin_mutex;
bool scan_for_unused_pt; bool scan_for_unused_pt;
}; };

View File

@@ -196,7 +196,10 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
if (intel_vgpu_active(vm->i915)) if (intel_vgpu_active(vm->i915))
gen8_ppgtt_notify_vgt(ppgtt, false); gen8_ppgtt_notify_vgt(ppgtt, false);
__gen8_ppgtt_cleanup(vm, ppgtt->pd, gen8_pd_top_count(vm), vm->top); if (ppgtt->pd)
__gen8_ppgtt_cleanup(vm, ppgtt->pd,
gen8_pd_top_count(vm), vm->top);
free_scratch(vm); free_scratch(vm);
} }
@@ -656,8 +659,10 @@ static int gen8_init_scratch(struct i915_address_space *vm)
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
obj = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); obj = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K);
if (IS_ERR(obj)) if (IS_ERR(obj)) {
ret = PTR_ERR(obj);
goto free_scratch; goto free_scratch;
}
ret = map_pt_dma(vm, obj); ret = map_pt_dma(vm, obj);
if (ret) { if (ret) {
@@ -676,7 +681,8 @@ static int gen8_init_scratch(struct i915_address_space *vm)
free_scratch: free_scratch:
while (i--) while (i--)
i915_gem_object_put(vm->scratch[i]); i915_gem_object_put(vm->scratch[i]);
return -ENOMEM; vm->scratch[0] = NULL;
return ret;
} }
static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt) static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
@@ -753,6 +759,7 @@ err_pd:
*/ */
struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt) struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
{ {
struct i915_page_directory *pd;
struct i915_ppgtt *ppgtt; struct i915_ppgtt *ppgtt;
int err; int err;
@@ -779,21 +786,7 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
else else
ppgtt->vm.alloc_pt_dma = alloc_pt_dma; ppgtt->vm.alloc_pt_dma = alloc_pt_dma;
err = gen8_init_scratch(&ppgtt->vm); ppgtt->vm.pte_encode = gen8_pte_encode;
if (err)
goto err_free;
ppgtt->pd = gen8_alloc_top_pd(&ppgtt->vm);
if (IS_ERR(ppgtt->pd)) {
err = PTR_ERR(ppgtt->pd);
goto err_free_scratch;
}
if (!i915_vm_is_4lvl(&ppgtt->vm)) {
err = gen8_preallocate_top_level_pdp(ppgtt);
if (err)
goto err_free_pd;
}
ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND; ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND;
ppgtt->vm.insert_entries = gen8_ppgtt_insert; ppgtt->vm.insert_entries = gen8_ppgtt_insert;
@@ -801,22 +794,31 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc; ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
ppgtt->vm.clear_range = gen8_ppgtt_clear; ppgtt->vm.clear_range = gen8_ppgtt_clear;
ppgtt->vm.foreach = gen8_ppgtt_foreach; ppgtt->vm.foreach = gen8_ppgtt_foreach;
ppgtt->vm.cleanup = gen8_ppgtt_cleanup;
ppgtt->vm.pte_encode = gen8_pte_encode; err = gen8_init_scratch(&ppgtt->vm);
if (err)
goto err_put;
pd = gen8_alloc_top_pd(&ppgtt->vm);
if (IS_ERR(pd)) {
err = PTR_ERR(pd);
goto err_put;
}
ppgtt->pd = pd;
if (!i915_vm_is_4lvl(&ppgtt->vm)) {
err = gen8_preallocate_top_level_pdp(ppgtt);
if (err)
goto err_put;
}
if (intel_vgpu_active(gt->i915)) if (intel_vgpu_active(gt->i915))
gen8_ppgtt_notify_vgt(ppgtt, true); gen8_ppgtt_notify_vgt(ppgtt, true);
ppgtt->vm.cleanup = gen8_ppgtt_cleanup;
return ppgtt; return ppgtt;
err_free_pd: err_put:
__gen8_ppgtt_cleanup(&ppgtt->vm, ppgtt->pd, i915_vm_put(&ppgtt->vm);
gen8_pd_top_count(&ppgtt->vm), ppgtt->vm.top);
err_free_scratch:
free_scratch(&ppgtt->vm);
err_free:
kfree(ppgtt);
return ERR_PTR(err); return ERR_PTR(err);
} }

View File

@@ -650,8 +650,13 @@ int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout)
return -EINTR; return -EINTR;
} }
return timeout ? timeout : intel_uc_wait_for_idle(&gt->uc, if (timeout)
remaining_timeout); return timeout;
if (remaining_timeout < 0)
remaining_timeout = 0;
return intel_uc_wait_for_idle(&gt->uc, remaining_timeout);
} }
int intel_gt_init(struct intel_gt *gt) int intel_gt_init(struct intel_gt *gt)

View File

@@ -199,7 +199,7 @@ out_active: spin_lock(&timelines->lock);
if (remaining_timeout) if (remaining_timeout)
*remaining_timeout = timeout; *remaining_timeout = timeout;
return active_count ? timeout : 0; return active_count ? timeout ?: -ETIME : 0;
} }
static void retire_work_handler(struct work_struct *work) static void retire_work_handler(struct work_struct *work)

View File

@@ -341,6 +341,9 @@ void free_scratch(struct i915_address_space *vm)
{ {
int i; int i;
if (!vm->scratch[0])
return;
for (i = 0; i <= vm->top; i++) for (i = 0; i <= vm->top; i++)
i915_gem_object_put(vm->scratch[i]); i915_gem_object_put(vm->scratch[i]);
} }

View File

@@ -1905,6 +1905,10 @@ int i915_gem_evict_vm(struct i915_address_space *vm);
struct drm_i915_gem_object * struct drm_i915_gem_object *
i915_gem_object_create_internal(struct drm_i915_private *dev_priv, i915_gem_object_create_internal(struct drm_i915_private *dev_priv,
phys_addr_t size); phys_addr_t size);
struct drm_i915_gem_object *
__i915_gem_object_create_internal(struct drm_i915_private *dev_priv,
const struct drm_i915_gem_object_ops *ops,
phys_addr_t size);
/* i915_gem_tiling.c */ /* i915_gem_tiling.c */
static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)

View File

@@ -242,10 +242,13 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
*/ */
if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) { if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) {
for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) { for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) {
if (host_bridge->device == tjmax_pci_table[i].device) if (host_bridge->device == tjmax_pci_table[i].device) {
pci_dev_put(host_bridge);
return tjmax_pci_table[i].tjmax; return tjmax_pci_table[i].tjmax;
} }
} }
}
pci_dev_put(host_bridge);
for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) { for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) {
if (strstr(c->x86_model_id, tjmax_table[i].id)) if (strstr(c->x86_model_id, tjmax_table[i].id))
@@ -533,6 +536,10 @@ static void coretemp_remove_core(struct platform_data *pdata, int indx)
{ {
struct temp_data *tdata = pdata->core_data[indx]; struct temp_data *tdata = pdata->core_data[indx];
/* if we errored on add then this is already gone */
if (!tdata)
return;
/* Remove the sysfs attributes */ /* Remove the sysfs attributes */
sysfs_remove_group(&pdata->hwmon_dev->kobj, &tdata->attr_group); sysfs_remove_group(&pdata->hwmon_dev->kobj, &tdata->attr_group);

View File

@@ -108,7 +108,7 @@ static int i5500_temp_probe(struct pci_dev *pdev,
u32 tstimer; u32 tstimer;
s8 tsfsc; s8 tsfsc;
err = pci_enable_device(pdev); err = pcim_enable_device(pdev);
if (err) { if (err) {
dev_err(&pdev->dev, "Failed to enable device\n"); dev_err(&pdev->dev, "Failed to enable device\n");
return err; return err;

View File

@@ -502,6 +502,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
return; return;
out_register: out_register:
list_del(&data->list);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
out_user: out_user:
ipmi_destroy_user(data->user); ipmi_destroy_user(data->user);

View File

@@ -228,7 +228,7 @@ static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg,
* Shunt Voltage Sum register has 14-bit value with 1-bit shift * Shunt Voltage Sum register has 14-bit value with 1-bit shift
* Other Shunt Voltage registers have 12 bits with 3-bit shift * Other Shunt Voltage registers have 12 bits with 3-bit shift
*/ */
if (reg == INA3221_SHUNT_SUM) if (reg == INA3221_SHUNT_SUM || reg == INA3221_CRIT_SUM)
*val = sign_extend32(regval >> 1, 14); *val = sign_extend32(regval >> 1, 14);
else else
*val = sign_extend32(regval >> 3, 12); *val = sign_extend32(regval >> 3, 12);
@@ -465,7 +465,7 @@ static int ina3221_write_curr(struct device *dev, u32 attr,
* SHUNT_SUM: (1 / 40uV) << 1 = 1 / 20uV * SHUNT_SUM: (1 / 40uV) << 1 = 1 / 20uV
* SHUNT[1-3]: (1 / 40uV) << 3 = 1 / 5uV * SHUNT[1-3]: (1 / 40uV) << 3 = 1 / 5uV
*/ */
if (reg == INA3221_SHUNT_SUM) if (reg == INA3221_SHUNT_SUM || reg == INA3221_CRIT_SUM)
regval = DIV_ROUND_CLOSEST(voltage_uv, 20) & 0xfffe; regval = DIV_ROUND_CLOSEST(voltage_uv, 20) & 0xfffe;
else else
regval = DIV_ROUND_CLOSEST(voltage_uv, 5) & 0xfff8; regval = DIV_ROUND_CLOSEST(voltage_uv, 5) & 0xfff8;

View File

@@ -396,7 +396,7 @@ static int ltc2947_read_temp(struct device *dev, const u32 attr, long *val,
return ret; return ret;
/* in milidegrees celcius, temp is given by: */ /* in milidegrees celcius, temp is given by: */
*val = (__val * 204) + 550; *val = (__val * 204) + 5500;
return 0; return 0;
} }

View File

@@ -1051,7 +1051,8 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
int i, result; int i, result;
unsigned int temp; unsigned int temp;
int block_data = msgs->flags & I2C_M_RECV_LEN; int block_data = msgs->flags & I2C_M_RECV_LEN;
int use_dma = i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data; int use_dma = i2c_imx->dma && msgs->flags & I2C_M_DMA_SAFE &&
msgs->len >= DMA_THRESHOLD && !block_data;
dev_dbg(&i2c_imx->adapter.dev, dev_dbg(&i2c_imx->adapter.dev,
"<%s> write slave address: addr=0x%x\n", "<%s> write slave address: addr=0x%x\n",
@@ -1217,7 +1218,8 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic); result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic);
} else { } else {
if (!atomic && if (!atomic &&
i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD) i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD &&
msgs[i].flags & I2C_M_DMA_SAFE)
result = i2c_imx_dma_write(i2c_imx, &msgs[i]); result = i2c_imx_dma_write(i2c_imx, &msgs[i]);
else else
result = i2c_imx_write(i2c_imx, &msgs[i], atomic); result = i2c_imx_write(i2c_imx, &msgs[i], atomic);

View File

@@ -2362,8 +2362,17 @@ static struct platform_driver npcm_i2c_bus_driver = {
static int __init npcm_i2c_init(void) static int __init npcm_i2c_init(void)
{ {
int ret;
npcm_i2c_debugfs_dir = debugfs_create_dir("npcm_i2c", NULL); npcm_i2c_debugfs_dir = debugfs_create_dir("npcm_i2c", NULL);
return platform_driver_register(&npcm_i2c_bus_driver);
ret = platform_driver_register(&npcm_i2c_bus_driver);
if (ret) {
debugfs_remove_recursive(npcm_i2c_debugfs_dir);
return ret;
}
return 0;
} }
module_init(npcm_i2c_init); module_init(npcm_i2c_init);

View File

@@ -245,14 +245,14 @@ static int afe4403_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask) int *val, int *val2, long mask)
{ {
struct afe4403_data *afe = iio_priv(indio_dev); struct afe4403_data *afe = iio_priv(indio_dev);
unsigned int reg = afe4403_channel_values[chan->address]; unsigned int reg, field;
unsigned int field = afe4403_channel_leds[chan->address];
int ret; int ret;
switch (chan->type) { switch (chan->type) {
case IIO_INTENSITY: case IIO_INTENSITY:
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
reg = afe4403_channel_values[chan->address];
ret = afe4403_read(afe, reg, val); ret = afe4403_read(afe, reg, val);
if (ret) if (ret)
return ret; return ret;
@@ -262,6 +262,7 @@ static int afe4403_read_raw(struct iio_dev *indio_dev,
case IIO_CURRENT: case IIO_CURRENT:
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
field = afe4403_channel_leds[chan->address];
ret = regmap_field_read(afe->fields[field], val); ret = regmap_field_read(afe->fields[field], val);
if (ret) if (ret)
return ret; return ret;

View File

@@ -250,20 +250,20 @@ static int afe4404_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask) int *val, int *val2, long mask)
{ {
struct afe4404_data *afe = iio_priv(indio_dev); struct afe4404_data *afe = iio_priv(indio_dev);
unsigned int value_reg = afe4404_channel_values[chan->address]; unsigned int value_reg, led_field, offdac_field;
unsigned int led_field = afe4404_channel_leds[chan->address];
unsigned int offdac_field = afe4404_channel_offdacs[chan->address];
int ret; int ret;
switch (chan->type) { switch (chan->type) {
case IIO_INTENSITY: case IIO_INTENSITY:
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
value_reg = afe4404_channel_values[chan->address];
ret = regmap_read(afe->regmap, value_reg, val); ret = regmap_read(afe->regmap, value_reg, val);
if (ret) if (ret)
return ret; return ret;
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET: case IIO_CHAN_INFO_OFFSET:
offdac_field = afe4404_channel_offdacs[chan->address];
ret = regmap_field_read(afe->fields[offdac_field], val); ret = regmap_field_read(afe->fields[offdac_field], val);
if (ret) if (ret)
return ret; return ret;
@@ -273,6 +273,7 @@ static int afe4404_read_raw(struct iio_dev *indio_dev,
case IIO_CURRENT: case IIO_CURRENT:
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
led_field = afe4404_channel_leds[chan->address];
ret = regmap_field_read(afe->fields[led_field], val); ret = regmap_field_read(afe->fields[led_field], val);
if (ret) if (ret)
return ret; return ret;
@@ -295,19 +296,20 @@ static int afe4404_write_raw(struct iio_dev *indio_dev,
int val, int val2, long mask) int val, int val2, long mask)
{ {
struct afe4404_data *afe = iio_priv(indio_dev); struct afe4404_data *afe = iio_priv(indio_dev);
unsigned int led_field = afe4404_channel_leds[chan->address]; unsigned int led_field, offdac_field;
unsigned int offdac_field = afe4404_channel_offdacs[chan->address];
switch (chan->type) { switch (chan->type) {
case IIO_INTENSITY: case IIO_INTENSITY:
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_OFFSET: case IIO_CHAN_INFO_OFFSET:
offdac_field = afe4404_channel_offdacs[chan->address];
return regmap_field_write(afe->fields[offdac_field], val); return regmap_field_write(afe->fields[offdac_field], val);
} }
break; break;
case IIO_CURRENT: case IIO_CURRENT:
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
led_field = afe4404_channel_leds[chan->address];
return regmap_field_write(afe->fields[led_field], val); return regmap_field_write(afe->fields[led_field], val);
} }
break; break;

View File

@@ -294,6 +294,8 @@ config RPR0521
tristate "ROHM RPR0521 ALS and proximity sensor driver" tristate "ROHM RPR0521 ALS and proximity sensor driver"
depends on I2C depends on I2C
select REGMAP_I2C select REGMAP_I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help help
Say Y here if you want to build support for ROHM's RPR0521 Say Y here if you want to build support for ROHM's RPR0521
ambient light and proximity sensor device. ambient light and proximity sensor device.

View File

@@ -210,12 +210,14 @@ static int raydium_i2c_send(struct i2c_client *client,
error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer)); error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer));
if (likely(!error)) if (likely(!error))
return 0; goto out;
msleep(RM_RETRY_DELAY_MS); msleep(RM_RETRY_DELAY_MS);
} while (++tries < RM_MAX_RETRIES); } while (++tries < RM_MAX_RETRIES);
dev_err(&client->dev, "%s failed: %d\n", __func__, error); dev_err(&client->dev, "%s failed: %d\n", __func__, error);
out:
kfree(tx_buf);
return error; return error;
} }

View File

@@ -822,6 +822,7 @@ int __init dmar_dev_scope_init(void)
info = dmar_alloc_pci_notify_info(dev, info = dmar_alloc_pci_notify_info(dev,
BUS_NOTIFY_ADD_DEVICE); BUS_NOTIFY_ADD_DEVICE);
if (!info) { if (!info) {
pci_dev_put(dev);
return dmar_dev_scope_status; return dmar_dev_scope_status;
} else { } else {
dmar_pci_bus_add_dev(info); dmar_pci_bus_add_dev(info);

View File

@@ -4241,8 +4241,10 @@ static inline bool has_external_pci(void)
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
for_each_pci_dev(pdev) for_each_pci_dev(pdev)
if (pdev->external_facing) if (pdev->external_facing) {
pci_dev_put(pdev);
return true; return true;
}
return false; return false;
} }

View File

@@ -35,10 +35,7 @@
int get_vaddr_frames(unsigned long start, unsigned int nr_frames, int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
struct frame_vector *vec) struct frame_vector *vec)
{ {
struct mm_struct *mm = current->mm; int ret;
struct vm_area_struct *vma;
int ret = 0;
int err;
if (nr_frames == 0) if (nr_frames == 0)
return 0; return 0;
@@ -51,45 +48,17 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
ret = pin_user_pages_fast(start, nr_frames, ret = pin_user_pages_fast(start, nr_frames,
FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM, FOLL_FORCE | FOLL_WRITE | FOLL_LONGTERM,
(struct page **)(vec->ptrs)); (struct page **)(vec->ptrs));
if (ret > 0) {
vec->got_ref = true; vec->got_ref = true;
vec->is_pfns = false; vec->is_pfns = false;
goto out_unlocked;
}
mmap_read_lock(mm);
vec->got_ref = false;
vec->is_pfns = true;
ret = 0;
do {
unsigned long *nums = frame_vector_pfns(vec);
vma = vma_lookup(mm, start);
if (!vma)
break;
while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) {
err = follow_pfn(vma, start, &nums[ret]);
if (err) {
if (ret == 0)
ret = err;
goto out;
}
start += PAGE_SIZE;
ret++;
}
/* Bail out if VMA doesn't completely cover the tail page. */
if (start < vma->vm_end)
break;
} while (ret < nr_frames);
out:
mmap_read_unlock(mm);
out_unlocked:
if (!ret)
ret = -EFAULT;
if (ret > 0)
vec->nr_frames = ret; vec->nr_frames = ret;
if (likely(ret > 0))
return ret; return ret;
/* This used to (racily) return non-refcounted pfns. Let people know */
WARN_ONCE(1, "get_vaddr_frames() cannot follow VM_IO mapping");
vec->nr_frames = 0;
return ret ? ret : -EFAULT;
} }
EXPORT_SYMBOL(get_vaddr_frames); EXPORT_SYMBOL(get_vaddr_frames);

View File

@@ -1490,6 +1490,11 @@ void mmc_init_erase(struct mmc_card *card)
card->pref_erase = 0; card->pref_erase = 0;
} }
static bool is_trim_arg(unsigned int arg)
{
return (arg & MMC_TRIM_OR_DISCARD_ARGS) && arg != MMC_DISCARD_ARG;
}
static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card, static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
unsigned int arg, unsigned int qty) unsigned int arg, unsigned int qty)
{ {
@@ -1772,7 +1777,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)) !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (mmc_card_mmc(card) && (arg & MMC_TRIM_ARGS) && if (mmc_card_mmc(card) && is_trim_arg(arg) &&
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)) !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN))
return -EOPNOTSUPP; return -EOPNOTSUPP;
@@ -1802,7 +1807,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
* identified by the card->eg_boundary flag. * identified by the card->eg_boundary flag.
*/ */
rem = card->erase_size - (from % card->erase_size); rem = card->erase_size - (from % card->erase_size);
if ((arg & MMC_TRIM_ARGS) && (card->eg_boundary) && (nr > rem)) { if ((arg & MMC_TRIM_OR_DISCARD_ARGS) && card->eg_boundary && nr > rem) {
err = mmc_do_erase(card, from, from + rem - 1, arg); err = mmc_do_erase(card, from, from + rem - 1, arg);
from += rem; from += rem;
if ((err) || (to <= from)) if ((err) || (to <= from))

View File

@@ -3181,7 +3181,8 @@ static int __mmc_test_register_dbgfs_file(struct mmc_card *card,
struct mmc_test_dbgfs_file *df; struct mmc_test_dbgfs_file *df;
if (card->debugfs_root) if (card->debugfs_root)
debugfs_create_file(name, mode, card->debugfs_root, card, fops); file = debugfs_create_file(name, mode, card->debugfs_root,
card, fops);
df = kmalloc(sizeof(*df), GFP_KERNEL); df = kmalloc(sizeof(*df), GFP_KERNEL);
if (!df) { if (!df) {

View File

@@ -1495,7 +1495,7 @@ static void esdhc_cqe_enable(struct mmc_host *mmc)
* system resume back. * system resume back.
*/ */
cqhci_writel(cq_host, 0, CQHCI_CTL); cqhci_writel(cq_host, 0, CQHCI_CTL);
if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT) if (cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT)
dev_err(mmc_dev(host->mmc), dev_err(mmc_dev(host->mmc),
"failed to exit halt state when enable CQE\n"); "failed to exit halt state when enable CQE\n");

View File

@@ -457,7 +457,7 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
} }
if (IS_ERR(sprd_host->pinctrl)) if (IS_ERR(sprd_host->pinctrl))
return 0; goto reset;
switch (ios->signal_voltage) { switch (ios->signal_voltage) {
case MMC_SIGNAL_VOLTAGE_180: case MMC_SIGNAL_VOLTAGE_180:
@@ -485,6 +485,8 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
/* Wait for 300 ~ 500 us for pin state stable */ /* Wait for 300 ~ 500 us for pin state stable */
usleep_range(300, 500); usleep_range(300, 500);
reset:
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
return 0; return 0;

View File

@@ -341,6 +341,7 @@ static void sdhci_init(struct sdhci_host *host, int soft)
if (soft) { if (soft) {
/* force clock reconfiguration */ /* force clock reconfiguration */
host->clock = 0; host->clock = 0;
host->reinit_uhs = true;
mmc->ops->set_ios(mmc, &mmc->ios); mmc->ops->set_ios(mmc, &mmc->ios);
} }
} }
@@ -2263,11 +2264,46 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
} }
EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
static bool sdhci_timing_has_preset(unsigned char timing)
{
switch (timing) {
case MMC_TIMING_UHS_SDR12:
case MMC_TIMING_UHS_SDR25:
case MMC_TIMING_UHS_SDR50:
case MMC_TIMING_UHS_SDR104:
case MMC_TIMING_UHS_DDR50:
case MMC_TIMING_MMC_DDR52:
return true;
};
return false;
}
static bool sdhci_preset_needed(struct sdhci_host *host, unsigned char timing)
{
return !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
sdhci_timing_has_preset(timing);
}
static bool sdhci_presetable_values_change(struct sdhci_host *host, struct mmc_ios *ios)
{
/*
* Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK
* Frequency. Check if preset values need to be enabled, or the Driver
* Strength needs updating. Note, clock changes are handled separately.
*/
return !host->preset_enabled &&
(sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type);
}
void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{ {
struct sdhci_host *host = mmc_priv(mmc); struct sdhci_host *host = mmc_priv(mmc);
bool reinit_uhs = host->reinit_uhs;
bool turning_on_clk = false;
u8 ctrl; u8 ctrl;
host->reinit_uhs = false;
if (ios->power_mode == MMC_POWER_UNDEFINED) if (ios->power_mode == MMC_POWER_UNDEFINED)
return; return;
@@ -2293,6 +2329,8 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_enable_preset_value(host, false); sdhci_enable_preset_value(host, false);
if (!ios->clock || ios->clock != host->clock) { if (!ios->clock || ios->clock != host->clock) {
turning_on_clk = ios->clock && !host->clock;
host->ops->set_clock(host, ios->clock); host->ops->set_clock(host, ios->clock);
host->clock = ios->clock; host->clock = ios->clock;
@@ -2319,6 +2357,17 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->ops->set_bus_width(host, ios->bus_width); host->ops->set_bus_width(host, ios->bus_width);
/*
* Special case to avoid multiple clock changes during voltage
* switching.
*/
if (!reinit_uhs &&
turning_on_clk &&
host->timing == ios->timing &&
host->version >= SDHCI_SPEC_300 &&
!sdhci_presetable_values_change(host, ios))
return;
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) { if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
@@ -2362,6 +2411,7 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
} }
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
host->drv_type = ios->drv_type;
} else { } else {
/* /*
* According to SDHC Spec v3.00, if the Preset Value * According to SDHC Spec v3.00, if the Preset Value
@@ -2389,19 +2439,14 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->ops->set_uhs_signaling(host, ios->timing); host->ops->set_uhs_signaling(host, ios->timing);
host->timing = ios->timing; host->timing = ios->timing;
if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && if (sdhci_preset_needed(host, ios->timing)) {
((ios->timing == MMC_TIMING_UHS_SDR12) ||
(ios->timing == MMC_TIMING_UHS_SDR25) ||
(ios->timing == MMC_TIMING_UHS_SDR50) ||
(ios->timing == MMC_TIMING_UHS_SDR104) ||
(ios->timing == MMC_TIMING_UHS_DDR50) ||
(ios->timing == MMC_TIMING_MMC_DDR52))) {
u16 preset; u16 preset;
sdhci_enable_preset_value(host, true); sdhci_enable_preset_value(host, true);
preset = sdhci_get_preset_value(host); preset = sdhci_get_preset_value(host);
ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK, ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK,
preset); preset);
host->drv_type = ios->drv_type;
} }
/* Re-enable SD Clock */ /* Re-enable SD Clock */
@@ -3739,6 +3784,7 @@ int sdhci_resume_host(struct sdhci_host *host)
sdhci_init(host, 0); sdhci_init(host, 0);
host->pwr = 0; host->pwr = 0;
host->clock = 0; host->clock = 0;
host->reinit_uhs = true;
mmc->ops->set_ios(mmc, &mmc->ios); mmc->ops->set_ios(mmc, &mmc->ios);
} else { } else {
sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER)); sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER));
@@ -3801,6 +3847,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
/* Force clock and power re-program */ /* Force clock and power re-program */
host->pwr = 0; host->pwr = 0;
host->clock = 0; host->clock = 0;
host->reinit_uhs = true;
mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
mmc->ops->set_ios(mmc, &mmc->ios); mmc->ops->set_ios(mmc, &mmc->ios);

View File

@@ -527,6 +527,8 @@ struct sdhci_host {
unsigned int clock; /* Current clock (MHz) */ unsigned int clock; /* Current clock (MHz) */
u8 pwr; /* Current voltage */ u8 pwr; /* Current voltage */
u8 drv_type; /* Current UHS-I driver type */
bool reinit_uhs; /* Force UHS-related re-initialization */
bool runtime_suspended; /* Host is runtime suspended */ bool runtime_suspended; /* Host is runtime suspended */
bool bus_on; /* Bus power prevents runtime suspend */ bool bus_on; /* Bus power prevents runtime suspend */

View File

@@ -264,22 +264,24 @@ static int cc770_isa_probe(struct platform_device *pdev)
if (err) { if (err) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"couldn't register device (err=%d)\n", err); "couldn't register device (err=%d)\n", err);
goto exit_unmap; goto exit_free;
} }
dev_info(&pdev->dev, "device registered (reg_base=0x%p, irq=%d)\n", dev_info(&pdev->dev, "device registered (reg_base=0x%p, irq=%d)\n",
priv->reg_base, dev->irq); priv->reg_base, dev->irq);
return 0; return 0;
exit_unmap: exit_free:
free_cc770dev(dev);
exit_unmap:
if (mem[idx]) if (mem[idx])
iounmap(base); iounmap(base);
exit_release: exit_release:
if (mem[idx]) if (mem[idx])
release_mem_region(mem[idx], iosize); release_mem_region(mem[idx], iosize);
else else
release_region(port[idx], iosize); release_region(port[idx], iosize);
exit: exit:
return err; return err;
} }

View File

@@ -1931,7 +1931,7 @@ int m_can_class_get_clocks(struct m_can_classdev *cdev)
cdev->hclk = devm_clk_get(cdev->dev, "hclk"); cdev->hclk = devm_clk_get(cdev->dev, "hclk");
cdev->cclk = devm_clk_get(cdev->dev, "cclk"); cdev->cclk = devm_clk_get(cdev->dev, "cclk");
if (IS_ERR(cdev->cclk)) { if (IS_ERR(cdev->hclk) || IS_ERR(cdev->cclk)) {
dev_err(cdev->dev, "no clock found\n"); dev_err(cdev->dev, "no clock found\n");
ret = -ENODEV; ret = -ENODEV;
} }

View File

@@ -120,7 +120,7 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_ALL_TYPES); ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_ALL_TYPES);
if (ret < 0) if (ret < 0)
return ret; goto err_free_dev;
mcan_class->dev = &pci->dev; mcan_class->dev = &pci->dev;
mcan_class->net->irq = pci_irq_vector(pci, 0); mcan_class->net->irq = pci_irq_vector(pci, 0);
@@ -132,7 +132,7 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
ret = m_can_class_register(mcan_class); ret = m_can_class_register(mcan_class);
if (ret) if (ret)
goto err; goto err_free_irq;
/* Enable interrupt control at CAN wrapper IP */ /* Enable interrupt control at CAN wrapper IP */
writel(0x1, base + CTL_CSR_INT_CTL_OFFSET); writel(0x1, base + CTL_CSR_INT_CTL_OFFSET);
@@ -144,8 +144,10 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
return 0; return 0;
err: err_free_irq:
pci_free_irq_vectors(pci); pci_free_irq_vectors(pci);
err_free_dev:
m_can_class_free_dev(mcan_class->net);
return ret; return ret;
} }
@@ -161,6 +163,7 @@ static void m_can_pci_remove(struct pci_dev *pci)
writel(0x0, priv->base + CTL_CSR_INT_CTL_OFFSET); writel(0x0, priv->base + CTL_CSR_INT_CTL_OFFSET);
m_can_class_unregister(mcan_class); m_can_class_unregister(mcan_class);
m_can_class_free_dev(mcan_class->net);
pci_free_irq_vectors(pci); pci_free_irq_vectors(pci);
} }

View File

@@ -202,22 +202,24 @@ static int sja1000_isa_probe(struct platform_device *pdev)
if (err) { if (err) {
dev_err(&pdev->dev, "registering %s failed (err=%d)\n", dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
DRV_NAME, err); DRV_NAME, err);
goto exit_unmap; goto exit_free;
} }
dev_info(&pdev->dev, "%s device registered (reg_base=0x%p, irq=%d)\n", dev_info(&pdev->dev, "%s device registered (reg_base=0x%p, irq=%d)\n",
DRV_NAME, priv->reg_base, dev->irq); DRV_NAME, priv->reg_base, dev->irq);
return 0; return 0;
exit_unmap: exit_free:
free_sja1000dev(dev);
exit_unmap:
if (mem[idx]) if (mem[idx])
iounmap(base); iounmap(base);
exit_release: exit_release:
if (mem[idx]) if (mem[idx])
release_mem_region(mem[idx], iosize); release_mem_region(mem[idx], iosize);
else else
release_region(port[idx], iosize); release_region(port[idx], iosize);
exit: exit:
return err; return err;
} }

View File

@@ -2098,8 +2098,11 @@ static int es58x_init_netdev(struct es58x_device *es58x_dev, int channel_idx)
netdev->flags |= IFF_ECHO; /* We support local echo */ netdev->flags |= IFF_ECHO; /* We support local echo */
ret = register_candev(netdev); ret = register_candev(netdev);
if (ret) if (ret) {
es58x_dev->netdev[channel_idx] = NULL;
free_candev(netdev);
return ret; return ret;
}
netdev_queue_set_dql_min_limit(netdev_get_tx_queue(netdev, 0), netdev_queue_set_dql_min_limit(netdev_get_tx_queue(netdev, 0),
es58x_dev->param->dql_min_limit); es58x_dev->param->dql_min_limit);

View File

@@ -959,7 +959,7 @@ static const struct lan9303_mib_desc lan9303_mib[] = {
{ .offset = LAN9303_MAC_TX_BRDCST_CNT_0, .name = "TxBroad", }, { .offset = LAN9303_MAC_TX_BRDCST_CNT_0, .name = "TxBroad", },
{ .offset = LAN9303_MAC_TX_PAUSE_CNT_0, .name = "TxPause", }, { .offset = LAN9303_MAC_TX_PAUSE_CNT_0, .name = "TxPause", },
{ .offset = LAN9303_MAC_TX_MULCST_CNT_0, .name = "TxMulti", }, { .offset = LAN9303_MAC_TX_MULCST_CNT_0, .name = "TxMulti", },
{ .offset = LAN9303_MAC_RX_UNDSZE_CNT_0, .name = "TxUnderRun", }, { .offset = LAN9303_MAC_RX_UNDSZE_CNT_0, .name = "RxShort", },
{ .offset = LAN9303_MAC_TX_64_CNT_0, .name = "Tx64Byte", }, { .offset = LAN9303_MAC_TX_64_CNT_0, .name = "Tx64Byte", },
{ .offset = LAN9303_MAC_TX_127_CNT_0, .name = "Tx128Byte", }, { .offset = LAN9303_MAC_TX_127_CNT_0, .name = "Tx128Byte", },
{ .offset = LAN9303_MAC_TX_255_CNT_0, .name = "Tx256Byte", }, { .offset = LAN9303_MAC_TX_255_CNT_0, .name = "Tx256Byte", },

View File

@@ -13,6 +13,7 @@
#include "aq_ptp.h" #include "aq_ptp.h"
#include "aq_filters.h" #include "aq_filters.h"
#include "aq_macsec.h" #include "aq_macsec.h"
#include "aq_main.h"
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
@@ -845,7 +846,7 @@ static int aq_set_ringparam(struct net_device *ndev,
if (netif_running(ndev)) { if (netif_running(ndev)) {
ndev_running = true; ndev_running = true;
dev_close(ndev); aq_ndev_close(ndev);
} }
cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
@@ -861,7 +862,7 @@ static int aq_set_ringparam(struct net_device *ndev,
goto err_exit; goto err_exit;
if (ndev_running) if (ndev_running)
err = dev_open(ndev, NULL); err = aq_ndev_open(ndev);
err_exit: err_exit:
return err; return err;

View File

@@ -53,7 +53,7 @@ struct net_device *aq_ndev_alloc(void)
return ndev; return ndev;
} }
static int aq_ndev_open(struct net_device *ndev) int aq_ndev_open(struct net_device *ndev)
{ {
struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_s *aq_nic = netdev_priv(ndev);
int err = 0; int err = 0;
@@ -83,7 +83,7 @@ err_exit:
return err; return err;
} }
static int aq_ndev_close(struct net_device *ndev) int aq_ndev_close(struct net_device *ndev)
{ {
struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_s *aq_nic = netdev_priv(ndev);
int err = 0; int err = 0;

View File

@@ -14,5 +14,7 @@
void aq_ndev_schedule_work(struct work_struct *work); void aq_ndev_schedule_work(struct work_struct *work);
struct net_device *aq_ndev_alloc(void); struct net_device *aq_ndev_alloc(void);
int aq_ndev_open(struct net_device *ndev);
int aq_ndev_close(struct net_device *ndev);
#endif /* AQ_MAIN_H */ #endif /* AQ_MAIN_H */

View File

@@ -1742,11 +1742,8 @@ static int e100_xmit_prepare(struct nic *nic, struct cb *cb,
dma_addr = dma_map_single(&nic->pdev->dev, skb->data, skb->len, dma_addr = dma_map_single(&nic->pdev->dev, skb->data, skb->len,
DMA_TO_DEVICE); DMA_TO_DEVICE);
/* If we can't map the skb, have the upper layer try later */ /* If we can't map the skb, have the upper layer try later */
if (dma_mapping_error(&nic->pdev->dev, dma_addr)) { if (dma_mapping_error(&nic->pdev->dev, dma_addr))
dev_kfree_skb_any(skb);
skb = NULL;
return -ENOMEM; return -ENOMEM;
}
/* /*
* Use the last 4 bytes of the SKB payload packet as the CRC, used for * Use the last 4 bytes of the SKB payload packet as the CRC, used for

View File

@@ -32,6 +32,8 @@ struct workqueue_struct *fm10k_workqueue;
**/ **/
static int __init fm10k_init_module(void) static int __init fm10k_init_module(void)
{ {
int ret;
pr_info("%s\n", fm10k_driver_string); pr_info("%s\n", fm10k_driver_string);
pr_info("%s\n", fm10k_copyright); pr_info("%s\n", fm10k_copyright);
@@ -43,7 +45,13 @@ static int __init fm10k_init_module(void)
fm10k_dbg_init(); fm10k_dbg_init();
return fm10k_register_pci_driver(); ret = fm10k_register_pci_driver();
if (ret) {
fm10k_dbg_exit();
destroy_workqueue(fm10k_workqueue);
}
return ret;
} }
module_init(fm10k_init_module); module_init(fm10k_init_module);

View File

@@ -16494,6 +16494,8 @@ static struct pci_driver i40e_driver = {
**/ **/
static int __init i40e_init_module(void) static int __init i40e_init_module(void)
{ {
int err;
pr_info("%s: %s\n", i40e_driver_name, i40e_driver_string); pr_info("%s: %s\n", i40e_driver_name, i40e_driver_string);
pr_info("%s: %s\n", i40e_driver_name, i40e_copyright); pr_info("%s: %s\n", i40e_driver_name, i40e_copyright);
@@ -16511,7 +16513,14 @@ static int __init i40e_init_module(void)
} }
i40e_dbg_init(); i40e_dbg_init();
return pci_register_driver(&i40e_driver); err = pci_register_driver(&i40e_driver);
if (err) {
destroy_workqueue(i40e_wq);
i40e_dbg_exit();
return err;
}
return 0;
} }
module_init(i40e_init_module); module_init(i40e_init_module);

View File

@@ -1448,7 +1448,6 @@ static void iavf_fill_rss_lut(struct iavf_adapter *adapter)
static int iavf_init_rss(struct iavf_adapter *adapter) static int iavf_init_rss(struct iavf_adapter *adapter)
{ {
struct iavf_hw *hw = &adapter->hw; struct iavf_hw *hw = &adapter->hw;
int ret;
if (!RSS_PF(adapter)) { if (!RSS_PF(adapter)) {
/* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */ /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */
@@ -1464,9 +1463,8 @@ static int iavf_init_rss(struct iavf_adapter *adapter)
iavf_fill_rss_lut(adapter); iavf_fill_rss_lut(adapter);
netdev_rss_key_fill((void *)adapter->rss_key, adapter->rss_key_size); netdev_rss_key_fill((void *)adapter->rss_key, adapter->rss_key_size);
ret = iavf_config_rss(adapter);
return ret; return iavf_config_rss(adapter);
} }
/** /**
@@ -4355,7 +4353,11 @@ static int __init iavf_init_module(void)
pr_err("%s: Failed to create workqueue\n", iavf_driver_name); pr_err("%s: Failed to create workqueue\n", iavf_driver_name);
return -ENOMEM; return -ENOMEM;
} }
ret = pci_register_driver(&iavf_driver); ret = pci_register_driver(&iavf_driver);
if (ret)
destroy_workqueue(iavf_wq);
return ret; return ret;
} }

View File

@@ -4859,6 +4859,8 @@ static struct pci_driver ixgbevf_driver = {
**/ **/
static int __init ixgbevf_init_module(void) static int __init ixgbevf_init_module(void)
{ {
int err;
pr_info("%s\n", ixgbevf_driver_string); pr_info("%s\n", ixgbevf_driver_string);
pr_info("%s\n", ixgbevf_copyright); pr_info("%s\n", ixgbevf_copyright);
ixgbevf_wq = create_singlethread_workqueue(ixgbevf_driver_name); ixgbevf_wq = create_singlethread_workqueue(ixgbevf_driver_name);
@@ -4867,7 +4869,13 @@ static int __init ixgbevf_init_module(void)
return -ENOMEM; return -ENOMEM;
} }
return pci_register_driver(&ixgbevf_driver); err = pci_register_driver(&ixgbevf_driver);
if (err) {
destroy_workqueue(ixgbevf_wq);
return err;
}
return 0;
} }
module_init(ixgbevf_init_module); module_init(ixgbevf_init_module);

View File

@@ -1434,8 +1434,8 @@ static ssize_t outlen_write(struct file *filp, const char __user *buf,
return -EFAULT; return -EFAULT;
err = sscanf(outlen_str, "%d", &outlen); err = sscanf(outlen_str, "%d", &outlen);
if (err < 0) if (err != 1)
return err; return -EINVAL;
ptr = kzalloc(outlen, GFP_KERNEL); ptr = kzalloc(outlen, GFP_KERNEL);
if (!ptr) if (!ptr)

View File

@@ -309,6 +309,8 @@ revert_changes:
for (curr_dest = 0; curr_dest < num_vport_dests; curr_dest++) { for (curr_dest = 0; curr_dest < num_vport_dests; curr_dest++) {
struct mlx5_termtbl_handle *tt = attr->dests[curr_dest].termtbl; struct mlx5_termtbl_handle *tt = attr->dests[curr_dest].termtbl;
attr->dests[curr_dest].termtbl = NULL;
/* search for the destination associated with the /* search for the destination associated with the
* current term table * current term table
*/ */

View File

@@ -709,7 +709,7 @@ static int dr_matcher_add_to_tbl(struct mlx5dr_matcher *matcher)
int ret; int ret;
next_matcher = NULL; next_matcher = NULL;
list_for_each_entry(tmp_matcher, &tbl->matcher_list, matcher_list) { list_for_each_entry(tmp_matcher, &tbl->matcher_list, list_node) {
if (tmp_matcher->prio >= matcher->prio) { if (tmp_matcher->prio >= matcher->prio) {
next_matcher = tmp_matcher; next_matcher = tmp_matcher;
break; break;
@@ -719,11 +719,11 @@ static int dr_matcher_add_to_tbl(struct mlx5dr_matcher *matcher)
prev_matcher = NULL; prev_matcher = NULL;
if (next_matcher && !first) if (next_matcher && !first)
prev_matcher = list_prev_entry(next_matcher, matcher_list); prev_matcher = list_prev_entry(next_matcher, list_node);
else if (!first) else if (!first)
prev_matcher = list_last_entry(&tbl->matcher_list, prev_matcher = list_last_entry(&tbl->matcher_list,
struct mlx5dr_matcher, struct mlx5dr_matcher,
matcher_list); list_node);
if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB || if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB ||
dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX) { dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX) {
@@ -744,12 +744,12 @@ static int dr_matcher_add_to_tbl(struct mlx5dr_matcher *matcher)
} }
if (prev_matcher) if (prev_matcher)
list_add(&matcher->matcher_list, &prev_matcher->matcher_list); list_add(&matcher->list_node, &prev_matcher->list_node);
else if (next_matcher) else if (next_matcher)
list_add_tail(&matcher->matcher_list, list_add_tail(&matcher->list_node,
&next_matcher->matcher_list); &next_matcher->list_node);
else else
list_add(&matcher->matcher_list, &tbl->matcher_list); list_add(&matcher->list_node, &tbl->matcher_list);
return 0; return 0;
} }
@@ -922,7 +922,7 @@ mlx5dr_matcher_create(struct mlx5dr_table *tbl,
matcher->prio = priority; matcher->prio = priority;
matcher->match_criteria = match_criteria_enable; matcher->match_criteria = match_criteria_enable;
refcount_set(&matcher->refcount, 1); refcount_set(&matcher->refcount, 1);
INIT_LIST_HEAD(&matcher->matcher_list); INIT_LIST_HEAD(&matcher->list_node);
mlx5dr_domain_lock(tbl->dmn); mlx5dr_domain_lock(tbl->dmn);
@@ -985,15 +985,15 @@ static int dr_matcher_remove_from_tbl(struct mlx5dr_matcher *matcher)
struct mlx5dr_domain *dmn = tbl->dmn; struct mlx5dr_domain *dmn = tbl->dmn;
int ret = 0; int ret = 0;
if (list_is_last(&matcher->matcher_list, &tbl->matcher_list)) if (list_is_last(&matcher->list_node, &tbl->matcher_list))
next_matcher = NULL; next_matcher = NULL;
else else
next_matcher = list_next_entry(matcher, matcher_list); next_matcher = list_next_entry(matcher, list_node);
if (matcher->matcher_list.prev == &tbl->matcher_list) if (matcher->list_node.prev == &tbl->matcher_list)
prev_matcher = NULL; prev_matcher = NULL;
else else
prev_matcher = list_prev_entry(matcher, matcher_list); prev_matcher = list_prev_entry(matcher, list_node);
if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB || if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB ||
dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX) { dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX) {
@@ -1013,7 +1013,7 @@ static int dr_matcher_remove_from_tbl(struct mlx5dr_matcher *matcher)
return ret; return ret;
} }
list_del(&matcher->matcher_list); list_del(&matcher->list_node);
return 0; return 0;
} }

View File

@@ -9,7 +9,7 @@ int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
struct mlx5dr_matcher *last_matcher = NULL; struct mlx5dr_matcher *last_matcher = NULL;
struct mlx5dr_htbl_connect_info info; struct mlx5dr_htbl_connect_info info;
struct mlx5dr_ste_htbl *last_htbl; struct mlx5dr_ste_htbl *last_htbl;
int ret; int ret = -EOPNOTSUPP;
if (action && action->action_type != DR_ACTION_TYP_FT) if (action && action->action_type != DR_ACTION_TYP_FT)
return -EOPNOTSUPP; return -EOPNOTSUPP;
@@ -19,7 +19,7 @@ int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
if (!list_empty(&tbl->matcher_list)) if (!list_empty(&tbl->matcher_list))
last_matcher = list_last_entry(&tbl->matcher_list, last_matcher = list_last_entry(&tbl->matcher_list,
struct mlx5dr_matcher, struct mlx5dr_matcher,
matcher_list); list_node);
if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX || if (tbl->dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX ||
tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) { tbl->dmn->type == MLX5DR_DOMAIN_TYPE_FDB) {
@@ -68,6 +68,9 @@ int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
} }
} }
if (ret)
goto out;
/* Release old action */ /* Release old action */
if (tbl->miss_action) if (tbl->miss_action)
refcount_dec(&tbl->miss_action->refcount); refcount_dec(&tbl->miss_action->refcount);

View File

@@ -891,7 +891,7 @@ struct mlx5dr_matcher {
struct mlx5dr_table *tbl; struct mlx5dr_table *tbl;
struct mlx5dr_matcher_rx_tx rx; struct mlx5dr_matcher_rx_tx rx;
struct mlx5dr_matcher_rx_tx tx; struct mlx5dr_matcher_rx_tx tx;
struct list_head matcher_list; struct list_head list_node;
u32 prio; u32 prio;
struct mlx5dr_match_param mask; struct mlx5dr_match_param mask;
u8 match_criteria; u8 match_criteria;

View File

@@ -249,6 +249,7 @@ static void nixge_hw_dma_bd_release(struct net_device *ndev)
struct sk_buff *skb; struct sk_buff *skb;
int i; int i;
if (priv->rx_bd_v) {
for (i = 0; i < RX_BD_NUM; i++) { for (i = 0; i < RX_BD_NUM; i++) {
phys_addr = nixge_hw_dma_bd_get_addr(&priv->rx_bd_v[i], phys_addr = nixge_hw_dma_bd_get_addr(&priv->rx_bd_v[i],
phys); phys);
@@ -263,11 +264,11 @@ static void nixge_hw_dma_bd_release(struct net_device *ndev)
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
if (priv->rx_bd_v)
dma_free_coherent(ndev->dev.parent, dma_free_coherent(ndev->dev.parent,
sizeof(*priv->rx_bd_v) * RX_BD_NUM, sizeof(*priv->rx_bd_v) * RX_BD_NUM,
priv->rx_bd_v, priv->rx_bd_v,
priv->rx_bd_p); priv->rx_bd_p);
}
if (priv->tx_skb) if (priv->tx_skb)
devm_kfree(ndev->dev.parent, priv->tx_skb); devm_kfree(ndev->dev.parent, priv->tx_skb);

View File

@@ -2991,7 +2991,7 @@ static void qlcnic_83xx_recover_driver_lock(struct qlcnic_adapter *adapter)
QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val); QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"%s: lock recovery initiated\n", __func__); "%s: lock recovery initiated\n", __func__);
msleep(QLC_83XX_DRV_LOCK_RECOVERY_DELAY); mdelay(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK); val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
id = ((val >> 2) & 0xF); id = ((val >> 2) & 0xF);
if (id == adapter->portnum) { if (id == adapter->portnum) {
@@ -3027,7 +3027,7 @@ int qlcnic_83xx_lock_driver(struct qlcnic_adapter *adapter)
if (status) if (status)
break; break;
msleep(QLC_83XX_DRV_LOCK_WAIT_DELAY); mdelay(QLC_83XX_DRV_LOCK_WAIT_DELAY);
i++; i++;
if (i == 1) if (i == 1)

View File

@@ -2491,6 +2491,7 @@ static int __maybe_unused ravb_resume(struct device *dev)
ret = ravb_open(ndev); ret = ravb_open(ndev);
if (ret < 0) if (ret < 0)
return ret; return ret;
ravb_set_rx_mode(ndev);
netif_device_attach(ndev); netif_device_attach(ndev);
} }

View File

@@ -745,6 +745,8 @@ static void dwmac4_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
if (fc & FLOW_RX) { if (fc & FLOW_RX) {
pr_debug("\tReceive Flow-Control ON\n"); pr_debug("\tReceive Flow-Control ON\n");
flow |= GMAC_RX_FLOW_CTRL_RFE; flow |= GMAC_RX_FLOW_CTRL_RFE;
} else {
pr_debug("\tReceive Flow-Control OFF\n");
} }
writel(flow, ioaddr + GMAC_RX_FLOW_CTRL); writel(flow, ioaddr + GMAC_RX_FLOW_CTRL);

View File

@@ -1158,7 +1158,15 @@ static void stmmac_mac_link_up(struct phylink_config *config,
ctrl |= priv->hw->link.duplex; ctrl |= priv->hw->link.duplex;
/* Flow Control operation */ /* Flow Control operation */
if (tx_pause && rx_pause) if (rx_pause && tx_pause)
priv->flow_ctrl = FLOW_AUTO;
else if (rx_pause && !tx_pause)
priv->flow_ctrl = FLOW_RX;
else if (!rx_pause && tx_pause)
priv->flow_ctrl = FLOW_TX;
else
priv->flow_ctrl = FLOW_OFF;
stmmac_mac_flow_ctrl(priv, duplex); stmmac_mac_flow_ctrl(priv, duplex);
if (ctrl != old_ctrl) if (ctrl != old_ctrl)

View File

@@ -2054,7 +2054,7 @@ static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
for (i = 0; i < common->port_num; i++) { for (i = 0; i < common->port_num; i++) {
port = &common->ports[i]; port = &common->ports[i];
if (port->ndev) if (port->ndev && port->ndev->reg_state == NETREG_REGISTERED)
unregister_netdev(port->ndev); unregister_netdev(port->ndev);
} }
} }

View File

@@ -120,7 +120,7 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
/* Associate the fwnode with the device structure so it /* Associate the fwnode with the device structure so it
* can be looked up later. * can be looked up later.
*/ */
phy->mdio.dev.fwnode = child; phy->mdio.dev.fwnode = fwnode_handle_get(child);
/* All data is now stored in the phy struct, so register it */ /* All data is now stored in the phy struct, so register it */
rc = phy_device_register(phy); rc = phy_device_register(phy);

View File

@@ -484,7 +484,14 @@ static int __init ntb_netdev_init_module(void)
rc = ntb_transport_register_client_dev(KBUILD_MODNAME); rc = ntb_transport_register_client_dev(KBUILD_MODNAME);
if (rc) if (rc)
return rc; return rc;
return ntb_transport_register_client(&ntb_netdev_client);
rc = ntb_transport_register_client(&ntb_netdev_client);
if (rc) {
ntb_transport_unregister_client_dev(KBUILD_MODNAME);
return rc;
}
return 0;
} }
module_init(ntb_netdev_init_module); module_init(ntb_netdev_init_module);

View File

@@ -215,6 +215,7 @@ static void phy_mdio_device_free(struct mdio_device *mdiodev)
static void phy_device_release(struct device *dev) static void phy_device_release(struct device *dev)
{ {
fwnode_handle_put(dev->fwnode);
kfree(to_phy_device(dev)); kfree(to_phy_device(dev));
} }
@@ -1518,6 +1519,7 @@ error:
error_module_put: error_module_put:
module_put(d->driver->owner); module_put(d->driver->owner);
d->driver = NULL;
error_put_device: error_put_device:
put_device(d); put_device(d);
if (ndev_owner != bus->owner) if (ndev_owner != bus->owner)

View File

@@ -687,7 +687,6 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
if (tun) if (tun)
xdp_rxq_info_unreg(&tfile->xdp_rxq); xdp_rxq_info_unreg(&tfile->xdp_rxq);
ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free); ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free);
sock_put(&tfile->sk);
} }
} }
@@ -703,6 +702,9 @@ static void tun_detach(struct tun_file *tfile, bool clean)
if (dev) if (dev)
netdev_state_change(dev); netdev_state_change(dev);
rtnl_unlock(); rtnl_unlock();
if (clean)
sock_put(&tfile->sk);
} }
static void tun_detach_all(struct net_device *dev) static void tun_detach_all(struct net_device *dev)

View File

@@ -830,8 +830,7 @@ void ipc_mux_ul_encoded_process(struct iosm_mux *ipc_mux, struct sk_buff *skb)
ipc_mux->ul_data_pend_bytes); ipc_mux->ul_data_pend_bytes);
/* Reset the skb settings. */ /* Reset the skb settings. */
skb->tail = 0; skb_trim(skb, 0);
skb->len = 0;
/* Add the consumed ADB to the free list. */ /* Add the consumed ADB to the free list. */
skb_queue_tail((&ipc_mux->ul_adb.free_list), skb); skb_queue_tail((&ipc_mux->ul_adb.free_list), skb);

View File

@@ -122,7 +122,7 @@ struct iosm_protocol {
struct iosm_imem *imem; struct iosm_imem *imem;
struct ipc_rsp *rsp_ring[IPC_MEM_MSG_ENTRIES]; struct ipc_rsp *rsp_ring[IPC_MEM_MSG_ENTRIES];
struct device *dev; struct device *dev;
phys_addr_t phy_ap_shm; dma_addr_t phy_ap_shm;
u32 old_msg_tail; u32 old_msg_tail;
}; };

View File

@@ -3920,7 +3920,7 @@ static void nvme_ns_remove(struct nvme_ns *ns)
mutex_unlock(&ns->ctrl->subsys->lock); mutex_unlock(&ns->ctrl->subsys->lock);
/* guarantee not available in head->list */ /* guarantee not available in head->list */
synchronize_rcu(); synchronize_srcu(&ns->head->srcu);
/* wait for concurrent submissions */ /* wait for concurrent submissions */
if (nvme_mpath_clear_current_path(ns)) if (nvme_mpath_clear_current_path(ns))

View File

@@ -151,11 +151,14 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
struct nvme_ns_head *head = ns->head; struct nvme_ns_head *head = ns->head;
sector_t capacity = get_capacity(head->disk); sector_t capacity = get_capacity(head->disk);
int node; int node;
int srcu_idx;
srcu_idx = srcu_read_lock(&head->srcu);
list_for_each_entry_rcu(ns, &head->list, siblings) { list_for_each_entry_rcu(ns, &head->list, siblings) {
if (capacity != get_capacity(ns->disk)) if (capacity != get_capacity(ns->disk))
clear_bit(NVME_NS_READY, &ns->flags); clear_bit(NVME_NS_READY, &ns->flags);
} }
srcu_read_unlock(&head->srcu, srcu_idx);
for_each_node(node) for_each_node(node)
rcu_assign_pointer(head->current_path[node], NULL); rcu_assign_pointer(head->current_path[node], NULL);

View File

@@ -37,9 +37,9 @@ static int rmem_read(void *context, unsigned int offset,
* but as of Dec 2020 this isn't possible on arm64. * but as of Dec 2020 this isn't possible on arm64.
*/ */
addr = memremap(priv->mem->base, available, MEMREMAP_WB); addr = memremap(priv->mem->base, available, MEMREMAP_WB);
if (IS_ERR(addr)) { if (!addr) {
dev_err(priv->dev, "Failed to remap memory region\n"); dev_err(priv->dev, "Failed to remap memory region\n");
return PTR_ERR(addr); return -ENOMEM;
} }
count = memory_read_from_buffer(val, bytes, &off, addr, available); count = memory_read_from_buffer(val, bytes, &off, addr, available);

View File

@@ -975,8 +975,10 @@ of_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
nargs, index, &of_args); nargs, index, &of_args);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!args) if (!args) {
of_node_put(of_args.np);
return 0; return 0;
}
args->nargs = of_args.args_count; args->nargs = of_args.args_count;
args->fwnode = of_fwnode_handle(of_args.np); args->fwnode = of_fwnode_handle(of_args.np);

View File

@@ -436,9 +436,14 @@ static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
writel(value, padcfg0); writel(value, padcfg0);
} }
static int __intel_gpio_get_gpio_mode(u32 value)
{
return (value & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
}
static int intel_gpio_get_gpio_mode(void __iomem *padcfg0) static int intel_gpio_get_gpio_mode(void __iomem *padcfg0)
{ {
return (readl(padcfg0) & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT; return __intel_gpio_get_gpio_mode(readl(padcfg0));
} }
static void intel_gpio_set_gpio_mode(void __iomem *padcfg0) static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
@@ -1659,6 +1664,7 @@ EXPORT_SYMBOL_GPL(intel_pinctrl_get_soc_data);
static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin) static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin)
{ {
const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin); const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
u32 value;
if (!pd || !intel_pad_usable(pctrl, pin)) if (!pd || !intel_pad_usable(pctrl, pin))
return false; return false;
@@ -1673,6 +1679,25 @@ static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int
gpiochip_line_is_irq(&pctrl->chip, intel_pin_to_gpio(pctrl, pin))) gpiochip_line_is_irq(&pctrl->chip, intel_pin_to_gpio(pctrl, pin)))
return true; return true;
/*
* The firmware on some systems may configure GPIO pins to be
* an interrupt source in so called "direct IRQ" mode. In such
* cases the GPIO controller driver has no idea if those pins
* are being used or not. At the same time, there is a known bug
* in the firmwares that don't restore the pin settings correctly
* after suspend, i.e. by an unknown reason the Rx value becomes
* inverted.
*
* Hence, let's save and restore the pins that are configured
* as GPIOs in the input mode with GPIROUTIOXAPIC bit set.
*
* See https://bugzilla.kernel.org/show_bug.cgi?id=214749.
*/
value = readl(intel_get_padcfg(pctrl, pin, PADCFG0));
if ((value & PADCFG0_GPIROUTIOXAPIC) && (value & PADCFG0_GPIOTXDIS) &&
(__intel_gpio_get_gpio_mode(value) == PADCFG0_PMODE_GPIO))
return true;
return false; return false;
} }

View File

@@ -727,7 +727,7 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
mux_bytes = pcs->width / BITS_PER_BYTE; mux_bytes = pcs->width / BITS_PER_BYTE;
if (pcs->bits_per_mux) { if (pcs->bits_per_mux && pcs->fmask) {
pcs->bits_per_pin = fls(pcs->fmask); pcs->bits_per_pin = fls(pcs->fmask);
nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin; nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
} else { } else {

View File

@@ -439,8 +439,7 @@ static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
unsigned int pre, post; unsigned int pre, post;
unsigned int fin = spi_imx->spi_clk; unsigned int fin = spi_imx->spi_clk;
if (unlikely(fspi > fin)) fspi = min(fspi, fin);
return 0;
post = fls(fin) - fls(fspi); post = fls(fin) - fls(fspi);
if (fin > fspi << post) if (fin > fspi << post)

View File

@@ -61,6 +61,53 @@ static void stm32_usart_clr_bits(struct uart_port *port, u32 reg, u32 bits)
writel_relaxed(val, port->membase + reg); writel_relaxed(val, port->membase + reg);
} }
static unsigned int stm32_usart_tx_empty(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
return TIOCSER_TEMT;
return 0;
}
static void stm32_usart_rs485_rts_enable(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct serial_rs485 *rs485conf = &port->rs485;
if (stm32_port->hw_flow_control ||
!(rs485conf->flags & SER_RS485_ENABLED))
return;
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl | TIOCM_RTS);
} else {
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl & ~TIOCM_RTS);
}
}
static void stm32_usart_rs485_rts_disable(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct serial_rs485 *rs485conf = &port->rs485;
if (stm32_port->hw_flow_control ||
!(rs485conf->flags & SER_RS485_ENABLED))
return;
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl & ~TIOCM_RTS);
} else {
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl | TIOCM_RTS);
}
}
static void stm32_usart_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE, static void stm32_usart_config_reg_rs485(u32 *cr1, u32 *cr3, u32 delay_ADE,
u32 delay_DDE, u32 baud) u32 delay_DDE, u32 baud)
{ {
@@ -149,6 +196,12 @@ static int stm32_usart_config_rs485(struct uart_port *port,
stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
/* Adjust RTS polarity in case it's driven in software */
if (stm32_usart_tx_empty(port))
stm32_usart_rs485_rts_disable(port);
else
stm32_usart_rs485_rts_enable(port);
return 0; return 0;
} }
@@ -314,6 +367,14 @@ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE); stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TXEIE);
} }
static void stm32_usart_tc_interrupt_enable(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
stm32_usart_set_bits(port, ofs->cr1, USART_CR1_TCIE);
}
static void stm32_usart_tx_interrupt_disable(struct uart_port *port) static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
{ {
struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_port *stm32_port = to_stm32_port(port);
@@ -325,6 +386,14 @@ static void stm32_usart_tx_interrupt_disable(struct uart_port *port)
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE); stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TXEIE);
} }
static void stm32_usart_tc_interrupt_disable(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_TCIE);
}
static void stm32_usart_transmit_chars_pio(struct uart_port *port) static void stm32_usart_transmit_chars_pio(struct uart_port *port)
{ {
struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_port *stm32_port = to_stm32_port(port);
@@ -426,6 +495,13 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
u32 isr; u32 isr;
int ret; int ret;
if (!stm32_port->hw_flow_control &&
port->rs485.flags & SER_RS485_ENABLED) {
stm32_port->txdone = false;
stm32_usart_tc_interrupt_disable(port);
stm32_usart_rs485_rts_enable(port);
}
if (port->x_char) { if (port->x_char) {
if (stm32_port->tx_dma_busy) if (stm32_port->tx_dma_busy)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT); stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_DMAT);
@@ -465,8 +541,14 @@ static void stm32_usart_transmit_chars(struct uart_port *port)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) if (uart_circ_empty(xmit)) {
stm32_usart_tx_interrupt_disable(port); stm32_usart_tx_interrupt_disable(port);
if (!stm32_port->hw_flow_control &&
port->rs485.flags & SER_RS485_ENABLED) {
stm32_port->txdone = true;
stm32_usart_tc_interrupt_enable(port);
}
}
} }
static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
@@ -479,6 +561,13 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
sr = readl_relaxed(port->membase + ofs->isr); sr = readl_relaxed(port->membase + ofs->isr);
if (!stm32_port->hw_flow_control &&
port->rs485.flags & SER_RS485_ENABLED &&
(sr & USART_SR_TC)) {
stm32_usart_tc_interrupt_disable(port);
stm32_usart_rs485_rts_disable(port);
}
if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
writel_relaxed(USART_ICR_RTOCF, writel_relaxed(USART_ICR_RTOCF,
port->membase + ofs->icr); port->membase + ofs->icr);
@@ -518,17 +607,6 @@ static irqreturn_t stm32_usart_threaded_interrupt(int irq, void *ptr)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static unsigned int stm32_usart_tx_empty(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
if (readl_relaxed(port->membase + ofs->isr) & USART_SR_TC)
return TIOCSER_TEMT;
return 0;
}
static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl) static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{ {
struct stm32_port *stm32_port = to_stm32_port(port); struct stm32_port *stm32_port = to_stm32_port(port);
@@ -566,41 +644,22 @@ static void stm32_usart_disable_ms(struct uart_port *port)
/* Transmit stop */ /* Transmit stop */
static void stm32_usart_stop_tx(struct uart_port *port) static void stm32_usart_stop_tx(struct uart_port *port)
{ {
struct stm32_port *stm32_port = to_stm32_port(port);
struct serial_rs485 *rs485conf = &port->rs485;
stm32_usart_tx_interrupt_disable(port); stm32_usart_tx_interrupt_disable(port);
if (rs485conf->flags & SER_RS485_ENABLED) { stm32_usart_rs485_rts_disable(port);
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl & ~TIOCM_RTS);
} else {
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl | TIOCM_RTS);
}
}
} }
/* There are probably characters waiting to be transmitted. */ /* There are probably characters waiting to be transmitted. */
static void stm32_usart_start_tx(struct uart_port *port) static void stm32_usart_start_tx(struct uart_port *port)
{ {
struct stm32_port *stm32_port = to_stm32_port(port);
struct serial_rs485 *rs485conf = &port->rs485;
struct circ_buf *xmit = &port->state->xmit; struct circ_buf *xmit = &port->state->xmit;
if (uart_circ_empty(xmit) && !port->x_char) if (uart_circ_empty(xmit) && !port->x_char) {
stm32_usart_rs485_rts_disable(port);
return; return;
}
if (rs485conf->flags & SER_RS485_ENABLED) { stm32_usart_rs485_rts_enable(port);
if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl | TIOCM_RTS);
} else {
mctrl_gpio_set(stm32_port->gpios,
stm32_port->port.mctrl & ~TIOCM_RTS);
}
}
stm32_usart_transmit_chars(port); stm32_usart_transmit_chars(port);
} }

View File

@@ -267,6 +267,7 @@ struct stm32_port {
bool hw_flow_control; bool hw_flow_control;
bool swap; /* swap RX & TX pins */ bool swap; /* swap RX & TX pins */
bool fifoen; bool fifoen;
bool txdone;
int rxftcfg; /* RX FIFO threshold CFG */ int rxftcfg; /* RX FIFO threshold CFG */
int txftcfg; /* TX FIFO threshold CFG */ int txftcfg; /* TX FIFO threshold CFG */
bool wakeup_src; bool wakeup_src;

View File

@@ -167,8 +167,8 @@ responded:
clear_bit(AFS_SERVER_FL_HAS_FS64, &server->flags); clear_bit(AFS_SERVER_FL_HAS_FS64, &server->flags);
} }
if (rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us) && rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us);
rtt_us < server->probe.rtt) { if (rtt_us < server->probe.rtt) {
server->probe.rtt = rtt_us; server->probe.rtt = rtt_us;
server->rtt = rtt_us; server->rtt = rtt_us;
alist->preferred = index; alist->preferred = index;

View File

@@ -2060,10 +2060,29 @@ out:
return ret; return ret;
} }
static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx)
{
struct btrfs_data_container *inodes = ctx;
const size_t c = 3 * sizeof(u64);
if (inodes->bytes_left >= c) {
inodes->bytes_left -= c;
inodes->val[inodes->elem_cnt] = inum;
inodes->val[inodes->elem_cnt + 1] = offset;
inodes->val[inodes->elem_cnt + 2] = root;
inodes->elem_cnt += 3;
} else {
inodes->bytes_missing += c - inodes->bytes_left;
inodes->bytes_left = 0;
inodes->elem_missed += 3;
}
return 0;
}
int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
struct btrfs_path *path, struct btrfs_path *path,
iterate_extent_inodes_t *iterate, void *ctx, void *ctx, bool ignore_offset)
bool ignore_offset)
{ {
int ret; int ret;
u64 extent_item_pos; u64 extent_item_pos;
@@ -2081,7 +2100,7 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
extent_item_pos = logical - found_key.objectid; extent_item_pos = logical - found_key.objectid;
ret = iterate_extent_inodes(fs_info, found_key.objectid, ret = iterate_extent_inodes(fs_info, found_key.objectid,
extent_item_pos, search_commit_root, extent_item_pos, search_commit_root,
iterate, ctx, ignore_offset); build_ino_list, ctx, ignore_offset);
return ret; return ret;
} }

View File

@@ -35,8 +35,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
bool ignore_offset); bool ignore_offset);
int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
struct btrfs_path *path, struct btrfs_path *path, void *ctx,
iterate_extent_inodes_t *iterate, void *ctx,
bool ignore_offset); bool ignore_offset);
int paths_from_inode(u64 inum, struct inode_fs_paths *ipath); int paths_from_inode(u64 inum, struct inode_fs_paths *ipath);

View File

@@ -3911,26 +3911,6 @@ out:
return ret; return ret;
} }
static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx)
{
struct btrfs_data_container *inodes = ctx;
const size_t c = 3 * sizeof(u64);
if (inodes->bytes_left >= c) {
inodes->bytes_left -= c;
inodes->val[inodes->elem_cnt] = inum;
inodes->val[inodes->elem_cnt + 1] = offset;
inodes->val[inodes->elem_cnt + 2] = root;
inodes->elem_cnt += 3;
} else {
inodes->bytes_missing += c - inodes->bytes_left;
inodes->bytes_left = 0;
inodes->elem_missed += 3;
}
return 0;
}
static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info, static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
void __user *arg, int version) void __user *arg, int version)
{ {
@@ -3966,21 +3946,20 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
size = min_t(u32, loi->size, SZ_16M); size = min_t(u32, loi->size, SZ_16M);
} }
inodes = init_data_container(size);
if (IS_ERR(inodes)) {
ret = PTR_ERR(inodes);
goto out_loi;
}
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) { if (!path) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
inodes = init_data_container(size);
if (IS_ERR(inodes)) {
ret = PTR_ERR(inodes);
inodes = NULL;
goto out;
}
ret = iterate_inodes_from_logical(loi->logical, fs_info, path, ret = iterate_inodes_from_logical(loi->logical, fs_info, path,
build_ino_list, inodes, ignore_offset); inodes, ignore_offset);
btrfs_free_path(path);
if (ret == -EINVAL) if (ret == -EINVAL)
ret = -ENOENT; ret = -ENOENT;
if (ret < 0) if (ret < 0)
@@ -3992,7 +3971,6 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
ret = -EFAULT; ret = -EFAULT;
out: out:
btrfs_free_path(path);
kvfree(inodes); kvfree(inodes);
out_loi: out_loi:
kfree(loi); kfree(loi);

View File

@@ -2903,14 +2903,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
dstgroup->rsv_rfer = inherit->lim.rsv_rfer; dstgroup->rsv_rfer = inherit->lim.rsv_rfer;
dstgroup->rsv_excl = inherit->lim.rsv_excl; dstgroup->rsv_excl = inherit->lim.rsv_excl;
ret = update_qgroup_limit_item(trans, dstgroup); qgroup_dirty(fs_info, dstgroup);
if (ret) {
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
btrfs_info(fs_info,
"unable to update quota limit for %llu",
dstgroup->qgroupid);
goto unlock;
}
} }
if (srcid) { if (srcid) {
@@ -3280,7 +3273,8 @@ out:
static bool rescan_should_stop(struct btrfs_fs_info *fs_info) static bool rescan_should_stop(struct btrfs_fs_info *fs_info)
{ {
return btrfs_fs_closing(fs_info) || return btrfs_fs_closing(fs_info) ||
test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state); test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state) ||
!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
} }
static void btrfs_qgroup_rescan_worker(struct btrfs_work *work) static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
@@ -3310,11 +3304,9 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
err = PTR_ERR(trans); err = PTR_ERR(trans);
break; break;
} }
if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
err = -EINTR;
} else {
err = qgroup_rescan_leaf(trans, path); err = qgroup_rescan_leaf(trans, path);
}
if (err > 0) if (err > 0)
btrfs_commit_transaction(trans); btrfs_commit_transaction(trans);
else else
@@ -3328,7 +3320,7 @@ out:
if (err > 0 && if (err > 0 &&
fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) { fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
} else if (err < 0) { } else if (err < 0 || stopped) {
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT; fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
} }
mutex_unlock(&fs_info->qgroup_rescan_lock); mutex_unlock(&fs_info->qgroup_rescan_lock);

View File

@@ -222,7 +222,7 @@ static int erofs_fill_symlink(struct inode *inode, void *data,
/* if it cannot be handled with fast symlink scheme */ /* if it cannot be handled with fast symlink scheme */
if (vi->datalayout != EROFS_INODE_FLAT_INLINE || if (vi->datalayout != EROFS_INODE_FLAT_INLINE ||
inode->i_size >= PAGE_SIZE) { inode->i_size >= PAGE_SIZE || inode->i_size < 0) {
inode->i_op = &erofs_symlink_iops; inode->i_op = &erofs_symlink_iops;
return 0; return 0;
} }

View File

@@ -5322,7 +5322,29 @@ struct io_poll_table {
}; };
#define IO_POLL_CANCEL_FLAG BIT(31) #define IO_POLL_CANCEL_FLAG BIT(31)
#define IO_POLL_REF_MASK GENMASK(30, 0) #define IO_POLL_RETRY_FLAG BIT(30)
#define IO_POLL_REF_MASK GENMASK(29, 0)
/*
* We usually have 1-2 refs taken, 128 is more than enough and we want to
* maximise the margin between this amount and the moment when it overflows.
*/
#define IO_POLL_REF_BIAS 128
static bool io_poll_get_ownership_slowpath(struct io_kiocb *req)
{
int v;
/*
* poll_refs are already elevated and we don't have much hope for
* grabbing the ownership. Instead of incrementing set a retry flag
* to notify the loop that there might have been some change.
*/
v = atomic_fetch_or(IO_POLL_RETRY_FLAG, &req->poll_refs);
if (v & IO_POLL_REF_MASK)
return false;
return !(atomic_fetch_inc(&req->poll_refs) & IO_POLL_REF_MASK);
}
/* /*
* If refs part of ->poll_refs (see IO_POLL_REF_MASK) is 0, it's free. We can * If refs part of ->poll_refs (see IO_POLL_REF_MASK) is 0, it's free. We can
@@ -5332,6 +5354,8 @@ struct io_poll_table {
*/ */
static inline bool io_poll_get_ownership(struct io_kiocb *req) static inline bool io_poll_get_ownership(struct io_kiocb *req)
{ {
if (unlikely(atomic_read(&req->poll_refs) >= IO_POLL_REF_BIAS))
return io_poll_get_ownership_slowpath(req);
return !(atomic_fetch_inc(&req->poll_refs) & IO_POLL_REF_MASK); return !(atomic_fetch_inc(&req->poll_refs) & IO_POLL_REF_MASK);
} }
@@ -5440,6 +5464,23 @@ static int io_poll_check_events(struct io_kiocb *req)
return 0; return 0;
if (v & IO_POLL_CANCEL_FLAG) if (v & IO_POLL_CANCEL_FLAG)
return -ECANCELED; return -ECANCELED;
/*
* cqe.res contains only events of the first wake up
* and all others are be lost. Redo vfs_poll() to get
* up to date state.
*/
if ((v & IO_POLL_REF_MASK) != 1)
req->result = 0;
if (v & IO_POLL_RETRY_FLAG) {
req->result = 0;
/*
* We won't find new events that came in between
* vfs_poll and the ref put unless we clear the
* flag in advance.
*/
atomic_andnot(IO_POLL_RETRY_FLAG, &req->poll_refs);
v &= ~IO_POLL_RETRY_FLAG;
}
if (!req->result) { if (!req->result) {
struct poll_table_struct pt = { ._key = poll->events }; struct poll_table_struct pt = { ._key = poll->events };
@@ -5464,11 +5505,15 @@ static int io_poll_check_events(struct io_kiocb *req)
return 0; return 0;
} }
/* force the next iteration to vfs_poll() */
req->result = 0;
/* /*
* Release all references, retry if someone tried to restart * Release all references, retry if someone tried to restart
* task_work while we were executing it. * task_work while we were executing it.
*/ */
} while (atomic_sub_return(v & IO_POLL_REF_MASK, &req->poll_refs)); } while (atomic_sub_return(v & IO_POLL_REF_MASK, &req->poll_refs) &
IO_POLL_REF_MASK);
return 1; return 1;
} }
@@ -5640,7 +5685,6 @@ static int __io_arm_poll_handler(struct io_kiocb *req,
struct io_poll_table *ipt, __poll_t mask) struct io_poll_table *ipt, __poll_t mask)
{ {
struct io_ring_ctx *ctx = req->ctx; struct io_ring_ctx *ctx = req->ctx;
int v;
INIT_HLIST_NODE(&req->hash_node); INIT_HLIST_NODE(&req->hash_node);
io_init_poll_iocb(poll, mask, io_poll_wake); io_init_poll_iocb(poll, mask, io_poll_wake);
@@ -5686,11 +5730,10 @@ static int __io_arm_poll_handler(struct io_kiocb *req,
} }
/* /*
* Release ownership. If someone tried to queue a tw while it was * Try to release ownership. If we see a change of state, e.g.
* locked, kick it off for them. * poll was waken up, queue up a tw, it'll deal with it.
*/ */
v = atomic_dec_return(&req->poll_refs); if (atomic_cmpxchg(&req->poll_refs, 1, 0) != 1)
if (unlikely(v & IO_POLL_REF_MASK))
__io_poll_execute(req, 0); __io_poll_execute(req, 0);
return 0; return 0;
} }

Some files were not shown because too many files have changed in this diff Show More