This is the 4.19.272 stable release
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmPgoxsACgkQONu9yGCS aT7P4hAAiY1TIECbi0kriTeuRmi/cGkU1eo8ODV+5h0x31cEObCZnsvU6v2LeqOJ X0H8U3MwjxyVYoK1L1SUBClgPXqBq0jI4+CrjVSQcl8kWGKhUm/JXzjcOC6wAlB7 M2BRD2z7M+K4Mem1Q6eV7UEuEBPteLquP4xPlaXKkRAoeWKXcbiRM3ns5h20Acmi igDqhzLUAiAIhL429vPAOp34aNDmaZzLXiMt9p0mYkDFP7I904FrlBAsceJV8NZ9 6oxxQspkoCf8MjBGrV6JcFwNgHjCHM+zXHWhROCE9WL7rknCJidttQKsOtzNE6Gx pFF60qFRx6JVsvm0D2lJpEW+ExdlcQ/aacByy3fXajkdyrsl9sTajiw0+1f6P4Oq hX8U+HianG4G1HgpOAUeZZBcTn7k7+pdTcogLaQW5Csch2RHMmmnPMZlZqudGUxD yJiyd9dRIEPOa8CAdCzI4/xgjEgogS1snS9jRhJ0rwRtSqL3lLrSRdeFWbVjgA54 HAF9dR76Y4sbmWv4MbUPK+lvROvWv/NtLeiHXCJCGsxWdcOYQTw8ASenaK2IQRUF 1ows0gRXX3Xzm6R8CvpJqT80ta1rUfD3INycV4kUHeRUlVsrBtu48KX325+ZUXD9 Lvcbips57QvMMigROx6HpQHbmA1fe/42mZfhf36sgzycAmIzThA= =yuwn -----END PGP SIGNATURE----- Merge 4.19.272 into android-4.19-stable Changes in 4.19.272 ARM: dts: imx6qdl-gw560x: Remove incorrect 'uart-has-rtscts' HID: intel_ish-hid: Add check for ishtp_dma_tx_map EDAC/highbank: Fix memory leak in highbank_mc_probe() tomoyo: fix broken dependency on *.conf.default IB/hfi1: Reject a zero-length user expected buffer IB/hfi1: Reserve user expected TIDs IB/hfi1: Fix expected receive setup error exit issues affs: initialize fsdata in affs_truncate() amd-xgbe: TX Flow Ctrl Registers are h/w ver dependent amd-xgbe: Delay AN timeout during KR training bpf: Fix pointer-leak due to insufficient speculative store bypass mitigation phy: rockchip-inno-usb2: Fix missing clk_disable_unprepare() in rockchip_usb2phy_power_on() net: nfc: Fix use-after-free in local_cleanup() wifi: rndis_wlan: Prevent buffer overflow in rndis_query_oid net: usb: sr9700: Handle negative len net: mdio: validate parameter addr in mdiobus_get_phy() HID: check empty report_list in hid_validate_values() usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait usb: gadget: f_fs: Ensure ep0req is dequeued before free_request net: mlx5: eliminate anonymous module_init & module_exit dmaengine: Fix double increment of client_count in dma_chan_get() net: macb: fix PTP TX timestamp failure due to packet padding HID: betop: check shape of output reports dmaengine: xilinx_dma: commonize DMA copy size calculation dmaengine: xilinx_dma: program hardware supported buffer length dmaengine: xilinx_dma: Fix devm_platform_ioremap_resource error handling dmaengine: xilinx_dma: call of_node_put() when breaking out of for_each_child_of_node() tcp: avoid the lookup process failing to get sk in ehash table w1: fix deadloop in __w1_remove_master_device() w1: fix WARNING after calling w1_process() netfilter: conntrack: do not renew entry stuck in tcp SYN_SENT state block: fix and cleanup bio_check_ro perf env: Do not return pointers to local variables fs: reiserfs: remove useless new_opts in reiserfs_remount Bluetooth: hci_sync: cancel cmd_timer if hci_open failed scsi: hpsa: Fix allocation size for scsi_host_alloc() module: Don't wait for GOING modules tracing: Make sure trace_printk() can output as soon as it can be used trace_events_hist: add check for return value of 'create_hist_field' smbd: Make upper layer decide when to destroy the transport cifs: Fix oops due to uncleared server->smbd_conn in reconnect ARM: 9280/1: mm: fix warning on phys_addr_t to void pointer assignment EDAC/device: Respect any driver-supplied workqueue polling value net: fix UaF in netns ops registration error path netfilter: nft_set_rbtree: skip elements in transaction from garbage collection netlink: remove hash::nelems check in netlink_insert netlink: annotate data races around nlk->portid netlink: annotate data races around dst_portid and dst_group netlink: annotate data races around sk_state ipv4: prevent potential spectre v1 gadget in ip_metrics_convert() netfilter: conntrack: fix vtag checks for ABORT/SHUTDOWN_COMPLETE netrom: Fix use-after-free of a listening socket. sctp: fail if no bound addresses can be used for a given scope net: ravb: Fix possible hang if RIS2_QFF1 happen net/tg3: resolve deadlock in tg3_reset_task() during EEH Revert "Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI mode" x86/i8259: Mark legacy PIC interrupts with IRQ_LEVEL drm/i915/display: fix compiler warning about array overrun x86/asm: Fix an assembler warning with current binutils x86/entry/64: Add instruction suffix to SYSRET ARM: dts: imx: Fix pca9547 i2c-mux node name dmaengine: imx-sdma: Fix a possible memory leak in sdma_transfer_init sysctl: add a new register_sysctl_init() interface panic: unset panic_on_warn inside panic() exit: Add and use make_task_dead. objtool: Add a missing comma to avoid string concatenation hexagon: Fix function name in die() h8300: Fix build errors from do_exit() to make_task_dead() transition ia64: make IA64_MCA_RECOVERY bool instead of tristate exit: Put an upper limit on how often we can oops exit: Expose "oops_count" to sysfs exit: Allow oops_limit to be disabled panic: Consolidate open-coded panic_on_warn checks panic: Introduce warn_limit panic: Expose "warn_count" to sysfs docs: Fix path paste-o for /sys/kernel/warn_count exit: Use READ_ONCE() for all oops/warn limit reads ipv6: ensure sane device mtu in tunnels usb: host: xhci-plat: add wakeup entry at sysfs Linux 4.19.272 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I4f9ddce1e108e81409d47e00fdeef2bc0d34f793
This commit is contained in:
commit
c97f22d970
108 changed files with 775 additions and 304 deletions
6
Documentation/ABI/testing/sysfs-kernel-oops_count
Normal file
6
Documentation/ABI/testing/sysfs-kernel-oops_count
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
What: /sys/kernel/oops_count
|
||||||
|
Date: November 2022
|
||||||
|
KernelVersion: 6.2.0
|
||||||
|
Contact: Linux Kernel Hardening List <linux-hardening@vger.kernel.org>
|
||||||
|
Description:
|
||||||
|
Shows how many times the system has Oopsed since last boot.
|
6
Documentation/ABI/testing/sysfs-kernel-warn_count
Normal file
6
Documentation/ABI/testing/sysfs-kernel-warn_count
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
What: /sys/kernel/warn_count
|
||||||
|
Date: November 2022
|
||||||
|
KernelVersion: 6.2.0
|
||||||
|
Contact: Linux Kernel Hardening List <linux-hardening@vger.kernel.org>
|
||||||
|
Description:
|
||||||
|
Shows how many times the system has Warned since last boot.
|
|
@ -51,6 +51,7 @@ show up in /proc/sys/kernel:
|
||||||
- msgmnb
|
- msgmnb
|
||||||
- msgmni
|
- msgmni
|
||||||
- nmi_watchdog
|
- nmi_watchdog
|
||||||
|
- oops_limit
|
||||||
- osrelease
|
- osrelease
|
||||||
- ostype
|
- ostype
|
||||||
- overflowgid
|
- overflowgid
|
||||||
|
@ -97,6 +98,7 @@ show up in /proc/sys/kernel:
|
||||||
- threads-max
|
- threads-max
|
||||||
- unprivileged_bpf_disabled
|
- unprivileged_bpf_disabled
|
||||||
- unknown_nmi_panic
|
- unknown_nmi_panic
|
||||||
|
- warn_limit
|
||||||
- watchdog
|
- watchdog
|
||||||
- watchdog_thresh
|
- watchdog_thresh
|
||||||
- version
|
- version
|
||||||
|
@ -556,6 +558,15 @@ scanned for a given scan.
|
||||||
|
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
||||||
|
oops_limit:
|
||||||
|
|
||||||
|
Number of kernel oopses after which the kernel should panic when
|
||||||
|
``panic_on_oops`` is not set. Setting this to 0 disables checking
|
||||||
|
the count. Setting this to 1 has the same effect as setting
|
||||||
|
``panic_on_oops=1``. The default value is 10000.
|
||||||
|
|
||||||
|
==============================================================
|
||||||
|
|
||||||
osrelease, ostype & version:
|
osrelease, ostype & version:
|
||||||
|
|
||||||
# cat osrelease
|
# cat osrelease
|
||||||
|
@ -1116,6 +1127,15 @@ example. If a system hangs up, try pressing the NMI switch.
|
||||||
|
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
||||||
|
warn_limit:
|
||||||
|
|
||||||
|
Number of kernel warnings after which the kernel should panic when
|
||||||
|
``panic_on_warn`` is not set. Setting this to 0 disables checking
|
||||||
|
the warning count. Setting this to 1 has the same effect as setting
|
||||||
|
``panic_on_warn=1``. The default value is 0.
|
||||||
|
|
||||||
|
==============================================================
|
||||||
|
|
||||||
watchdog:
|
watchdog:
|
||||||
|
|
||||||
This parameter can be used to disable or enable the soft lockup detector
|
This parameter can be used to disable or enable the soft lockup detector
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 19
|
PATCHLEVEL = 19
|
||||||
SUBLEVEL = 271
|
SUBLEVEL = 272
|
||||||
EXTRAVERSION =
|
EXTRAVERSION =
|
||||||
NAME = "People's Front"
|
NAME = "People's Front"
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,7 @@ die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_MATHEMU
|
#ifndef CONFIG_MATHEMU
|
||||||
|
@ -577,7 +577,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
|
||||||
|
|
||||||
printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n",
|
printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n",
|
||||||
pc, va, opcode, reg);
|
pc, va, opcode, reg);
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
|
|
||||||
got_exception:
|
got_exception:
|
||||||
/* Ok, we caught the exception, but we don't want it. Is there
|
/* Ok, we caught the exception, but we don't want it. Is there
|
||||||
|
@ -632,7 +632,7 @@ got_exception:
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -206,7 +206,7 @@ retry:
|
||||||
printk(KERN_ALERT "Unable to handle kernel paging request at "
|
printk(KERN_ALERT "Unable to handle kernel paging request at "
|
||||||
"virtual address %016lx\n", address);
|
"virtual address %016lx\n", address);
|
||||||
die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
|
die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
|
|
||||||
/* We ran out of memory, or some other thing happened to us that
|
/* We ran out of memory, or some other thing happened to us that
|
||||||
made us unable to handle the page fault gracefully. */
|
made us unable to handle the page fault gracefully. */
|
||||||
|
|
|
@ -462,7 +462,7 @@
|
||||||
scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
|
scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
i2c-switch@70 {
|
i2c-mux@70 {
|
||||||
compatible = "nxp,pca9547";
|
compatible = "nxp,pca9547";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
|
|
@ -463,7 +463,6 @@
|
||||||
&uart1 {
|
&uart1 {
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
pinctrl-0 = <&pinctrl_uart1>;
|
pinctrl-0 = <&pinctrl_uart1>;
|
||||||
uart-has-rtscts;
|
|
||||||
rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
|
rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
|
@ -344,7 +344,7 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
|
||||||
if (panic_on_oops)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
if (signr)
|
if (signr)
|
||||||
do_exit(signr);
|
make_task_dead(signr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -149,7 +149,7 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
|
||||||
show_pte(mm, addr);
|
show_pte(mm, addr);
|
||||||
die("Oops", regs, fsr);
|
die("Oops", regs, fsr);
|
||||||
bust_spinlocks(0);
|
bust_spinlocks(0);
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -160,7 +160,7 @@ void __init paging_init(const struct machine_desc *mdesc)
|
||||||
mpu_setup();
|
mpu_setup();
|
||||||
|
|
||||||
/* allocate the zero page. */
|
/* allocate the zero page. */
|
||||||
zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
|
zero_page = (void *)memblock_alloc(PAGE_SIZE, PAGE_SIZE);
|
||||||
if (!zero_page)
|
if (!zero_page)
|
||||||
panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
|
panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
|
||||||
__func__, PAGE_SIZE, PAGE_SIZE);
|
__func__, PAGE_SIZE, PAGE_SIZE);
|
||||||
|
|
|
@ -225,7 +225,7 @@ void die(const char *str, struct pt_regs *regs, int err)
|
||||||
raw_spin_unlock_irqrestore(&die_lock, flags);
|
raw_spin_unlock_irqrestore(&die_lock, flags);
|
||||||
|
|
||||||
if (ret != NOTIFY_STOP)
|
if (ret != NOTIFY_STOP)
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool show_unhandled_signals_ratelimited(void)
|
static bool show_unhandled_signals_ratelimited(void)
|
||||||
|
|
|
@ -281,7 +281,7 @@ static void die_kernel_fault(const char *msg, unsigned long addr,
|
||||||
show_pte(addr);
|
show_pte(addr);
|
||||||
die("Oops", regs, esr);
|
die("Oops", regs, esr);
|
||||||
bust_spinlocks(0);
|
bust_spinlocks(0);
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __do_kernel_fault(unsigned long addr, unsigned int esr,
|
static void __do_kernel_fault(unsigned long addr, unsigned int esr,
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/sched/debug.h>
|
#include <linux/sched/debug.h>
|
||||||
|
#include <linux/sched/task.h>
|
||||||
#include <linux/mm_types.h>
|
#include <linux/mm_types.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
@ -110,7 +111,7 @@ void die(const char *str, struct pt_regs *fp, unsigned long err)
|
||||||
dump(fp);
|
dump(fp);
|
||||||
|
|
||||||
spin_unlock_irq(&die_lock);
|
spin_unlock_irq(&die_lock);
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kstack_depth_to_print = 24;
|
static int kstack_depth_to_print = 24;
|
||||||
|
|
|
@ -52,7 +52,7 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||||
printk(" at virtual address %08lx\n", address);
|
printk(" at virtual address %08lx\n", address);
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
die("Oops", regs, error_code);
|
die("Oops", regs, error_code);
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,7 +234,7 @@ int die(const char *str, struct pt_regs *regs, long err)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
|
|
||||||
oops_exit();
|
oops_exit();
|
||||||
do_exit(err);
|
make_task_dead(err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -445,7 +445,7 @@ config ARCH_PROC_KCORE_TEXT
|
||||||
depends on PROC_KCORE
|
depends on PROC_KCORE
|
||||||
|
|
||||||
config IA64_MCA_RECOVERY
|
config IA64_MCA_RECOVERY
|
||||||
tristate "MCA recovery from errors other than TLB."
|
bool "MCA recovery from errors other than TLB."
|
||||||
|
|
||||||
config PERFMON
|
config PERFMON
|
||||||
bool "Performance monitor support"
|
bool "Performance monitor support"
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/sched/task.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
|
@ -176,7 +177,7 @@ mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
|
||||||
spin_unlock(&mca_bh_lock);
|
spin_unlock(&mca_bh_lock);
|
||||||
|
|
||||||
/* This process is about to be killed itself */
|
/* This process is about to be killed itself */
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -85,7 +85,7 @@ die (const char *str, struct pt_regs *regs, long err)
|
||||||
if (panic_on_oops)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
|
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -302,7 +302,7 @@ retry:
|
||||||
regs = NULL;
|
regs = NULL;
|
||||||
bust_spinlocks(0);
|
bust_spinlocks(0);
|
||||||
if (regs)
|
if (regs)
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
out_of_memory:
|
out_of_memory:
|
||||||
|
|
|
@ -1139,7 +1139,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
|
||||||
pr_crit("%s: %08x\n", str, nr);
|
pr_crit("%s: %08x\n", str, nr);
|
||||||
show_registers(fp);
|
show_registers(fp);
|
||||||
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
|
add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage void set_esp0(unsigned long ssp)
|
asmlinkage void set_esp0(unsigned long ssp)
|
||||||
|
|
|
@ -48,7 +48,7 @@ int send_fault_sig(struct pt_regs *regs)
|
||||||
pr_alert("Unable to handle kernel access");
|
pr_alert("Unable to handle kernel access");
|
||||||
pr_cont(" at virtual address %p\n", addr);
|
pr_cont(" at virtual address %p\n", addr);
|
||||||
die_if_kernel("Oops", regs, 0 /*error_code*/);
|
die_if_kernel("Oops", regs, 0 /*error_code*/);
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -44,10 +44,10 @@ void die(const char *str, struct pt_regs *fp, long err)
|
||||||
pr_warn("Oops: %s, sig: %ld\n", str, err);
|
pr_warn("Oops: %s, sig: %ld\n", str, err);
|
||||||
show_regs(fp);
|
show_regs(fp);
|
||||||
spin_unlock_irq(&die_lock);
|
spin_unlock_irq(&die_lock);
|
||||||
/* do_exit() should take care of panic'ing from an interrupt
|
/* make_task_dead() should take care of panic'ing from an interrupt
|
||||||
* context so we don't handle it here
|
* context so we don't handle it here
|
||||||
*/
|
*/
|
||||||
do_exit(err);
|
make_task_dead(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for user application debugging */
|
/* for user application debugging */
|
||||||
|
|
|
@ -412,7 +412,7 @@ void __noreturn die(const char *str, struct pt_regs *regs)
|
||||||
if (regs && kexec_should_crash(current))
|
if (regs && kexec_should_crash(current))
|
||||||
crash_kexec(regs);
|
crash_kexec(regs);
|
||||||
|
|
||||||
do_exit(sig);
|
make_task_dead(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct exception_table_entry __start___dbe_table[];
|
extern struct exception_table_entry __start___dbe_table[];
|
||||||
|
|
|
@ -183,7 +183,7 @@ void die(const char *str, struct pt_regs *regs, int err)
|
||||||
|
|
||||||
bust_spinlocks(0);
|
bust_spinlocks(0);
|
||||||
spin_unlock_irq(&die_lock);
|
spin_unlock_irq(&die_lock);
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(die);
|
EXPORT_SYMBOL(die);
|
||||||
|
@ -286,7 +286,7 @@ void unhandled_interruption(struct pt_regs *regs)
|
||||||
pr_emerg("unhandled_interruption\n");
|
pr_emerg("unhandled_interruption\n");
|
||||||
show_regs(regs);
|
show_regs(regs);
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
force_sig(SIGKILL, current);
|
force_sig(SIGKILL, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ void unhandled_exceptions(unsigned long entry, unsigned long addr,
|
||||||
addr, type);
|
addr, type);
|
||||||
show_regs(regs);
|
show_regs(regs);
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
force_sig(SIGKILL, current);
|
force_sig(SIGKILL, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ void do_revinsn(struct pt_regs *regs)
|
||||||
pr_emerg("Reserved Instruction\n");
|
pr_emerg("Reserved Instruction\n");
|
||||||
show_regs(regs);
|
show_regs(regs);
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
do_exit(SIGILL);
|
make_task_dead(SIGILL);
|
||||||
force_sig(SIGILL, current);
|
force_sig(SIGILL, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,10 @@ void die(const char *str, struct pt_regs *regs, long err)
|
||||||
show_regs(regs);
|
show_regs(regs);
|
||||||
spin_unlock_irq(&die_lock);
|
spin_unlock_irq(&die_lock);
|
||||||
/*
|
/*
|
||||||
* do_exit() should take care of panic'ing from an interrupt
|
* make_task_dead() should take care of panic'ing from an interrupt
|
||||||
* context so we don't handle it here
|
* context so we don't handle it here
|
||||||
*/
|
*/
|
||||||
do_exit(err);
|
make_task_dead(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr)
|
void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr)
|
||||||
|
|
|
@ -224,7 +224,7 @@ void die(const char *str, struct pt_regs *regs, long err)
|
||||||
__asm__ __volatile__("l.nop 1");
|
__asm__ __volatile__("l.nop 1");
|
||||||
do {} while (1);
|
do {} while (1);
|
||||||
#endif
|
#endif
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is normally the 'Oops' routine */
|
/* This is normally the 'Oops' routine */
|
||||||
|
|
|
@ -265,7 +265,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
|
|
||||||
oops_exit();
|
oops_exit();
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gdb uses break 4,8 */
|
/* gdb uses break 4,8 */
|
||||||
|
|
|
@ -251,7 +251,7 @@ static void oops_end(unsigned long flags, struct pt_regs *regs,
|
||||||
panic("Fatal exception in interrupt");
|
panic("Fatal exception in interrupt");
|
||||||
if (panic_on_oops)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
do_exit(signr);
|
make_task_dead(signr);
|
||||||
}
|
}
|
||||||
NOKPROBE_SYMBOL(oops_end);
|
NOKPROBE_SYMBOL(oops_end);
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ void die(struct pt_regs *regs, const char *str)
|
||||||
if (panic_on_oops)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
if (ret != NOTIFY_STOP)
|
if (ret != NOTIFY_STOP)
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_trap(struct pt_regs *regs, int signo, int code,
|
void do_trap(struct pt_regs *regs, int signo, int code,
|
||||||
|
|
|
@ -200,7 +200,7 @@ no_context:
|
||||||
(addr < PAGE_SIZE) ? "NULL pointer dereference" :
|
(addr < PAGE_SIZE) ? "NULL pointer dereference" :
|
||||||
"paging request", addr);
|
"paging request", addr);
|
||||||
die(regs, "Oops");
|
die(regs, "Oops");
|
||||||
do_exit(SIGKILL);
|
make_task_dead(SIGKILL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We ran out of memory, call the OOM killer, and return the userspace
|
* We ran out of memory, call the OOM killer, and return the userspace
|
||||||
|
|
|
@ -187,5 +187,5 @@ void die(struct pt_regs *regs, const char *str)
|
||||||
if (panic_on_oops)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception: panic_on_oops");
|
panic("Fatal exception: panic_on_oops");
|
||||||
oops_exit();
|
oops_exit();
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,7 +179,7 @@ void s390_handle_mcck(void)
|
||||||
"malfunction (code 0x%016lx).\n", mcck.mcck_code);
|
"malfunction (code 0x%016lx).\n", mcck.mcck_code);
|
||||||
printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
|
printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
|
||||||
current->comm, current->pid);
|
current->comm, current->pid);
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(s390_handle_mcck);
|
EXPORT_SYMBOL_GPL(s390_handle_mcck);
|
||||||
|
|
|
@ -57,7 +57,7 @@ void die(const char *str, struct pt_regs *regs, long err)
|
||||||
if (panic_on_oops)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
|
|
||||||
do_exit(SIGSEGV);
|
make_task_dead(SIGSEGV);
|
||||||
}
|
}
|
||||||
|
|
||||||
void die_if_kernel(const char *str, struct pt_regs *regs, long err)
|
void die_if_kernel(const char *str, struct pt_regs *regs, long err)
|
||||||
|
|
|
@ -86,9 +86,7 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
printk("Instruction DUMP:");
|
printk("Instruction DUMP:");
|
||||||
instruction_dump ((unsigned long *) regs->pc);
|
instruction_dump ((unsigned long *) regs->pc);
|
||||||
if(regs->psr & PSR_PS)
|
make_task_dead((regs->psr & PSR_PS) ? SIGKILL : SIGSEGV);
|
||||||
do_exit(SIGKILL);
|
|
||||||
do_exit(SIGSEGV);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_hw_interrupt(struct pt_regs *regs, unsigned long type)
|
void do_hw_interrupt(struct pt_regs *regs, unsigned long type)
|
||||||
|
|
|
@ -2565,9 +2565,7 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
if (panic_on_oops)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
if (regs->tstate & TSTATE_PRIV)
|
make_task_dead((regs->tstate & TSTATE_PRIV)? SIGKILL : SIGSEGV);
|
||||||
do_exit(SIGKILL);
|
|
||||||
do_exit(SIGSEGV);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(die_if_kernel);
|
EXPORT_SYMBOL(die_if_kernel);
|
||||||
|
|
||||||
|
|
|
@ -1500,13 +1500,13 @@ ENTRY(async_page_fault)
|
||||||
END(async_page_fault)
|
END(async_page_fault)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ENTRY(rewind_stack_do_exit)
|
ENTRY(rewind_stack_and_make_dead)
|
||||||
/* Prevent any naive code from trying to unwind to our caller. */
|
/* Prevent any naive code from trying to unwind to our caller. */
|
||||||
xorl %ebp, %ebp
|
xorl %ebp, %ebp
|
||||||
|
|
||||||
movl PER_CPU_VAR(cpu_current_top_of_stack), %esi
|
movl PER_CPU_VAR(cpu_current_top_of_stack), %esi
|
||||||
leal -TOP_OF_KERNEL_STACK_PADDING-PTREGS_SIZE(%esi), %esp
|
leal -TOP_OF_KERNEL_STACK_PADDING-PTREGS_SIZE(%esi), %esp
|
||||||
|
|
||||||
call do_exit
|
call make_task_dead
|
||||||
1: jmp 1b
|
1: jmp 1b
|
||||||
END(rewind_stack_do_exit)
|
END(rewind_stack_and_make_dead)
|
||||||
|
|
|
@ -1759,10 +1759,10 @@ END(nmi)
|
||||||
ENTRY(ignore_sysret)
|
ENTRY(ignore_sysret)
|
||||||
UNWIND_HINT_EMPTY
|
UNWIND_HINT_EMPTY
|
||||||
mov $-ENOSYS, %eax
|
mov $-ENOSYS, %eax
|
||||||
sysret
|
sysretl
|
||||||
END(ignore_sysret)
|
END(ignore_sysret)
|
||||||
|
|
||||||
ENTRY(rewind_stack_do_exit)
|
ENTRY(rewind_stack_and_make_dead)
|
||||||
UNWIND_HINT_FUNC
|
UNWIND_HINT_FUNC
|
||||||
/* Prevent any naive code from trying to unwind to our caller. */
|
/* Prevent any naive code from trying to unwind to our caller. */
|
||||||
xorl %ebp, %ebp
|
xorl %ebp, %ebp
|
||||||
|
@ -1771,5 +1771,5 @@ ENTRY(rewind_stack_do_exit)
|
||||||
leaq -PTREGS_SIZE(%rax), %rsp
|
leaq -PTREGS_SIZE(%rax), %rsp
|
||||||
UNWIND_HINT_REGS
|
UNWIND_HINT_REGS
|
||||||
|
|
||||||
call do_exit
|
call make_task_dead
|
||||||
END(rewind_stack_do_exit)
|
END(rewind_stack_and_make_dead)
|
||||||
|
|
|
@ -326,7 +326,7 @@ unsigned long oops_begin(void)
|
||||||
}
|
}
|
||||||
NOKPROBE_SYMBOL(oops_begin);
|
NOKPROBE_SYMBOL(oops_begin);
|
||||||
|
|
||||||
void __noreturn rewind_stack_do_exit(int signr);
|
void __noreturn rewind_stack_and_make_dead(int signr);
|
||||||
|
|
||||||
void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
|
void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
|
||||||
{
|
{
|
||||||
|
@ -361,7 +361,7 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
|
||||||
* reuse the task stack and that existing poisons are invalid.
|
* reuse the task stack and that existing poisons are invalid.
|
||||||
*/
|
*/
|
||||||
kasan_unpoison_task_stack(current);
|
kasan_unpoison_task_stack(current);
|
||||||
rewind_stack_do_exit(signr);
|
rewind_stack_and_make_dead(signr);
|
||||||
}
|
}
|
||||||
NOKPROBE_SYMBOL(oops_end);
|
NOKPROBE_SYMBOL(oops_end);
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ static void make_8259A_irq(unsigned int irq)
|
||||||
disable_irq_nosync(irq);
|
disable_irq_nosync(irq);
|
||||||
io_apic_irqs &= ~(1<<irq);
|
io_apic_irqs &= ~(1<<irq);
|
||||||
irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
|
irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
|
||||||
|
irq_set_status_flags(irq, IRQ_LEVEL);
|
||||||
enable_irq(irq);
|
enable_irq(irq);
|
||||||
lapic_assign_legacy_vector(irq, true);
|
lapic_assign_legacy_vector(irq, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,8 +72,10 @@ void __init init_ISA_irqs(void)
|
||||||
|
|
||||||
legacy_pic->init(0);
|
legacy_pic->init(0);
|
||||||
|
|
||||||
for (i = 0; i < nr_legacy_irqs(); i++)
|
for (i = 0; i < nr_legacy_irqs(); i++) {
|
||||||
irq_set_chip_and_handler(i, chip, handle_level_irq);
|
irq_set_chip_and_handler(i, chip, handle_level_irq);
|
||||||
|
irq_set_status_flags(i, IRQ_LEVEL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init init_IRQ(void)
|
void __init init_IRQ(void)
|
||||||
|
|
|
@ -22,6 +22,6 @@
|
||||||
*/
|
*/
|
||||||
ENTRY(__iowrite32_copy)
|
ENTRY(__iowrite32_copy)
|
||||||
movl %edx,%ecx
|
movl %edx,%ecx
|
||||||
rep movsd
|
rep movsl
|
||||||
ret
|
ret
|
||||||
ENDPROC(__iowrite32_copy)
|
ENDPROC(__iowrite32_copy)
|
||||||
|
|
|
@ -542,5 +542,5 @@ void die(const char * str, struct pt_regs * regs, long err)
|
||||||
if (panic_on_oops)
|
if (panic_on_oops)
|
||||||
panic("Fatal exception");
|
panic("Fatal exception");
|
||||||
|
|
||||||
do_exit(err);
|
make_task_dead(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2180,10 +2180,7 @@ static inline bool bio_check_ro(struct bio *bio, struct hd_struct *part)
|
||||||
|
|
||||||
if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
|
if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
|
||||||
return false;
|
return false;
|
||||||
|
pr_warn("Trying to write to read-only block-device %s (partno %d)\n",
|
||||||
WARN_ONCE(1,
|
|
||||||
"generic_make_request: Trying to write "
|
|
||||||
"to read-only block-device %s (partno %d)\n",
|
|
||||||
bio_devname(bio, b), part->partno);
|
bio_devname(bio, b), part->partno);
|
||||||
/* Older lvm-tools actually trigger this */
|
/* Older lvm-tools actually trigger this */
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -223,7 +223,8 @@ static int dma_chan_get(struct dma_chan *chan)
|
||||||
/* The channel is already in use, update client count */
|
/* The channel is already in use, update client count */
|
||||||
if (chan->client_count) {
|
if (chan->client_count) {
|
||||||
__module_get(owner);
|
__module_get(owner);
|
||||||
goto out;
|
chan->client_count++;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!try_module_get(owner))
|
if (!try_module_get(owner))
|
||||||
|
@ -236,11 +237,11 @@ static int dma_chan_get(struct dma_chan *chan)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chan->client_count++;
|
||||||
|
|
||||||
if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask))
|
if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask))
|
||||||
balance_ref_count(chan);
|
balance_ref_count(chan);
|
||||||
|
|
||||||
out:
|
|
||||||
chan->client_count++;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
|
|
@ -1347,10 +1347,12 @@ static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
|
||||||
sdma_config_ownership(sdmac, false, true, false);
|
sdma_config_ownership(sdmac, false, true, false);
|
||||||
|
|
||||||
if (sdma_load_context(sdmac))
|
if (sdma_load_context(sdmac))
|
||||||
goto err_desc_out;
|
goto err_bd_out;
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
|
|
||||||
|
err_bd_out:
|
||||||
|
sdma_free_bd(desc);
|
||||||
err_desc_out:
|
err_desc_out:
|
||||||
kfree(desc);
|
kfree(desc);
|
||||||
err_out:
|
err_out:
|
||||||
|
|
|
@ -164,7 +164,9 @@
|
||||||
#define XILINX_DMA_REG_BTT 0x28
|
#define XILINX_DMA_REG_BTT 0x28
|
||||||
|
|
||||||
/* AXI DMA Specific Masks/Bit fields */
|
/* AXI DMA Specific Masks/Bit fields */
|
||||||
#define XILINX_DMA_MAX_TRANS_LEN GENMASK(22, 0)
|
#define XILINX_DMA_MAX_TRANS_LEN_MIN 8
|
||||||
|
#define XILINX_DMA_MAX_TRANS_LEN_MAX 23
|
||||||
|
#define XILINX_DMA_V2_MAX_TRANS_LEN_MAX 26
|
||||||
#define XILINX_DMA_CR_COALESCE_MAX GENMASK(23, 16)
|
#define XILINX_DMA_CR_COALESCE_MAX GENMASK(23, 16)
|
||||||
#define XILINX_DMA_CR_CYCLIC_BD_EN_MASK BIT(4)
|
#define XILINX_DMA_CR_CYCLIC_BD_EN_MASK BIT(4)
|
||||||
#define XILINX_DMA_CR_COALESCE_SHIFT 16
|
#define XILINX_DMA_CR_COALESCE_SHIFT 16
|
||||||
|
@ -428,6 +430,7 @@ struct xilinx_dma_config {
|
||||||
* @rxs_clk: DMA s2mm stream clock
|
* @rxs_clk: DMA s2mm stream clock
|
||||||
* @nr_channels: Number of channels DMA device supports
|
* @nr_channels: Number of channels DMA device supports
|
||||||
* @chan_id: DMA channel identifier
|
* @chan_id: DMA channel identifier
|
||||||
|
* @max_buffer_len: Max buffer length
|
||||||
*/
|
*/
|
||||||
struct xilinx_dma_device {
|
struct xilinx_dma_device {
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
|
@ -447,6 +450,7 @@ struct xilinx_dma_device {
|
||||||
struct clk *rxs_clk;
|
struct clk *rxs_clk;
|
||||||
u32 nr_channels;
|
u32 nr_channels;
|
||||||
u32 chan_id;
|
u32 chan_id;
|
||||||
|
u32 max_buffer_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Macros */
|
/* Macros */
|
||||||
|
@ -969,6 +973,25 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xilinx_dma_calc_copysize - Calculate the amount of data to copy
|
||||||
|
* @chan: Driver specific DMA channel
|
||||||
|
* @size: Total data that needs to be copied
|
||||||
|
* @done: Amount of data that has been already copied
|
||||||
|
*
|
||||||
|
* Return: Amount of data that has to be copied
|
||||||
|
*/
|
||||||
|
static int xilinx_dma_calc_copysize(struct xilinx_dma_chan *chan,
|
||||||
|
int size, int done)
|
||||||
|
{
|
||||||
|
size_t copy;
|
||||||
|
|
||||||
|
copy = min_t(size_t, size - done,
|
||||||
|
chan->xdev->max_buffer_len);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xilinx_dma_tx_status - Get DMA transaction status
|
* xilinx_dma_tx_status - Get DMA transaction status
|
||||||
* @dchan: DMA channel
|
* @dchan: DMA channel
|
||||||
|
@ -1002,7 +1025,7 @@ static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan,
|
||||||
list_for_each_entry(segment, &desc->segments, node) {
|
list_for_each_entry(segment, &desc->segments, node) {
|
||||||
hw = &segment->hw;
|
hw = &segment->hw;
|
||||||
residue += (hw->control - hw->status) &
|
residue += (hw->control - hw->status) &
|
||||||
XILINX_DMA_MAX_TRANS_LEN;
|
chan->xdev->max_buffer_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&chan->lock, flags);
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
@ -1262,7 +1285,7 @@ static void xilinx_cdma_start_transfer(struct xilinx_dma_chan *chan)
|
||||||
|
|
||||||
/* Start the transfer */
|
/* Start the transfer */
|
||||||
dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
|
dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
|
||||||
hw->control & XILINX_DMA_MAX_TRANS_LEN);
|
hw->control & chan->xdev->max_buffer_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_splice_tail_init(&chan->pending_list, &chan->active_list);
|
list_splice_tail_init(&chan->pending_list, &chan->active_list);
|
||||||
|
@ -1365,7 +1388,7 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
|
||||||
|
|
||||||
/* Start the transfer */
|
/* Start the transfer */
|
||||||
dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
|
dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
|
||||||
hw->control & XILINX_DMA_MAX_TRANS_LEN);
|
hw->control & chan->xdev->max_buffer_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_splice_tail_init(&chan->pending_list, &chan->active_list);
|
list_splice_tail_init(&chan->pending_list, &chan->active_list);
|
||||||
|
@ -1729,7 +1752,7 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
|
||||||
struct xilinx_cdma_tx_segment *segment;
|
struct xilinx_cdma_tx_segment *segment;
|
||||||
struct xilinx_cdma_desc_hw *hw;
|
struct xilinx_cdma_desc_hw *hw;
|
||||||
|
|
||||||
if (!len || len > XILINX_DMA_MAX_TRANS_LEN)
|
if (!len || len > chan->xdev->max_buffer_len)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
desc = xilinx_dma_alloc_tx_descriptor(chan);
|
desc = xilinx_dma_alloc_tx_descriptor(chan);
|
||||||
|
@ -1819,8 +1842,8 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
|
||||||
* Calculate the maximum number of bytes to transfer,
|
* Calculate the maximum number of bytes to transfer,
|
||||||
* making sure it is less than the hw limit
|
* making sure it is less than the hw limit
|
||||||
*/
|
*/
|
||||||
copy = min_t(size_t, sg_dma_len(sg) - sg_used,
|
copy = xilinx_dma_calc_copysize(chan, sg_dma_len(sg),
|
||||||
XILINX_DMA_MAX_TRANS_LEN);
|
sg_used);
|
||||||
hw = &segment->hw;
|
hw = &segment->hw;
|
||||||
|
|
||||||
/* Fill in the descriptor */
|
/* Fill in the descriptor */
|
||||||
|
@ -1924,8 +1947,8 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic(
|
||||||
* Calculate the maximum number of bytes to transfer,
|
* Calculate the maximum number of bytes to transfer,
|
||||||
* making sure it is less than the hw limit
|
* making sure it is less than the hw limit
|
||||||
*/
|
*/
|
||||||
copy = min_t(size_t, period_len - sg_used,
|
copy = xilinx_dma_calc_copysize(chan, period_len,
|
||||||
XILINX_DMA_MAX_TRANS_LEN);
|
sg_used);
|
||||||
hw = &segment->hw;
|
hw = &segment->hw;
|
||||||
xilinx_axidma_buf(chan, hw, buf_addr, sg_used,
|
xilinx_axidma_buf(chan, hw, buf_addr, sg_used,
|
||||||
period_len * i);
|
period_len * i);
|
||||||
|
@ -2613,7 +2636,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
|
||||||
struct xilinx_dma_device *xdev;
|
struct xilinx_dma_device *xdev;
|
||||||
struct device_node *child, *np = pdev->dev.of_node;
|
struct device_node *child, *np = pdev->dev.of_node;
|
||||||
struct resource *io;
|
struct resource *io;
|
||||||
u32 num_frames, addr_width;
|
u32 num_frames, addr_width, len_width;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
/* Allocate and initialize the DMA engine structure */
|
/* Allocate and initialize the DMA engine structure */
|
||||||
|
@ -2640,13 +2663,30 @@ static int xilinx_dma_probe(struct platform_device *pdev)
|
||||||
/* Request and map I/O memory */
|
/* Request and map I/O memory */
|
||||||
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
xdev->regs = devm_ioremap_resource(&pdev->dev, io);
|
xdev->regs = devm_ioremap_resource(&pdev->dev, io);
|
||||||
if (IS_ERR(xdev->regs))
|
if (IS_ERR(xdev->regs)) {
|
||||||
return PTR_ERR(xdev->regs);
|
err = PTR_ERR(xdev->regs);
|
||||||
|
goto disable_clks;
|
||||||
|
}
|
||||||
/* Retrieve the DMA engine properties from the device tree */
|
/* Retrieve the DMA engine properties from the device tree */
|
||||||
xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
|
xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
|
||||||
if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
|
xdev->max_buffer_len = GENMASK(XILINX_DMA_MAX_TRANS_LEN_MAX - 1, 0);
|
||||||
|
|
||||||
|
if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
|
||||||
xdev->mcdma = of_property_read_bool(node, "xlnx,mcdma");
|
xdev->mcdma = of_property_read_bool(node, "xlnx,mcdma");
|
||||||
|
if (!of_property_read_u32(node, "xlnx,sg-length-width",
|
||||||
|
&len_width)) {
|
||||||
|
if (len_width < XILINX_DMA_MAX_TRANS_LEN_MIN ||
|
||||||
|
len_width > XILINX_DMA_V2_MAX_TRANS_LEN_MAX) {
|
||||||
|
dev_warn(xdev->dev,
|
||||||
|
"invalid xlnx,sg-length-width property value. Using default width\n");
|
||||||
|
} else {
|
||||||
|
if (len_width > XILINX_DMA_MAX_TRANS_LEN_MAX)
|
||||||
|
dev_warn(xdev->dev, "Please ensure that IP supports buffer length > 23 bits\n");
|
||||||
|
xdev->max_buffer_len =
|
||||||
|
GENMASK(len_width - 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
|
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
|
||||||
err = of_property_read_u32(node, "xlnx,num-fstores",
|
err = of_property_read_u32(node, "xlnx,num-fstores",
|
||||||
|
@ -2719,8 +2759,10 @@ static int xilinx_dma_probe(struct platform_device *pdev)
|
||||||
/* Initialize the channels */
|
/* Initialize the channels */
|
||||||
for_each_child_of_node(node, child) {
|
for_each_child_of_node(node, child) {
|
||||||
err = xilinx_dma_child_probe(xdev, child);
|
err = xilinx_dma_child_probe(xdev, child);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
goto disable_clks;
|
of_node_put(child);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
|
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
|
||||||
|
@ -2753,12 +2795,12 @@ static int xilinx_dma_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
disable_clks:
|
|
||||||
xdma_disable_allclks(xdev);
|
|
||||||
error:
|
error:
|
||||||
for (i = 0; i < xdev->nr_channels; i++)
|
for (i = 0; i < xdev->nr_channels; i++)
|
||||||
if (xdev->chan[i])
|
if (xdev->chan[i])
|
||||||
xilinx_dma_chan_remove(xdev->chan[i]);
|
xilinx_dma_chan_remove(xdev->chan[i]);
|
||||||
|
disable_clks:
|
||||||
|
xdma_disable_allclks(xdev);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
static DEFINE_MUTEX(device_ctls_mutex);
|
static DEFINE_MUTEX(device_ctls_mutex);
|
||||||
static LIST_HEAD(edac_device_list);
|
static LIST_HEAD(edac_device_list);
|
||||||
|
|
||||||
|
/* Default workqueue processing interval on this instance, in msecs */
|
||||||
|
#define DEFAULT_POLL_INTERVAL 1000
|
||||||
|
|
||||||
#ifdef CONFIG_EDAC_DEBUG
|
#ifdef CONFIG_EDAC_DEBUG
|
||||||
static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
|
static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
|
||||||
{
|
{
|
||||||
|
@ -366,7 +369,7 @@ static void edac_device_workq_function(struct work_struct *work_req)
|
||||||
* whole one second to save timers firing all over the period
|
* whole one second to save timers firing all over the period
|
||||||
* between integral seconds
|
* between integral seconds
|
||||||
*/
|
*/
|
||||||
if (edac_dev->poll_msec == 1000)
|
if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
|
||||||
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
||||||
else
|
else
|
||||||
edac_queue_work(&edac_dev->work, edac_dev->delay);
|
edac_queue_work(&edac_dev->work, edac_dev->delay);
|
||||||
|
@ -396,7 +399,7 @@ static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
|
||||||
* timers firing on sub-second basis, while they are happy
|
* timers firing on sub-second basis, while they are happy
|
||||||
* to fire together on the 1 second exactly
|
* to fire together on the 1 second exactly
|
||||||
*/
|
*/
|
||||||
if (edac_dev->poll_msec == 1000)
|
if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
|
||||||
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
||||||
else
|
else
|
||||||
edac_queue_work(&edac_dev->work, edac_dev->delay);
|
edac_queue_work(&edac_dev->work, edac_dev->delay);
|
||||||
|
@ -430,7 +433,7 @@ void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
|
||||||
edac_dev->delay = msecs_to_jiffies(msec);
|
edac_dev->delay = msecs_to_jiffies(msec);
|
||||||
|
|
||||||
/* See comment in edac_device_workq_setup() above */
|
/* See comment in edac_device_workq_setup() above */
|
||||||
if (edac_dev->poll_msec == 1000)
|
if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
|
||||||
edac_mod_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
edac_mod_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
||||||
else
|
else
|
||||||
edac_mod_work(&edac_dev->work, edac_dev->delay);
|
edac_mod_work(&edac_dev->work, edac_dev->delay);
|
||||||
|
@ -472,11 +475,7 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
|
||||||
/* This instance is NOW RUNNING */
|
/* This instance is NOW RUNNING */
|
||||||
edac_dev->op_state = OP_RUNNING_POLL;
|
edac_dev->op_state = OP_RUNNING_POLL;
|
||||||
|
|
||||||
/*
|
edac_device_workq_setup(edac_dev, edac_dev->poll_msec ?: DEFAULT_POLL_INTERVAL);
|
||||||
* enable workq processing on this instance,
|
|
||||||
* default = 1000 msec
|
|
||||||
*/
|
|
||||||
edac_device_workq_setup(edac_dev, 1000);
|
|
||||||
} else {
|
} else {
|
||||||
edac_dev->op_state = OP_RUNNING_INTERRUPT;
|
edac_dev->op_state = OP_RUNNING_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,8 +185,10 @@ static int highbank_mc_probe(struct platform_device *pdev)
|
||||||
drvdata = mci->pvt_info;
|
drvdata = mci->pvt_info;
|
||||||
platform_set_drvdata(pdev, mci);
|
platform_set_drvdata(pdev, mci);
|
||||||
|
|
||||||
if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL))
|
if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
|
||||||
return -ENOMEM;
|
res = -ENOMEM;
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
|
|
||||||
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
|
@ -254,6 +256,7 @@ err2:
|
||||||
edac_mc_del_mc(&pdev->dev);
|
edac_mc_del_mc(&pdev->dev);
|
||||||
err:
|
err:
|
||||||
devres_release_group(&pdev->dev, NULL);
|
devres_release_group(&pdev->dev, NULL);
|
||||||
|
free:
|
||||||
edac_mc_free(mci);
|
edac_mc_free(mci);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4116,7 +4116,18 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
|
||||||
bool bret;
|
bool bret;
|
||||||
|
|
||||||
if (intel_dp->is_mst) {
|
if (intel_dp->is_mst) {
|
||||||
u8 esi[DP_DPRX_ESI_LEN] = { 0 };
|
/*
|
||||||
|
* The +2 is because DP_DPRX_ESI_LEN is 14, but we then
|
||||||
|
* pass in "esi+10" to drm_dp_channel_eq_ok(), which
|
||||||
|
* takes a 6-byte array. So we actually need 16 bytes
|
||||||
|
* here.
|
||||||
|
*
|
||||||
|
* Somebody who knows what the limits actually are
|
||||||
|
* should check this, but for now this is at least
|
||||||
|
* harmless and avoids a valid compiler warning about
|
||||||
|
* using more of the array than we have allocated.
|
||||||
|
*/
|
||||||
|
u8 esi[DP_DPRX_ESI_LEN+2] = { 0 };
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int retry;
|
int retry;
|
||||||
bool handled;
|
bool handled;
|
||||||
|
|
|
@ -63,7 +63,6 @@ static int betopff_init(struct hid_device *hid)
|
||||||
struct list_head *report_list =
|
struct list_head *report_list =
|
||||||
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
|
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
|
||||||
struct input_dev *dev;
|
struct input_dev *dev;
|
||||||
int field_count = 0;
|
|
||||||
int error;
|
int error;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
|
@ -89,19 +88,21 @@ static int betopff_init(struct hid_device *hid)
|
||||||
* -----------------------------------------
|
* -----------------------------------------
|
||||||
* Do init them with default value.
|
* Do init them with default value.
|
||||||
*/
|
*/
|
||||||
|
if (report->maxfield < 4) {
|
||||||
|
hid_err(hid, "not enough fields in the report: %d\n",
|
||||||
|
report->maxfield);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
for (i = 0; i < report->maxfield; i++) {
|
for (i = 0; i < report->maxfield; i++) {
|
||||||
|
if (report->field[i]->report_count < 1) {
|
||||||
|
hid_err(hid, "no values in the field\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
for (j = 0; j < report->field[i]->report_count; j++) {
|
for (j = 0; j < report->field[i]->report_count; j++) {
|
||||||
report->field[i]->value[j] = 0x00;
|
report->field[i]->value[j] = 0x00;
|
||||||
field_count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field_count < 4) {
|
|
||||||
hid_err(hid, "not enough fields in the report: %d\n",
|
|
||||||
field_count);
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
betopff = kzalloc(sizeof(*betopff), GFP_KERNEL);
|
betopff = kzalloc(sizeof(*betopff), GFP_KERNEL);
|
||||||
if (!betopff)
|
if (!betopff)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -980,8 +980,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid,
|
||||||
* Validating on id 0 means we should examine the first
|
* Validating on id 0 means we should examine the first
|
||||||
* report in the list.
|
* report in the list.
|
||||||
*/
|
*/
|
||||||
report = list_entry(
|
report = list_first_entry_or_null(
|
||||||
hid->report_enum[type].report_list.next,
|
&hid->report_enum[type].report_list,
|
||||||
struct hid_report, list);
|
struct hid_report, list);
|
||||||
} else {
|
} else {
|
||||||
report = hid->report_enum[type].report_id_hash[id];
|
report = hid->report_enum[type].report_id_hash[id];
|
||||||
|
|
|
@ -113,6 +113,11 @@ void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev,
|
||||||
int required_slots = (size / DMA_SLOT_SIZE)
|
int required_slots = (size / DMA_SLOT_SIZE)
|
||||||
+ 1 * (size % DMA_SLOT_SIZE != 0);
|
+ 1 * (size % DMA_SLOT_SIZE != 0);
|
||||||
|
|
||||||
|
if (!dev->ishtp_dma_tx_map) {
|
||||||
|
dev_err(dev->devc, "Fail to allocate Tx map\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
|
spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
|
||||||
for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) {
|
for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) {
|
||||||
free = 1;
|
free = 1;
|
||||||
|
@ -159,6 +164,11 @@ void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!dev->ishtp_dma_tx_map) {
|
||||||
|
dev_err(dev->devc, "Fail to allocate Tx map\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE;
|
i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE;
|
||||||
spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
|
spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
|
||||||
for (j = 0; j < acked_slots; j++) {
|
for (j = 0; j < acked_slots; j++) {
|
||||||
|
|
|
@ -325,6 +325,8 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
|
||||||
|
|
||||||
if (!PAGE_ALIGNED(tinfo->vaddr))
|
if (!PAGE_ALIGNED(tinfo->vaddr))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (tinfo->length == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
tidbuf = kzalloc(sizeof(*tidbuf), GFP_KERNEL);
|
tidbuf = kzalloc(sizeof(*tidbuf), GFP_KERNEL);
|
||||||
if (!tidbuf)
|
if (!tidbuf)
|
||||||
|
@ -335,40 +337,38 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
|
||||||
tidbuf->psets = kcalloc(uctxt->expected_count, sizeof(*tidbuf->psets),
|
tidbuf->psets = kcalloc(uctxt->expected_count, sizeof(*tidbuf->psets),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!tidbuf->psets) {
|
if (!tidbuf->psets) {
|
||||||
kfree(tidbuf);
|
ret = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto fail_release_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
pinned = pin_rcv_pages(fd, tidbuf);
|
pinned = pin_rcv_pages(fd, tidbuf);
|
||||||
if (pinned <= 0) {
|
if (pinned <= 0) {
|
||||||
kfree(tidbuf->psets);
|
ret = (pinned < 0) ? pinned : -ENOSPC;
|
||||||
kfree(tidbuf);
|
goto fail_unpin;
|
||||||
return pinned;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find sets of physically contiguous pages */
|
/* Find sets of physically contiguous pages */
|
||||||
tidbuf->n_psets = find_phys_blocks(tidbuf, pinned);
|
tidbuf->n_psets = find_phys_blocks(tidbuf, pinned);
|
||||||
|
|
||||||
/*
|
/* Reserve the number of expected tids to be used. */
|
||||||
* We don't need to access this under a lock since tid_used is per
|
|
||||||
* process and the same process cannot be in hfi1_user_exp_rcv_clear()
|
|
||||||
* and hfi1_user_exp_rcv_setup() at the same time.
|
|
||||||
*/
|
|
||||||
spin_lock(&fd->tid_lock);
|
spin_lock(&fd->tid_lock);
|
||||||
if (fd->tid_used + tidbuf->n_psets > fd->tid_limit)
|
if (fd->tid_used + tidbuf->n_psets > fd->tid_limit)
|
||||||
pageset_count = fd->tid_limit - fd->tid_used;
|
pageset_count = fd->tid_limit - fd->tid_used;
|
||||||
else
|
else
|
||||||
pageset_count = tidbuf->n_psets;
|
pageset_count = tidbuf->n_psets;
|
||||||
|
fd->tid_used += pageset_count;
|
||||||
spin_unlock(&fd->tid_lock);
|
spin_unlock(&fd->tid_lock);
|
||||||
|
|
||||||
if (!pageset_count)
|
if (!pageset_count) {
|
||||||
goto bail;
|
ret = -ENOSPC;
|
||||||
|
goto fail_unreserve;
|
||||||
|
}
|
||||||
|
|
||||||
ngroups = pageset_count / dd->rcv_entries.group_size;
|
ngroups = pageset_count / dd->rcv_entries.group_size;
|
||||||
tidlist = kcalloc(pageset_count, sizeof(*tidlist), GFP_KERNEL);
|
tidlist = kcalloc(pageset_count, sizeof(*tidlist), GFP_KERNEL);
|
||||||
if (!tidlist) {
|
if (!tidlist) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto nomem;
|
goto fail_unreserve;
|
||||||
}
|
}
|
||||||
|
|
||||||
tididx = 0;
|
tididx = 0;
|
||||||
|
@ -464,43 +464,60 @@ int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
|
||||||
}
|
}
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&uctxt->exp_mutex);
|
mutex_unlock(&uctxt->exp_mutex);
|
||||||
nomem:
|
|
||||||
hfi1_cdbg(TID, "total mapped: tidpairs:%u pages:%u (%d)", tididx,
|
hfi1_cdbg(TID, "total mapped: tidpairs:%u pages:%u (%d)", tididx,
|
||||||
mapped_pages, ret);
|
mapped_pages, ret);
|
||||||
if (tididx) {
|
|
||||||
spin_lock(&fd->tid_lock);
|
|
||||||
fd->tid_used += tididx;
|
|
||||||
spin_unlock(&fd->tid_lock);
|
|
||||||
tinfo->tidcnt = tididx;
|
|
||||||
tinfo->length = mapped_pages * PAGE_SIZE;
|
|
||||||
|
|
||||||
if (copy_to_user(u64_to_user_ptr(tinfo->tidlist),
|
/* fail if nothing was programmed, set error if none provided */
|
||||||
tidlist, sizeof(tidlist[0]) * tididx)) {
|
if (tididx == 0) {
|
||||||
/*
|
if (ret >= 0)
|
||||||
* On failure to copy to the user level, we need to undo
|
ret = -ENOSPC;
|
||||||
* everything done so far so we don't leak resources.
|
goto fail_unreserve;
|
||||||
*/
|
}
|
||||||
tinfo->tidlist = (unsigned long)&tidlist;
|
|
||||||
hfi1_user_exp_rcv_clear(fd, tinfo);
|
/* adjust reserved tid_used to actual count */
|
||||||
tinfo->tidlist = 0;
|
spin_lock(&fd->tid_lock);
|
||||||
ret = -EFAULT;
|
fd->tid_used -= pageset_count - tididx;
|
||||||
goto bail;
|
spin_unlock(&fd->tid_lock);
|
||||||
}
|
|
||||||
|
/* unpin all pages not covered by a TID */
|
||||||
|
unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages, pinned - mapped_pages,
|
||||||
|
false);
|
||||||
|
|
||||||
|
tinfo->tidcnt = tididx;
|
||||||
|
tinfo->length = mapped_pages * PAGE_SIZE;
|
||||||
|
|
||||||
|
if (copy_to_user(u64_to_user_ptr(tinfo->tidlist),
|
||||||
|
tidlist, sizeof(tidlist[0]) * tididx)) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto fail_unprogram;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If not everything was mapped (due to insufficient RcvArray entries,
|
|
||||||
* for example), unpin all unmapped pages so we can pin them nex time.
|
|
||||||
*/
|
|
||||||
if (mapped_pages != pinned)
|
|
||||||
unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages,
|
|
||||||
(pinned - mapped_pages), false);
|
|
||||||
bail:
|
|
||||||
kfree(tidbuf->psets);
|
|
||||||
kfree(tidlist);
|
|
||||||
kfree(tidbuf->pages);
|
kfree(tidbuf->pages);
|
||||||
|
kfree(tidbuf->psets);
|
||||||
kfree(tidbuf);
|
kfree(tidbuf);
|
||||||
return ret > 0 ? 0 : ret;
|
kfree(tidlist);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_unprogram:
|
||||||
|
/* unprogram, unmap, and unpin all allocated TIDs */
|
||||||
|
tinfo->tidlist = (unsigned long)tidlist;
|
||||||
|
hfi1_user_exp_rcv_clear(fd, tinfo);
|
||||||
|
tinfo->tidlist = 0;
|
||||||
|
pinned = 0; /* nothing left to unpin */
|
||||||
|
pageset_count = 0; /* nothing left reserved */
|
||||||
|
fail_unreserve:
|
||||||
|
spin_lock(&fd->tid_lock);
|
||||||
|
fd->tid_used -= pageset_count;
|
||||||
|
spin_unlock(&fd->tid_lock);
|
||||||
|
fail_unpin:
|
||||||
|
if (pinned > 0)
|
||||||
|
unpin_rcv_pages(fd, tidbuf, NULL, 0, pinned, false);
|
||||||
|
fail_release_mem:
|
||||||
|
kfree(tidbuf->pages);
|
||||||
|
kfree(tidbuf->psets);
|
||||||
|
kfree(tidbuf);
|
||||||
|
kfree(tidlist);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
|
int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
|
||||||
|
|
|
@ -192,7 +192,6 @@ static const char * const smbus_pnp_ids[] = {
|
||||||
"SYN3221", /* HP 15-ay000 */
|
"SYN3221", /* HP 15-ay000 */
|
||||||
"SYN323d", /* HP Spectre X360 13-w013dx */
|
"SYN323d", /* HP Spectre X360 13-w013dx */
|
||||||
"SYN3257", /* HP Envy 13-ad105ng */
|
"SYN3257", /* HP Envy 13-ad105ng */
|
||||||
"SYN3286", /* HP Laptop 15-da3001TU */
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -524,19 +524,28 @@ static void xgbe_disable_vxlan(struct xgbe_prv_data *pdata)
|
||||||
netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration disabled\n");
|
netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration disabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int xgbe_get_fc_queue_count(struct xgbe_prv_data *pdata)
|
||||||
|
{
|
||||||
|
unsigned int max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
|
||||||
|
|
||||||
|
/* From MAC ver 30H the TFCR is per priority, instead of per queue */
|
||||||
|
if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) >= 0x30)
|
||||||
|
return max_q_count;
|
||||||
|
else
|
||||||
|
return min_t(unsigned int, pdata->tx_q_count, max_q_count);
|
||||||
|
}
|
||||||
|
|
||||||
static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
|
static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
|
||||||
{
|
{
|
||||||
unsigned int max_q_count, q_count;
|
|
||||||
unsigned int reg, reg_val;
|
unsigned int reg, reg_val;
|
||||||
unsigned int i;
|
unsigned int i, q_count;
|
||||||
|
|
||||||
/* Clear MTL flow control */
|
/* Clear MTL flow control */
|
||||||
for (i = 0; i < pdata->rx_q_count; i++)
|
for (i = 0; i < pdata->rx_q_count; i++)
|
||||||
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
|
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
|
||||||
|
|
||||||
/* Clear MAC flow control */
|
/* Clear MAC flow control */
|
||||||
max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
|
q_count = xgbe_get_fc_queue_count(pdata);
|
||||||
q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
|
|
||||||
reg = MAC_Q0TFCR;
|
reg = MAC_Q0TFCR;
|
||||||
for (i = 0; i < q_count; i++) {
|
for (i = 0; i < q_count; i++) {
|
||||||
reg_val = XGMAC_IOREAD(pdata, reg);
|
reg_val = XGMAC_IOREAD(pdata, reg);
|
||||||
|
@ -553,9 +562,8 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
|
||||||
{
|
{
|
||||||
struct ieee_pfc *pfc = pdata->pfc;
|
struct ieee_pfc *pfc = pdata->pfc;
|
||||||
struct ieee_ets *ets = pdata->ets;
|
struct ieee_ets *ets = pdata->ets;
|
||||||
unsigned int max_q_count, q_count;
|
|
||||||
unsigned int reg, reg_val;
|
unsigned int reg, reg_val;
|
||||||
unsigned int i;
|
unsigned int i, q_count;
|
||||||
|
|
||||||
/* Set MTL flow control */
|
/* Set MTL flow control */
|
||||||
for (i = 0; i < pdata->rx_q_count; i++) {
|
for (i = 0; i < pdata->rx_q_count; i++) {
|
||||||
|
@ -579,8 +587,7 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set MAC flow control */
|
/* Set MAC flow control */
|
||||||
max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
|
q_count = xgbe_get_fc_queue_count(pdata);
|
||||||
q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
|
|
||||||
reg = MAC_Q0TFCR;
|
reg = MAC_Q0TFCR;
|
||||||
for (i = 0; i < q_count; i++) {
|
for (i = 0; i < q_count; i++) {
|
||||||
reg_val = XGMAC_IOREAD(pdata, reg);
|
reg_val = XGMAC_IOREAD(pdata, reg);
|
||||||
|
|
|
@ -496,6 +496,7 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
|
||||||
reg |= XGBE_KR_TRAINING_ENABLE;
|
reg |= XGBE_KR_TRAINING_ENABLE;
|
||||||
reg |= XGBE_KR_TRAINING_START;
|
reg |= XGBE_KR_TRAINING_START;
|
||||||
XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
|
XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
|
||||||
|
pdata->kr_start_time = jiffies;
|
||||||
|
|
||||||
netif_dbg(pdata, link, pdata->netdev,
|
netif_dbg(pdata, link, pdata->netdev,
|
||||||
"KR training initiated\n");
|
"KR training initiated\n");
|
||||||
|
@ -632,6 +633,8 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
|
||||||
|
|
||||||
xgbe_switch_mode(pdata);
|
xgbe_switch_mode(pdata);
|
||||||
|
|
||||||
|
pdata->an_result = XGBE_AN_READY;
|
||||||
|
|
||||||
xgbe_an_restart(pdata);
|
xgbe_an_restart(pdata);
|
||||||
|
|
||||||
return XGBE_AN_INCOMPAT_LINK;
|
return XGBE_AN_INCOMPAT_LINK;
|
||||||
|
@ -1275,9 +1278,30 @@ static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
|
||||||
static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
|
static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
|
||||||
{
|
{
|
||||||
unsigned long link_timeout;
|
unsigned long link_timeout;
|
||||||
|
unsigned long kr_time;
|
||||||
|
int wait;
|
||||||
|
|
||||||
link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
|
link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
|
||||||
if (time_after(jiffies, link_timeout)) {
|
if (time_after(jiffies, link_timeout)) {
|
||||||
|
if ((xgbe_cur_mode(pdata) == XGBE_MODE_KR) &&
|
||||||
|
pdata->phy.autoneg == AUTONEG_ENABLE) {
|
||||||
|
/* AN restart should not happen while KR training is in progress.
|
||||||
|
* The while loop ensures no AN restart during KR training,
|
||||||
|
* waits up to 500ms and AN restart is triggered only if KR
|
||||||
|
* training is failed.
|
||||||
|
*/
|
||||||
|
wait = XGBE_KR_TRAINING_WAIT_ITER;
|
||||||
|
while (wait--) {
|
||||||
|
kr_time = pdata->kr_start_time +
|
||||||
|
msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
|
||||||
|
if (time_after(jiffies, kr_time))
|
||||||
|
break;
|
||||||
|
/* AN restart is not required, if AN result is COMPLETE */
|
||||||
|
if (pdata->an_result == XGBE_AN_COMPLETE)
|
||||||
|
return;
|
||||||
|
usleep_range(10000, 11000);
|
||||||
|
}
|
||||||
|
}
|
||||||
netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
|
netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
|
||||||
xgbe_phy_config_aneg(pdata);
|
xgbe_phy_config_aneg(pdata);
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,6 +290,7 @@
|
||||||
/* Auto-negotiation */
|
/* Auto-negotiation */
|
||||||
#define XGBE_AN_MS_TIMEOUT 500
|
#define XGBE_AN_MS_TIMEOUT 500
|
||||||
#define XGBE_LINK_TIMEOUT 5
|
#define XGBE_LINK_TIMEOUT 5
|
||||||
|
#define XGBE_KR_TRAINING_WAIT_ITER 50
|
||||||
|
|
||||||
#define XGBE_SGMII_AN_LINK_STATUS BIT(1)
|
#define XGBE_SGMII_AN_LINK_STATUS BIT(1)
|
||||||
#define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3))
|
#define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3))
|
||||||
|
@ -1266,6 +1267,7 @@ struct xgbe_prv_data {
|
||||||
unsigned int parallel_detect;
|
unsigned int parallel_detect;
|
||||||
unsigned int fec_ability;
|
unsigned int fec_ability;
|
||||||
unsigned long an_start;
|
unsigned long an_start;
|
||||||
|
unsigned long kr_start_time;
|
||||||
enum xgbe_an_mode an_mode;
|
enum xgbe_an_mode an_mode;
|
||||||
|
|
||||||
/* I2C support */
|
/* I2C support */
|
||||||
|
|
|
@ -11189,7 +11189,7 @@ static void tg3_reset_task(struct work_struct *work)
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
tg3_full_lock(tp, 0);
|
tg3_full_lock(tp, 0);
|
||||||
|
|
||||||
if (!netif_running(tp->dev)) {
|
if (tp->pcierr_recovery || !netif_running(tp->dev)) {
|
||||||
tg3_flag_clear(tp, RESET_TASK_PENDING);
|
tg3_flag_clear(tp, RESET_TASK_PENDING);
|
||||||
tg3_full_unlock(tp);
|
tg3_full_unlock(tp);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
@ -18240,6 +18240,9 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
|
||||||
|
|
||||||
netdev_info(netdev, "PCI I/O error detected\n");
|
netdev_info(netdev, "PCI I/O error detected\n");
|
||||||
|
|
||||||
|
/* Want to make sure that the reset task doesn't run */
|
||||||
|
tg3_reset_task_cancel(tp);
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
|
|
||||||
/* Could be second call or maybe we don't have netdev yet */
|
/* Could be second call or maybe we don't have netdev yet */
|
||||||
|
@ -18256,9 +18259,6 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
|
||||||
|
|
||||||
tg3_timer_stop(tp);
|
tg3_timer_stop(tp);
|
||||||
|
|
||||||
/* Want to make sure that the reset task doesn't run */
|
|
||||||
tg3_reset_task_cancel(tp);
|
|
||||||
|
|
||||||
netif_device_detach(netdev);
|
netif_device_detach(netdev);
|
||||||
|
|
||||||
/* Clean up software state, even if MMIO is blocked */
|
/* Clean up software state, even if MMIO is blocked */
|
||||||
|
|
|
@ -1738,7 +1738,6 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
|
||||||
bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||
|
bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||
|
||||||
skb_is_nonlinear(*skb);
|
skb_is_nonlinear(*skb);
|
||||||
int padlen = ETH_ZLEN - (*skb)->len;
|
int padlen = ETH_ZLEN - (*skb)->len;
|
||||||
int headroom = skb_headroom(*skb);
|
|
||||||
int tailroom = skb_tailroom(*skb);
|
int tailroom = skb_tailroom(*skb);
|
||||||
struct sk_buff *nskb;
|
struct sk_buff *nskb;
|
||||||
u32 fcs;
|
u32 fcs;
|
||||||
|
@ -1752,9 +1751,6 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
|
||||||
/* FCS could be appeded to tailroom. */
|
/* FCS could be appeded to tailroom. */
|
||||||
if (tailroom >= ETH_FCS_LEN)
|
if (tailroom >= ETH_FCS_LEN)
|
||||||
goto add_fcs;
|
goto add_fcs;
|
||||||
/* FCS could be appeded by moving data to headroom. */
|
|
||||||
else if (!cloned && headroom + tailroom >= ETH_FCS_LEN)
|
|
||||||
padlen = 0;
|
|
||||||
/* No room for FCS, need to reallocate skb. */
|
/* No room for FCS, need to reallocate skb. */
|
||||||
else
|
else
|
||||||
padlen = ETH_FCS_LEN;
|
padlen = ETH_FCS_LEN;
|
||||||
|
@ -1763,10 +1759,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
|
||||||
padlen += ETH_FCS_LEN;
|
padlen += ETH_FCS_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cloned && headroom + tailroom >= padlen) {
|
if (cloned || tailroom < padlen) {
|
||||||
(*skb)->data = memmove((*skb)->head, (*skb)->data, (*skb)->len);
|
|
||||||
skb_set_tail_pointer(*skb, (*skb)->len);
|
|
||||||
} else {
|
|
||||||
nskb = skb_copy_expand(*skb, 0, padlen, GFP_ATOMIC);
|
nskb = skb_copy_expand(*skb, 0, padlen, GFP_ATOMIC);
|
||||||
if (!nskb)
|
if (!nskb)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -1683,7 +1683,7 @@ static void mlx5_core_verify_params(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init init(void)
|
static int __init mlx5_init(void)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -1708,7 +1708,7 @@ err_debug:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit cleanup(void)
|
static void __exit mlx5_cleanup(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_MLX5_CORE_EN
|
#ifdef CONFIG_MLX5_CORE_EN
|
||||||
mlx5e_cleanup();
|
mlx5e_cleanup();
|
||||||
|
@ -1717,5 +1717,5 @@ static void __exit cleanup(void)
|
||||||
mlx5_unregister_debugfs();
|
mlx5_unregister_debugfs();
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(init);
|
module_init(mlx5_init);
|
||||||
module_exit(cleanup);
|
module_exit(mlx5_cleanup);
|
||||||
|
|
|
@ -738,14 +738,14 @@ static void ravb_error_interrupt(struct net_device *ndev)
|
||||||
ravb_write(ndev, ~(EIS_QFS | EIS_RESERVED), EIS);
|
ravb_write(ndev, ~(EIS_QFS | EIS_RESERVED), EIS);
|
||||||
if (eis & EIS_QFS) {
|
if (eis & EIS_QFS) {
|
||||||
ris2 = ravb_read(ndev, RIS2);
|
ris2 = ravb_read(ndev, RIS2);
|
||||||
ravb_write(ndev, ~(RIS2_QFF0 | RIS2_RFFF | RIS2_RESERVED),
|
ravb_write(ndev, ~(RIS2_QFF0 | RIS2_QFF1 | RIS2_RFFF | RIS2_RESERVED),
|
||||||
RIS2);
|
RIS2);
|
||||||
|
|
||||||
/* Receive Descriptor Empty int */
|
/* Receive Descriptor Empty int */
|
||||||
if (ris2 & RIS2_QFF0)
|
if (ris2 & RIS2_QFF0)
|
||||||
priv->stats[RAVB_BE].rx_over_errors++;
|
priv->stats[RAVB_BE].rx_over_errors++;
|
||||||
|
|
||||||
/* Receive Descriptor Empty int */
|
/* Receive Descriptor Empty int */
|
||||||
if (ris2 & RIS2_QFF1)
|
if (ris2 & RIS2_QFF1)
|
||||||
priv->stats[RAVB_NC].rx_over_errors++;
|
priv->stats[RAVB_NC].rx_over_errors++;
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,12 @@ EXPORT_SYMBOL(mdiobus_unregister_device);
|
||||||
|
|
||||||
struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
|
struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
|
||||||
{
|
{
|
||||||
struct mdio_device *mdiodev = bus->mdio_map[addr];
|
struct mdio_device *mdiodev;
|
||||||
|
|
||||||
|
if (addr < 0 || addr >= ARRAY_SIZE(bus->mdio_map))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mdiodev = bus->mdio_map[addr];
|
||||||
|
|
||||||
if (!mdiodev)
|
if (!mdiodev)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -410,7 +410,7 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
||||||
/* ignore the CRC length */
|
/* ignore the CRC length */
|
||||||
len = (skb->data[1] | (skb->data[2] << 8)) - 4;
|
len = (skb->data[1] | (skb->data[2] << 8)) - 4;
|
||||||
|
|
||||||
if (len > ETH_FRAME_LEN || len > skb->len)
|
if (len > ETH_FRAME_LEN || len > skb->len || len < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* the last packet of current skb */
|
/* the last packet of current skb */
|
||||||
|
|
|
@ -712,8 +712,8 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
|
||||||
struct rndis_query *get;
|
struct rndis_query *get;
|
||||||
struct rndis_query_c *get_c;
|
struct rndis_query_c *get_c;
|
||||||
} u;
|
} u;
|
||||||
int ret, buflen;
|
int ret;
|
||||||
int resplen, respoffs, copylen;
|
size_t buflen, resplen, respoffs, copylen;
|
||||||
|
|
||||||
buflen = *len + sizeof(*u.get);
|
buflen = *len + sizeof(*u.get);
|
||||||
if (buflen < CONTROL_BUFFER_SIZE)
|
if (buflen < CONTROL_BUFFER_SIZE)
|
||||||
|
@ -748,22 +748,15 @@ static int rndis_query_oid(struct usbnet *dev, u32 oid, void *data, int *len)
|
||||||
|
|
||||||
if (respoffs > buflen) {
|
if (respoffs > buflen) {
|
||||||
/* Device returned data offset outside buffer, error. */
|
/* Device returned data offset outside buffer, error. */
|
||||||
netdev_dbg(dev->net, "%s(%s): received invalid "
|
netdev_dbg(dev->net,
|
||||||
"data offset: %d > %d\n", __func__,
|
"%s(%s): received invalid data offset: %zu > %zu\n",
|
||||||
oid_to_string(oid), respoffs, buflen);
|
__func__, oid_to_string(oid), respoffs, buflen);
|
||||||
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto exit_unlock;
|
goto exit_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((resplen + respoffs) > buflen) {
|
copylen = min(resplen, buflen - respoffs);
|
||||||
/* Device would have returned more data if buffer would
|
|
||||||
* have been big enough. Copy just the bits that we got.
|
|
||||||
*/
|
|
||||||
copylen = buflen - respoffs;
|
|
||||||
} else {
|
|
||||||
copylen = resplen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copylen > *len)
|
if (copylen > *len)
|
||||||
copylen = *len;
|
copylen = *len;
|
||||||
|
|
|
@ -477,8 +477,10 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = property_enable(base, &rport->port_cfg->phy_sus, false);
|
ret = property_enable(base, &rport->port_cfg->phy_sus, false);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
clk_disable_unprepare(rphy->clk480m);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* waiting for the utmi_clk to become stable */
|
/* waiting for the utmi_clk to become stable */
|
||||||
usleep_range(1500, 2000);
|
usleep_range(1500, 2000);
|
||||||
|
|
|
@ -5771,7 +5771,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h)
|
||||||
{
|
{
|
||||||
struct Scsi_Host *sh;
|
struct Scsi_Host *sh;
|
||||||
|
|
||||||
sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h));
|
sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info));
|
||||||
if (sh == NULL) {
|
if (sh == NULL) {
|
||||||
dev_err(&h->pdev->dev, "scsi_host_alloc failed\n");
|
dev_err(&h->pdev->dev, "scsi_host_alloc failed\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -271,6 +271,9 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
|
||||||
struct usb_request *req = ffs->ep0req;
|
struct usb_request *req = ffs->ep0req;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!req)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
req->zero = len < le16_to_cpu(ffs->ev.setup.wLength);
|
req->zero = len < le16_to_cpu(ffs->ev.setup.wLength);
|
||||||
|
|
||||||
spin_unlock_irq(&ffs->ev.waitq.lock);
|
spin_unlock_irq(&ffs->ev.waitq.lock);
|
||||||
|
@ -1807,10 +1810,14 @@ static void functionfs_unbind(struct ffs_data *ffs)
|
||||||
ENTER();
|
ENTER();
|
||||||
|
|
||||||
if (!WARN_ON(!ffs->gadget)) {
|
if (!WARN_ON(!ffs->gadget)) {
|
||||||
|
/* dequeue before freeing ep0req */
|
||||||
|
usb_ep_dequeue(ffs->gadget->ep0, ffs->ep0req);
|
||||||
|
mutex_lock(&ffs->mutex);
|
||||||
usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
|
usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
|
||||||
ffs->ep0req = NULL;
|
ffs->ep0req = NULL;
|
||||||
ffs->gadget = NULL;
|
ffs->gadget = NULL;
|
||||||
clear_bit(FFS_FL_BOUND, &ffs->flags);
|
clear_bit(FFS_FL_BOUND, &ffs->flags);
|
||||||
|
mutex_unlock(&ffs->mutex);
|
||||||
ffs_data_put(ffs);
|
ffs_data_put(ffs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,7 +261,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
|
||||||
*priv = *priv_match;
|
*priv = *priv_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_wakeup_enable(hcd->self.controller);
|
device_set_wakeup_capable(&pdev->dev, true);
|
||||||
|
|
||||||
xhci->clk = clk;
|
xhci->clk = clk;
|
||||||
xhci->reg_clk = reg_clk;
|
xhci->reg_clk = reg_clk;
|
||||||
|
|
|
@ -1140,6 +1140,8 @@ int w1_process(void *data)
|
||||||
/* remainder if it woke up early */
|
/* remainder if it woke up early */
|
||||||
unsigned long jremain = 0;
|
unsigned long jremain = 0;
|
||||||
|
|
||||||
|
atomic_inc(&dev->refcnt);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
if (!jremain && dev->search_count) {
|
if (!jremain && dev->search_count) {
|
||||||
|
@ -1167,8 +1169,10 @@ int w1_process(void *data)
|
||||||
*/
|
*/
|
||||||
mutex_unlock(&dev->list_mutex);
|
mutex_unlock(&dev->list_mutex);
|
||||||
|
|
||||||
if (kthread_should_stop())
|
if (kthread_should_stop()) {
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Only sleep when the search is active. */
|
/* Only sleep when the search is active. */
|
||||||
if (dev->search_count) {
|
if (dev->search_count) {
|
||||||
|
|
|
@ -60,10 +60,9 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
|
||||||
dev->search_count = w1_search_count;
|
dev->search_count = w1_search_count;
|
||||||
dev->enable_pullup = w1_enable_pullup;
|
dev->enable_pullup = w1_enable_pullup;
|
||||||
|
|
||||||
/* 1 for w1_process to decrement
|
/* For __w1_remove_master_device to decrement
|
||||||
* 1 for __w1_remove_master_device to decrement
|
|
||||||
*/
|
*/
|
||||||
atomic_set(&dev->refcnt, 2);
|
atomic_set(&dev->refcnt, 1);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&dev->slist);
|
INIT_LIST_HEAD(&dev->slist);
|
||||||
INIT_LIST_HEAD(&dev->async_list);
|
INIT_LIST_HEAD(&dev->async_list);
|
||||||
|
|
|
@ -878,7 +878,7 @@ affs_truncate(struct inode *inode)
|
||||||
if (inode->i_size > AFFS_I(inode)->mmu_private) {
|
if (inode->i_size > AFFS_I(inode)->mmu_private) {
|
||||||
struct address_space *mapping = inode->i_mapping;
|
struct address_space *mapping = inode->i_mapping;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
void *fsdata;
|
void *fsdata = NULL;
|
||||||
loff_t isize = inode->i_size;
|
loff_t isize = inode->i_size;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
|
|
@ -429,7 +429,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||||
server->ssocket->state, server->ssocket->flags);
|
server->ssocket->state, server->ssocket->flags);
|
||||||
sock_release(server->ssocket);
|
sock_release(server->ssocket);
|
||||||
server->ssocket = NULL;
|
server->ssocket = NULL;
|
||||||
}
|
} else if (cifs_rdma_enabled(server))
|
||||||
|
smbd_destroy(server);
|
||||||
server->sequence_number = 0;
|
server->sequence_number = 0;
|
||||||
server->session_estab = false;
|
server->session_estab = false;
|
||||||
kfree(server->session_key.response);
|
kfree(server->session_key.response);
|
||||||
|
@ -799,10 +800,8 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
|
||||||
wake_up_all(&server->request_q);
|
wake_up_all(&server->request_q);
|
||||||
/* give those requests time to exit */
|
/* give those requests time to exit */
|
||||||
msleep(125);
|
msleep(125);
|
||||||
if (cifs_rdma_enabled(server) && server->smbd_conn) {
|
if (cifs_rdma_enabled(server))
|
||||||
smbd_destroy(server->smbd_conn);
|
smbd_destroy(server);
|
||||||
server->smbd_conn = NULL;
|
|
||||||
}
|
|
||||||
if (server->ssocket) {
|
if (server->ssocket) {
|
||||||
sock_release(server->ssocket);
|
sock_release(server->ssocket);
|
||||||
server->ssocket = NULL;
|
server->ssocket = NULL;
|
||||||
|
|
|
@ -320,6 +320,9 @@ static int smbd_conn_upcall(
|
||||||
|
|
||||||
info->transport_status = SMBD_DISCONNECTED;
|
info->transport_status = SMBD_DISCONNECTED;
|
||||||
smbd_process_disconnected(info);
|
smbd_process_disconnected(info);
|
||||||
|
wake_up(&info->disconn_wait);
|
||||||
|
wake_up_interruptible(&info->wait_reassembly_queue);
|
||||||
|
wake_up_interruptible_all(&info->wait_send_queue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1478,21 +1481,102 @@ static void idle_connection_timer(struct work_struct *work)
|
||||||
info->keep_alive_interval*HZ);
|
info->keep_alive_interval*HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy this SMBD connection, called from upper layer */
|
/*
|
||||||
void smbd_destroy(struct smbd_connection *info)
|
* Destroy the transport and related RDMA and memory resources
|
||||||
|
* Need to go through all the pending counters and make sure on one is using
|
||||||
|
* the transport while it is destroyed
|
||||||
|
*/
|
||||||
|
void smbd_destroy(struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
|
struct smbd_connection *info = server->smbd_conn;
|
||||||
|
struct smbd_response *response;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (!info) {
|
||||||
|
log_rdma_event(INFO, "rdma session already destroyed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
log_rdma_event(INFO, "destroying rdma session\n");
|
log_rdma_event(INFO, "destroying rdma session\n");
|
||||||
|
if (info->transport_status != SMBD_DISCONNECTED) {
|
||||||
|
rdma_disconnect(server->smbd_conn->id);
|
||||||
|
log_rdma_event(INFO, "wait for transport being disconnected\n");
|
||||||
|
wait_event(
|
||||||
|
info->disconn_wait,
|
||||||
|
info->transport_status == SMBD_DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
/* Kick off the disconnection process */
|
log_rdma_event(INFO, "destroying qp\n");
|
||||||
smbd_disconnect_rdma_connection(info);
|
ib_drain_qp(info->id->qp);
|
||||||
|
rdma_destroy_qp(info->id);
|
||||||
|
|
||||||
log_rdma_event(INFO, "wait for transport being destroyed\n");
|
log_rdma_event(INFO, "cancelling idle timer\n");
|
||||||
wait_event(info->wait_destroy,
|
cancel_delayed_work_sync(&info->idle_timer_work);
|
||||||
info->transport_status == SMBD_DESTROYED);
|
log_rdma_event(INFO, "cancelling send immediate work\n");
|
||||||
|
cancel_delayed_work_sync(&info->send_immediate_work);
|
||||||
|
|
||||||
|
log_rdma_event(INFO, "wait for all send posted to IB to finish\n");
|
||||||
|
wait_event(info->wait_send_pending,
|
||||||
|
atomic_read(&info->send_pending) == 0);
|
||||||
|
wait_event(info->wait_send_payload_pending,
|
||||||
|
atomic_read(&info->send_payload_pending) == 0);
|
||||||
|
|
||||||
|
/* It's not posssible for upper layer to get to reassembly */
|
||||||
|
log_rdma_event(INFO, "drain the reassembly queue\n");
|
||||||
|
do {
|
||||||
|
spin_lock_irqsave(&info->reassembly_queue_lock, flags);
|
||||||
|
response = _get_first_reassembly(info);
|
||||||
|
if (response) {
|
||||||
|
list_del(&response->list);
|
||||||
|
spin_unlock_irqrestore(
|
||||||
|
&info->reassembly_queue_lock, flags);
|
||||||
|
put_receive_buffer(info, response);
|
||||||
|
} else
|
||||||
|
spin_unlock_irqrestore(
|
||||||
|
&info->reassembly_queue_lock, flags);
|
||||||
|
} while (response);
|
||||||
|
info->reassembly_data_length = 0;
|
||||||
|
|
||||||
|
log_rdma_event(INFO, "free receive buffers\n");
|
||||||
|
wait_event(info->wait_receive_queues,
|
||||||
|
info->count_receive_queue + info->count_empty_packet_queue
|
||||||
|
== info->receive_credit_max);
|
||||||
|
destroy_receive_buffers(info);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For performance reasons, memory registration and deregistration
|
||||||
|
* are not locked by srv_mutex. It is possible some processes are
|
||||||
|
* blocked on transport srv_mutex while holding memory registration.
|
||||||
|
* Release the transport srv_mutex to allow them to hit the failure
|
||||||
|
* path when sending data, and then release memory registartions.
|
||||||
|
*/
|
||||||
|
log_rdma_event(INFO, "freeing mr list\n");
|
||||||
|
wake_up_interruptible_all(&info->wait_mr);
|
||||||
|
while (atomic_read(&info->mr_used_count)) {
|
||||||
|
mutex_unlock(&server->srv_mutex);
|
||||||
|
msleep(1000);
|
||||||
|
mutex_lock(&server->srv_mutex);
|
||||||
|
}
|
||||||
|
destroy_mr_list(info);
|
||||||
|
|
||||||
|
ib_free_cq(info->send_cq);
|
||||||
|
ib_free_cq(info->recv_cq);
|
||||||
|
ib_dealloc_pd(info->pd);
|
||||||
|
rdma_destroy_id(info->id);
|
||||||
|
|
||||||
|
/* free mempools */
|
||||||
|
mempool_destroy(info->request_mempool);
|
||||||
|
kmem_cache_destroy(info->request_cache);
|
||||||
|
|
||||||
|
mempool_destroy(info->response_mempool);
|
||||||
|
kmem_cache_destroy(info->response_cache);
|
||||||
|
|
||||||
|
info->transport_status = SMBD_DESTROYED;
|
||||||
|
|
||||||
destroy_workqueue(info->workqueue);
|
destroy_workqueue(info->workqueue);
|
||||||
log_rdma_event(INFO, "rdma session destroyed\n");
|
log_rdma_event(INFO, "rdma session destroyed\n");
|
||||||
kfree(info);
|
kfree(info);
|
||||||
|
server->smbd_conn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1514,17 +1598,9 @@ int smbd_reconnect(struct TCP_Server_Info *server)
|
||||||
*/
|
*/
|
||||||
if (server->smbd_conn->transport_status == SMBD_CONNECTED) {
|
if (server->smbd_conn->transport_status == SMBD_CONNECTED) {
|
||||||
log_rdma_event(INFO, "disconnecting transport\n");
|
log_rdma_event(INFO, "disconnecting transport\n");
|
||||||
smbd_disconnect_rdma_connection(server->smbd_conn);
|
smbd_destroy(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wait until the transport is destroyed */
|
|
||||||
if (!wait_event_timeout(server->smbd_conn->wait_destroy,
|
|
||||||
server->smbd_conn->transport_status == SMBD_DESTROYED, 5*HZ))
|
|
||||||
return -EAGAIN;
|
|
||||||
|
|
||||||
destroy_workqueue(server->smbd_conn->workqueue);
|
|
||||||
kfree(server->smbd_conn);
|
|
||||||
|
|
||||||
create_conn:
|
create_conn:
|
||||||
log_rdma_event(INFO, "creating rdma session\n");
|
log_rdma_event(INFO, "creating rdma session\n");
|
||||||
server->smbd_conn = smbd_get_connection(
|
server->smbd_conn = smbd_get_connection(
|
||||||
|
@ -1741,12 +1817,13 @@ static struct smbd_connection *_smbd_get_connection(
|
||||||
conn_param.retry_count = SMBD_CM_RETRY;
|
conn_param.retry_count = SMBD_CM_RETRY;
|
||||||
conn_param.rnr_retry_count = SMBD_CM_RNR_RETRY;
|
conn_param.rnr_retry_count = SMBD_CM_RNR_RETRY;
|
||||||
conn_param.flow_control = 0;
|
conn_param.flow_control = 0;
|
||||||
init_waitqueue_head(&info->wait_destroy);
|
|
||||||
|
|
||||||
log_rdma_event(INFO, "connecting to IP %pI4 port %d\n",
|
log_rdma_event(INFO, "connecting to IP %pI4 port %d\n",
|
||||||
&addr_in->sin_addr, port);
|
&addr_in->sin_addr, port);
|
||||||
|
|
||||||
init_waitqueue_head(&info->conn_wait);
|
init_waitqueue_head(&info->conn_wait);
|
||||||
|
init_waitqueue_head(&info->disconn_wait);
|
||||||
|
init_waitqueue_head(&info->wait_reassembly_queue);
|
||||||
rc = rdma_connect(info->id, &conn_param);
|
rc = rdma_connect(info->id, &conn_param);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
log_rdma_event(ERR, "rdma_connect() failed with %i\n", rc);
|
log_rdma_event(ERR, "rdma_connect() failed with %i\n", rc);
|
||||||
|
@ -1770,8 +1847,6 @@ static struct smbd_connection *_smbd_get_connection(
|
||||||
}
|
}
|
||||||
|
|
||||||
init_waitqueue_head(&info->wait_send_queue);
|
init_waitqueue_head(&info->wait_send_queue);
|
||||||
init_waitqueue_head(&info->wait_reassembly_queue);
|
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer);
|
INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer);
|
||||||
INIT_DELAYED_WORK(&info->send_immediate_work, send_immediate_work);
|
INIT_DELAYED_WORK(&info->send_immediate_work, send_immediate_work);
|
||||||
queue_delayed_work(info->workqueue, &info->idle_timer_work,
|
queue_delayed_work(info->workqueue, &info->idle_timer_work,
|
||||||
|
@ -1812,7 +1887,7 @@ static struct smbd_connection *_smbd_get_connection(
|
||||||
|
|
||||||
allocate_mr_failed:
|
allocate_mr_failed:
|
||||||
/* At this point, need to a full transport shutdown */
|
/* At this point, need to a full transport shutdown */
|
||||||
smbd_destroy(info);
|
smbd_destroy(server);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
negotiation_failed:
|
negotiation_failed:
|
||||||
|
|
|
@ -71,6 +71,7 @@ struct smbd_connection {
|
||||||
struct completion ri_done;
|
struct completion ri_done;
|
||||||
wait_queue_head_t conn_wait;
|
wait_queue_head_t conn_wait;
|
||||||
wait_queue_head_t wait_destroy;
|
wait_queue_head_t wait_destroy;
|
||||||
|
wait_queue_head_t disconn_wait;
|
||||||
|
|
||||||
struct completion negotiate_completion;
|
struct completion negotiate_completion;
|
||||||
bool negotiate_done;
|
bool negotiate_done;
|
||||||
|
@ -288,7 +289,7 @@ struct smbd_connection *smbd_get_connection(
|
||||||
/* Reconnect SMBDirect session */
|
/* Reconnect SMBDirect session */
|
||||||
int smbd_reconnect(struct TCP_Server_Info *server);
|
int smbd_reconnect(struct TCP_Server_Info *server);
|
||||||
/* Destroy SMBDirect session */
|
/* Destroy SMBDirect session */
|
||||||
void smbd_destroy(struct smbd_connection *info);
|
void smbd_destroy(struct TCP_Server_Info *server);
|
||||||
|
|
||||||
/* Interface for carrying upper layer I/O through send/recv */
|
/* Interface for carrying upper layer I/O through send/recv */
|
||||||
int smbd_recv(struct smbd_connection *info, struct msghdr *msg);
|
int smbd_recv(struct smbd_connection *info, struct msghdr *msg);
|
||||||
|
@ -331,7 +332,7 @@ struct smbd_connection {};
|
||||||
static inline void *smbd_get_connection(
|
static inline void *smbd_get_connection(
|
||||||
struct TCP_Server_Info *server, struct sockaddr *dstaddr) {return NULL;}
|
struct TCP_Server_Info *server, struct sockaddr *dstaddr) {return NULL;}
|
||||||
static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; }
|
static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1; }
|
||||||
static inline void smbd_destroy(struct smbd_connection *info) {}
|
static inline void smbd_destroy(struct TCP_Server_Info *server) {}
|
||||||
static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; }
|
static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1; }
|
||||||
static inline int smbd_send(struct TCP_Server_Info *server, int num_rqst, struct smb_rqst *rqst) {return -1; }
|
static inline int smbd_send(struct TCP_Server_Info *server, int num_rqst, struct smb_rqst *rqst) {return -1; }
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/kmemleak.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
static const struct dentry_operations proc_sys_dentry_operations;
|
static const struct dentry_operations proc_sys_dentry_operations;
|
||||||
|
@ -1376,6 +1377,38 @@ struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *tab
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(register_sysctl);
|
EXPORT_SYMBOL(register_sysctl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __register_sysctl_init() - register sysctl table to path
|
||||||
|
* @path: path name for sysctl base
|
||||||
|
* @table: This is the sysctl table that needs to be registered to the path
|
||||||
|
* @table_name: The name of sysctl table, only used for log printing when
|
||||||
|
* registration fails
|
||||||
|
*
|
||||||
|
* The sysctl interface is used by userspace to query or modify at runtime
|
||||||
|
* a predefined value set on a variable. These variables however have default
|
||||||
|
* values pre-set. Code which depends on these variables will always work even
|
||||||
|
* if register_sysctl() fails. If register_sysctl() fails you'd just loose the
|
||||||
|
* ability to query or modify the sysctls dynamically at run time. Chances of
|
||||||
|
* register_sysctl() failing on init are extremely low, and so for both reasons
|
||||||
|
* this function does not return any error as it is used by initialization code.
|
||||||
|
*
|
||||||
|
* Context: Can only be called after your respective sysctl base path has been
|
||||||
|
* registered. So for instance, most base directories are registered early on
|
||||||
|
* init before init levels are processed through proc_sys_init() and
|
||||||
|
* sysctl_init().
|
||||||
|
*/
|
||||||
|
void __init __register_sysctl_init(const char *path, struct ctl_table *table,
|
||||||
|
const char *table_name)
|
||||||
|
{
|
||||||
|
struct ctl_table_header *hdr = register_sysctl(path, table);
|
||||||
|
|
||||||
|
if (unlikely(!hdr)) {
|
||||||
|
pr_err("failed when register_sysctl %s to %s\n", table_name, path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
kmemleak_not_leak(hdr);
|
||||||
|
}
|
||||||
|
|
||||||
static char *append_path(const char *path, char *pos, const char *name)
|
static char *append_path(const char *path, char *pos, const char *name)
|
||||||
{
|
{
|
||||||
int namelen;
|
int namelen;
|
||||||
|
|
|
@ -1443,7 +1443,6 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
||||||
unsigned long safe_mask = 0;
|
unsigned long safe_mask = 0;
|
||||||
unsigned int commit_max_age = (unsigned int)-1;
|
unsigned int commit_max_age = (unsigned int)-1;
|
||||||
struct reiserfs_journal *journal = SB_JOURNAL(s);
|
struct reiserfs_journal *journal = SB_JOURNAL(s);
|
||||||
char *new_opts;
|
|
||||||
int err;
|
int err;
|
||||||
char *qf_names[REISERFS_MAXQUOTAS];
|
char *qf_names[REISERFS_MAXQUOTAS];
|
||||||
unsigned int qfmt = 0;
|
unsigned int qfmt = 0;
|
||||||
|
@ -1451,10 +1450,6 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
new_opts = kstrdup(arg, GFP_KERNEL);
|
|
||||||
if (arg && !new_opts)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
sync_filesystem(s);
|
sync_filesystem(s);
|
||||||
reiserfs_write_lock(s);
|
reiserfs_write_lock(s);
|
||||||
|
|
||||||
|
@ -1605,7 +1600,6 @@ out_ok_unlocked:
|
||||||
out_err_unlock:
|
out_err_unlock:
|
||||||
reiserfs_write_unlock(s);
|
reiserfs_write_unlock(s);
|
||||||
out_err:
|
out_err:
|
||||||
kfree(new_opts);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,6 +300,7 @@ extern long (*panic_blink)(int state);
|
||||||
__printf(1, 2)
|
__printf(1, 2)
|
||||||
void panic(const char *fmt, ...) __noreturn __cold;
|
void panic(const char *fmt, ...) __noreturn __cold;
|
||||||
void nmi_panic(struct pt_regs *regs, const char *msg);
|
void nmi_panic(struct pt_regs *regs, const char *msg);
|
||||||
|
void check_panic_on_warn(const char *origin);
|
||||||
extern void oops_enter(void);
|
extern void oops_enter(void);
|
||||||
extern void oops_exit(void);
|
extern void oops_exit(void);
|
||||||
void print_oops_end_marker(void);
|
void print_oops_end_marker(void);
|
||||||
|
|
|
@ -36,6 +36,7 @@ extern int sched_fork(unsigned long clone_flags, struct task_struct *p);
|
||||||
extern void sched_dead(struct task_struct *p);
|
extern void sched_dead(struct task_struct *p);
|
||||||
|
|
||||||
void __noreturn do_task_dead(void);
|
void __noreturn do_task_dead(void);
|
||||||
|
void __noreturn make_task_dead(int signr);
|
||||||
|
|
||||||
extern void proc_caches_init(void);
|
extern void proc_caches_init(void);
|
||||||
|
|
||||||
|
|
|
@ -198,6 +198,9 @@ struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
|
||||||
void unregister_sysctl_table(struct ctl_table_header * table);
|
void unregister_sysctl_table(struct ctl_table_header * table);
|
||||||
|
|
||||||
extern int sysctl_init(void);
|
extern int sysctl_init(void);
|
||||||
|
extern void __register_sysctl_init(const char *path, struct ctl_table *table,
|
||||||
|
const char *table_name);
|
||||||
|
#define register_sysctl_init(path, table) __register_sysctl_init(path, table, #table)
|
||||||
|
|
||||||
extern struct ctl_table sysctl_mount_point[];
|
extern struct ctl_table sysctl_mount_point[];
|
||||||
|
|
||||||
|
|
|
@ -1012,7 +1012,9 @@ static int check_stack_write(struct bpf_verifier_env *env,
|
||||||
bool sanitize = reg && is_spillable_regtype(reg->type);
|
bool sanitize = reg && is_spillable_regtype(reg->type);
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
if (state->stack[spi].slot_type[i] == STACK_INVALID) {
|
u8 type = state->stack[spi].slot_type[i];
|
||||||
|
|
||||||
|
if (type != STACK_MISC && type != STACK_ZERO) {
|
||||||
sanitize = true;
|
sanitize = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,12 +62,59 @@
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/rcuwait.h>
|
#include <linux/rcuwait.h>
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
|
#include <linux/sysfs.h>
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The default value should be high enough to not crash a system that randomly
|
||||||
|
* crashes its kernel from time to time, but low enough to at least not permit
|
||||||
|
* overflowing 32-bit refcounts or the ldsem writer count.
|
||||||
|
*/
|
||||||
|
static unsigned int oops_limit = 10000;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYSCTL
|
||||||
|
static struct ctl_table kern_exit_table[] = {
|
||||||
|
{
|
||||||
|
.procname = "oops_limit",
|
||||||
|
.data = &oops_limit,
|
||||||
|
.maxlen = sizeof(oops_limit),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = proc_douintvec,
|
||||||
|
},
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static __init int kernel_exit_sysctls_init(void)
|
||||||
|
{
|
||||||
|
register_sysctl_init("kernel", kern_exit_table);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall(kernel_exit_sysctls_init);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static atomic_t oops_count = ATOMIC_INIT(0);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYSFS
|
||||||
|
static ssize_t oops_count_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sysfs_emit(page, "%d\n", atomic_read(&oops_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute oops_count_attr = __ATTR_RO(oops_count);
|
||||||
|
|
||||||
|
static __init int kernel_exit_sysfs_init(void)
|
||||||
|
{
|
||||||
|
sysfs_add_file_to_group(kernel_kobj, &oops_count_attr.attr, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall(kernel_exit_sysfs_init);
|
||||||
|
#endif
|
||||||
|
|
||||||
static void __unhash_process(struct task_struct *p, bool group_dead)
|
static void __unhash_process(struct task_struct *p, bool group_dead)
|
||||||
{
|
{
|
||||||
nr_threads--;
|
nr_threads--;
|
||||||
|
@ -923,6 +970,31 @@ void __noreturn do_exit(long code)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(do_exit);
|
EXPORT_SYMBOL_GPL(do_exit);
|
||||||
|
|
||||||
|
void __noreturn make_task_dead(int signr)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Take the task off the cpu after something catastrophic has
|
||||||
|
* happened.
|
||||||
|
*/
|
||||||
|
unsigned int limit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Every time the system oopses, if the oops happens while a reference
|
||||||
|
* to an object was held, the reference leaks.
|
||||||
|
* If the oops doesn't also leak memory, repeated oopsing can cause
|
||||||
|
* reference counters to wrap around (if they're not using refcount_t).
|
||||||
|
* This means that repeated oopsing can make unexploitable-looking bugs
|
||||||
|
* exploitable through repeated oopsing.
|
||||||
|
* To make sure this can't happen, place an upper bound on how often the
|
||||||
|
* kernel may oops without panic().
|
||||||
|
*/
|
||||||
|
limit = READ_ONCE(oops_limit);
|
||||||
|
if (atomic_inc_return(&oops_count) >= limit && limit)
|
||||||
|
panic("Oopsed too often (kernel.oops_limit is %d)", limit);
|
||||||
|
|
||||||
|
do_exit(signr);
|
||||||
|
}
|
||||||
|
|
||||||
void complete_and_exit(struct completion *comp, long code)
|
void complete_and_exit(struct completion *comp, long code)
|
||||||
{
|
{
|
||||||
if (comp)
|
if (comp)
|
||||||
|
|
|
@ -3462,7 +3462,8 @@ static bool finished_loading(const char *name)
|
||||||
sched_annotate_sleep();
|
sched_annotate_sleep();
|
||||||
mutex_lock(&module_mutex);
|
mutex_lock(&module_mutex);
|
||||||
mod = find_module_all(name, strlen(name), true);
|
mod = find_module_all(name, strlen(name), true);
|
||||||
ret = !mod || mod->state == MODULE_STATE_LIVE;
|
ret = !mod || mod->state == MODULE_STATE_LIVE
|
||||||
|
|| mod->state == MODULE_STATE_GOING;
|
||||||
mutex_unlock(&module_mutex);
|
mutex_unlock(&module_mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -3616,20 +3617,35 @@ static int add_unformed_module(struct module *mod)
|
||||||
|
|
||||||
mod->state = MODULE_STATE_UNFORMED;
|
mod->state = MODULE_STATE_UNFORMED;
|
||||||
|
|
||||||
again:
|
|
||||||
mutex_lock(&module_mutex);
|
mutex_lock(&module_mutex);
|
||||||
old = find_module_all(mod->name, strlen(mod->name), true);
|
old = find_module_all(mod->name, strlen(mod->name), true);
|
||||||
if (old != NULL) {
|
if (old != NULL) {
|
||||||
if (old->state != MODULE_STATE_LIVE) {
|
if (old->state == MODULE_STATE_COMING
|
||||||
|
|| old->state == MODULE_STATE_UNFORMED) {
|
||||||
/* Wait in case it fails to load. */
|
/* Wait in case it fails to load. */
|
||||||
mutex_unlock(&module_mutex);
|
mutex_unlock(&module_mutex);
|
||||||
err = wait_event_interruptible(module_wq,
|
err = wait_event_interruptible(module_wq,
|
||||||
finished_loading(mod->name));
|
finished_loading(mod->name));
|
||||||
if (err)
|
if (err)
|
||||||
goto out_unlocked;
|
goto out_unlocked;
|
||||||
goto again;
|
|
||||||
|
/* The module might have gone in the meantime. */
|
||||||
|
mutex_lock(&module_mutex);
|
||||||
|
old = find_module_all(mod->name, strlen(mod->name),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
err = -EEXIST;
|
|
||||||
|
/*
|
||||||
|
* We are here only when the same module was being loaded. Do
|
||||||
|
* not try to load it again right now. It prevents long delays
|
||||||
|
* caused by serialized module load failures. It might happen
|
||||||
|
* when more devices of the same type trigger load of
|
||||||
|
* a particular module.
|
||||||
|
*/
|
||||||
|
if (old && old->state == MODULE_STATE_LIVE)
|
||||||
|
err = -EEXIST;
|
||||||
|
else
|
||||||
|
err = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
mod_update_bounds(mod);
|
mod_update_bounds(mod);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/sysfs.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
|
|
||||||
#define PANIC_TIMER_STEP 100
|
#define PANIC_TIMER_STEP 100
|
||||||
|
@ -42,6 +43,7 @@ static int pause_on_oops_flag;
|
||||||
static DEFINE_SPINLOCK(pause_on_oops_lock);
|
static DEFINE_SPINLOCK(pause_on_oops_lock);
|
||||||
bool crash_kexec_post_notifiers;
|
bool crash_kexec_post_notifiers;
|
||||||
int panic_on_warn __read_mostly;
|
int panic_on_warn __read_mostly;
|
||||||
|
static unsigned int warn_limit __read_mostly;
|
||||||
|
|
||||||
int panic_timeout = CONFIG_PANIC_TIMEOUT;
|
int panic_timeout = CONFIG_PANIC_TIMEOUT;
|
||||||
EXPORT_SYMBOL_GPL(panic_timeout);
|
EXPORT_SYMBOL_GPL(panic_timeout);
|
||||||
|
@ -52,6 +54,45 @@ EXPORT_SYMBOL(panic_notifier_list);
|
||||||
void (*vendor_panic_cb)(u64 sp);
|
void (*vendor_panic_cb)(u64 sp);
|
||||||
EXPORT_SYMBOL_GPL(vendor_panic_cb);
|
EXPORT_SYMBOL_GPL(vendor_panic_cb);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYSCTL
|
||||||
|
static struct ctl_table kern_panic_table[] = {
|
||||||
|
{
|
||||||
|
.procname = "warn_limit",
|
||||||
|
.data = &warn_limit,
|
||||||
|
.maxlen = sizeof(warn_limit),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = proc_douintvec,
|
||||||
|
},
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static __init int kernel_panic_sysctls_init(void)
|
||||||
|
{
|
||||||
|
register_sysctl_init("kernel", kern_panic_table);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall(kernel_panic_sysctls_init);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static atomic_t warn_count = ATOMIC_INIT(0);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SYSFS
|
||||||
|
static ssize_t warn_count_show(struct kobject *kobj, struct kobj_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sysfs_emit(page, "%d\n", atomic_read(&warn_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute warn_count_attr = __ATTR_RO(warn_count);
|
||||||
|
|
||||||
|
static __init int kernel_panic_sysfs_init(void)
|
||||||
|
{
|
||||||
|
sysfs_add_file_to_group(kernel_kobj, &warn_count_attr.attr, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall(kernel_panic_sysfs_init);
|
||||||
|
#endif
|
||||||
|
|
||||||
static long no_blink(int state)
|
static long no_blink(int state)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -127,6 +168,19 @@ void nmi_panic(struct pt_regs *regs, const char *msg)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nmi_panic);
|
EXPORT_SYMBOL(nmi_panic);
|
||||||
|
|
||||||
|
void check_panic_on_warn(const char *origin)
|
||||||
|
{
|
||||||
|
unsigned int limit;
|
||||||
|
|
||||||
|
if (panic_on_warn)
|
||||||
|
panic("%s: panic_on_warn set ...\n", origin);
|
||||||
|
|
||||||
|
limit = READ_ONCE(warn_limit);
|
||||||
|
if (atomic_inc_return(&warn_count) >= limit && limit)
|
||||||
|
panic("%s: system warned too often (kernel.warn_limit is %d)",
|
||||||
|
origin, limit);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* panic - halt the system
|
* panic - halt the system
|
||||||
* @fmt: The text string to print
|
* @fmt: The text string to print
|
||||||
|
@ -144,6 +198,16 @@ void panic(const char *fmt, ...)
|
||||||
int old_cpu, this_cpu;
|
int old_cpu, this_cpu;
|
||||||
bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers;
|
bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers;
|
||||||
|
|
||||||
|
if (panic_on_warn) {
|
||||||
|
/*
|
||||||
|
* This thread may hit another WARN() in the panic path.
|
||||||
|
* Resetting this prevents additional WARN() from panicking the
|
||||||
|
* system on this thread. Other threads are blocked by the
|
||||||
|
* panic_mutex in panic().
|
||||||
|
*/
|
||||||
|
panic_on_warn = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable local interrupts. This will prevent panic_smp_self_stop
|
* Disable local interrupts. This will prevent panic_smp_self_stop
|
||||||
* from deadlocking the first cpu that invokes the panic, since
|
* from deadlocking the first cpu that invokes the panic, since
|
||||||
|
@ -536,16 +600,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
|
||||||
if (args)
|
if (args)
|
||||||
vprintk(args->fmt, args->args);
|
vprintk(args->fmt, args->args);
|
||||||
|
|
||||||
if (panic_on_warn) {
|
check_panic_on_warn("kernel");
|
||||||
/*
|
|
||||||
* This thread may hit another WARN() in the panic path.
|
|
||||||
* Resetting this prevents additional WARN() from panicking the
|
|
||||||
* system on this thread. Other threads are blocked by the
|
|
||||||
* panic_mutex in panic().
|
|
||||||
*/
|
|
||||||
panic_on_warn = 0;
|
|
||||||
panic("panic_on_warn set ...\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
print_modules();
|
print_modules();
|
||||||
|
|
||||||
|
|
|
@ -4006,8 +4006,7 @@ static noinline void __schedule_bug(struct task_struct *prev)
|
||||||
print_ip_sym(preempt_disable_ip);
|
print_ip_sym(preempt_disable_ip);
|
||||||
pr_cont("\n");
|
pr_cont("\n");
|
||||||
}
|
}
|
||||||
if (panic_on_warn)
|
check_panic_on_warn("scheduling while atomic");
|
||||||
panic("scheduling while atomic\n");
|
|
||||||
|
|
||||||
dump_stack();
|
dump_stack();
|
||||||
add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
|
add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
|
||||||
|
|
|
@ -8674,6 +8674,8 @@ void __init early_trace_init(void)
|
||||||
static_key_enable(&tracepoint_printk_key.key);
|
static_key_enable(&tracepoint_printk_key.key);
|
||||||
}
|
}
|
||||||
tracer_alloc_buffers();
|
tracer_alloc_buffers();
|
||||||
|
|
||||||
|
init_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init trace_init(void)
|
void __init trace_init(void)
|
||||||
|
|
|
@ -1530,6 +1530,7 @@ extern void trace_event_enable_cmd_record(bool enable);
|
||||||
extern void trace_event_enable_tgid_record(bool enable);
|
extern void trace_event_enable_tgid_record(bool enable);
|
||||||
|
|
||||||
extern int event_trace_init(void);
|
extern int event_trace_init(void);
|
||||||
|
extern int init_events(void);
|
||||||
extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr);
|
extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr);
|
||||||
extern int event_trace_del_tracer(struct trace_array *tr);
|
extern int event_trace_del_tracer(struct trace_array *tr);
|
||||||
|
|
||||||
|
|
|
@ -2314,6 +2314,8 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
|
||||||
unsigned long fl = flags & ~HIST_FIELD_FL_LOG2;
|
unsigned long fl = flags & ~HIST_FIELD_FL_LOG2;
|
||||||
hist_field->fn = hist_field_log2;
|
hist_field->fn = hist_field_log2;
|
||||||
hist_field->operands[0] = create_hist_field(hist_data, field, fl, NULL);
|
hist_field->operands[0] = create_hist_field(hist_data, field, fl, NULL);
|
||||||
|
if (!hist_field->operands[0])
|
||||||
|
goto free;
|
||||||
hist_field->size = hist_field->operands[0]->size;
|
hist_field->size = hist_field->operands[0]->size;
|
||||||
hist_field->type = kstrdup(hist_field->operands[0]->type, GFP_KERNEL);
|
hist_field->type = kstrdup(hist_field->operands[0]->type, GFP_KERNEL);
|
||||||
if (!hist_field->type)
|
if (!hist_field->type)
|
||||||
|
|
|
@ -1395,7 +1395,7 @@ static struct trace_event *events[] __initdata = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
__init static int init_events(void)
|
__init int init_events(void)
|
||||||
{
|
{
|
||||||
struct trace_event *event;
|
struct trace_event *event;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
@ -1413,4 +1413,3 @@ __init static int init_events(void)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
early_initcall(init_events);
|
|
||||||
|
|
|
@ -91,8 +91,7 @@ static void end_report(unsigned long *flags)
|
||||||
pr_err("==================================================================\n");
|
pr_err("==================================================================\n");
|
||||||
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
|
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
|
||||||
spin_unlock_irqrestore(&report_lock, *flags);
|
spin_unlock_irqrestore(&report_lock, *flags);
|
||||||
if (panic_on_warn)
|
check_panic_on_warn("KASAN");
|
||||||
panic("panic_on_warn set ...\n");
|
|
||||||
kasan_enable_current();
|
kasan_enable_current();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1519,6 +1519,7 @@ static int hci_dev_do_open(struct hci_dev *hdev)
|
||||||
hdev->flush(hdev);
|
hdev->flush(hdev);
|
||||||
|
|
||||||
if (hdev->sent_cmd) {
|
if (hdev->sent_cmd) {
|
||||||
|
cancel_delayed_work_sync(&hdev->cmd_timer);
|
||||||
kfree_skb(hdev->sent_cmd);
|
kfree_skb(hdev->sent_cmd);
|
||||||
hdev->sent_cmd = NULL;
|
hdev->sent_cmd = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,12 +132,12 @@ static int ops_init(const struct pernet_operations *ops, struct net *net)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (ops->id && ops->size) {
|
if (ops->id && ops->size) {
|
||||||
cleanup:
|
|
||||||
ng = rcu_dereference_protected(net->gen,
|
ng = rcu_dereference_protected(net->gen,
|
||||||
lockdep_is_held(&pernet_ops_rwsem));
|
lockdep_is_held(&pernet_ops_rwsem));
|
||||||
ng->ptr[*ops->id] = NULL;
|
ng->ptr[*ops->id] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
kfree(data);
|
kfree(data);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -579,8 +579,20 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
|
||||||
spin_lock(lock);
|
spin_lock(lock);
|
||||||
if (osk) {
|
if (osk) {
|
||||||
WARN_ON_ONCE(sk->sk_hash != osk->sk_hash);
|
WARN_ON_ONCE(sk->sk_hash != osk->sk_hash);
|
||||||
ret = sk_nulls_del_node_init_rcu(osk);
|
ret = sk_hashed(osk);
|
||||||
} else if (found_dup_sk) {
|
if (ret) {
|
||||||
|
/* Before deleting the node, we insert a new one to make
|
||||||
|
* sure that the look-up-sk process would not miss either
|
||||||
|
* of them and that at least one node would exist in ehash
|
||||||
|
* table all the time. Otherwise there's a tiny chance
|
||||||
|
* that lookup process could find nothing in ehash table.
|
||||||
|
*/
|
||||||
|
__sk_nulls_add_node_tail_rcu(sk, list);
|
||||||
|
sk_nulls_del_node_init_rcu(osk);
|
||||||
|
}
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
if (found_dup_sk) {
|
||||||
*found_dup_sk = inet_ehash_lookup_by_sk(sk, list);
|
*found_dup_sk = inet_ehash_lookup_by_sk(sk, list);
|
||||||
if (*found_dup_sk)
|
if (*found_dup_sk)
|
||||||
ret = false;
|
ret = false;
|
||||||
|
@ -589,6 +601,7 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
|
||||||
if (ret)
|
if (ret)
|
||||||
__sk_nulls_add_node_rcu(sk, list);
|
__sk_nulls_add_node_rcu(sk, list);
|
||||||
|
|
||||||
|
unlock:
|
||||||
spin_unlock(lock);
|
spin_unlock(lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -80,10 +80,10 @@ void inet_twsk_put(struct inet_timewait_sock *tw)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(inet_twsk_put);
|
EXPORT_SYMBOL_GPL(inet_twsk_put);
|
||||||
|
|
||||||
static void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
|
static void inet_twsk_add_node_tail_rcu(struct inet_timewait_sock *tw,
|
||||||
struct hlist_nulls_head *list)
|
struct hlist_nulls_head *list)
|
||||||
{
|
{
|
||||||
hlist_nulls_add_head_rcu(&tw->tw_node, list);
|
hlist_nulls_add_tail_rcu(&tw->tw_node, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
|
static void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
|
||||||
|
@ -119,7 +119,7 @@ void inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
|
||||||
|
|
||||||
spin_lock(lock);
|
spin_lock(lock);
|
||||||
|
|
||||||
inet_twsk_add_node_rcu(tw, &ehead->chain);
|
inet_twsk_add_node_tail_rcu(tw, &ehead->chain);
|
||||||
|
|
||||||
/* Step 3: Remove SK from hash chain */
|
/* Step 3: Remove SK from hash chain */
|
||||||
if (__sk_nulls_del_node_init_rcu(sk))
|
if (__sk_nulls_del_node_init_rcu(sk))
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/nospec.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <net/ip.h>
|
#include <net/ip.h>
|
||||||
|
@ -24,6 +25,7 @@ int ip_metrics_convert(struct net *net, struct nlattr *fc_mx, int fc_mx_len,
|
||||||
if (type > RTAX_MAX)
|
if (type > RTAX_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
type = array_index_nospec(type, RTAX_MAX + 1);
|
||||||
if (type == RTAX_CC_ALGO) {
|
if (type == RTAX_CC_ALGO) {
|
||||||
char tmp[TCP_CA_NAME_MAX];
|
char tmp[TCP_CA_NAME_MAX];
|
||||||
|
|
||||||
|
|
|
@ -1154,14 +1154,16 @@ static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu,
|
||||||
dev->needed_headroom = dst_len;
|
dev->needed_headroom = dst_len;
|
||||||
|
|
||||||
if (set_mtu) {
|
if (set_mtu) {
|
||||||
dev->mtu = rt->dst.dev->mtu - t_hlen;
|
int mtu = rt->dst.dev->mtu - t_hlen;
|
||||||
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
|
|
||||||
dev->mtu -= 8;
|
|
||||||
if (dev->type == ARPHRD_ETHER)
|
|
||||||
dev->mtu -= ETH_HLEN;
|
|
||||||
|
|
||||||
if (dev->mtu < IPV6_MIN_MTU)
|
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
|
||||||
dev->mtu = IPV6_MIN_MTU;
|
mtu -= 8;
|
||||||
|
if (dev->type == ARPHRD_ETHER)
|
||||||
|
mtu -= ETH_HLEN;
|
||||||
|
|
||||||
|
if (mtu < IPV6_MIN_MTU)
|
||||||
|
mtu = IPV6_MIN_MTU;
|
||||||
|
WRITE_ONCE(dev->mtu, mtu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ip6_rt_put(rt);
|
ip6_rt_put(rt);
|
||||||
|
|
|
@ -1435,6 +1435,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
|
||||||
struct __ip6_tnl_parm *p = &t->parms;
|
struct __ip6_tnl_parm *p = &t->parms;
|
||||||
struct flowi6 *fl6 = &t->fl.u.ip6;
|
struct flowi6 *fl6 = &t->fl.u.ip6;
|
||||||
int t_hlen;
|
int t_hlen;
|
||||||
|
int mtu;
|
||||||
|
|
||||||
memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
|
memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
|
||||||
memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
|
memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
|
||||||
|
@ -1477,12 +1478,13 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
|
||||||
dev->hard_header_len = rt->dst.dev->hard_header_len +
|
dev->hard_header_len = rt->dst.dev->hard_header_len +
|
||||||
t_hlen;
|
t_hlen;
|
||||||
|
|
||||||
dev->mtu = rt->dst.dev->mtu - t_hlen;
|
mtu = rt->dst.dev->mtu - t_hlen;
|
||||||
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
|
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
|
||||||
dev->mtu -= 8;
|
mtu -= 8;
|
||||||
|
|
||||||
if (dev->mtu < IPV6_MIN_MTU)
|
if (mtu < IPV6_MIN_MTU)
|
||||||
dev->mtu = IPV6_MIN_MTU;
|
mtu = IPV6_MIN_MTU;
|
||||||
|
WRITE_ONCE(dev->mtu, mtu);
|
||||||
}
|
}
|
||||||
ip6_rt_put(rt);
|
ip6_rt_put(rt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1082,10 +1082,12 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
|
||||||
|
|
||||||
if (tdev && !netif_is_l3_master(tdev)) {
|
if (tdev && !netif_is_l3_master(tdev)) {
|
||||||
int t_hlen = tunnel->hlen + sizeof(struct iphdr);
|
int t_hlen = tunnel->hlen + sizeof(struct iphdr);
|
||||||
|
int mtu;
|
||||||
|
|
||||||
dev->mtu = tdev->mtu - t_hlen;
|
mtu = tdev->mtu - t_hlen;
|
||||||
if (dev->mtu < IPV6_MIN_MTU)
|
if (mtu < IPV6_MIN_MTU)
|
||||||
dev->mtu = IPV6_MIN_MTU;
|
mtu = IPV6_MIN_MTU;
|
||||||
|
WRITE_ONCE(dev->mtu, mtu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -317,22 +317,29 @@ static int sctp_packet(struct nf_conn *ct,
|
||||||
for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
|
for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
|
||||||
/* Special cases of Verification tag check (Sec 8.5.1) */
|
/* Special cases of Verification tag check (Sec 8.5.1) */
|
||||||
if (sch->type == SCTP_CID_INIT) {
|
if (sch->type == SCTP_CID_INIT) {
|
||||||
/* Sec 8.5.1 (A) */
|
/* (A) vtag MUST be zero */
|
||||||
if (sh->vtag != 0)
|
if (sh->vtag != 0)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
} else if (sch->type == SCTP_CID_ABORT) {
|
} else if (sch->type == SCTP_CID_ABORT) {
|
||||||
/* Sec 8.5.1 (B) */
|
/* (B) vtag MUST match own vtag if T flag is unset OR
|
||||||
if (sh->vtag != ct->proto.sctp.vtag[dir] &&
|
* MUST match peer's vtag if T flag is set
|
||||||
sh->vtag != ct->proto.sctp.vtag[!dir])
|
*/
|
||||||
|
if ((!(sch->flags & SCTP_CHUNK_FLAG_T) &&
|
||||||
|
sh->vtag != ct->proto.sctp.vtag[dir]) ||
|
||||||
|
((sch->flags & SCTP_CHUNK_FLAG_T) &&
|
||||||
|
sh->vtag != ct->proto.sctp.vtag[!dir]))
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
} else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
|
} else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
|
||||||
/* Sec 8.5.1 (C) */
|
/* (C) vtag MUST match own vtag if T flag is unset OR
|
||||||
if (sh->vtag != ct->proto.sctp.vtag[dir] &&
|
* MUST match peer's vtag if T flag is set
|
||||||
sh->vtag != ct->proto.sctp.vtag[!dir] &&
|
*/
|
||||||
sch->flags & SCTP_CHUNK_FLAG_T)
|
if ((!(sch->flags & SCTP_CHUNK_FLAG_T) &&
|
||||||
|
sh->vtag != ct->proto.sctp.vtag[dir]) ||
|
||||||
|
((sch->flags & SCTP_CHUNK_FLAG_T) &&
|
||||||
|
sh->vtag != ct->proto.sctp.vtag[!dir]))
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
} else if (sch->type == SCTP_CID_COOKIE_ECHO) {
|
} else if (sch->type == SCTP_CID_COOKIE_ECHO) {
|
||||||
/* Sec 8.5.1 (D) */
|
/* (D) vtag must be same as init_vtag as found in INIT_ACK */
|
||||||
if (sh->vtag != ct->proto.sctp.vtag[dir])
|
if (sh->vtag != ct->proto.sctp.vtag[dir])
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
} else if (sch->type == SCTP_CID_HEARTBEAT) {
|
} else if (sch->type == SCTP_CID_HEARTBEAT) {
|
||||||
|
|
|
@ -1094,6 +1094,16 @@ static int tcp_packet(struct nf_conn *ct,
|
||||||
nf_ct_kill_acct(ct, ctinfo, skb);
|
nf_ct_kill_acct(ct, ctinfo, skb);
|
||||||
return NF_ACCEPT;
|
return NF_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index == TCP_SYN_SET && old_state == TCP_CONNTRACK_SYN_SENT) {
|
||||||
|
/* do not renew timeout on SYN retransmit.
|
||||||
|
*
|
||||||
|
* Else port reuse by client or NAT middlebox can keep
|
||||||
|
* entry alive indefinitely (including nat info).
|
||||||
|
*/
|
||||||
|
return NF_ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
/* ESTABLISHED without SEEN_REPLY, i.e. mid-connection
|
/* ESTABLISHED without SEEN_REPLY, i.e. mid-connection
|
||||||
* pickup with loose=1. Avoid large ESTABLISHED timeout.
|
* pickup with loose=1. Avoid large ESTABLISHED timeout.
|
||||||
*/
|
*/
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue