Merge 6.1.140 into android14-6.1-lts

Changes in 6.1.140
	binfmt: Fix whitespace issues
	binfmt_elf: Support segments with 0 filesz and misaligned starts
	binfmt_elf: elf_bss no longer used by load_elf_binary()
	selftests/exec: load_address: conform test to TAP format output
	binfmt_elf: Leave a gap between .bss and brk
	selftests/exec: Build both static and non-static load_address tests
	binfmt_elf: Calculate total_size earlier
	binfmt_elf: Honor PT_LOAD alignment for static PIE
	binfmt_elf: Move brk for static PIE even if ASLR disabled
	platform/x86: asus-wmi: Fix wlan_ctrl_by_user detection
	tracing: probes: Fix a possible race in trace_probe_log APIs
	tpm: tis: Double the timeout B to 4s
	iio: adc: ad7266: Fix potential timestamp alignment issue.
	drm/amd: Stop evicting resources on APUs in suspend
	drm/amdgpu: Fix the runtime resume failure issue
	drm/amdgpu: trigger flr_work if reading pf2vf data failed
	drm/amd: Add Suspend/Hibernate notification callback support
	Revert "drm/amd: Stop evicting resources on APUs in suspend"
	iio: adc: ad7768-1: Fix insufficient alignment of timestamp.
	iio: chemical: sps30: use aligned_s64 for timestamp
	clocksource/i8253: Use raw_spinlock_irqsave() in clockevent_i8253_disable()
	RDMA/rxe: Fix slab-use-after-free Read in rxe_queue_cleanup bug
	HID: thrustmaster: fix memory leak in thrustmaster_interrupts()
	HID: uclogic: Add NULL check in uclogic_input_configured()
	nfs: handle failure of nfs_get_lock_context in unlock path
	spi: loopback-test: Do not split 1024-byte hexdumps
	net_sched: Flush gso_skb list too during ->change()
	net: mctp: Ensure keys maintain only one ref to corresponding dev
	net: cadence: macb: Fix a possible deadlock in macb_halt_tx.
	net: dsa: sja1105: discard incoming frames in BR_STATE_LISTENING
	nvme-pci: make nvme_pci_npages_prp() __always_inline
	nvme-pci: acquire cq_poll_lock in nvme_poll_irqdisable
	ALSA: sh: SND_AICA should depend on SH_DMA_API
	net/mlx5e: Disable MACsec offload for uplink representor profile
	qlcnic: fix memory leak in qlcnic_sriov_channel_cfg_cmd()
	regulator: max20086: fix invalid memory access
	octeontx2-pf: macsec: Fix incorrect max transmit size in TX secy
	net/tls: fix kernel panic when alloc_page failed
	NFSv4/pnfs: Reset the layout state after a layoutreturn
	dmaengine: Revert "dmaengine: dmatest: Fix dmatest waiting less when interrupted"
	LoongArch: Fix MAX_REG_OFFSET calculation
	btrfs: fix discard worker infinite loop after disabling discard
	drm/amd/display: Correct the reply value when AUX write incomplete
	drm/amd/display: Avoid flooding unnecessary info messages
	ACPI: PPTT: Fix processor subtable walk
	ALSA: es1968: Add error handling for snd_pcm_hw_constraint_pow2()
	ALSA: usb-audio: Add sample rate quirk for Audioengine D1
	ALSA: usb-audio: Add sample rate quirk for Microdia JP001 USB Camera
	dma-buf: insert memory barrier before updating num_fences
	hv_netvsc: Use vmbus_sendpacket_mpb_desc() to send VMBus messages
	hv_netvsc: Preserve contiguous PFN grouping in the page buffer array
	hv_netvsc: Remove rmsg_pgcnt
	Drivers: hv: Allow vmbus_sendpacket_mpb_desc() to create multiple ranges
	Drivers: hv: vmbus: Remove vmbus_sendpacket_pagebuffer()
	ftrace: Fix preemption accounting for stacktrace trigger command
	ftrace: Fix preemption accounting for stacktrace filter command
	tracing: samples: Initialize trace_array_printk() with the correct function
	phy: Fix error handling in tegra_xusb_port_init
	phy: renesas: rcar-gen3-usb2: Fix role detection on unbind/bind
	phy: renesas: rcar-gen3-usb2: Set timing registers only once
	scsi: sd_zbc: block: Respect bio vector limits for REPORT ZONES buffer
	smb: client: fix memory leak during error handling for POSIX mkdir
	wifi: mt76: disable napi on driver removal
	net: qede: Initialize qede_ll_ops with designated initializer
	dmaengine: ti: k3-udma: Add missing locking
	dmaengine: ti: k3-udma: Use cap_mask directly from dma_device structure instead of a local copy
	dmaengine: idxd: fix memory leak in error handling path of idxd_setup_wqs
	dmaengine: idxd: fix memory leak in error handling path of idxd_setup_engines
	dmaengine: idxd: fix memory leak in error handling path of idxd_setup_groups
	dmaengine: idxd: Add missing cleanup for early error out in idxd_setup_internals
	dmaengine: idxd: Add missing cleanups in cleanup internals
	dmaengine: idxd: Add missing idxd cleanup to fix memory leak in remove call
	dmaengine: idxd: fix memory leak in error handling path of idxd_alloc
	dmaengine: idxd: fix memory leak in error handling path of idxd_pci_probe
	usb: typec: ucsi: displayport: Fix deadlock
	usb: typec: altmodes/displayport: create sysfs nodes as driver's default device attribute group
	usb: typec: fix potential array underflow in ucsi_ccg_sync_control()
	usb: typec: fix pm usage counter imbalance in ucsi_ccg_sync_control()
	selftests/mm: compaction_test: support platform with huge mount of memory
	mm/vmscan: fix a bug calling wakeup_kswapd() with a wrong zone index
	riscv: mm: Fix the out of bound issue of vmemmap address
	bpf, arm64: Fix trampoline for BPF_TRAMP_F_CALL_ORIG
	bpf, arm64: Fix address emission with tag-based KASAN enabled
	LoongArch: Explicitly specify code model in Makefile
	hwpoison, memory_hotplug: lock folio before unmap hwpoisoned folio
	sctp: add mutual exclusion in proc_sctp_do_udp_port()
	btrfs: don't BUG_ON() when 0 reference count at btrfs_lookup_extent_info()
	netfilter: nf_tables: pass nft_chain to destroy function, not nft_ctx
	netfilter: nf_tables: wait for rcu grace period on net_device removal
	netfilter: nf_tables: do not defer rule destruction via call_rcu
	arm64/sme: Always exit sme_alloc() early with existing storage
	platform/x86/amd/pmc: Only disable IRQ1 wakeup where i8042 actually enabled it
	bnxt_en: Fix receive ring space parameters when XDP is active
	ipv6: Fix potential uninit-value access in __ip6_make_skb()
	ipv4: Fix uninit-value access in __ip_make_skb()
	spi: cadence-qspi: fix pointer reference in runtime PM hooks
	drm/amdgpu: fix pm notifier handling
	x86/modules: Set VM_FLUSH_RESET_PERMS in module_alloc()
	Linux 6.1.140

Change-Id: Ieb4e51eea0bf366d869913439bc2a4c35d77334c
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2025-05-22 13:26:53 +00:00
105 changed files with 932 additions and 527 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 6 VERSION = 6
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 139 SUBLEVEL = 140
EXTRAVERSION = EXTRAVERSION =
NAME = Curry Ramen NAME = Curry Ramen

View File

@@ -1234,8 +1234,10 @@ void fpsimd_release_task(struct task_struct *dead_task)
*/ */
void sme_alloc(struct task_struct *task, bool flush) void sme_alloc(struct task_struct *task, bool flush)
{ {
if (task->thread.za_state && flush) { if (task->thread.za_state) {
memset(task->thread.za_state, 0, za_state_size(task)); if (flush)
memset(task->thread.za_state, 0,
za_state_size(task));
return; return;
} }

View File

@@ -1942,7 +1942,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
emit(A64_STR64I(A64_R(20), A64_SP, regs_off + 8), ctx); emit(A64_STR64I(A64_R(20), A64_SP, regs_off + 8), ctx);
if (flags & BPF_TRAMP_F_CALL_ORIG) { if (flags & BPF_TRAMP_F_CALL_ORIG) {
emit_addr_mov_i64(A64_R(0), (const u64)im, ctx); /* for the first pass, assume the worst case */
if (!ctx->image)
ctx->idx += 4;
else
emit_a64_mov_i64(A64_R(0), (const u64)im, ctx);
emit_call((const u64)__bpf_tramp_enter, ctx); emit_call((const u64)__bpf_tramp_enter, ctx);
} }
@@ -1986,7 +1990,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
if (flags & BPF_TRAMP_F_CALL_ORIG) { if (flags & BPF_TRAMP_F_CALL_ORIG) {
im->ip_epilogue = ctx->image + ctx->idx; im->ip_epilogue = ctx->image + ctx->idx;
emit_addr_mov_i64(A64_R(0), (const u64)im, ctx); /* for the first pass, assume the worst case */
if (!ctx->image)
ctx->idx += 4;
else
emit_a64_mov_i64(A64_R(0), (const u64)im, ctx);
emit_call((const u64)__bpf_tramp_exit, ctx); emit_call((const u64)__bpf_tramp_exit, ctx);
} }

View File

@@ -38,7 +38,7 @@ endif
ifdef CONFIG_64BIT ifdef CONFIG_64BIT
ld-emul = $(64bit-emul) ld-emul = $(64bit-emul)
cflags-y += -mabi=lp64s cflags-y += -mabi=lp64s -mcmodel=normal
endif endif
cflags-y += -pipe -msoft-float cflags-y += -pipe -msoft-float

View File

@@ -54,7 +54,7 @@ static inline void instruction_pointer_set(struct pt_regs *regs, unsigned long v
/* Query offset/name of register from its name/offset */ /* Query offset/name of register from its name/offset */
extern int regs_query_register_offset(const char *name); extern int regs_query_register_offset(const char *name);
#define MAX_REG_OFFSET (offsetof(struct pt_regs, __last)) #define MAX_REG_OFFSET (offsetof(struct pt_regs, __last) - sizeof(unsigned long))
/** /**
* regs_get_register() - get register value from its offset * regs_get_register() - get register value from its offset

View File

@@ -115,6 +115,7 @@ struct kernel_mapping {
extern struct kernel_mapping kernel_map; extern struct kernel_mapping kernel_map;
extern phys_addr_t phys_ram_base; extern phys_addr_t phys_ram_base;
extern unsigned long vmemmap_start_pfn;
#define is_kernel_mapping(x) \ #define is_kernel_mapping(x) \
((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size)) ((x) >= kernel_map.virt_addr && (x) < (kernel_map.virt_addr + kernel_map.size))

View File

@@ -79,7 +79,7 @@
* Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel * Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel
* is configured with CONFIG_SPARSEMEM_VMEMMAP enabled. * is configured with CONFIG_SPARSEMEM_VMEMMAP enabled.
*/ */
#define vmemmap ((struct page *)VMEMMAP_START - (phys_ram_base >> PAGE_SHIFT)) #define vmemmap ((struct page *)VMEMMAP_START - vmemmap_start_pfn)
#define PCI_IO_SIZE SZ_16M #define PCI_IO_SIZE SZ_16M
#define PCI_IO_END VMEMMAP_START #define PCI_IO_END VMEMMAP_START

View File

@@ -22,6 +22,7 @@
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
#include <asm/sparsemem.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/soc.h> #include <asm/soc.h>
@@ -52,6 +53,13 @@ EXPORT_SYMBOL(pgtable_l5_enabled);
phys_addr_t phys_ram_base __ro_after_init; phys_addr_t phys_ram_base __ro_after_init;
EXPORT_SYMBOL(phys_ram_base); EXPORT_SYMBOL(phys_ram_base);
#ifdef CONFIG_SPARSEMEM_VMEMMAP
#define VMEMMAP_ADDR_ALIGN (1ULL << SECTION_SIZE_BITS)
unsigned long vmemmap_start_pfn __ro_after_init;
EXPORT_SYMBOL(vmemmap_start_pfn);
#endif
unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
__page_aligned_bss; __page_aligned_bss;
EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(empty_zero_page);
@@ -210,8 +218,12 @@ static void __init setup_bootmem(void)
memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
phys_ram_end = memblock_end_of_DRAM(); phys_ram_end = memblock_end_of_DRAM();
if (!IS_ENABLED(CONFIG_XIP_KERNEL)) if (!IS_ENABLED(CONFIG_XIP_KERNEL)) {
phys_ram_base = memblock_start_of_DRAM(); phys_ram_base = memblock_start_of_DRAM();
#ifdef CONFIG_SPARSEMEM_VMEMMAP
vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
#endif
}
/* /*
* Reserve physical address space that would be mapped to virtual * Reserve physical address space that would be mapped to virtual
* addresses greater than (void *)(-PAGE_SIZE) because: * addresses greater than (void *)(-PAGE_SIZE) because:
@@ -946,6 +958,9 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom); kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom);
phys_ram_base = CONFIG_PHYS_RAM_BASE; phys_ram_base = CONFIG_PHYS_RAM_BASE;
#ifdef CONFIG_SPARSEMEM_VMEMMAP
vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
#endif
kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE; kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE;
kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start); kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start);

View File

@@ -415,8 +415,6 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
/* ALLOC_TRAMP flags lets us know we created it */ /* ALLOC_TRAMP flags lets us know we created it */
ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP; ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP;
set_vm_flush_reset_perms(trampoline);
if (likely(system_state != SYSTEM_BOOTING)) if (likely(system_state != SYSTEM_BOOTING))
set_memory_ro((unsigned long)trampoline, npages); set_memory_ro((unsigned long)trampoline, npages);
set_memory_x((unsigned long)trampoline, npages); set_memory_x((unsigned long)trampoline, npages);

View File

@@ -427,7 +427,6 @@ void *alloc_insn_page(void)
if (!page) if (!page)
return NULL; return NULL;
set_vm_flush_reset_perms(page);
/* /*
* First make the page read-only, and only then make it executable to * First make the page read-only, and only then make it executable to
* prevent it from being W+X in between. * prevent it from being W+X in between.

View File

@@ -74,10 +74,11 @@ void *module_alloc(unsigned long size)
return NULL; return NULL;
p = __vmalloc_node_range(size, MODULE_ALIGN, p = __vmalloc_node_range(size, MODULE_ALIGN,
MODULES_VADDR + get_module_load_offset(), MODULES_VADDR + get_module_load_offset(),
MODULES_END, gfp_mask, MODULES_END, gfp_mask, PAGE_KERNEL,
PAGE_KERNEL, VM_DEFER_KMEMLEAK, NUMA_NO_NODE, VM_FLUSH_RESET_PERMS | VM_DEFER_KMEMLEAK,
__builtin_return_address(0)); NUMA_NO_NODE, __builtin_return_address(0));
if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) { if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) {
vfree(p); vfree(p);
return NULL; return NULL;

View File

@@ -579,7 +579,7 @@ struct bio *bio_kmalloc(unsigned short nr_vecs, gfp_t gfp_mask)
{ {
struct bio *bio; struct bio *bio;
if (nr_vecs > UIO_MAXIOV) if (nr_vecs > BIO_MAX_INLINE_VECS)
return NULL; return NULL;
return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask); return kmalloc(struct_size(bio, bi_inline_vecs, nr_vecs), gfp_mask);
} }

View File

@@ -219,16 +219,18 @@ static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr,
sizeof(struct acpi_table_pptt)); sizeof(struct acpi_table_pptt));
proc_sz = sizeof(struct acpi_pptt_processor); proc_sz = sizeof(struct acpi_pptt_processor);
while ((unsigned long)entry + proc_sz < table_end) { /* ignore subtable types that are smaller than a processor node */
while ((unsigned long)entry + proc_sz <= table_end) {
cpu_node = (struct acpi_pptt_processor *)entry; cpu_node = (struct acpi_pptt_processor *)entry;
if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
cpu_node->parent == node_entry) cpu_node->parent == node_entry)
return 0; return 0;
if (entry->length == 0) if (entry->length == 0)
return 0; return 0;
entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
entry->length); entry->length);
} }
return 1; return 1;
} }
@@ -261,15 +263,18 @@ static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_he
proc_sz = sizeof(struct acpi_pptt_processor); proc_sz = sizeof(struct acpi_pptt_processor);
/* find the processor structure associated with this cpuid */ /* find the processor structure associated with this cpuid */
while ((unsigned long)entry + proc_sz < table_end) { while ((unsigned long)entry + proc_sz <= table_end) {
cpu_node = (struct acpi_pptt_processor *)entry; cpu_node = (struct acpi_pptt_processor *)entry;
if (entry->length == 0) { if (entry->length == 0) {
pr_warn("Invalid zero length subtable\n"); pr_warn("Invalid zero length subtable\n");
break; break;
} }
/* entry->length may not equal proc_sz, revalidate the processor structure length */
if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && if (entry->type == ACPI_PPTT_TYPE_PROCESSOR &&
acpi_cpu_id == cpu_node->acpi_processor_id && acpi_cpu_id == cpu_node->acpi_processor_id &&
(unsigned long)entry + entry->length <= table_end &&
entry->length == proc_sz + cpu_node->number_of_priv_resources * sizeof(u32) &&
acpi_pptt_leaf_node(table_hdr, cpu_node)) { acpi_pptt_leaf_node(table_hdr, cpu_node)) {
return (struct acpi_pptt_processor *)entry; return (struct acpi_pptt_processor *)entry;
} }

View File

@@ -53,7 +53,7 @@ enum tis_int_flags {
enum tis_defaults { enum tis_defaults {
TIS_MEM_LEN = 0x5000, TIS_MEM_LEN = 0x5000,
TIS_SHORT_TIMEOUT = 750, /* ms */ TIS_SHORT_TIMEOUT = 750, /* ms */
TIS_LONG_TIMEOUT = 2000, /* 2 sec */ TIS_LONG_TIMEOUT = 4000, /* 4 secs */
TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */ TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */
TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */ TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */
}; };

View File

@@ -103,7 +103,7 @@ int __init clocksource_i8253_init(void)
#ifdef CONFIG_CLKEVT_I8253 #ifdef CONFIG_CLKEVT_I8253
void clockevent_i8253_disable(void) void clockevent_i8253_disable(void)
{ {
raw_spin_lock(&i8253_lock); guard(raw_spinlock_irqsave)(&i8253_lock);
/* /*
* Writing the MODE register should stop the counter, according to * Writing the MODE register should stop the counter, according to
@@ -132,8 +132,6 @@ void clockevent_i8253_disable(void)
outb_p(0, PIT_CH0); outb_p(0, PIT_CH0);
outb_p(0x30, PIT_MODE); outb_p(0x30, PIT_MODE);
raw_spin_unlock(&i8253_lock);
} }
static int pit_shutdown(struct clock_event_device *evt) static int pit_shutdown(struct clock_event_device *evt)

View File

@@ -308,8 +308,9 @@ void dma_resv_add_fence(struct dma_resv *obj, struct dma_fence *fence,
count++; count++;
dma_resv_list_set(fobj, i, fence, usage); dma_resv_list_set(fobj, i, fence, usage);
/* pointer update must be visible before we extend the num_fences */ /* fence update must be visible before we extend the num_fences */
smp_store_mb(fobj->num_fences, count); smp_wmb();
fobj->num_fences = count;
} }
EXPORT_SYMBOL(dma_resv_add_fence); EXPORT_SYMBOL(dma_resv_add_fence);

View File

@@ -827,9 +827,9 @@ static int dmatest_func(void *data)
} else { } else {
dma_async_issue_pending(chan); dma_async_issue_pending(chan);
wait_event_timeout(thread->done_wait, wait_event_freezable_timeout(thread->done_wait,
done->done, done->done,
msecs_to_jiffies(params->timeout)); msecs_to_jiffies(params->timeout));
status = dma_async_is_tx_complete(chan, cookie, NULL, status = dma_async_is_tx_complete(chan, cookie, NULL,
NULL); NULL);

View File

@@ -140,6 +140,25 @@ static void idxd_cleanup_interrupts(struct idxd_device *idxd)
pci_free_irq_vectors(pdev); pci_free_irq_vectors(pdev);
} }
static void idxd_clean_wqs(struct idxd_device *idxd)
{
struct idxd_wq *wq;
struct device *conf_dev;
int i;
for (i = 0; i < idxd->max_wqs; i++) {
wq = idxd->wqs[i];
if (idxd->hw.wq_cap.op_config)
bitmap_free(wq->opcap_bmap);
kfree(wq->wqcfg);
conf_dev = wq_confdev(wq);
put_device(conf_dev);
kfree(wq);
}
bitmap_free(idxd->wq_enable_map);
kfree(idxd->wqs);
}
static int idxd_setup_wqs(struct idxd_device *idxd) static int idxd_setup_wqs(struct idxd_device *idxd)
{ {
struct device *dev = &idxd->pdev->dev; struct device *dev = &idxd->pdev->dev;
@@ -154,8 +173,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev)); idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev));
if (!idxd->wq_enable_map) { if (!idxd->wq_enable_map) {
kfree(idxd->wqs); rc = -ENOMEM;
return -ENOMEM; goto err_bitmap;
} }
for (i = 0; i < idxd->max_wqs; i++) { for (i = 0; i < idxd->max_wqs; i++) {
@@ -174,10 +193,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
conf_dev->bus = &dsa_bus_type; conf_dev->bus = &dsa_bus_type;
conf_dev->type = &idxd_wq_device_type; conf_dev->type = &idxd_wq_device_type;
rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id); rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id);
if (rc < 0) { if (rc < 0)
put_device(conf_dev);
goto err; goto err;
}
mutex_init(&wq->wq_lock); mutex_init(&wq->wq_lock);
init_waitqueue_head(&wq->err_queue); init_waitqueue_head(&wq->err_queue);
@@ -188,7 +205,6 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
if (!wq->wqcfg) { if (!wq->wqcfg) {
put_device(conf_dev);
rc = -ENOMEM; rc = -ENOMEM;
goto err; goto err;
} }
@@ -196,9 +212,8 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
if (idxd->hw.wq_cap.op_config) { if (idxd->hw.wq_cap.op_config) {
wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL); wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL);
if (!wq->opcap_bmap) { if (!wq->opcap_bmap) {
put_device(conf_dev);
rc = -ENOMEM; rc = -ENOMEM;
goto err; goto err_opcap_bmap;
} }
bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS); bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
} }
@@ -207,15 +222,46 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
return 0; return 0;
err: err_opcap_bmap:
kfree(wq->wqcfg);
err:
put_device(conf_dev);
kfree(wq);
while (--i >= 0) { while (--i >= 0) {
wq = idxd->wqs[i]; wq = idxd->wqs[i];
if (idxd->hw.wq_cap.op_config)
bitmap_free(wq->opcap_bmap);
kfree(wq->wqcfg);
conf_dev = wq_confdev(wq); conf_dev = wq_confdev(wq);
put_device(conf_dev); put_device(conf_dev);
kfree(wq);
} }
bitmap_free(idxd->wq_enable_map);
err_bitmap:
kfree(idxd->wqs);
return rc; return rc;
} }
static void idxd_clean_engines(struct idxd_device *idxd)
{
struct idxd_engine *engine;
struct device *conf_dev;
int i;
for (i = 0; i < idxd->max_engines; i++) {
engine = idxd->engines[i];
conf_dev = engine_confdev(engine);
put_device(conf_dev);
kfree(engine);
}
kfree(idxd->engines);
}
static int idxd_setup_engines(struct idxd_device *idxd) static int idxd_setup_engines(struct idxd_device *idxd)
{ {
struct idxd_engine *engine; struct idxd_engine *engine;
@@ -246,6 +292,7 @@ static int idxd_setup_engines(struct idxd_device *idxd)
rc = dev_set_name(conf_dev, "engine%d.%d", idxd->id, engine->id); rc = dev_set_name(conf_dev, "engine%d.%d", idxd->id, engine->id);
if (rc < 0) { if (rc < 0) {
put_device(conf_dev); put_device(conf_dev);
kfree(engine);
goto err; goto err;
} }
@@ -259,10 +306,26 @@ static int idxd_setup_engines(struct idxd_device *idxd)
engine = idxd->engines[i]; engine = idxd->engines[i];
conf_dev = engine_confdev(engine); conf_dev = engine_confdev(engine);
put_device(conf_dev); put_device(conf_dev);
kfree(engine);
} }
kfree(idxd->engines);
return rc; return rc;
} }
static void idxd_clean_groups(struct idxd_device *idxd)
{
struct idxd_group *group;
int i;
for (i = 0; i < idxd->max_groups; i++) {
group = idxd->groups[i];
put_device(group_confdev(group));
kfree(group);
}
kfree(idxd->groups);
}
static int idxd_setup_groups(struct idxd_device *idxd) static int idxd_setup_groups(struct idxd_device *idxd)
{ {
struct device *dev = &idxd->pdev->dev; struct device *dev = &idxd->pdev->dev;
@@ -293,6 +356,7 @@ static int idxd_setup_groups(struct idxd_device *idxd)
rc = dev_set_name(conf_dev, "group%d.%d", idxd->id, group->id); rc = dev_set_name(conf_dev, "group%d.%d", idxd->id, group->id);
if (rc < 0) { if (rc < 0) {
put_device(conf_dev); put_device(conf_dev);
kfree(group);
goto err; goto err;
} }
@@ -312,27 +376,25 @@ static int idxd_setup_groups(struct idxd_device *idxd)
while (--i >= 0) { while (--i >= 0) {
group = idxd->groups[i]; group = idxd->groups[i];
put_device(group_confdev(group)); put_device(group_confdev(group));
kfree(group);
} }
kfree(idxd->groups);
return rc; return rc;
} }
static void idxd_cleanup_internals(struct idxd_device *idxd) static void idxd_cleanup_internals(struct idxd_device *idxd)
{ {
int i; idxd_clean_groups(idxd);
idxd_clean_engines(idxd);
for (i = 0; i < idxd->max_groups; i++) idxd_clean_wqs(idxd);
put_device(group_confdev(idxd->groups[i]));
for (i = 0; i < idxd->max_engines; i++)
put_device(engine_confdev(idxd->engines[i]));
for (i = 0; i < idxd->max_wqs; i++)
put_device(wq_confdev(idxd->wqs[i]));
destroy_workqueue(idxd->wq); destroy_workqueue(idxd->wq);
} }
static int idxd_setup_internals(struct idxd_device *idxd) static int idxd_setup_internals(struct idxd_device *idxd)
{ {
struct device *dev = &idxd->pdev->dev; struct device *dev = &idxd->pdev->dev;
int rc, i; int rc;
init_waitqueue_head(&idxd->cmd_waitq); init_waitqueue_head(&idxd->cmd_waitq);
@@ -357,14 +419,11 @@ static int idxd_setup_internals(struct idxd_device *idxd)
return 0; return 0;
err_wkq_create: err_wkq_create:
for (i = 0; i < idxd->max_groups; i++) idxd_clean_groups(idxd);
put_device(group_confdev(idxd->groups[i]));
err_group: err_group:
for (i = 0; i < idxd->max_engines; i++) idxd_clean_engines(idxd);
put_device(engine_confdev(idxd->engines[i]));
err_engine: err_engine:
for (i = 0; i < idxd->max_wqs; i++) idxd_clean_wqs(idxd);
put_device(wq_confdev(idxd->wqs[i]));
err_wqs: err_wqs:
return rc; return rc;
} }
@@ -460,6 +519,17 @@ static void idxd_read_caps(struct idxd_device *idxd)
multi_u64_to_bmap(idxd->opcap_bmap, &idxd->hw.opcap.bits[0], 4); multi_u64_to_bmap(idxd->opcap_bmap, &idxd->hw.opcap.bits[0], 4);
} }
static void idxd_free(struct idxd_device *idxd)
{
if (!idxd)
return;
put_device(idxd_confdev(idxd));
bitmap_free(idxd->opcap_bmap);
ida_free(&idxd_ida, idxd->id);
kfree(idxd);
}
static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data) static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@@ -477,28 +547,34 @@ static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_d
idxd_dev_set_type(&idxd->idxd_dev, idxd->data->type); idxd_dev_set_type(&idxd->idxd_dev, idxd->data->type);
idxd->id = ida_alloc(&idxd_ida, GFP_KERNEL); idxd->id = ida_alloc(&idxd_ida, GFP_KERNEL);
if (idxd->id < 0) if (idxd->id < 0)
return NULL; goto err_ida;
idxd->opcap_bmap = bitmap_zalloc_node(IDXD_MAX_OPCAP_BITS, GFP_KERNEL, dev_to_node(dev)); idxd->opcap_bmap = bitmap_zalloc_node(IDXD_MAX_OPCAP_BITS, GFP_KERNEL, dev_to_node(dev));
if (!idxd->opcap_bmap) { if (!idxd->opcap_bmap)
ida_free(&idxd_ida, idxd->id); goto err_opcap;
return NULL;
}
device_initialize(conf_dev); device_initialize(conf_dev);
conf_dev->parent = dev; conf_dev->parent = dev;
conf_dev->bus = &dsa_bus_type; conf_dev->bus = &dsa_bus_type;
conf_dev->type = idxd->data->dev_type; conf_dev->type = idxd->data->dev_type;
rc = dev_set_name(conf_dev, "%s%d", idxd->data->name_prefix, idxd->id); rc = dev_set_name(conf_dev, "%s%d", idxd->data->name_prefix, idxd->id);
if (rc < 0) { if (rc < 0)
put_device(conf_dev); goto err_name;
return NULL;
}
spin_lock_init(&idxd->dev_lock); spin_lock_init(&idxd->dev_lock);
spin_lock_init(&idxd->cmd_lock); spin_lock_init(&idxd->cmd_lock);
return idxd; return idxd;
err_name:
put_device(conf_dev);
bitmap_free(idxd->opcap_bmap);
err_opcap:
ida_free(&idxd_ida, idxd->id);
err_ida:
kfree(idxd);
return NULL;
} }
static int idxd_enable_system_pasid(struct idxd_device *idxd) static int idxd_enable_system_pasid(struct idxd_device *idxd)
@@ -651,7 +727,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
err: err:
pci_iounmap(pdev, idxd->reg_base); pci_iounmap(pdev, idxd->reg_base);
err_iomap: err_iomap:
put_device(idxd_confdev(idxd)); idxd_free(idxd);
err_idxd_alloc: err_idxd_alloc:
pci_disable_device(pdev); pci_disable_device(pdev);
return rc; return rc;
@@ -714,6 +790,7 @@ static void idxd_remove(struct pci_dev *pdev)
destroy_workqueue(idxd->wq); destroy_workqueue(idxd->wq);
perfmon_pmu_remove(idxd); perfmon_pmu_remove(idxd);
put_device(idxd_confdev(idxd)); put_device(idxd_confdev(idxd));
idxd_free(idxd);
} }
static struct pci_driver idxd_pci_driver = { static struct pci_driver idxd_pci_driver = {

View File

@@ -1088,8 +1088,11 @@ static void udma_check_tx_completion(struct work_struct *work)
u32 residue_diff; u32 residue_diff;
ktime_t time_diff; ktime_t time_diff;
unsigned long delay; unsigned long delay;
unsigned long flags;
while (1) { while (1) {
spin_lock_irqsave(&uc->vc.lock, flags);
if (uc->desc) { if (uc->desc) {
/* Get previous residue and time stamp */ /* Get previous residue and time stamp */
residue_diff = uc->tx_drain.residue; residue_diff = uc->tx_drain.residue;
@@ -1124,6 +1127,8 @@ static void udma_check_tx_completion(struct work_struct *work)
break; break;
} }
spin_unlock_irqrestore(&uc->vc.lock, flags);
usleep_range(ktime_to_us(delay), usleep_range(ktime_to_us(delay),
ktime_to_us(delay) + 10); ktime_to_us(delay) + 10);
continue; continue;
@@ -1140,6 +1145,8 @@ static void udma_check_tx_completion(struct work_struct *work)
break; break;
} }
spin_unlock_irqrestore(&uc->vc.lock, flags);
} }
static irqreturn_t udma_ring_irq_handler(int irq, void *data) static irqreturn_t udma_ring_irq_handler(int irq, void *data)
@@ -4209,7 +4216,6 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma) struct of_dma *ofdma)
{ {
struct udma_dev *ud = ofdma->of_dma_data; struct udma_dev *ud = ofdma->of_dma_data;
dma_cap_mask_t mask = ud->ddev.cap_mask;
struct udma_filter_param filter_param; struct udma_filter_param filter_param;
struct dma_chan *chan; struct dma_chan *chan;
@@ -4241,7 +4247,7 @@ static struct dma_chan *udma_of_xlate(struct of_phandle_args *dma_spec,
} }
} }
chan = __dma_request_channel(&mask, udma_dma_filter_fn, &filter_param, chan = __dma_request_channel(&ud->ddev.cap_mask, udma_dma_filter_fn, &filter_param,
ofdma->of_node); ofdma->of_node);
if (!chan) { if (!chan) {
dev_err(ud->dev, "get channel fail in %s.\n", __func__); dev_err(ud->dev, "get channel fail in %s.\n", __func__);

View File

@@ -781,6 +781,7 @@ struct amdgpu_device {
bool need_swiotlb; bool need_swiotlb;
bool accel_working; bool accel_working;
struct notifier_block acpi_nb; struct notifier_block acpi_nb;
struct notifier_block pm_nb;
struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS]; struct amdgpu_i2c_chan *i2c_bus[AMDGPU_MAX_I2C_BUS];
struct debugfs_blob_wrapper debugfs_vbios_blob; struct debugfs_blob_wrapper debugfs_vbios_blob;
struct debugfs_blob_wrapper debugfs_discovery_blob; struct debugfs_blob_wrapper debugfs_discovery_blob;

View File

@@ -139,6 +139,10 @@ const char *amdgpu_asic_name[] = {
"LAST", "LAST",
}; };
static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev);
static int amdgpu_device_pm_notifier(struct notifier_block *nb, unsigned long mode,
void *data);
/** /**
* DOC: pcie_replay_count * DOC: pcie_replay_count
* *
@@ -3990,6 +3994,11 @@ fence_driver_init:
amdgpu_device_check_iommu_direct_map(adev); amdgpu_device_check_iommu_direct_map(adev);
adev->pm_nb.notifier_call = amdgpu_device_pm_notifier;
r = register_pm_notifier(&adev->pm_nb);
if (r)
goto failed;
return 0; return 0;
release_ras_con: release_ras_con:
@@ -4051,6 +4060,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
flush_delayed_work(&adev->delayed_init_work); flush_delayed_work(&adev->delayed_init_work);
adev->shutdown = true; adev->shutdown = true;
unregister_pm_notifier(&adev->pm_nb);
/* make sure IB test finished before entering exclusive mode /* make sure IB test finished before entering exclusive mode
* to avoid preemption on IB test * to avoid preemption on IB test
* */ * */
@@ -4181,6 +4192,33 @@ static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
/* /*
* Suspend & resume. * Suspend & resume.
*/ */
/**
* amdgpu_device_pm_notifier - Notification block for Suspend/Hibernate events
* @nb: notifier block
* @mode: suspend mode
* @data: data
*
* This function is called when the system is about to suspend or hibernate.
* It is used to set the appropriate flags so that eviction can be optimized
* in the pm prepare callback.
*/
static int amdgpu_device_pm_notifier(struct notifier_block *nb, unsigned long mode,
void *data)
{
struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, pm_nb);
switch (mode) {
case PM_HIBERNATION_PREPARE:
adev->in_s4 = true;
break;
case PM_POST_HIBERNATION:
adev->in_s4 = false;
break;
}
return NOTIFY_DONE;
}
/** /**
* amdgpu_device_prepare - prepare for device suspend * amdgpu_device_prepare - prepare for device suspend
* *
@@ -4631,6 +4669,8 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
retry: retry:
amdgpu_amdkfd_pre_reset(adev); amdgpu_amdkfd_pre_reset(adev);
amdgpu_device_stop_pending_resets(adev);
if (from_hypervisor) if (from_hypervisor)
r = amdgpu_virt_request_full_gpu(adev, true); r = amdgpu_virt_request_full_gpu(adev, true);
else else
@@ -5502,11 +5542,12 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
tmp_adev->asic_reset_res = r; tmp_adev->asic_reset_res = r;
} }
/* if (!amdgpu_sriov_vf(tmp_adev))
* Drop all pending non scheduler resets. Scheduler resets /*
* were already dropped during drm_sched_stop * Drop all pending non scheduler resets. Scheduler resets
*/ * were already dropped during drm_sched_stop
amdgpu_device_stop_pending_resets(tmp_adev); */
amdgpu_device_stop_pending_resets(tmp_adev);
} }
tmp_vram_lost_counter = atomic_read(&((adev)->vram_lost_counter)); tmp_vram_lost_counter = atomic_read(&((adev)->vram_lost_counter));

View File

@@ -2468,7 +2468,6 @@ static int amdgpu_pmops_freeze(struct device *dev)
struct amdgpu_device *adev = drm_to_adev(drm_dev); struct amdgpu_device *adev = drm_to_adev(drm_dev);
int r; int r;
adev->in_s4 = true;
r = amdgpu_device_suspend(drm_dev, true); r = amdgpu_device_suspend(drm_dev, true);
if (r) if (r)
return r; return r;
@@ -2481,13 +2480,8 @@ static int amdgpu_pmops_freeze(struct device *dev)
static int amdgpu_pmops_thaw(struct device *dev) static int amdgpu_pmops_thaw(struct device *dev)
{ {
struct drm_device *drm_dev = dev_get_drvdata(dev); struct drm_device *drm_dev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
int r;
r = amdgpu_device_resume(drm_dev, true); return amdgpu_device_resume(drm_dev, true);
adev->in_s4 = false;
return r;
} }
static int amdgpu_pmops_poweroff(struct device *dev) static int amdgpu_pmops_poweroff(struct device *dev)
@@ -2500,9 +2494,6 @@ static int amdgpu_pmops_poweroff(struct device *dev)
static int amdgpu_pmops_restore(struct device *dev) static int amdgpu_pmops_restore(struct device *dev)
{ {
struct drm_device *drm_dev = dev_get_drvdata(dev); struct drm_device *drm_dev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
adev->in_s4 = false;
return amdgpu_device_resume(drm_dev, true); return amdgpu_device_resume(drm_dev, true);
} }

View File

@@ -32,6 +32,7 @@
#include "amdgpu.h" #include "amdgpu.h"
#include "amdgpu_ras.h" #include "amdgpu_ras.h"
#include "amdgpu_reset.h"
#include "vi.h" #include "vi.h"
#include "soc15.h" #include "soc15.h"
#include "nv.h" #include "nv.h"
@@ -456,7 +457,7 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
return -EINVAL; return -EINVAL;
if (pf2vf_info->size > 1024) { if (pf2vf_info->size > 1024) {
DRM_ERROR("invalid pf2vf message size\n"); dev_err(adev->dev, "invalid pf2vf message size: 0x%x\n", pf2vf_info->size);
return -EINVAL; return -EINVAL;
} }
@@ -467,7 +468,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size, adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size,
adev->virt.fw_reserve.checksum_key, checksum); adev->virt.fw_reserve.checksum_key, checksum);
if (checksum != checkval) { if (checksum != checkval) {
DRM_ERROR("invalid pf2vf message\n"); dev_err(adev->dev,
"invalid pf2vf message: header checksum=0x%x calculated checksum=0x%x\n",
checksum, checkval);
return -EINVAL; return -EINVAL;
} }
@@ -481,7 +484,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size, adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size,
0, checksum); 0, checksum);
if (checksum != checkval) { if (checksum != checkval) {
DRM_ERROR("invalid pf2vf message\n"); dev_err(adev->dev,
"invalid pf2vf message: header checksum=0x%x calculated checksum=0x%x\n",
checksum, checkval);
return -EINVAL; return -EINVAL;
} }
@@ -517,7 +522,7 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->uuid; ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->uuid;
break; break;
default: default:
DRM_ERROR("invalid pf2vf version\n"); dev_err(adev->dev, "invalid pf2vf version: 0x%x\n", pf2vf_info->version);
return -EINVAL; return -EINVAL;
} }
@@ -617,8 +622,21 @@ static void amdgpu_virt_update_vf2pf_work_item(struct work_struct *work)
int ret; int ret;
ret = amdgpu_virt_read_pf2vf_data(adev); ret = amdgpu_virt_read_pf2vf_data(adev);
if (ret) if (ret) {
adev->virt.vf2pf_update_retry_cnt++;
if ((adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) &&
amdgpu_sriov_runtime(adev) && !amdgpu_in_reset(adev)) {
if (amdgpu_reset_domain_schedule(adev->reset_domain,
&adev->virt.flr_work))
return;
else
dev_err(adev->dev, "Failed to queue work! at %s", __func__);
}
goto out; goto out;
}
adev->virt.vf2pf_update_retry_cnt = 0;
amdgpu_virt_write_vf2pf_data(adev); amdgpu_virt_write_vf2pf_data(adev);
out: out:
@@ -639,6 +657,7 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev)
adev->virt.fw_reserve.p_pf2vf = NULL; adev->virt.fw_reserve.p_pf2vf = NULL;
adev->virt.fw_reserve.p_vf2pf = NULL; adev->virt.fw_reserve.p_vf2pf = NULL;
adev->virt.vf2pf_update_interval_ms = 0; adev->virt.vf2pf_update_interval_ms = 0;
adev->virt.vf2pf_update_retry_cnt = 0;
if (adev->mman.fw_vram_usage_va != NULL) { if (adev->mman.fw_vram_usage_va != NULL) {
/* go through this logic in ip_init and reset to init workqueue*/ /* go through this logic in ip_init and reset to init workqueue*/

View File

@@ -51,6 +51,8 @@
/* tonga/fiji use this offset */ /* tonga/fiji use this offset */
#define mmBIF_IOV_FUNC_IDENTIFIER 0x1503 #define mmBIF_IOV_FUNC_IDENTIFIER 0x1503
#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 30
enum amdgpu_sriov_vf_mode { enum amdgpu_sriov_vf_mode {
SRIOV_VF_MODE_BARE_METAL = 0, SRIOV_VF_MODE_BARE_METAL = 0,
SRIOV_VF_MODE_ONE_VF, SRIOV_VF_MODE_ONE_VF,
@@ -250,6 +252,7 @@ struct amdgpu_virt {
/* vf2pf message */ /* vf2pf message */
struct delayed_work vf2pf_work; struct delayed_work vf2pf_work;
uint32_t vf2pf_update_interval_ms; uint32_t vf2pf_update_interval_ms;
int vf2pf_update_retry_cnt;
/* multimedia bandwidth config */ /* multimedia bandwidth config */
bool is_mm_bw_enabled; bool is_mm_bw_enabled;

View File

@@ -276,6 +276,8 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work)
timeout -= 10; timeout -= 10;
} while (timeout > 1); } while (timeout > 1);
dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
flr_done: flr_done:
atomic_set(&adev->reset_domain->in_gpu_reset, 0); atomic_set(&adev->reset_domain->in_gpu_reset, 0);
up_write(&adev->reset_domain->sem); up_write(&adev->reset_domain->sem);

View File

@@ -300,6 +300,8 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work)
timeout -= 10; timeout -= 10;
} while (timeout > 1); } while (timeout > 1);
dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n");
flr_done: flr_done:
atomic_set(&adev->reset_domain->in_gpu_reset, 0); atomic_set(&adev->reset_domain->in_gpu_reset, 0);
up_write(&adev->reset_domain->sem); up_write(&adev->reset_domain->sem);

View File

@@ -10707,7 +10707,8 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(
/* The reply is stored in the top nibble of the command. */ /* The reply is stored in the top nibble of the command. */
payload->reply[0] = (adev->dm.dmub_notify->aux_reply.command >> 4) & 0xF; payload->reply[0] = (adev->dm.dmub_notify->aux_reply.command >> 4) & 0xF;
if (!payload->write && p_notify->aux_reply.length) /*write req may receive a byte indicating partially written number as well*/
if (p_notify->aux_reply.length)
memcpy(payload->data, p_notify->aux_reply.data, memcpy(payload->data, p_notify->aux_reply.data,
p_notify->aux_reply.length); p_notify->aux_reply.length);

View File

@@ -66,6 +66,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
enum aux_return_code_type operation_result; enum aux_return_code_type operation_result;
struct amdgpu_device *adev; struct amdgpu_device *adev;
struct ddc_service *ddc; struct ddc_service *ddc;
uint8_t copy[16];
if (WARN_ON(msg->size > 16)) if (WARN_ON(msg->size > 16))
return -E2BIG; return -E2BIG;
@@ -81,6 +82,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
(msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0; (msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0;
payload.defer_delay = 0; payload.defer_delay = 0;
if (payload.write) {
memcpy(copy, msg->buffer, msg->size);
payload.data = copy;
}
result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload, result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
&operation_result); &operation_result);
@@ -104,9 +110,9 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
*/ */
if (payload.write && result >= 0) { if (payload.write && result >= 0) {
if (result) { if (result) {
/*one byte indicating partially written bytes. Force 0 to retry*/ /*one byte indicating partially written bytes*/
drm_info(adev_to_drm(adev), "amdgpu: AUX partially written\n"); drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX partially written\n");
result = 0; result = payload.data[0];
} else if (!payload.reply[0]) } else if (!payload.reply[0])
/*I2C_ACK|AUX_ACK*/ /*I2C_ACK|AUX_ACK*/
result = msg->size; result = msg->size;
@@ -131,11 +137,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
break; break;
} }
drm_info(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result); drm_dbg_dp(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result);
} }
if (payload.reply[0]) if (payload.reply[0])
drm_info(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.", drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.",
payload.reply[0]); payload.reply[0]);
return result; return result;

View File

@@ -174,6 +174,7 @@ static void thrustmaster_interrupts(struct hid_device *hdev)
u8 ep_addr[2] = {b_ep, 0}; u8 ep_addr[2] = {b_ep, 0};
if (!usb_check_int_endpoints(usbif, ep_addr)) { if (!usb_check_int_endpoints(usbif, ep_addr)) {
kfree(send_buf);
hid_err(hdev, "Unexpected non-int endpoint\n"); hid_err(hdev, "Unexpected non-int endpoint\n");
return; return;
} }

View File

@@ -142,11 +142,12 @@ static int uclogic_input_configured(struct hid_device *hdev,
suffix = "System Control"; suffix = "System Control";
break; break;
} }
} } else {
if (suffix)
hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
"%s %s", hdev->name, suffix); "%s %s", hdev->name, suffix);
if (!hi->input->name)
return -ENOMEM;
}
return 0; return 0;
} }

View File

@@ -1114,68 +1114,10 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
EXPORT_SYMBOL(vmbus_sendpacket); EXPORT_SYMBOL(vmbus_sendpacket);
/* /*
* vmbus_sendpacket_pagebuffer - Send a range of single-page buffer * vmbus_sendpacket_mpb_desc - Send one or more multi-page buffer packets
* packets using a GPADL Direct packet type. This interface allows you
* to control notifying the host. This will be useful for sending
* batched data. Also the sender can control the send flags
* explicitly.
*/
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
struct hv_page_buffer pagebuffers[],
u32 pagecount, void *buffer, u32 bufferlen,
u64 requestid)
{
int i;
struct vmbus_channel_packet_page_buffer desc;
u32 descsize;
u32 packetlen;
u32 packetlen_aligned;
struct kvec bufferlist[3];
u64 aligned_data = 0;
if (pagecount > MAX_PAGE_BUFFER_COUNT)
return -EINVAL;
/*
* Adjust the size down since vmbus_channel_packet_page_buffer is the
* largest size we support
*/
descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
((MAX_PAGE_BUFFER_COUNT - pagecount) *
sizeof(struct hv_page_buffer));
packetlen = descsize + bufferlen;
packetlen_aligned = ALIGN(packetlen, sizeof(u64));
/* Setup the descriptor */
desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */
desc.length8 = (u16)(packetlen_aligned >> 3);
desc.transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */
desc.reserved = 0;
desc.rangecount = pagecount;
for (i = 0; i < pagecount; i++) {
desc.range[i].len = pagebuffers[i].len;
desc.range[i].offset = pagebuffers[i].offset;
desc.range[i].pfn = pagebuffers[i].pfn;
}
bufferlist[0].iov_base = &desc;
bufferlist[0].iov_len = descsize;
bufferlist[1].iov_base = buffer;
bufferlist[1].iov_len = bufferlen;
bufferlist[2].iov_base = &aligned_data;
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
return hv_ringbuffer_write(channel, bufferlist, 3, requestid, NULL);
}
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
/*
* vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
* using a GPADL Direct packet type. * using a GPADL Direct packet type.
* The buffer includes the vmbus descriptor. * The desc argument must include space for the VMBus descriptor. The
* rangecount field must already be set.
*/ */
int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
struct vmbus_packet_mpb_array *desc, struct vmbus_packet_mpb_array *desc,
@@ -1197,7 +1139,6 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
desc->length8 = (u16)(packetlen_aligned >> 3); desc->length8 = (u16)(packetlen_aligned >> 3);
desc->transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */ desc->transactionid = VMBUS_RQST_ERROR; /* will be updated in hv_ringbuffer_write() */
desc->reserved = 0; desc->reserved = 0;
desc->rangecount = 1;
bufferlist[0].iov_base = desc; bufferlist[0].iov_base = desc;
bufferlist[0].iov_len = desc_size; bufferlist[0].iov_len = desc_size;

View File

@@ -44,7 +44,7 @@ struct ad7266_state {
*/ */
struct { struct {
__be16 sample[2]; __be16 sample[2];
s64 timestamp; aligned_s64 timestamp;
} data __aligned(IIO_DMA_MINALIGN); } data __aligned(IIO_DMA_MINALIGN);
}; };

View File

@@ -169,7 +169,7 @@ struct ad7768_state {
union { union {
struct { struct {
__be32 chan; __be32 chan;
s64 timestamp; aligned_s64 timestamp;
} scan; } scan;
__be32 d32; __be32 d32;
u8 d8[2]; u8 d8[2];

View File

@@ -108,7 +108,7 @@ static irqreturn_t sps30_trigger_handler(int irq, void *p)
int ret; int ret;
struct { struct {
s32 data[4]; /* PM1, PM2P5, PM4, PM10 */ s32 data[4]; /* PM1, PM2P5, PM4, PM10 */
s64 ts; aligned_s64 ts;
} scan; } scan;
mutex_lock(&state->lock); mutex_lock(&state->lock);

View File

@@ -71,11 +71,8 @@ int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe,
err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata, err = do_mmap_info(rxe, uresp ? &uresp->mi : NULL, udata,
cq->queue->buf, cq->queue->buf_size, &cq->queue->ip); cq->queue->buf, cq->queue->buf_size, &cq->queue->ip);
if (err) { if (err)
vfree(cq->queue->buf);
kfree(cq->queue);
return err; return err;
}
cq->is_user = uresp; cq->is_user = uresp;

View File

@@ -2083,6 +2083,7 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port,
switch (state) { switch (state) {
case BR_STATE_DISABLED: case BR_STATE_DISABLED:
case BR_STATE_BLOCKING: case BR_STATE_BLOCKING:
case BR_STATE_LISTENING:
/* From UM10944 description of DRPDTAG (why put this there?): /* From UM10944 description of DRPDTAG (why put this there?):
* "Management traffic flows to the port regardless of the state * "Management traffic flows to the port regardless of the state
* of the INGRESS flag". So BPDUs are still be allowed to pass. * of the INGRESS flag". So BPDUs are still be allowed to pass.
@@ -2092,11 +2093,6 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port,
mac[port].egress = false; mac[port].egress = false;
mac[port].dyn_learn = false; mac[port].dyn_learn = false;
break; break;
case BR_STATE_LISTENING:
mac[port].ingress = true;
mac[port].egress = false;
mac[port].dyn_learn = false;
break;
case BR_STATE_LEARNING: case BR_STATE_LEARNING:
mac[port].ingress = true; mac[port].ingress = true;
mac[port].egress = false; mac[port].egress = false;

View File

@@ -4041,7 +4041,7 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
struct net_device *dev = bp->dev; struct net_device *dev = bp->dev;
if (page_mode) { if (page_mode) {
bp->flags &= ~BNXT_FLAG_AGG_RINGS; bp->flags &= ~(BNXT_FLAG_AGG_RINGS | BNXT_FLAG_NO_AGG_RINGS);
bp->flags |= BNXT_FLAG_RX_PAGE_MODE; bp->flags |= BNXT_FLAG_RX_PAGE_MODE;
if (bp->xdp_prog->aux->xdp_has_frags) if (bp->xdp_prog->aux->xdp_has_frags)
@@ -12799,6 +12799,14 @@ static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
bnxt_close_nic(bp, true, false); bnxt_close_nic(bp, true, false);
dev->mtu = new_mtu; dev->mtu = new_mtu;
/* MTU change may change the AGG ring settings if an XDP multi-buffer
* program is attached. We need to set the AGG rings settings and
* rx_skb_func accordingly.
*/
if (READ_ONCE(bp->xdp_prog))
bnxt_set_rx_skb_mode(bp, true);
bnxt_set_ring_params(bp); bnxt_set_ring_params(bp);
if (netif_running(dev)) if (netif_running(dev))

View File

@@ -962,22 +962,15 @@ static void macb_update_stats(struct macb *bp)
static int macb_halt_tx(struct macb *bp) static int macb_halt_tx(struct macb *bp)
{ {
unsigned long halt_time, timeout; u32 status;
u32 status;
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT)); macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT));
timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT); /* Poll TSR until TGO is cleared or timeout. */
do { return read_poll_timeout_atomic(macb_readl, status,
halt_time = jiffies; !(status & MACB_BIT(TGO)),
status = macb_readl(bp, TSR); 250, MACB_HALT_TIMEOUT, false,
if (!(status & MACB_BIT(TGO))) bp, TSR);
return 0;
udelay(250);
} while (time_before(halt_time, timeout));
return -ETIMEDOUT;
} }
static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budget) static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budget)

View File

@@ -428,7 +428,8 @@ static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf,
if (sw_tx_sc->encrypt) if (sw_tx_sc->encrypt)
sectag_tci |= (MCS_TCI_E | MCS_TCI_C); sectag_tci |= (MCS_TCI_E | MCS_TCI_C);
policy = FIELD_PREP(MCS_TX_SECY_PLCY_MTU, secy->netdev->mtu); policy = FIELD_PREP(MCS_TX_SECY_PLCY_MTU,
pfvf->netdev->mtu + OTX2_ETH_HLEN);
/* Write SecTag excluding AN bits(1..0) */ /* Write SecTag excluding AN bits(1..0) */
policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_TCI, sectag_tci >> 2); policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_TCI, sectag_tci >> 2);
policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset); policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset);

View File

@@ -4023,6 +4023,10 @@ static netdev_features_t mlx5e_fix_uplink_rep_features(struct net_device *netdev
if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER) if (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
netdev_warn(netdev, "Disabling HW_VLAN CTAG FILTERING, not supported in switchdev mode\n"); netdev_warn(netdev, "Disabling HW_VLAN CTAG FILTERING, not supported in switchdev mode\n");
features &= ~NETIF_F_HW_MACSEC;
if (netdev->features & NETIF_F_HW_MACSEC)
netdev_warn(netdev, "Disabling HW MACsec offload, not supported in switchdev mode\n");
return features; return features;
} }

View File

@@ -204,7 +204,7 @@ static struct pci_driver qede_pci_driver = {
}; };
static struct qed_eth_cb_ops qede_ll_ops = { static struct qed_eth_cb_ops qede_ll_ops = {
{ .common = {
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
.arfs_filter_op = qede_arfs_filter_op, .arfs_filter_op = qede_arfs_filter_op,
#endif #endif

View File

@@ -1484,8 +1484,11 @@ static int qlcnic_sriov_channel_cfg_cmd(struct qlcnic_adapter *adapter, u8 cmd_o
} }
cmd_op = (cmd.rsp.arg[0] & 0xff); cmd_op = (cmd.rsp.arg[0] & 0xff);
if (cmd.rsp.arg[0] >> 25 == 2) if (cmd.rsp.arg[0] >> 25 == 2) {
return 2; ret = 2;
goto out;
}
if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT) if (cmd_op == QLCNIC_BC_CMD_CHANNEL_INIT)
set_bit(QLC_BC_VF_STATE, &vf->state); set_bit(QLC_BC_VF_STATE, &vf->state);
else else

View File

@@ -156,7 +156,6 @@ struct hv_netvsc_packet {
u8 cp_partial; /* partial copy into send buffer */ u8 cp_partial; /* partial copy into send buffer */
u8 rmsg_size; /* RNDIS header and PPI size */ u8 rmsg_size; /* RNDIS header and PPI size */
u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */
u8 page_buf_cnt; u8 page_buf_cnt;
u16 q_idx; u16 q_idx;
@@ -891,6 +890,18 @@ struct nvsp_message {
sizeof(struct nvsp_message)) sizeof(struct nvsp_message))
#define NETVSC_MIN_IN_MSG_SIZE sizeof(struct vmpacket_descriptor) #define NETVSC_MIN_IN_MSG_SIZE sizeof(struct vmpacket_descriptor)
/* Maximum # of contiguous data ranges that can make up a trasmitted packet.
* Typically it's the max SKB fragments plus 2 for the rndis packet and the
* linear portion of the SKB. But if MAX_SKB_FRAGS is large, the value may
* need to be limited to MAX_PAGE_BUFFER_COUNT, which is the max # of entries
* in a GPA direct packet sent to netvsp over VMBus.
*/
#if MAX_SKB_FRAGS + 2 < MAX_PAGE_BUFFER_COUNT
#define MAX_DATA_RANGES (MAX_SKB_FRAGS + 2)
#else
#define MAX_DATA_RANGES MAX_PAGE_BUFFER_COUNT
#endif
/* Estimated requestor size: /* Estimated requestor size:
* out_ring_size/min_out_msg_size + in_ring_size/min_in_msg_size * out_ring_size/min_out_msg_size + in_ring_size/min_in_msg_size
*/ */

View File

@@ -980,8 +980,7 @@ static void netvsc_copy_to_send_buf(struct netvsc_device *net_device,
+ pend_size; + pend_size;
int i; int i;
u32 padding = 0; u32 padding = 0;
u32 page_count = packet->cp_partial ? packet->rmsg_pgcnt : u32 page_count = packet->cp_partial ? 1 : packet->page_buf_cnt;
packet->page_buf_cnt;
u32 remain; u32 remain;
/* Add padding */ /* Add padding */
@@ -1082,6 +1081,42 @@ static int netvsc_dma_map(struct hv_device *hv_dev,
return 0; return 0;
} }
/* Build an "array" of mpb entries describing the data to be transferred
* over VMBus. After the desc header fields, each "array" entry is variable
* size, and each entry starts after the end of the previous entry. The
* "offset" and "len" fields for each entry imply the size of the entry.
*
* The pfns are in HV_HYP_PAGE_SIZE, because all communication with Hyper-V
* uses that granularity, even if the system page size of the guest is larger.
* Each entry in the input "pb" array must describe a contiguous range of
* guest physical memory so that the pfns are sequential if the range crosses
* a page boundary. The offset field must be < HV_HYP_PAGE_SIZE.
*/
static inline void netvsc_build_mpb_array(struct hv_page_buffer *pb,
u32 page_buffer_count,
struct vmbus_packet_mpb_array *desc,
u32 *desc_size)
{
struct hv_mpb_array *mpb_entry = &desc->range;
int i, j;
for (i = 0; i < page_buffer_count; i++) {
u32 offset = pb[i].offset;
u32 len = pb[i].len;
mpb_entry->offset = offset;
mpb_entry->len = len;
for (j = 0; j < HVPFN_UP(offset + len); j++)
mpb_entry->pfn_array[j] = pb[i].pfn + j;
mpb_entry = (struct hv_mpb_array *)&mpb_entry->pfn_array[j];
}
desc->rangecount = page_buffer_count;
*desc_size = (char *)mpb_entry - (char *)desc;
}
static inline int netvsc_send_pkt( static inline int netvsc_send_pkt(
struct hv_device *device, struct hv_device *device,
struct hv_netvsc_packet *packet, struct hv_netvsc_packet *packet,
@@ -1124,8 +1159,11 @@ static inline int netvsc_send_pkt(
packet->dma_range = NULL; packet->dma_range = NULL;
if (packet->page_buf_cnt) { if (packet->page_buf_cnt) {
struct vmbus_channel_packet_page_buffer desc;
u32 desc_size;
if (packet->cp_partial) if (packet->cp_partial)
pb += packet->rmsg_pgcnt; pb++;
ret = netvsc_dma_map(ndev_ctx->device_ctx, packet, pb); ret = netvsc_dma_map(ndev_ctx->device_ctx, packet, pb);
if (ret) { if (ret) {
@@ -1133,11 +1171,12 @@ static inline int netvsc_send_pkt(
goto exit; goto exit;
} }
ret = vmbus_sendpacket_pagebuffer(out_channel, netvsc_build_mpb_array(pb, packet->page_buf_cnt,
pb, packet->page_buf_cnt, (struct vmbus_packet_mpb_array *)&desc,
&nvmsg, sizeof(nvmsg), &desc_size);
req_id); ret = vmbus_sendpacket_mpb_desc(out_channel,
(struct vmbus_packet_mpb_array *)&desc,
desc_size, &nvmsg, sizeof(nvmsg), req_id);
if (ret) if (ret)
netvsc_dma_unmap(ndev_ctx->device_ctx, packet); netvsc_dma_unmap(ndev_ctx->device_ctx, packet);
} else { } else {
@@ -1286,7 +1325,7 @@ int netvsc_send(struct net_device *ndev,
packet->send_buf_index = section_index; packet->send_buf_index = section_index;
if (packet->cp_partial) { if (packet->cp_partial) {
packet->page_buf_cnt -= packet->rmsg_pgcnt; packet->page_buf_cnt--;
packet->total_data_buflen = msd_len + packet->rmsg_size; packet->total_data_buflen = msd_len + packet->rmsg_size;
} else { } else {
packet->page_buf_cnt = 0; packet->page_buf_cnt = 0;

View File

@@ -325,43 +325,10 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb,
return txq; return txq;
} }
static u32 fill_pg_buf(unsigned long hvpfn, u32 offset, u32 len,
struct hv_page_buffer *pb)
{
int j = 0;
hvpfn += offset >> HV_HYP_PAGE_SHIFT;
offset = offset & ~HV_HYP_PAGE_MASK;
while (len > 0) {
unsigned long bytes;
bytes = HV_HYP_PAGE_SIZE - offset;
if (bytes > len)
bytes = len;
pb[j].pfn = hvpfn;
pb[j].offset = offset;
pb[j].len = bytes;
offset += bytes;
len -= bytes;
if (offset == HV_HYP_PAGE_SIZE && len) {
hvpfn++;
offset = 0;
j++;
}
}
return j + 1;
}
static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
struct hv_netvsc_packet *packet, struct hv_netvsc_packet *packet,
struct hv_page_buffer *pb) struct hv_page_buffer *pb)
{ {
u32 slots_used = 0;
char *data = skb->data;
int frags = skb_shinfo(skb)->nr_frags; int frags = skb_shinfo(skb)->nr_frags;
int i; int i;
@@ -370,28 +337,27 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
* 2. skb linear data * 2. skb linear data
* 3. skb fragment data * 3. skb fragment data
*/ */
slots_used += fill_pg_buf(virt_to_hvpfn(hdr),
offset_in_hvpage(hdr),
len,
&pb[slots_used]);
pb[0].offset = offset_in_hvpage(hdr);
pb[0].len = len;
pb[0].pfn = virt_to_hvpfn(hdr);
packet->rmsg_size = len; packet->rmsg_size = len;
packet->rmsg_pgcnt = slots_used;
slots_used += fill_pg_buf(virt_to_hvpfn(data), pb[1].offset = offset_in_hvpage(skb->data);
offset_in_hvpage(data), pb[1].len = skb_headlen(skb);
skb_headlen(skb), pb[1].pfn = virt_to_hvpfn(skb->data);
&pb[slots_used]);
for (i = 0; i < frags; i++) { for (i = 0; i < frags; i++) {
skb_frag_t *frag = skb_shinfo(skb)->frags + i; skb_frag_t *frag = skb_shinfo(skb)->frags + i;
struct hv_page_buffer *cur_pb = &pb[i + 2];
u64 pfn = page_to_hvpfn(skb_frag_page(frag));
u32 offset = skb_frag_off(frag);
slots_used += fill_pg_buf(page_to_hvpfn(skb_frag_page(frag)), cur_pb->offset = offset_in_hvpage(offset);
skb_frag_off(frag), cur_pb->len = skb_frag_size(frag);
skb_frag_size(frag), cur_pb->pfn = pfn + (offset >> HV_HYP_PAGE_SHIFT);
&pb[slots_used]);
} }
return slots_used; return frags + 2;
} }
static int count_skb_frag_slots(struct sk_buff *skb) static int count_skb_frag_slots(struct sk_buff *skb)
@@ -482,7 +448,7 @@ static int netvsc_xmit(struct sk_buff *skb, struct net_device *net, bool xdp_tx)
struct net_device *vf_netdev; struct net_device *vf_netdev;
u32 rndis_msg_size; u32 rndis_msg_size;
u32 hash; u32 hash;
struct hv_page_buffer pb[MAX_PAGE_BUFFER_COUNT]; struct hv_page_buffer pb[MAX_DATA_RANGES];
/* If VF is present and up then redirect packets to it. /* If VF is present and up then redirect packets to it.
* Skip the VF if it is marked down or has no carrier. * Skip the VF if it is marked down or has no carrier.

View File

@@ -225,8 +225,7 @@ static int rndis_filter_send_request(struct rndis_device *dev,
struct rndis_request *req) struct rndis_request *req)
{ {
struct hv_netvsc_packet *packet; struct hv_netvsc_packet *packet;
struct hv_page_buffer page_buf[2]; struct hv_page_buffer pb;
struct hv_page_buffer *pb = page_buf;
int ret; int ret;
/* Setup the packet to send it */ /* Setup the packet to send it */
@@ -235,27 +234,14 @@ static int rndis_filter_send_request(struct rndis_device *dev,
packet->total_data_buflen = req->request_msg.msg_len; packet->total_data_buflen = req->request_msg.msg_len;
packet->page_buf_cnt = 1; packet->page_buf_cnt = 1;
pb[0].pfn = virt_to_phys(&req->request_msg) >> pb.pfn = virt_to_phys(&req->request_msg) >> HV_HYP_PAGE_SHIFT;
HV_HYP_PAGE_SHIFT; pb.len = req->request_msg.msg_len;
pb[0].len = req->request_msg.msg_len; pb.offset = offset_in_hvpage(&req->request_msg);
pb[0].offset = offset_in_hvpage(&req->request_msg);
/* Add one page_buf when request_msg crossing page boundary */
if (pb[0].offset + pb[0].len > HV_HYP_PAGE_SIZE) {
packet->page_buf_cnt++;
pb[0].len = HV_HYP_PAGE_SIZE -
pb[0].offset;
pb[1].pfn = virt_to_phys((void *)&req->request_msg
+ pb[0].len) >> HV_HYP_PAGE_SHIFT;
pb[1].offset = 0;
pb[1].len = req->request_msg.msg_len -
pb[0].len;
}
trace_rndis_send(dev->ndev, 0, &req->request_msg); trace_rndis_send(dev->ndev, 0, &req->request_msg);
rcu_read_lock_bh(); rcu_read_lock_bh();
ret = netvsc_send(dev->ndev, packet, NULL, pb, NULL, false); ret = netvsc_send(dev->ndev, packet, NULL, &pb, NULL, false);
rcu_read_unlock_bh(); rcu_read_unlock_bh();
return ret; return ret;

View File

@@ -789,6 +789,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
int i; int i;
mt76_worker_disable(&dev->tx_worker); mt76_worker_disable(&dev->tx_worker);
napi_disable(&dev->tx_napi);
netif_napi_del(&dev->tx_napi); netif_napi_del(&dev->tx_napi);
for (i = 0; i < ARRAY_SIZE(dev->phys); i++) { for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {

View File

@@ -376,7 +376,7 @@ static bool nvme_dbbuf_update_and_check_event(u16 value, __le32 *dbbuf_db,
* as it only leads to a small amount of wasted memory for the lifetime of * as it only leads to a small amount of wasted memory for the lifetime of
* the I/O. * the I/O.
*/ */
static int nvme_pci_npages_prp(void) static __always_inline int nvme_pci_npages_prp(void)
{ {
unsigned max_bytes = (NVME_MAX_KB_SZ * 1024) + NVME_CTRL_PAGE_SIZE; unsigned max_bytes = (NVME_MAX_KB_SZ * 1024) + NVME_CTRL_PAGE_SIZE;
unsigned nprps = DIV_ROUND_UP(max_bytes, NVME_CTRL_PAGE_SIZE); unsigned nprps = DIV_ROUND_UP(max_bytes, NVME_CTRL_PAGE_SIZE);
@@ -1154,7 +1154,9 @@ static void nvme_poll_irqdisable(struct nvme_queue *nvmeq)
WARN_ON_ONCE(test_bit(NVMEQ_POLLED, &nvmeq->flags)); WARN_ON_ONCE(test_bit(NVMEQ_POLLED, &nvmeq->flags));
disable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); disable_irq(pci_irq_vector(pdev, nvmeq->cq_vector));
spin_lock(&nvmeq->cq_poll_lock);
nvme_poll_cq(nvmeq, NULL); nvme_poll_cq(nvmeq, NULL);
spin_unlock(&nvmeq->cq_poll_lock);
enable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); enable_irq(pci_irq_vector(pdev, nvmeq->cq_vector));
} }

View File

@@ -103,7 +103,6 @@ struct rcar_gen3_phy {
struct rcar_gen3_chan *ch; struct rcar_gen3_chan *ch;
u32 int_enable_bits; u32 int_enable_bits;
bool initialized; bool initialized;
bool otg_initialized;
bool powered; bool powered;
}; };
@@ -311,16 +310,15 @@ static bool rcar_gen3_is_any_rphy_initialized(struct rcar_gen3_chan *ch)
return false; return false;
} }
static bool rcar_gen3_needs_init_otg(struct rcar_gen3_chan *ch) static bool rcar_gen3_is_any_otg_rphy_initialized(struct rcar_gen3_chan *ch)
{ {
int i; for (enum rcar_gen3_phy_index i = PHY_INDEX_BOTH_HC; i <= PHY_INDEX_EHCI;
i++) {
for (i = 0; i < NUM_OF_PHYS; i++) { if (ch->rphys[i].initialized)
if (ch->rphys[i].otg_initialized) return true;
return false;
} }
return true; return false;
} }
static bool rcar_gen3_are_all_rphys_power_off(struct rcar_gen3_chan *ch) static bool rcar_gen3_are_all_rphys_power_off(struct rcar_gen3_chan *ch)
@@ -342,7 +340,7 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
bool is_b_device; bool is_b_device;
enum phy_mode cur_mode, new_mode; enum phy_mode cur_mode, new_mode;
if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch)) if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch))
return -EIO; return -EIO;
if (sysfs_streq(buf, "host")) if (sysfs_streq(buf, "host"))
@@ -380,7 +378,7 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr,
{ {
struct rcar_gen3_chan *ch = dev_get_drvdata(dev); struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch)) if (!ch->is_otg_channel || !rcar_gen3_is_any_otg_rphy_initialized(ch))
return -EIO; return -EIO;
return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" : return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" :
@@ -393,6 +391,9 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch)
void __iomem *usb2_base = ch->base; void __iomem *usb2_base = ch->base;
u32 val; u32 val;
if (!ch->is_otg_channel || rcar_gen3_is_any_otg_rphy_initialized(ch))
return;
/* Should not use functions of read-modify-write a register */ /* Should not use functions of read-modify-write a register */
val = readl(usb2_base + USB2_LINECTRL1); val = readl(usb2_base + USB2_LINECTRL1);
val = (val & ~USB2_LINECTRL1_DP_RPD) | USB2_LINECTRL1_DPRPD_EN | val = (val & ~USB2_LINECTRL1_DP_RPD) | USB2_LINECTRL1_DPRPD_EN |
@@ -453,16 +454,16 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
val = readl(usb2_base + USB2_INT_ENABLE); val = readl(usb2_base + USB2_INT_ENABLE);
val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits; val |= USB2_INT_ENABLE_UCOM_INTEN | rphy->int_enable_bits;
writel(val, usb2_base + USB2_INT_ENABLE); writel(val, usb2_base + USB2_INT_ENABLE);
writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET);
writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
/* Initialize otg part */ if (!rcar_gen3_is_any_rphy_initialized(channel)) {
if (channel->is_otg_channel) { writel(USB2_SPD_RSM_TIMSET_INIT, usb2_base + USB2_SPD_RSM_TIMSET);
if (rcar_gen3_needs_init_otg(channel)) writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
rcar_gen3_init_otg(channel);
rphy->otg_initialized = true;
} }
/* Initialize otg part (only if we initialize a PHY with IRQs). */
if (rphy->int_enable_bits)
rcar_gen3_init_otg(channel);
rphy->initialized = true; rphy->initialized = true;
return 0; return 0;
@@ -477,9 +478,6 @@ static int rcar_gen3_phy_usb2_exit(struct phy *p)
rphy->initialized = false; rphy->initialized = false;
if (channel->is_otg_channel)
rphy->otg_initialized = false;
val = readl(usb2_base + USB2_INT_ENABLE); val = readl(usb2_base + USB2_INT_ENABLE);
val &= ~rphy->int_enable_bits; val &= ~rphy->int_enable_bits;
if (!rcar_gen3_is_any_rphy_initialized(channel)) if (!rcar_gen3_is_any_rphy_initialized(channel))

View File

@@ -542,16 +542,16 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
err = dev_set_name(&port->dev, "%s-%u", name, index); err = dev_set_name(&port->dev, "%s-%u", name, index);
if (err < 0) if (err < 0)
goto unregister; goto put_device;
err = device_add(&port->dev); err = device_add(&port->dev);
if (err < 0) if (err < 0)
goto unregister; goto put_device;
return 0; return 0;
unregister: put_device:
device_unregister(&port->dev); put_device(&port->dev);
return err; return err;
} }

View File

@@ -834,6 +834,10 @@ static int __maybe_unused amd_pmc_suspend_handler(struct device *dev)
{ {
struct amd_pmc_dev *pdev = dev_get_drvdata(dev); struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
/*
* Must be called only from the same set of dev_pm_ops handlers
* as i8042_pm_suspend() is called: currently just from .suspend.
*/
if (pdev->cpu_id == AMD_CPU_ID_CZN) { if (pdev->cpu_id == AMD_CPU_ID_CZN) {
int rc = amd_pmc_czn_wa_irq1(pdev); int rc = amd_pmc_czn_wa_irq1(pdev);
@@ -846,7 +850,9 @@ static int __maybe_unused amd_pmc_suspend_handler(struct device *dev)
return 0; return 0;
} }
static SIMPLE_DEV_PM_OPS(amd_pmc_pm, amd_pmc_suspend_handler, NULL); static const struct dev_pm_ops amd_pmc_pm = {
.suspend = amd_pmc_suspend_handler,
};
#endif #endif

View File

@@ -3804,7 +3804,8 @@ static int asus_wmi_add(struct platform_device *pdev)
goto fail_leds; goto fail_leds;
asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);
if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) if ((result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) ==
(ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))
asus->driver->wlan_ctrl_by_user = 1; asus->driver->wlan_ctrl_by_user = 1;
if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) { if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) {

View File

@@ -133,7 +133,7 @@ static int max20086_regulators_register(struct max20086 *chip)
static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on)
{ {
struct of_regulator_match matches[MAX20086_MAX_REGULATORS] = { }; struct of_regulator_match *matches;
struct device_node *node; struct device_node *node;
unsigned int i; unsigned int i;
int ret; int ret;
@@ -144,6 +144,11 @@ static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on)
return -ENODEV; return -ENODEV;
} }
matches = devm_kcalloc(chip->dev, chip->info->num_outputs,
sizeof(*matches), GFP_KERNEL);
if (!matches)
return -ENOMEM;
for (i = 0; i < chip->info->num_outputs; ++i) for (i = 0; i < chip->info->num_outputs; ++i)
matches[i].name = max20086_output_names[i]; matches[i].name = max20086_output_names[i];

View File

@@ -199,6 +199,7 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp,
unsigned int nr_zones, size_t *buflen) unsigned int nr_zones, size_t *buflen)
{ {
struct request_queue *q = sdkp->disk->queue; struct request_queue *q = sdkp->disk->queue;
unsigned int max_segments;
size_t bufsize; size_t bufsize;
void *buf; void *buf;
@@ -210,12 +211,15 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp,
* Furthermore, since the report zone command cannot be split, make * Furthermore, since the report zone command cannot be split, make
* sure that the allocated buffer can always be mapped by limiting the * sure that the allocated buffer can always be mapped by limiting the
* number of pages allocated to the HBA max segments limit. * number of pages allocated to the HBA max segments limit.
* Since max segments can be larger than the max inline bio vectors,
* further limit the allocated buffer to BIO_MAX_INLINE_VECS.
*/ */
nr_zones = min(nr_zones, sdkp->zone_info.nr_zones); nr_zones = min(nr_zones, sdkp->zone_info.nr_zones);
bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE); bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE);
bufsize = min_t(size_t, bufsize, bufsize = min_t(size_t, bufsize,
queue_max_hw_sectors(q) << SECTOR_SHIFT); queue_max_hw_sectors(q) << SECTOR_SHIFT);
bufsize = min_t(size_t, bufsize, queue_max_segments(q) << PAGE_SHIFT); max_segments = min(BIO_MAX_INLINE_VECS, queue_max_segments(q));
bufsize = min_t(size_t, bufsize, max_segments << PAGE_SHIFT);
while (bufsize >= SECTOR_SIZE) { while (bufsize >= SECTOR_SIZE) {
buf = kvzalloc(bufsize, GFP_KERNEL | __GFP_NORETRY); buf = kvzalloc(bufsize, GFP_KERNEL | __GFP_NORETRY);

View File

@@ -1810,6 +1810,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
return SCSI_MLQUEUE_DEVICE_BUSY; return SCSI_MLQUEUE_DEVICE_BUSY;
} }
payload->rangecount = 1;
payload->range.len = length; payload->range.len = length;
payload->range.offset = offset_in_hvpg; payload->range.offset = offset_in_hvpg;

View File

@@ -1775,10 +1775,9 @@ static int cqspi_remove(struct platform_device *pdev)
static int cqspi_suspend(struct device *dev) static int cqspi_suspend(struct device *dev)
{ {
struct cqspi_st *cqspi = dev_get_drvdata(dev); struct cqspi_st *cqspi = dev_get_drvdata(dev);
struct spi_master *master = dev_get_drvdata(dev);
int ret; int ret;
ret = spi_master_suspend(master); ret = spi_master_suspend(cqspi->master);
cqspi_controller_enable(cqspi, 0); cqspi_controller_enable(cqspi, 0);
clk_disable_unprepare(cqspi->clk); clk_disable_unprepare(cqspi->clk);
@@ -1789,7 +1788,6 @@ static int cqspi_suspend(struct device *dev)
static int cqspi_resume(struct device *dev) static int cqspi_resume(struct device *dev)
{ {
struct cqspi_st *cqspi = dev_get_drvdata(dev); struct cqspi_st *cqspi = dev_get_drvdata(dev);
struct spi_master *master = dev_get_drvdata(dev);
clk_prepare_enable(cqspi->clk); clk_prepare_enable(cqspi->clk);
cqspi_wait_idle(cqspi); cqspi_wait_idle(cqspi);
@@ -1798,7 +1796,7 @@ static int cqspi_resume(struct device *dev)
cqspi->current_cs = -1; cqspi->current_cs = -1;
cqspi->sclk = 0; cqspi->sclk = 0;
return spi_master_resume(master); return spi_master_resume(cqspi->master);
} }
static DEFINE_SIMPLE_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, cqspi_resume); static DEFINE_SIMPLE_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, cqspi_resume);

View File

@@ -410,7 +410,7 @@ MODULE_LICENSE("GPL");
static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len) static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len)
{ {
/* limit the hex_dump */ /* limit the hex_dump */
if (len < 1024) { if (len <= 1024) {
print_hex_dump(KERN_INFO, pre, print_hex_dump(KERN_INFO, pre,
DUMP_PREFIX_OFFSET, 16, 1, DUMP_PREFIX_OFFSET, 16, 1,
ptr, len, 0); ptr, len, 0);

View File

@@ -54,7 +54,8 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
u8 cur = 0; u8 cur = 0;
int ret; int ret;
mutex_lock(&dp->con->lock); if (!ucsi_con_mutex_lock(dp->con))
return -ENOTCONN;
if (!dp->override && dp->initialized) { if (!dp->override && dp->initialized) {
const struct typec_altmode *p = typec_altmode_get_partner(alt); const struct typec_altmode *p = typec_altmode_get_partner(alt);
@@ -100,7 +101,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
schedule_work(&dp->work); schedule_work(&dp->work);
ret = 0; ret = 0;
err_unlock: err_unlock:
mutex_unlock(&dp->con->lock); ucsi_con_mutex_unlock(dp->con);
return ret; return ret;
} }
@@ -112,7 +113,8 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)
u64 command; u64 command;
int ret = 0; int ret = 0;
mutex_lock(&dp->con->lock); if (!ucsi_con_mutex_lock(dp->con))
return -ENOTCONN;
if (!dp->override) { if (!dp->override) {
const struct typec_altmode *p = typec_altmode_get_partner(alt); const struct typec_altmode *p = typec_altmode_get_partner(alt);
@@ -144,7 +146,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)
schedule_work(&dp->work); schedule_work(&dp->work);
out_unlock: out_unlock:
mutex_unlock(&dp->con->lock); ucsi_con_mutex_unlock(dp->con);
return ret; return ret;
} }
@@ -202,20 +204,21 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,
int cmd = PD_VDO_CMD(header); int cmd = PD_VDO_CMD(header);
int svdm_version; int svdm_version;
mutex_lock(&dp->con->lock); if (!ucsi_con_mutex_lock(dp->con))
return -ENOTCONN;
if (!dp->override && dp->initialized) { if (!dp->override && dp->initialized) {
const struct typec_altmode *p = typec_altmode_get_partner(alt); const struct typec_altmode *p = typec_altmode_get_partner(alt);
dev_warn(&p->dev, dev_warn(&p->dev,
"firmware doesn't support alternate mode overriding\n"); "firmware doesn't support alternate mode overriding\n");
mutex_unlock(&dp->con->lock); ucsi_con_mutex_unlock(dp->con);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
svdm_version = typec_altmode_get_svdm_version(alt); svdm_version = typec_altmode_get_svdm_version(alt);
if (svdm_version < 0) { if (svdm_version < 0) {
mutex_unlock(&dp->con->lock); ucsi_con_mutex_unlock(dp->con);
return svdm_version; return svdm_version;
} }
@@ -259,7 +262,7 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,
break; break;
} }
mutex_unlock(&dp->con->lock); ucsi_con_mutex_unlock(dp->con);
return 0; return 0;
} }

View File

@@ -1398,6 +1398,40 @@ void ucsi_set_drvdata(struct ucsi *ucsi, void *data)
} }
EXPORT_SYMBOL_GPL(ucsi_set_drvdata); EXPORT_SYMBOL_GPL(ucsi_set_drvdata);
/**
* ucsi_con_mutex_lock - Acquire the connector mutex
* @con: The connector interface to lock
*
* Returns true on success, false if the connector is disconnected
*/
bool ucsi_con_mutex_lock(struct ucsi_connector *con)
{
bool mutex_locked = false;
bool connected = true;
while (connected && !mutex_locked) {
mutex_locked = mutex_trylock(&con->lock) != 0;
connected = con->status.flags & UCSI_CONSTAT_CONNECTED;
if (connected && !mutex_locked)
msleep(20);
}
connected = connected && con->partner;
if (!connected && mutex_locked)
mutex_unlock(&con->lock);
return connected;
}
/**
* ucsi_con_mutex_unlock - Release the connector mutex
* @con: The connector interface to unlock
*/
void ucsi_con_mutex_unlock(struct ucsi_connector *con)
{
mutex_unlock(&con->lock);
}
/** /**
* ucsi_create - Allocate UCSI instance * ucsi_create - Allocate UCSI instance
* @dev: Device interface to the PPM (Platform Policy Manager) * @dev: Device interface to the PPM (Platform Policy Manager)

View File

@@ -15,6 +15,7 @@
struct ucsi; struct ucsi;
struct ucsi_altmode; struct ucsi_altmode;
struct ucsi_connector;
/* UCSI offsets (Bytes) */ /* UCSI offsets (Bytes) */
#define UCSI_VERSION 0 #define UCSI_VERSION 0
@@ -62,6 +63,8 @@ int ucsi_register(struct ucsi *ucsi);
void ucsi_unregister(struct ucsi *ucsi); void ucsi_unregister(struct ucsi *ucsi);
void *ucsi_get_drvdata(struct ucsi *ucsi); void *ucsi_get_drvdata(struct ucsi *ucsi);
void ucsi_set_drvdata(struct ucsi *ucsi, void *data); void ucsi_set_drvdata(struct ucsi *ucsi, void *data);
bool ucsi_con_mutex_lock(struct ucsi_connector *con);
void ucsi_con_mutex_unlock(struct ucsi_connector *con);
void ucsi_connector_change(struct ucsi *ucsi, u8 num); void ucsi_connector_change(struct ucsi *ucsi, u8 num);

View File

@@ -585,6 +585,10 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset,
uc->has_multiple_dp) { uc->has_multiple_dp) {
con_index = (uc->last_cmd_sent >> 16) & con_index = (uc->last_cmd_sent >> 16) &
UCSI_CMD_CONNECTOR_MASK; UCSI_CMD_CONNECTOR_MASK;
if (con_index == 0) {
ret = -EINVAL;
goto err_put;
}
con = &uc->ucsi->connector[con_index - 1]; con = &uc->ucsi->connector[con_index - 1];
ucsi_ccg_update_set_new_cam_cmd(uc, con, (u64 *)val); ucsi_ccg_update_set_new_cam_cmd(uc, con, (u64 *)val);
} }
@@ -599,6 +603,7 @@ static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset,
err_clear_bit: err_clear_bit:
clear_bit(DEV_CMD_PENDING, &uc->flags); clear_bit(DEV_CMD_PENDING, &uc->flags);
err_put:
pm_runtime_put_sync(uc->dev); pm_runtime_put_sync(uc->dev);
mutex_unlock(&uc->lock); mutex_unlock(&uc->lock);

View File

@@ -109,25 +109,6 @@ static struct linux_binfmt elf_format = {
#define BAD_ADDR(x) (unlikely((unsigned long)(x) >= TASK_SIZE)) #define BAD_ADDR(x) (unlikely((unsigned long)(x) >= TASK_SIZE))
static int set_brk(unsigned long start, unsigned long end, int prot)
{
start = ELF_PAGEALIGN(start);
end = ELF_PAGEALIGN(end);
if (end > start) {
/*
* Map the last of the bss segment.
* If the header is requesting these pages to be
* executable, honour that (ppc32 needs this).
*/
int error = vm_brk_flags(start, end - start,
prot & PROT_EXEC ? VM_EXEC : 0);
if (error)
return error;
}
current->mm->start_brk = current->mm->brk = end;
return 0;
}
/* We need to explicitly zero any fractional pages /* We need to explicitly zero any fractional pages
after the data section (i.e. bss). This would after the data section (i.e. bss). This would
contain the junk from the file that should not contain the junk from the file that should not
@@ -248,7 +229,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
} while (0) } while (0)
#ifdef ARCH_DLINFO #ifdef ARCH_DLINFO
/* /*
* ARCH_DLINFO must come first so PPC can do its special alignment of * ARCH_DLINFO must come first so PPC can do its special alignment of
* AUXV. * AUXV.
* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT() in * update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT() in
@@ -401,6 +382,51 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
return(map_addr); return(map_addr);
} }
static unsigned long elf_load(struct file *filep, unsigned long addr,
const struct elf_phdr *eppnt, int prot, int type,
unsigned long total_size)
{
unsigned long zero_start, zero_end;
unsigned long map_addr;
if (eppnt->p_filesz) {
map_addr = elf_map(filep, addr, eppnt, prot, type, total_size);
if (BAD_ADDR(map_addr))
return map_addr;
if (eppnt->p_memsz > eppnt->p_filesz) {
zero_start = map_addr + ELF_PAGEOFFSET(eppnt->p_vaddr) +
eppnt->p_filesz;
zero_end = map_addr + ELF_PAGEOFFSET(eppnt->p_vaddr) +
eppnt->p_memsz;
/* Zero the end of the last mapped page */
padzero(zero_start);
}
} else {
map_addr = zero_start = ELF_PAGESTART(addr);
zero_end = zero_start + ELF_PAGEOFFSET(eppnt->p_vaddr) +
eppnt->p_memsz;
}
if (eppnt->p_memsz > eppnt->p_filesz) {
/*
* Map the last of the segment.
* If the header is requesting these pages to be
* executable, honour that (ppc32 needs this).
*/
int error;
zero_start = ELF_PAGEALIGN(zero_start);
zero_end = ELF_PAGEALIGN(zero_end);
error = vm_brk_flags(zero_start, zero_end - zero_start,
prot & PROT_EXEC ? VM_EXEC : 0);
if (error)
map_addr = error;
}
return map_addr;
}
static unsigned long total_mapping_size(const struct elf_phdr *phdr, int nr) static unsigned long total_mapping_size(const struct elf_phdr *phdr, int nr)
{ {
elf_addr_t min_addr = -1; elf_addr_t min_addr = -1;
@@ -829,8 +855,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
unsigned long error; unsigned long error;
struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
struct elf_phdr *elf_property_phdata = NULL; struct elf_phdr *elf_property_phdata = NULL;
unsigned long elf_bss, elf_brk; unsigned long elf_brk;
int bss_prot = 0; bool brk_moved = false;
int retval, i; int retval, i;
unsigned long elf_entry; unsigned long elf_entry;
unsigned long e_entry; unsigned long e_entry;
@@ -1021,8 +1047,7 @@ out_free_interp:
executable_stack); executable_stack);
if (retval < 0) if (retval < 0)
goto out_free_dentry; goto out_free_dentry;
elf_bss = 0;
elf_brk = 0; elf_brk = 0;
start_code = ~0UL; start_code = ~0UL;
@@ -1042,33 +1067,6 @@ out_free_interp:
if (elf_ppnt->p_type != PT_LOAD) if (elf_ppnt->p_type != PT_LOAD)
continue; continue;
if (unlikely (elf_brk > elf_bss)) {
unsigned long nbyte;
/* There was a PT_LOAD segment with p_memsz > p_filesz
before this one. Map anonymous pages, if needed,
and clear the area. */
retval = set_brk(elf_bss + load_bias,
elf_brk + load_bias,
bss_prot);
if (retval)
goto out_free_dentry;
nbyte = ELF_PAGEOFFSET(elf_bss);
if (nbyte) {
nbyte = ELF_MIN_ALIGN - nbyte;
if (nbyte > elf_brk - elf_bss)
nbyte = elf_brk - elf_bss;
if (clear_user((void __user *)elf_bss +
load_bias, nbyte)) {
/*
* This bss-zeroing can fail if the ELF
* file specifies odd protections. So
* we don't check the return value
*/
}
}
}
elf_prot = make_prot(elf_ppnt->p_flags, &arch_state, elf_prot = make_prot(elf_ppnt->p_flags, &arch_state,
!!interpreter, false); !!interpreter, false);
@@ -1096,47 +1094,7 @@ out_free_interp:
* Header for ET_DYN binaries to calculate the * Header for ET_DYN binaries to calculate the
* randomization (load_bias) for all the LOAD * randomization (load_bias) for all the LOAD
* Program Headers. * Program Headers.
*
* There are effectively two types of ET_DYN
* binaries: programs (i.e. PIE: ET_DYN with INTERP)
* and loaders (ET_DYN without INTERP, since they
* _are_ the ELF interpreter). The loaders must
* be loaded away from programs since the program
* may otherwise collide with the loader (especially
* for ET_EXEC which does not have a randomized
* position). For example to handle invocations of
* "./ld.so someprog" to test out a new version of
* the loader, the subsequent program that the
* loader loads must avoid the loader itself, so
* they cannot share the same load range. Sufficient
* room for the brk must be allocated with the
* loader as well, since brk must be available with
* the loader.
*
* Therefore, programs are loaded offset from
* ELF_ET_DYN_BASE and loaders are loaded into the
* independently randomized mmap region (0 load_bias
* without MAP_FIXED nor MAP_FIXED_NOREPLACE).
*/ */
if (interpreter) {
load_bias = ELF_ET_DYN_BASE;
if (current->flags & PF_RANDOMIZE)
load_bias += arch_mmap_rnd();
alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum);
if (alignment)
load_bias &= ~(alignment - 1);
elf_flags |= MAP_FIXED_NOREPLACE;
} else
load_bias = 0;
/*
* Since load_bias is used for all subsequent loading
* calculations, we must lower it by the first vaddr
* so that the remaining calculations based on the
* ELF vaddrs will be correctly offset. The result
* is then page aligned.
*/
load_bias = ELF_PAGESTART(load_bias - vaddr);
/* /*
* Calculate the entire size of the ELF mapping * Calculate the entire size of the ELF mapping
@@ -1162,9 +1120,90 @@ out_free_interp:
retval = -EINVAL; retval = -EINVAL;
goto out_free_dentry; goto out_free_dentry;
} }
/* Calculate any requested alignment. */
alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum);
/**
* DOC: PIE handling
*
* There are effectively two types of ET_DYN ELF
* binaries: programs (i.e. PIE: ET_DYN with
* PT_INTERP) and loaders (i.e. static PIE: ET_DYN
* without PT_INTERP, usually the ELF interpreter
* itself). Loaders must be loaded away from programs
* since the program may otherwise collide with the
* loader (especially for ET_EXEC which does not have
* a randomized position).
*
* For example, to handle invocations of
* "./ld.so someprog" to test out a new version of
* the loader, the subsequent program that the
* loader loads must avoid the loader itself, so
* they cannot share the same load range. Sufficient
* room for the brk must be allocated with the
* loader as well, since brk must be available with
* the loader.
*
* Therefore, programs are loaded offset from
* ELF_ET_DYN_BASE and loaders are loaded into the
* independently randomized mmap region (0 load_bias
* without MAP_FIXED nor MAP_FIXED_NOREPLACE).
*
* See below for "brk" handling details, which is
* also affected by program vs loader and ASLR.
*/
if (interpreter) {
/* On ET_DYN with PT_INTERP, we do the ASLR. */
load_bias = ELF_ET_DYN_BASE;
if (current->flags & PF_RANDOMIZE)
load_bias += arch_mmap_rnd();
/* Adjust alignment as requested. */
if (alignment)
load_bias &= ~(alignment - 1);
elf_flags |= MAP_FIXED_NOREPLACE;
} else {
/*
* For ET_DYN without PT_INTERP, we rely on
* the architectures's (potentially ASLR) mmap
* base address (via a load_bias of 0).
*
* When a large alignment is requested, we
* must do the allocation at address "0" right
* now to discover where things will load so
* that we can adjust the resulting alignment.
* In this case (load_bias != 0), we can use
* MAP_FIXED_NOREPLACE to make sure the mapping
* doesn't collide with anything.
*/
if (alignment > ELF_MIN_ALIGN) {
load_bias = elf_load(bprm->file, 0, elf_ppnt,
elf_prot, elf_flags, total_size);
if (BAD_ADDR(load_bias)) {
retval = IS_ERR_VALUE(load_bias) ?
PTR_ERR((void*)load_bias) : -EINVAL;
goto out_free_dentry;
}
vm_munmap(load_bias, total_size);
/* Adjust alignment as requested. */
if (alignment)
load_bias &= ~(alignment - 1);
elf_flags |= MAP_FIXED_NOREPLACE;
} else
load_bias = 0;
}
/*
* Since load_bias is used for all subsequent loading
* calculations, we must lower it by the first vaddr
* so that the remaining calculations based on the
* ELF vaddrs will be correctly offset. The result
* is then page aligned.
*/
load_bias = ELF_PAGESTART(load_bias - vaddr);
} }
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, error = elf_load(bprm->file, load_bias + vaddr, elf_ppnt,
elf_prot, elf_flags, total_size); elf_prot, elf_flags, total_size);
if (BAD_ADDR(error)) { if (BAD_ADDR(error)) {
retval = IS_ERR((void *)error) ? retval = IS_ERR((void *)error) ?
@@ -1212,41 +1251,23 @@ out_free_interp:
k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
if (k > elf_bss)
elf_bss = k;
if ((elf_ppnt->p_flags & PF_X) && end_code < k) if ((elf_ppnt->p_flags & PF_X) && end_code < k)
end_code = k; end_code = k;
if (end_data < k) if (end_data < k)
end_data = k; end_data = k;
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
if (k > elf_brk) { if (k > elf_brk)
bss_prot = elf_prot;
elf_brk = k; elf_brk = k;
}
} }
e_entry = elf_ex->e_entry + load_bias; e_entry = elf_ex->e_entry + load_bias;
phdr_addr += load_bias; phdr_addr += load_bias;
elf_bss += load_bias;
elf_brk += load_bias; elf_brk += load_bias;
start_code += load_bias; start_code += load_bias;
end_code += load_bias; end_code += load_bias;
start_data += load_bias; start_data += load_bias;
end_data += load_bias; end_data += load_bias;
/* Calling set_brk effectively mmaps the pages that we need
* for the bss and break sections. We must do this before
* mapping in the interpreter, to make sure it doesn't wind
* up getting placed where the bss needs to go.
*/
retval = set_brk(elf_bss, elf_brk, bss_prot);
if (retval)
goto out_free_dentry;
if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) {
retval = -EFAULT; /* Nobody gets to see this, but.. */
goto out_free_dentry;
}
if (interpreter) { if (interpreter) {
elf_entry = load_elf_interp(interp_elf_ex, elf_entry = load_elf_interp(interp_elf_ex,
interpreter, interpreter,
@@ -1302,24 +1323,44 @@ out_free_interp:
mm->end_data = end_data; mm->end_data = end_data;
mm->start_stack = bprm->p; mm->start_stack = bprm->p;
if ((current->flags & PF_RANDOMIZE) && (snapshot_randomize_va_space > 1)) { /**
* DOC: "brk" handling
*
* For architectures with ELF randomization, when executing a
* loader directly (i.e. static PIE: ET_DYN without PT_INTERP),
* move the brk area out of the mmap region and into the unused
* ELF_ET_DYN_BASE region. Since "brk" grows up it may collide
* early with the stack growing down or other regions being put
* into the mmap region by the kernel (e.g. vdso).
*
* In the CONFIG_COMPAT_BRK case, though, everything is turned
* off because we're not allowed to move the brk at all.
*/
if (!IS_ENABLED(CONFIG_COMPAT_BRK) &&
IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
elf_ex->e_type == ET_DYN && !interpreter) {
elf_brk = ELF_ET_DYN_BASE;
/* This counts as moving the brk, so let brk(2) know. */
brk_moved = true;
}
mm->start_brk = mm->brk = ELF_PAGEALIGN(elf_brk);
if ((current->flags & PF_RANDOMIZE) && snapshot_randomize_va_space > 1) {
/* /*
* For architectures with ELF randomization, when executing * If we didn't move the brk to ELF_ET_DYN_BASE (above),
* a loader directly (i.e. no interpreter listed in ELF * leave a gap between .bss and brk.
* headers), move the brk area out of the mmap region
* (since it grows up, and may collide early with the stack
* growing down), and into the unused ELF_ET_DYN_BASE region.
*/ */
if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && if (!brk_moved)
elf_ex->e_type == ET_DYN && !interpreter) { mm->brk = mm->start_brk = mm->brk + PAGE_SIZE;
mm->brk = mm->start_brk = ELF_ET_DYN_BASE;
}
mm->brk = mm->start_brk = arch_randomize_brk(mm); mm->brk = mm->start_brk = arch_randomize_brk(mm);
brk_moved = true;
}
#ifdef compat_brk_randomized #ifdef compat_brk_randomized
if (brk_moved)
current->brk_randomized = 1; current->brk_randomized = 1;
#endif #endif
}
if (current->personality & MMAP_PAGE_ZERO) { if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask??? Well SVr4 maps page 0 as read-only, /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
@@ -1522,7 +1563,7 @@ static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, loff_t offset)
phdr->p_align = 0; phdr->p_align = 0;
} }
static void fill_note(struct memelfnote *note, const char *name, int type, static void fill_note(struct memelfnote *note, const char *name, int type,
unsigned int sz, void *data) unsigned int sz, void *data)
{ {
note->name = name; note->name = name;
@@ -2005,8 +2046,8 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
t->num_notes = 0; t->num_notes = 0;
fill_prstatus(&t->prstatus.common, p, signr); fill_prstatus(&t->prstatus.common, p, signr);
elf_core_copy_task_regs(p, &t->prstatus.pr_reg); elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus),
&(t->prstatus)); &(t->prstatus));
t->num_notes++; t->num_notes++;
@@ -2296,7 +2337,7 @@ static int elf_core_dump(struct coredump_params *cprm)
if (!elf_core_write_extra_phdrs(cprm, offset)) if (!elf_core_write_extra_phdrs(cprm, offset))
goto end_coredump; goto end_coredump;
/* write out the notes section */ /* write out the notes section */
if (!write_note_info(&info, cprm)) if (!write_note_info(&info, cprm))
goto end_coredump; goto end_coredump;

View File

@@ -1603,7 +1603,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
if (!elf_core_write_extra_phdrs(cprm, offset)) if (!elf_core_write_extra_phdrs(cprm, offset))
goto end_coredump; goto end_coredump;
/* write out the notes section */ /* write out the notes section */
if (!writenote(thread_list->notes, cprm)) if (!writenote(thread_list->notes, cprm))
goto end_coredump; goto end_coredump;
if (!writenote(&psinfo_note, cprm)) if (!writenote(&psinfo_note, cprm))

View File

@@ -78,8 +78,6 @@ static void __add_to_discard_list(struct btrfs_discard_ctl *discard_ctl,
struct btrfs_block_group *block_group) struct btrfs_block_group *block_group)
{ {
lockdep_assert_held(&discard_ctl->lock); lockdep_assert_held(&discard_ctl->lock);
if (!btrfs_run_discard_work(discard_ctl))
return;
if (list_empty(&block_group->discard_list) || if (list_empty(&block_group->discard_list) ||
block_group->discard_index == BTRFS_DISCARD_INDEX_UNUSED) { block_group->discard_index == BTRFS_DISCARD_INDEX_UNUSED) {
@@ -102,6 +100,9 @@ static void add_to_discard_list(struct btrfs_discard_ctl *discard_ctl,
if (!btrfs_is_block_group_data_only(block_group)) if (!btrfs_is_block_group_data_only(block_group))
return; return;
if (!btrfs_run_discard_work(discard_ctl))
return;
spin_lock(&discard_ctl->lock); spin_lock(&discard_ctl->lock);
__add_to_discard_list(discard_ctl, block_group); __add_to_discard_list(discard_ctl, block_group);
spin_unlock(&discard_ctl->lock); spin_unlock(&discard_ctl->lock);
@@ -233,6 +234,18 @@ again:
block_group->used != 0) { block_group->used != 0) {
if (btrfs_is_block_group_data_only(block_group)) { if (btrfs_is_block_group_data_only(block_group)) {
__add_to_discard_list(discard_ctl, block_group); __add_to_discard_list(discard_ctl, block_group);
/*
* The block group must have been moved to other
* discard list even if discard was disabled in
* the meantime or a transaction abort happened,
* otherwise we can end up in an infinite loop,
* always jumping into the 'again' label and
* keep getting this block group over and over
* in case there are no other block groups in
* the discard lists.
*/
ASSERT(block_group->discard_index !=
BTRFS_DISCARD_INDEX_UNUSED);
} else { } else {
list_del_init(&block_group->discard_list); list_del_init(&block_group->discard_list);
btrfs_put_block_group(block_group); btrfs_put_block_group(block_group);

View File

@@ -179,6 +179,14 @@ search_again:
ei = btrfs_item_ptr(leaf, path->slots[0], ei = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_extent_item); struct btrfs_extent_item);
num_refs = btrfs_extent_refs(leaf, ei); num_refs = btrfs_extent_refs(leaf, ei);
if (unlikely(num_refs == 0)) {
ret = -EUCLEAN;
btrfs_err(fs_info,
"unexpected zero reference count for extent item (%llu %u %llu)",
key.objectid, key.type, key.offset);
btrfs_abort_transaction(trans, ret);
goto out_free;
}
extent_flags = btrfs_extent_flags(leaf, ei); extent_flags = btrfs_extent_flags(leaf, ei);
} else { } else {
ret = -EINVAL; ret = -EINVAL;
@@ -190,8 +198,6 @@ search_again:
goto out_free; goto out_free;
} }
BUG_ON(num_refs == 0);
} else { } else {
num_refs = 0; num_refs = 0;
extent_flags = 0; extent_flags = 0;
@@ -221,10 +227,19 @@ search_again:
goto search_again; goto search_again;
} }
spin_lock(&head->lock); spin_lock(&head->lock);
if (head->extent_op && head->extent_op->update_flags) if (head->extent_op && head->extent_op->update_flags) {
extent_flags |= head->extent_op->flags_to_set; extent_flags |= head->extent_op->flags_to_set;
else } else if (unlikely(num_refs == 0)) {
BUG_ON(num_refs == 0); spin_unlock(&head->lock);
mutex_unlock(&head->mutex);
spin_unlock(&delayed_refs->lock);
ret = -EUCLEAN;
btrfs_err(fs_info,
"unexpected zero reference count for extent %llu (%s)",
bytenr, metadata ? "metadata" : "data");
btrfs_abort_transaction(trans, ret);
goto out_free;
}
num_refs += head->ref_mod; num_refs += head->ref_mod;
spin_unlock(&head->lock); spin_unlock(&head->lock);

View File

@@ -170,7 +170,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
exit: exit:
fput(file); fput(file);
out: out:
return error; return error;
} }
#endif /* #ifdef CONFIG_USELIB */ #endif /* #ifdef CONFIG_USELIB */

View File

@@ -6886,10 +6886,18 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
struct nfs4_unlockdata *p; struct nfs4_unlockdata *p;
struct nfs4_state *state = lsp->ls_state; struct nfs4_state *state = lsp->ls_state;
struct inode *inode = state->inode; struct inode *inode = state->inode;
struct nfs_lock_context *l_ctx;
p = kzalloc(sizeof(*p), GFP_KERNEL); p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
l_ctx = nfs_get_lock_context(ctx);
if (!IS_ERR(l_ctx)) {
p->l_ctx = l_ctx;
} else {
kfree(p);
return NULL;
}
p->arg.fh = NFS_FH(inode); p->arg.fh = NFS_FH(inode);
p->arg.fl = &p->fl; p->arg.fl = &p->fl;
p->arg.seqid = seqid; p->arg.seqid = seqid;
@@ -6897,7 +6905,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
p->lsp = lsp; p->lsp = lsp;
/* Ensure we don't close file until we're done freeing locks! */ /* Ensure we don't close file until we're done freeing locks! */
p->ctx = get_nfs_open_context(ctx); p->ctx = get_nfs_open_context(ctx);
p->l_ctx = nfs_get_lock_context(ctx);
locks_init_lock(&p->fl); locks_init_lock(&p->fl);
locks_copy_lock(&p->fl, fl); locks_copy_lock(&p->fl, fl);
p->server = NFS_SERVER(inode); p->server = NFS_SERVER(inode);

View File

@@ -732,6 +732,14 @@ pnfs_mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
return remaining; return remaining;
} }
static void pnfs_reset_return_info(struct pnfs_layout_hdr *lo)
{
struct pnfs_layout_segment *lseg;
list_for_each_entry(lseg, &lo->plh_return_segs, pls_list)
pnfs_set_plh_return_info(lo, lseg->pls_range.iomode, 0);
}
static void static void
pnfs_free_returned_lsegs(struct pnfs_layout_hdr *lo, pnfs_free_returned_lsegs(struct pnfs_layout_hdr *lo,
struct list_head *free_me, struct list_head *free_me,
@@ -1180,6 +1188,7 @@ void pnfs_layoutreturn_free_lsegs(struct pnfs_layout_hdr *lo,
pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq); pnfs_mark_matching_lsegs_invalid(lo, &freeme, range, seq);
pnfs_free_returned_lsegs(lo, &freeme, range, seq); pnfs_free_returned_lsegs(lo, &freeme, range, seq);
pnfs_set_layout_stateid(lo, stateid, NULL, true); pnfs_set_layout_stateid(lo, stateid, NULL, true);
pnfs_reset_return_info(lo);
} else } else
pnfs_mark_layout_stateid_invalid(lo, &freeme); pnfs_mark_layout_stateid_invalid(lo, &freeme);
out_unlock: out_unlock:

View File

@@ -2826,7 +2826,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
/* Eventually save off posix specific response info and timestaps */ /* Eventually save off posix specific response info and timestaps */
err_free_rsp_buf: err_free_rsp_buf:
free_rsp_buf(resp_buftype, rsp); free_rsp_buf(resp_buftype, rsp_iov.iov_base);
kfree(pc_buf); kfree(pc_buf);
err_free_req: err_free_req:
cifs_small_buf_release(req); cifs_small_buf_release(req);

View File

@@ -11,6 +11,7 @@
#include <linux/uio.h> #include <linux/uio.h>
#define BIO_MAX_VECS 256U #define BIO_MAX_VECS 256U
#define BIO_MAX_INLINE_VECS UIO_MAXIOV
static inline unsigned int bio_max_segs(unsigned int nr_segs) static inline unsigned int bio_max_segs(unsigned int nr_segs)
{ {

View File

@@ -1224,13 +1224,6 @@ extern int vmbus_sendpacket(struct vmbus_channel *channel,
enum vmbus_packet_type type, enum vmbus_packet_type type,
u32 flags); u32 flags);
extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
struct hv_page_buffer pagebuffers[],
u32 pagecount,
void *buffer,
u32 bufferlen,
u64 requestid);
extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
struct vmbus_packet_mpb_array *mpb, struct vmbus_packet_mpb_array *mpb,
u32 desc_size, u32 desc_size,

View File

@@ -181,7 +181,7 @@ enum tpm2_const {
enum tpm2_timeouts { enum tpm2_timeouts {
TPM2_TIMEOUT_A = 750, TPM2_TIMEOUT_A = 750,
TPM2_TIMEOUT_B = 2000, TPM2_TIMEOUT_B = 4000,
TPM2_TIMEOUT_C = 200, TPM2_TIMEOUT_C = 200,
TPM2_TIMEOUT_D = 30, TPM2_TIMEOUT_D = 30,
TPM2_DURATION_SHORT = 20, TPM2_DURATION_SHORT = 20,

View File

@@ -1045,6 +1045,7 @@ struct nft_rule_blob {
* @use: number of jump references to this chain * @use: number of jump references to this chain
* @flags: bitmask of enum nft_chain_flags * @flags: bitmask of enum nft_chain_flags
* @name: name of the chain * @name: name of the chain
* @rcu_head: rcu head for deferred release
*/ */
struct nft_chain { struct nft_chain {
struct nft_rule_blob __rcu *blob_gen_0; struct nft_rule_blob __rcu *blob_gen_0;
@@ -1121,7 +1122,7 @@ static inline bool nft_chain_is_bound(struct nft_chain *chain)
int nft_chain_add(struct nft_table *table, struct nft_chain *chain); int nft_chain_add(struct nft_table *table, struct nft_chain *chain);
void nft_chain_del(struct nft_chain *chain); void nft_chain_del(struct nft_chain *chain);
void nf_tables_chain_destroy(struct nft_ctx *ctx); void nf_tables_chain_destroy(struct nft_chain *chain);
struct nft_stats { struct nft_stats {
u64 bytes; u64 bytes;

View File

@@ -1003,6 +1003,21 @@ static inline struct sk_buff *__qdisc_dequeue_head(struct qdisc_skb_head *qh)
return skb; return skb;
} }
static inline struct sk_buff *qdisc_dequeue_internal(struct Qdisc *sch, bool direct)
{
struct sk_buff *skb;
skb = __skb_dequeue(&sch->gso_skb);
if (skb) {
sch->q.qlen--;
return skb;
}
if (direct)
return __qdisc_dequeue_head(&sch->q);
else
return sch->dequeue(sch);
}
static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)
{ {
struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);

View File

@@ -91,7 +91,7 @@ typedef __s64 Elf64_Sxword;
#define DT_INIT 12 #define DT_INIT 12
#define DT_FINI 13 #define DT_FINI 13
#define DT_SONAME 14 #define DT_SONAME 14
#define DT_RPATH 15 #define DT_RPATH 15
#define DT_SYMBOLIC 16 #define DT_SYMBOLIC 16
#define DT_REL 17 #define DT_REL 17
#define DT_RELSZ 18 #define DT_RELSZ 18

View File

@@ -16,7 +16,7 @@
#include "trace_output.h" /* for trace_event_sem */ #include "trace_output.h" /* for trace_event_sem */
#include "trace_dynevent.h" #include "trace_dynevent.h"
static DEFINE_MUTEX(dyn_event_ops_mutex); DEFINE_MUTEX(dyn_event_ops_mutex);
static LIST_HEAD(dyn_event_ops_list); static LIST_HEAD(dyn_event_ops_list);
bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call) bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call)
@@ -125,6 +125,20 @@ out:
return ret; return ret;
} }
/*
* Locked version of event creation. The event creation must be protected by
* dyn_event_ops_mutex because of protecting trace_probe_log.
*/
int dyn_event_create(const char *raw_command, struct dyn_event_operations *type)
{
int ret;
mutex_lock(&dyn_event_ops_mutex);
ret = type->create(raw_command);
mutex_unlock(&dyn_event_ops_mutex);
return ret;
}
static int create_dyn_event(const char *raw_command) static int create_dyn_event(const char *raw_command)
{ {
struct dyn_event_operations *ops; struct dyn_event_operations *ops;

View File

@@ -100,6 +100,7 @@ void *dyn_event_seq_next(struct seq_file *m, void *v, loff_t *pos);
void dyn_event_seq_stop(struct seq_file *m, void *v); void dyn_event_seq_stop(struct seq_file *m, void *v);
int dyn_events_release_all(struct dyn_event_operations *type); int dyn_events_release_all(struct dyn_event_operations *type);
int dyn_event_release(const char *raw_command, struct dyn_event_operations *type); int dyn_event_release(const char *raw_command, struct dyn_event_operations *type);
int dyn_event_create(const char *raw_command, struct dyn_event_operations *type);
/* /*
* for_each_dyn_event - iterate over the dyn_event list * for_each_dyn_event - iterate over the dyn_event list

View File

@@ -1539,7 +1539,7 @@ stacktrace_trigger(struct event_trigger_data *data,
struct trace_event_file *file = data->private_data; struct trace_event_file *file = data->private_data;
if (file) if (file)
__trace_stack(file->tr, tracing_gen_ctx(), STACK_SKIP); __trace_stack(file->tr, tracing_gen_ctx_dec(), STACK_SKIP);
else else
trace_dump_stack(STACK_SKIP); trace_dump_stack(STACK_SKIP);
} }

View File

@@ -561,11 +561,7 @@ ftrace_traceoff(unsigned long ip, unsigned long parent_ip,
static __always_inline void trace_stack(struct trace_array *tr) static __always_inline void trace_stack(struct trace_array *tr)
{ {
unsigned int trace_ctx; __trace_stack(tr, tracing_gen_ctx_dec(), FTRACE_STACK_SKIP);
trace_ctx = tracing_gen_ctx();
__trace_stack(tr, trace_ctx, FTRACE_STACK_SKIP);
} }
static void static void

View File

@@ -975,7 +975,7 @@ static int create_or_delete_trace_kprobe(const char *raw_command)
if (raw_command[0] == '-') if (raw_command[0] == '-')
return dyn_event_release(raw_command, &trace_kprobe_ops); return dyn_event_release(raw_command, &trace_kprobe_ops);
ret = trace_kprobe_create(raw_command); ret = dyn_event_create(raw_command, &trace_kprobe_ops);
return ret == -ECANCELED ? -EINVAL : ret; return ret == -ECANCELED ? -EINVAL : ret;
} }

View File

@@ -143,9 +143,12 @@ fail:
} }
static struct trace_probe_log trace_probe_log; static struct trace_probe_log trace_probe_log;
extern struct mutex dyn_event_ops_mutex;
void trace_probe_log_init(const char *subsystem, int argc, const char **argv) void trace_probe_log_init(const char *subsystem, int argc, const char **argv)
{ {
lockdep_assert_held(&dyn_event_ops_mutex);
trace_probe_log.subsystem = subsystem; trace_probe_log.subsystem = subsystem;
trace_probe_log.argc = argc; trace_probe_log.argc = argc;
trace_probe_log.argv = argv; trace_probe_log.argv = argv;
@@ -154,11 +157,15 @@ void trace_probe_log_init(const char *subsystem, int argc, const char **argv)
void trace_probe_log_clear(void) void trace_probe_log_clear(void)
{ {
lockdep_assert_held(&dyn_event_ops_mutex);
memset(&trace_probe_log, 0, sizeof(trace_probe_log)); memset(&trace_probe_log, 0, sizeof(trace_probe_log));
} }
void trace_probe_log_set_index(int index) void trace_probe_log_set_index(int index)
{ {
lockdep_assert_held(&dyn_event_ops_mutex);
trace_probe_log.index = index; trace_probe_log.index = index;
} }
@@ -167,6 +174,8 @@ void __trace_probe_log_err(int offset, int err_type)
char *command, *p; char *command, *p;
int i, len = 0, pos = 0; int i, len = 0, pos = 0;
lockdep_assert_held(&dyn_event_ops_mutex);
if (!trace_probe_log.argv) if (!trace_probe_log.argv)
return; return;

View File

@@ -732,7 +732,7 @@ static int create_or_delete_trace_uprobe(const char *raw_command)
if (raw_command[0] == '-') if (raw_command[0] == '-')
return dyn_event_release(raw_command, &trace_uprobe_ops); return dyn_event_release(raw_command, &trace_uprobe_ops);
ret = trace_uprobe_create(raw_command); ret = dyn_event_create(raw_command, &trace_uprobe_ops);
return ret == -ECANCELED ? -EINVAL : ret; return ret == -ECANCELED ? -EINVAL : ret;
} }

View File

@@ -1656,8 +1656,12 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
if (PageHWPoison(page)) { if (PageHWPoison(page)) {
if (WARN_ON(folio_test_lru(folio))) if (WARN_ON(folio_test_lru(folio)))
folio_isolate_lru(folio); folio_isolate_lru(folio);
if (folio_mapped(folio)) if (folio_mapped(folio)) {
folio_lock(folio);
try_to_unmap(folio, TTU_IGNORE_MLOCK); try_to_unmap(folio, TTU_IGNORE_MLOCK);
folio_unlock(folio);
}
continue; continue;
} }

View File

@@ -2430,6 +2430,14 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
if (managed_zone(pgdat->node_zones + z)) if (managed_zone(pgdat->node_zones + z))
break; break;
} }
/*
* If there are no managed zones, it should not proceed
* further.
*/
if (z < 0)
return 0;
wakeup_kswapd(pgdat->node_zones + z, 0, order, ZONE_MOVABLE); wakeup_kswapd(pgdat->node_zones + z, 0, order, ZONE_MOVABLE);
return 0; return 0;
} }

View File

@@ -1580,7 +1580,8 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
* so icmphdr does not in skb linear region and can not get icmp_type * so icmphdr does not in skb linear region and can not get icmp_type
* by icmp_hdr(skb)->type. * by icmp_hdr(skb)->type.
*/ */
if (sk->sk_type == SOCK_RAW && !inet_sk(sk)->hdrincl) if (sk->sk_type == SOCK_RAW &&
!(fl4->flowi4_flags & FLOWI_FLAG_KNOWN_NH))
icmp_type = fl4->fl4_icmp_type; icmp_type = fl4->fl4_icmp_type;
else else
icmp_type = icmp_hdr(skb)->type; icmp_type = icmp_hdr(skb)->type;

View File

@@ -608,6 +608,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
(hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
daddr, saddr, 0, 0, sk->sk_uid); daddr, saddr, 0, 0, sk->sk_uid);
fl4.fl4_icmp_type = 0;
fl4.fl4_icmp_code = 0;
if (!hdrincl) { if (!hdrincl) {
rfv.msg = msg; rfv.msg = msg;
rfv.hlen = 0; rfv.hlen = 0;

View File

@@ -1985,7 +1985,8 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
u8 icmp6_type; u8 icmp6_type;
if (sk->sk_socket->type == SOCK_RAW && !inet_sk(sk)->hdrincl) if (sk->sk_socket->type == SOCK_RAW &&
!(fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH))
icmp6_type = fl6->fl6_icmp_type; icmp6_type = fl6->fl6_icmp_type;
else else
icmp6_type = icmp6_hdr(skb)->icmp6_type; icmp6_type = icmp6_hdr(skb)->icmp6_type;

View File

@@ -274,8 +274,10 @@ static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev)
key = flow->key; key = flow->key;
if (WARN_ON(key->dev && key->dev != dev)) if (key->dev) {
WARN_ON(key->dev != dev);
return; return;
}
mctp_dev_set_key(dev, key); mctp_dev_set_key(dev, key);
} }

View File

@@ -2034,9 +2034,9 @@ static void nf_tables_chain_free_chain_rules(struct nft_chain *chain)
kvfree(chain->blob_next); kvfree(chain->blob_next);
} }
void nf_tables_chain_destroy(struct nft_ctx *ctx) void nf_tables_chain_destroy(struct nft_chain *chain)
{ {
struct nft_chain *chain = ctx->chain; const struct nft_table *table = chain->table;
struct nft_hook *hook, *next; struct nft_hook *hook, *next;
if (WARN_ON(chain->use > 0)) if (WARN_ON(chain->use > 0))
@@ -2048,7 +2048,7 @@ void nf_tables_chain_destroy(struct nft_ctx *ctx)
if (nft_is_base_chain(chain)) { if (nft_is_base_chain(chain)) {
struct nft_base_chain *basechain = nft_base_chain(chain); struct nft_base_chain *basechain = nft_base_chain(chain);
if (nft_base_chain_netdev(ctx->family, basechain->ops.hooknum)) { if (nft_base_chain_netdev(table->family, basechain->ops.hooknum)) {
list_for_each_entry_safe(hook, next, list_for_each_entry_safe(hook, next,
&basechain->hook_list, list) { &basechain->hook_list, list) {
list_del_rcu(&hook->list); list_del_rcu(&hook->list);
@@ -2515,7 +2515,7 @@ err_chain_add:
err_trans: err_trans:
nft_use_dec_restore(&table->use); nft_use_dec_restore(&table->use);
err_destroy_chain: err_destroy_chain:
nf_tables_chain_destroy(ctx); nf_tables_chain_destroy(chain);
return err; return err;
} }
@@ -3510,8 +3510,11 @@ void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
kfree(rule); kfree(rule);
} }
/* can only be used if rule is no longer visible to dumps */
static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule) static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
{ {
lockdep_commit_lock_is_held(ctx->net);
nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE); nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
nf_tables_rule_destroy(ctx, rule); nf_tables_rule_destroy(ctx, rule);
} }
@@ -5247,6 +5250,8 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_binding *binding, struct nft_set_binding *binding,
enum nft_trans_phase phase) enum nft_trans_phase phase)
{ {
lockdep_commit_lock_is_held(ctx->net);
switch (phase) { switch (phase) {
case NFT_TRANS_PREPARE_ERROR: case NFT_TRANS_PREPARE_ERROR:
nft_set_trans_unbind(ctx, set); nft_set_trans_unbind(ctx, set);
@@ -8994,7 +8999,7 @@ static void nft_commit_release(struct nft_trans *trans)
kfree(nft_trans_chain_name(trans)); kfree(nft_trans_chain_name(trans));
break; break;
case NFT_MSG_DELCHAIN: case NFT_MSG_DELCHAIN:
nf_tables_chain_destroy(&trans->ctx); nf_tables_chain_destroy(nft_trans_chain(trans));
break; break;
case NFT_MSG_DELRULE: case NFT_MSG_DELRULE:
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
@@ -9955,7 +9960,7 @@ static void nf_tables_abort_release(struct nft_trans *trans)
nf_tables_table_destroy(&trans->ctx); nf_tables_table_destroy(&trans->ctx);
break; break;
case NFT_MSG_NEWCHAIN: case NFT_MSG_NEWCHAIN:
nf_tables_chain_destroy(&trans->ctx); nf_tables_chain_destroy(nft_trans_chain(trans));
break; break;
case NFT_MSG_NEWRULE: case NFT_MSG_NEWRULE:
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
@@ -10662,23 +10667,43 @@ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
} }
EXPORT_SYMBOL_GPL(nft_data_dump); EXPORT_SYMBOL_GPL(nft_data_dump);
int __nft_release_basechain(struct nft_ctx *ctx) static void __nft_release_basechain_now(struct nft_ctx *ctx)
{ {
struct nft_rule *rule, *nr; struct nft_rule *rule, *nr;
if (WARN_ON(!nft_is_base_chain(ctx->chain))) list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
list_del(&rule->list);
nf_tables_rule_release(ctx, rule);
}
nf_tables_chain_destroy(ctx->chain);
}
int __nft_release_basechain(struct nft_ctx *ctx)
{
struct nft_rule *rule;
if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain)))
return 0; return 0;
nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain); nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain);
list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { list_for_each_entry(rule, &ctx->chain->rules, list)
list_del(&rule->list);
nft_use_dec(&ctx->chain->use); nft_use_dec(&ctx->chain->use);
nf_tables_rule_release(ctx, rule);
}
nft_chain_del(ctx->chain); nft_chain_del(ctx->chain);
nft_use_dec(&ctx->table->use); nft_use_dec(&ctx->table->use);
nf_tables_chain_destroy(ctx);
if (!maybe_get_net(ctx->net)) {
__nft_release_basechain_now(ctx);
return 0;
}
/* wait for ruleset dumps to complete. Owning chain is no longer in
* lists, so new dumps can't find any of these rules anymore.
*/
synchronize_rcu();
__nft_release_basechain_now(ctx);
put_net(ctx->net);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(__nft_release_basechain); EXPORT_SYMBOL_GPL(__nft_release_basechain);
@@ -10753,10 +10778,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
nft_obj_destroy(&ctx, obj); nft_obj_destroy(&ctx, obj);
} }
list_for_each_entry_safe(chain, nc, &table->chains, list) { list_for_each_entry_safe(chain, nc, &table->chains, list) {
ctx.chain = chain;
nft_chain_del(chain); nft_chain_del(chain);
nft_use_dec(&table->use); nft_use_dec(&table->use);
nf_tables_chain_destroy(&ctx); nf_tables_chain_destroy(chain);
} }
nf_tables_table_destroy(&ctx); nf_tables_table_destroy(&ctx);
} }

View File

@@ -221,7 +221,7 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
list_del(&rule->list); list_del(&rule->list);
nf_tables_rule_destroy(&chain_ctx, rule); nf_tables_rule_destroy(&chain_ctx, rule);
} }
nf_tables_chain_destroy(&chain_ctx); nf_tables_chain_destroy(chain);
break; break;
default: default:
break; break;

View File

@@ -168,7 +168,7 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt,
qlen = sch->q.qlen; qlen = sch->q.qlen;
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
dropped += qdisc_pkt_len(skb); dropped += qdisc_pkt_len(skb);
qdisc_qstats_backlog_dec(sch, skb); qdisc_qstats_backlog_dec(sch, skb);

View File

@@ -901,7 +901,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
sch_tree_lock(sch); sch_tree_lock(sch);
} }
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = fq_dequeue(sch); struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
if (!skb) if (!skb)
break; break;

View File

@@ -431,7 +431,7 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
while (sch->q.qlen > sch->limit || while (sch->q.qlen > sch->limit ||
q->memory_usage > q->memory_limit) { q->memory_usage > q->memory_limit) {
struct sk_buff *skb = fq_codel_dequeue(sch); struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
q->cstats.drop_len += qdisc_pkt_len(skb); q->cstats.drop_len += qdisc_pkt_len(skb);
rtnl_kfree_skbs(skb, skb); rtnl_kfree_skbs(skb, skb);

View File

@@ -357,7 +357,7 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt,
/* Drop excess packets if new limit is lower */ /* Drop excess packets if new limit is lower */
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = fq_pie_qdisc_dequeue(sch); struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
len_dropped += qdisc_pkt_len(skb); len_dropped += qdisc_pkt_len(skb);
num_dropped += 1; num_dropped += 1;

View File

@@ -560,7 +560,7 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt,
qlen = sch->q.qlen; qlen = sch->q.qlen;
prev_backlog = sch->qstats.backlog; prev_backlog = sch->qstats.backlog;
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = hhf_dequeue(sch); struct sk_buff *skb = qdisc_dequeue_internal(sch, false);
rtnl_kfree_skbs(skb, skb); rtnl_kfree_skbs(skb, skb);
} }

View File

@@ -190,7 +190,7 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt,
/* Drop excess packets if new limit is lower */ /* Drop excess packets if new limit is lower */
qlen = sch->q.qlen; qlen = sch->q.qlen;
while (sch->q.qlen > sch->limit) { while (sch->q.qlen > sch->limit) {
struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); struct sk_buff *skb = qdisc_dequeue_internal(sch, true);
dropped += qdisc_pkt_len(skb); dropped += qdisc_pkt_len(skb);
qdisc_qstats_backlog_dec(sch, skb); qdisc_qstats_backlog_dec(sch, skb);

View File

@@ -518,6 +518,8 @@ static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
return ret; return ret;
} }
static DEFINE_MUTEX(sctp_sysctl_mutex);
static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write, static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos) void *buffer, size_t *lenp, loff_t *ppos)
{ {
@@ -542,6 +544,7 @@ static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write,
if (new_value > max || new_value < min) if (new_value > max || new_value < min)
return -EINVAL; return -EINVAL;
mutex_lock(&sctp_sysctl_mutex);
net->sctp.udp_port = new_value; net->sctp.udp_port = new_value;
sctp_udp_sock_stop(net); sctp_udp_sock_stop(net);
if (new_value) { if (new_value) {
@@ -554,6 +557,7 @@ static int proc_sctp_do_udp_port(struct ctl_table *ctl, int write,
lock_sock(sk); lock_sock(sk);
sctp_sk(sk)->udp_port = htons(net->sctp.udp_port); sctp_sk(sk)->udp_port = htons(net->sctp.udp_port);
release_sock(sk); release_sock(sk);
mutex_unlock(&sctp_sysctl_mutex);
} }
return ret; return ret;

View File

@@ -396,7 +396,6 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
return 0; return 0;
shinfo = skb_shinfo(strp->anchor); shinfo = skb_shinfo(strp->anchor);
shinfo->frag_list = NULL;
/* If we don't know the length go max plus page for cipher overhead */ /* If we don't know the length go max plus page for cipher overhead */
need_spc = strp->stm.full_len ?: TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE; need_spc = strp->stm.full_len ?: TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE;
@@ -412,6 +411,8 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
page, 0, 0); page, 0, 0);
} }
shinfo->frag_list = NULL;
strp->copy_mode = 1; strp->copy_mode = 1;
strp->stm.offset = 0; strp->stm.offset = 0;

View File

@@ -112,7 +112,7 @@ static int __init sample_trace_array_init(void)
/* /*
* If context specific per-cpu buffers havent already been allocated. * If context specific per-cpu buffers havent already been allocated.
*/ */
trace_printk_init_buffers(); trace_array_init_printk(tr);
simple_tsk = kthread_run(simple_thread, NULL, "sample-instance"); simple_tsk = kthread_run(simple_thread, NULL, "sample-instance");
if (IS_ERR(simple_tsk)) { if (IS_ERR(simple_tsk)) {

View File

@@ -1569,7 +1569,7 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct es1968 *chip = snd_pcm_substream_chip(substream); struct es1968 *chip = snd_pcm_substream_chip(substream);
struct esschan *es; struct esschan *es;
int apu1, apu2; int err, apu1, apu2;
apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE); apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE);
if (apu1 < 0) if (apu1 < 0)
@@ -1613,7 +1613,9 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream)
runtime->hw = snd_es1968_capture; runtime->hw = snd_es1968_capture;
runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max = runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max =
calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */ calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */
snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES); err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
if (err < 0)
return err;
spin_lock_irq(&chip->substream_lock); spin_lock_irq(&chip->substream_lock);
list_add(&es->list, &chip->substream_list); list_add(&es->list, &chip->substream_list);

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