mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
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:
2
Makefile
2
Makefile
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -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__);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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*/
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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++) {
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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())) {
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
293
fs/binfmt_elf.c
293
fs/binfmt_elf.c
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user