mirror of
https://github.com/Fishwaldo/build.git
synced 2025-04-14 10:01:31 +00:00
9809 lines
316 KiB
Diff
9809 lines
316 KiB
Diff
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt
|
|
index b6a7e7397b8b..b944fe067188 100644
|
|
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt
|
|
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt
|
|
@@ -16,6 +16,9 @@ Required properties:
|
|
Documentation/devicetree/bindings/graph.txt. This port should be connected
|
|
to the input port of an attached HDMI or LVDS encoder chip.
|
|
|
|
+Optional properties:
|
|
+- pinctrl-names: Contain "default" and "sleep".
|
|
+
|
|
Example:
|
|
|
|
dpi0: dpi@1401d000 {
|
|
@@ -26,6 +29,9 @@ dpi0: dpi@1401d000 {
|
|
<&mmsys CLK_MM_DPI_ENGINE>,
|
|
<&apmixedsys CLK_APMIXED_TVDPLL>;
|
|
clock-names = "pixel", "engine", "pll";
|
|
+ pinctrl-names = "default", "sleep";
|
|
+ pinctrl-0 = <&dpi_pin_func>;
|
|
+ pinctrl-1 = <&dpi_pin_idle>;
|
|
|
|
port {
|
|
dpi0_out: endpoint {
|
|
diff --git a/Documentation/virt/kvm/api.txt b/Documentation/virt/kvm/api.txt
|
|
index 4833904d32a5..a18e996fa54b 100644
|
|
--- a/Documentation/virt/kvm/api.txt
|
|
+++ b/Documentation/virt/kvm/api.txt
|
|
@@ -4444,9 +4444,11 @@ EOI was received.
|
|
#define KVM_EXIT_HYPERV_SYNIC 1
|
|
#define KVM_EXIT_HYPERV_HCALL 2
|
|
__u32 type;
|
|
+ __u32 pad1;
|
|
union {
|
|
struct {
|
|
__u32 msr;
|
|
+ __u32 pad2;
|
|
__u64 control;
|
|
__u64 evt_page;
|
|
__u64 msg_page;
|
|
diff --git a/Makefile b/Makefile
|
|
index 1da2944b842e..fee4101b5d22 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 5
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 47
|
|
+SUBLEVEL = 48
|
|
EXTRAVERSION =
|
|
NAME = Kleptomaniac Octopus
|
|
|
|
@@ -587,12 +587,8 @@ KBUILD_MODULES :=
|
|
KBUILD_BUILTIN := 1
|
|
|
|
# If we have only "make modules", don't compile built-in objects.
|
|
-# When we're building modules with modversions, we need to consider
|
|
-# the built-in objects during the descend as well, in order to
|
|
-# make sure the checksums are up to date before we record them.
|
|
-
|
|
ifeq ($(MAKECMDGOALS),modules)
|
|
- KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
|
|
+ KBUILD_BUILTIN :=
|
|
endif
|
|
|
|
# If we have "make <whatever> modules", compile modules
|
|
@@ -1282,6 +1278,13 @@ ifdef CONFIG_MODULES
|
|
|
|
all: modules
|
|
|
|
+# When we're building modules with modversions, we need to consider
|
|
+# the built-in objects during the descend as well, in order to
|
|
+# make sure the checksums are up to date before we record them.
|
|
+ifdef CONFIG_MODVERSIONS
|
|
+ KBUILD_BUILTIN := 1
|
|
+endif
|
|
+
|
|
# Build modules
|
|
#
|
|
# A module can be listed more than once in obj-m resulting in
|
|
diff --git a/arch/alpha/include/asm/io.h b/arch/alpha/include/asm/io.h
|
|
index af2c0063dc75..b771bf1b5352 100644
|
|
--- a/arch/alpha/include/asm/io.h
|
|
+++ b/arch/alpha/include/asm/io.h
|
|
@@ -322,14 +322,18 @@ static inline int __is_mmio(const volatile void __iomem *addr)
|
|
#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
|
|
extern inline unsigned int ioread8(void __iomem *addr)
|
|
{
|
|
- unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
|
|
+ unsigned int ret;
|
|
+ mb();
|
|
+ ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
|
|
extern inline unsigned int ioread16(void __iomem *addr)
|
|
{
|
|
- unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
|
|
+ unsigned int ret;
|
|
+ mb();
|
|
+ ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
@@ -370,7 +374,9 @@ extern inline void outw(u16 b, unsigned long port)
|
|
#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
|
|
extern inline unsigned int ioread32(void __iomem *addr)
|
|
{
|
|
- unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
|
|
+ unsigned int ret;
|
|
+ mb();
|
|
+ ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
@@ -415,14 +421,18 @@ extern inline void __raw_writew(u16 b, volatile void __iomem *addr)
|
|
|
|
extern inline u8 readb(const volatile void __iomem *addr)
|
|
{
|
|
- u8 ret = __raw_readb(addr);
|
|
+ u8 ret;
|
|
+ mb();
|
|
+ ret = __raw_readb(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
|
|
extern inline u16 readw(const volatile void __iomem *addr)
|
|
{
|
|
- u16 ret = __raw_readw(addr);
|
|
+ u16 ret;
|
|
+ mb();
|
|
+ ret = __raw_readw(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
@@ -463,14 +473,18 @@ extern inline void __raw_writeq(u64 b, volatile void __iomem *addr)
|
|
|
|
extern inline u32 readl(const volatile void __iomem *addr)
|
|
{
|
|
- u32 ret = __raw_readl(addr);
|
|
+ u32 ret;
|
|
+ mb();
|
|
+ ret = __raw_readl(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
|
|
extern inline u64 readq(const volatile void __iomem *addr)
|
|
{
|
|
- u64 ret = __raw_readq(addr);
|
|
+ u64 ret;
|
|
+ mb();
|
|
+ ret = __raw_readq(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
@@ -499,14 +513,44 @@ extern inline void writeq(u64 b, volatile void __iomem *addr)
|
|
#define outb_p outb
|
|
#define outw_p outw
|
|
#define outl_p outl
|
|
-#define readb_relaxed(addr) __raw_readb(addr)
|
|
-#define readw_relaxed(addr) __raw_readw(addr)
|
|
-#define readl_relaxed(addr) __raw_readl(addr)
|
|
-#define readq_relaxed(addr) __raw_readq(addr)
|
|
-#define writeb_relaxed(b, addr) __raw_writeb(b, addr)
|
|
-#define writew_relaxed(b, addr) __raw_writew(b, addr)
|
|
-#define writel_relaxed(b, addr) __raw_writel(b, addr)
|
|
-#define writeq_relaxed(b, addr) __raw_writeq(b, addr)
|
|
+
|
|
+extern u8 readb_relaxed(const volatile void __iomem *addr);
|
|
+extern u16 readw_relaxed(const volatile void __iomem *addr);
|
|
+extern u32 readl_relaxed(const volatile void __iomem *addr);
|
|
+extern u64 readq_relaxed(const volatile void __iomem *addr);
|
|
+
|
|
+#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
|
|
+extern inline u8 readb_relaxed(const volatile void __iomem *addr)
|
|
+{
|
|
+ mb();
|
|
+ return __raw_readb(addr);
|
|
+}
|
|
+
|
|
+extern inline u16 readw_relaxed(const volatile void __iomem *addr)
|
|
+{
|
|
+ mb();
|
|
+ return __raw_readw(addr);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
|
|
+extern inline u32 readl_relaxed(const volatile void __iomem *addr)
|
|
+{
|
|
+ mb();
|
|
+ return __raw_readl(addr);
|
|
+}
|
|
+
|
|
+extern inline u64 readq_relaxed(const volatile void __iomem *addr)
|
|
+{
|
|
+ mb();
|
|
+ return __raw_readq(addr);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#define writeb_relaxed writeb
|
|
+#define writew_relaxed writew
|
|
+#define writel_relaxed writel
|
|
+#define writeq_relaxed writeq
|
|
|
|
/*
|
|
* String version of IO memory access ops:
|
|
diff --git a/arch/alpha/kernel/io.c b/arch/alpha/kernel/io.c
|
|
index c025a3e5e357..938de13adfbf 100644
|
|
--- a/arch/alpha/kernel/io.c
|
|
+++ b/arch/alpha/kernel/io.c
|
|
@@ -16,21 +16,27 @@
|
|
unsigned int
|
|
ioread8(void __iomem *addr)
|
|
{
|
|
- unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
|
|
+ unsigned int ret;
|
|
+ mb();
|
|
+ ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
|
|
unsigned int ioread16(void __iomem *addr)
|
|
{
|
|
- unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
|
|
+ unsigned int ret;
|
|
+ mb();
|
|
+ ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
|
|
unsigned int ioread32(void __iomem *addr)
|
|
{
|
|
- unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
|
|
+ unsigned int ret;
|
|
+ mb();
|
|
+ ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
@@ -148,28 +154,36 @@ EXPORT_SYMBOL(__raw_writeq);
|
|
|
|
u8 readb(const volatile void __iomem *addr)
|
|
{
|
|
- u8 ret = __raw_readb(addr);
|
|
+ u8 ret;
|
|
+ mb();
|
|
+ ret = __raw_readb(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
|
|
u16 readw(const volatile void __iomem *addr)
|
|
{
|
|
- u16 ret = __raw_readw(addr);
|
|
+ u16 ret;
|
|
+ mb();
|
|
+ ret = __raw_readw(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
|
|
u32 readl(const volatile void __iomem *addr)
|
|
{
|
|
- u32 ret = __raw_readl(addr);
|
|
+ u32 ret;
|
|
+ mb();
|
|
+ ret = __raw_readl(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
|
|
u64 readq(const volatile void __iomem *addr)
|
|
{
|
|
- u64 ret = __raw_readq(addr);
|
|
+ u64 ret;
|
|
+ mb();
|
|
+ ret = __raw_readq(addr);
|
|
mb();
|
|
return ret;
|
|
}
|
|
@@ -207,6 +221,38 @@ EXPORT_SYMBOL(writew);
|
|
EXPORT_SYMBOL(writel);
|
|
EXPORT_SYMBOL(writeq);
|
|
|
|
+/*
|
|
+ * The _relaxed functions must be ordered w.r.t. each other, but they don't
|
|
+ * have to be ordered w.r.t. other memory accesses.
|
|
+ */
|
|
+u8 readb_relaxed(const volatile void __iomem *addr)
|
|
+{
|
|
+ mb();
|
|
+ return __raw_readb(addr);
|
|
+}
|
|
+
|
|
+u16 readw_relaxed(const volatile void __iomem *addr)
|
|
+{
|
|
+ mb();
|
|
+ return __raw_readw(addr);
|
|
+}
|
|
+
|
|
+u32 readl_relaxed(const volatile void __iomem *addr)
|
|
+{
|
|
+ mb();
|
|
+ return __raw_readl(addr);
|
|
+}
|
|
+
|
|
+u64 readq_relaxed(const volatile void __iomem *addr)
|
|
+{
|
|
+ mb();
|
|
+ return __raw_readq(addr);
|
|
+}
|
|
+
|
|
+EXPORT_SYMBOL(readb_relaxed);
|
|
+EXPORT_SYMBOL(readw_relaxed);
|
|
+EXPORT_SYMBOL(readl_relaxed);
|
|
+EXPORT_SYMBOL(readq_relaxed);
|
|
|
|
/*
|
|
* Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
|
|
diff --git a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
|
|
index 1333a68b9373..b8db77b7f5d8 100644
|
|
--- a/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
|
|
+++ b/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
|
|
@@ -40,7 +40,7 @@
|
|
|
|
ahb {
|
|
usb0: gadget@300000 {
|
|
- atmel,vbus-gpio = <&pioA PIN_PA27 GPIO_ACTIVE_HIGH>;
|
|
+ atmel,vbus-gpio = <&pioA PIN_PB11 GPIO_ACTIVE_HIGH>;
|
|
pinctrl-names = "default";
|
|
pinctrl-0 = <&pinctrl_usba_vbus>;
|
|
status = "okay";
|
|
diff --git a/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi b/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi
|
|
index ce87d2ff27aa..4b9c4cab0314 100644
|
|
--- a/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi
|
|
+++ b/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi
|
|
@@ -68,7 +68,7 @@
|
|
|
|
i2c_cm36651: i2c-gpio-2 {
|
|
compatible = "i2c-gpio";
|
|
- gpios = <&gpf0 0 GPIO_ACTIVE_LOW>, <&gpf0 1 GPIO_ACTIVE_LOW>;
|
|
+ gpios = <&gpf0 0 GPIO_ACTIVE_HIGH>, <&gpf0 1 GPIO_ACTIVE_HIGH>;
|
|
i2c-gpio,delay-us = <2>;
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
diff --git a/arch/arm/boot/dts/s5pv210-aries.dtsi b/arch/arm/boot/dts/s5pv210-aries.dtsi
|
|
index 8ff70b856334..d419b77201f7 100644
|
|
--- a/arch/arm/boot/dts/s5pv210-aries.dtsi
|
|
+++ b/arch/arm/boot/dts/s5pv210-aries.dtsi
|
|
@@ -454,6 +454,7 @@
|
|
pinctrl-names = "default";
|
|
cap-sd-highspeed;
|
|
cap-mmc-highspeed;
|
|
+ keep-power-in-suspend;
|
|
|
|
mmc-pwrseq = <&wifi_pwrseq>;
|
|
non-removable;
|
|
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
|
|
index e512e606eabd..5ea3421fa1e8 100644
|
|
--- a/arch/arm/mach-tegra/tegra.c
|
|
+++ b/arch/arm/mach-tegra/tegra.c
|
|
@@ -106,8 +106,8 @@ static const char * const tegra_dt_board_compat[] = {
|
|
};
|
|
|
|
DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
|
|
- .l2c_aux_val = 0x3c400001,
|
|
- .l2c_aux_mask = 0xc20fc3fe,
|
|
+ .l2c_aux_val = 0x3c400000,
|
|
+ .l2c_aux_mask = 0xc20fc3ff,
|
|
.smp = smp_ops(tegra_smp_ops),
|
|
.map_io = tegra_map_common_io,
|
|
.init_early = tegra_init_early,
|
|
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
|
|
index 5461d589a1e2..60ac7c5999a9 100644
|
|
--- a/arch/arm/mm/proc-macros.S
|
|
+++ b/arch/arm/mm/proc-macros.S
|
|
@@ -5,6 +5,7 @@
|
|
* VMA_VM_FLAGS
|
|
* VM_EXEC
|
|
*/
|
|
+#include <linux/const.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/thread_info.h>
|
|
|
|
@@ -30,7 +31,7 @@
|
|
* act_mm - get current->active_mm
|
|
*/
|
|
.macro act_mm, rd
|
|
- bic \rd, sp, #8128
|
|
+ bic \rd, sp, #(THREAD_SIZE - 1) & ~63
|
|
bic \rd, \rd, #63
|
|
ldr \rd, [\rd, #TI_TASK]
|
|
.if (TSK_ACTIVE_MM > IMM12_MASK)
|
|
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
|
|
index 665c78e0665a..3e7dda6f1ab1 100644
|
|
--- a/arch/arm64/include/asm/cacheflush.h
|
|
+++ b/arch/arm64/include/asm/cacheflush.h
|
|
@@ -79,7 +79,7 @@ static inline void flush_icache_range(unsigned long start, unsigned long end)
|
|
* IPI all online CPUs so that they undergo a context synchronization
|
|
* event and are forced to refetch the new instructions.
|
|
*/
|
|
-#ifdef CONFIG_KGDB
|
|
+
|
|
/*
|
|
* KGDB performs cache maintenance with interrupts disabled, so we
|
|
* will deadlock trying to IPI the secondary CPUs. In theory, we can
|
|
@@ -89,9 +89,9 @@ static inline void flush_icache_range(unsigned long start, unsigned long end)
|
|
* the patching operation, so we don't need extra IPIs here anyway.
|
|
* In which case, add a KGDB-specific bodge and return early.
|
|
*/
|
|
- if (kgdb_connected && irqs_disabled())
|
|
+ if (in_dbg_master())
|
|
return;
|
|
-#endif
|
|
+
|
|
kick_all_cpus_sync();
|
|
}
|
|
|
|
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
|
|
index 13ebe2bad79f..41dd4b1f0ccb 100644
|
|
--- a/arch/arm64/include/asm/pgtable.h
|
|
+++ b/arch/arm64/include/asm/pgtable.h
|
|
@@ -456,6 +456,7 @@ extern pgd_t init_pg_dir[PTRS_PER_PGD];
|
|
extern pgd_t init_pg_end[];
|
|
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
|
|
extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
|
|
+extern pgd_t idmap_pg_end[];
|
|
extern pgd_t tramp_pg_dir[PTRS_PER_PGD];
|
|
|
|
extern void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd);
|
|
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
|
|
index 989b1944cb71..bdb5ec341900 100644
|
|
--- a/arch/arm64/kernel/head.S
|
|
+++ b/arch/arm64/kernel/head.S
|
|
@@ -393,13 +393,19 @@ __create_page_tables:
|
|
|
|
/*
|
|
* Since the page tables have been populated with non-cacheable
|
|
- * accesses (MMU disabled), invalidate the idmap and swapper page
|
|
- * tables again to remove any speculatively loaded cache lines.
|
|
+ * accesses (MMU disabled), invalidate those tables again to
|
|
+ * remove any speculatively loaded cache lines.
|
|
*/
|
|
+ dmb sy
|
|
+
|
|
adrp x0, idmap_pg_dir
|
|
+ adrp x1, idmap_pg_end
|
|
+ sub x1, x1, x0
|
|
+ bl __inval_dcache_area
|
|
+
|
|
+ adrp x0, init_pg_dir
|
|
adrp x1, init_pg_end
|
|
sub x1, x1, x0
|
|
- dmb sy
|
|
bl __inval_dcache_area
|
|
|
|
ret x28
|
|
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
|
|
index d801a7094076..a612da533ea2 100644
|
|
--- a/arch/arm64/kernel/insn.c
|
|
+++ b/arch/arm64/kernel/insn.c
|
|
@@ -1508,16 +1508,10 @@ static u32 aarch64_encode_immediate(u64 imm,
|
|
u32 insn)
|
|
{
|
|
unsigned int immr, imms, n, ones, ror, esz, tmp;
|
|
- u64 mask = ~0UL;
|
|
-
|
|
- /* Can't encode full zeroes or full ones */
|
|
- if (!imm || !~imm)
|
|
- return AARCH64_BREAK_FAULT;
|
|
+ u64 mask;
|
|
|
|
switch (variant) {
|
|
case AARCH64_INSN_VARIANT_32BIT:
|
|
- if (upper_32_bits(imm))
|
|
- return AARCH64_BREAK_FAULT;
|
|
esz = 32;
|
|
break;
|
|
case AARCH64_INSN_VARIANT_64BIT:
|
|
@@ -1529,6 +1523,12 @@ static u32 aarch64_encode_immediate(u64 imm,
|
|
return AARCH64_BREAK_FAULT;
|
|
}
|
|
|
|
+ mask = GENMASK(esz - 1, 0);
|
|
+
|
|
+ /* Can't encode full zeroes, full ones, or value wider than the mask */
|
|
+ if (!imm || imm == mask || imm & ~mask)
|
|
+ return AARCH64_BREAK_FAULT;
|
|
+
|
|
/*
|
|
* Inverse of Replicate(). Try to spot a repeating pattern
|
|
* with a pow2 stride.
|
|
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
|
|
index aa76f7259668..e1af25dbc57e 100644
|
|
--- a/arch/arm64/kernel/vmlinux.lds.S
|
|
+++ b/arch/arm64/kernel/vmlinux.lds.S
|
|
@@ -142,6 +142,7 @@ SECTIONS
|
|
. = ALIGN(PAGE_SIZE);
|
|
idmap_pg_dir = .;
|
|
. += IDMAP_DIR_SIZE;
|
|
+ idmap_pg_end = .;
|
|
|
|
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
|
|
tramp_pg_dir = .;
|
|
diff --git a/arch/m68k/include/asm/mac_via.h b/arch/m68k/include/asm/mac_via.h
|
|
index de1470c4d829..1149251ea58d 100644
|
|
--- a/arch/m68k/include/asm/mac_via.h
|
|
+++ b/arch/m68k/include/asm/mac_via.h
|
|
@@ -257,6 +257,7 @@ extern int rbv_present,via_alt_mapping;
|
|
|
|
struct irq_desc;
|
|
|
|
+extern void via_l2_flush(int writeback);
|
|
extern void via_register_interrupts(void);
|
|
extern void via_irq_enable(int);
|
|
extern void via_irq_disable(int);
|
|
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
|
|
index 611f73bfc87c..d0126ab01360 100644
|
|
--- a/arch/m68k/mac/config.c
|
|
+++ b/arch/m68k/mac/config.c
|
|
@@ -59,7 +59,6 @@ extern void iop_preinit(void);
|
|
extern void iop_init(void);
|
|
extern void via_init(void);
|
|
extern void via_init_clock(irq_handler_t func);
|
|
-extern void via_flush_cache(void);
|
|
extern void oss_init(void);
|
|
extern void psc_init(void);
|
|
extern void baboon_init(void);
|
|
@@ -130,21 +129,6 @@ int __init mac_parse_bootinfo(const struct bi_record *record)
|
|
return unknown;
|
|
}
|
|
|
|
-/*
|
|
- * Flip into 24bit mode for an instant - flushes the L2 cache card. We
|
|
- * have to disable interrupts for this. Our IRQ handlers will crap
|
|
- * themselves if they take an IRQ in 24bit mode!
|
|
- */
|
|
-
|
|
-static void mac_cache_card_flush(int writeback)
|
|
-{
|
|
- unsigned long flags;
|
|
-
|
|
- local_irq_save(flags);
|
|
- via_flush_cache();
|
|
- local_irq_restore(flags);
|
|
-}
|
|
-
|
|
void __init config_mac(void)
|
|
{
|
|
if (!MACH_IS_MAC)
|
|
@@ -175,9 +159,8 @@ void __init config_mac(void)
|
|
* not.
|
|
*/
|
|
|
|
- if (macintosh_config->ident == MAC_MODEL_IICI
|
|
- || macintosh_config->ident == MAC_MODEL_IIFX)
|
|
- mach_l2_flush = mac_cache_card_flush;
|
|
+ if (macintosh_config->ident == MAC_MODEL_IICI)
|
|
+ mach_l2_flush = via_l2_flush;
|
|
}
|
|
|
|
|
|
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
|
|
index 3c2cfcb74982..1f0fad2a98a0 100644
|
|
--- a/arch/m68k/mac/via.c
|
|
+++ b/arch/m68k/mac/via.c
|
|
@@ -294,10 +294,14 @@ void via_debug_dump(void)
|
|
* the system into 24-bit mode for an instant.
|
|
*/
|
|
|
|
-void via_flush_cache(void)
|
|
+void via_l2_flush(int writeback)
|
|
{
|
|
+ unsigned long flags;
|
|
+
|
|
+ local_irq_save(flags);
|
|
via2[gBufB] &= ~VIA2B_vMode32;
|
|
via2[gBufB] |= VIA2B_vMode32;
|
|
+ local_irq_restore(flags);
|
|
}
|
|
|
|
/*
|
|
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
|
|
index cdc09b71febe..5403a91ce098 100644
|
|
--- a/arch/mips/Makefile
|
|
+++ b/arch/mips/Makefile
|
|
@@ -285,12 +285,23 @@ ifdef CONFIG_64BIT
|
|
endif
|
|
endif
|
|
|
|
+# When linking a 32-bit executable the LLVM linker cannot cope with a
|
|
+# 32-bit load address that has been sign-extended to 64 bits. Simply
|
|
+# remove the upper 32 bits then, as it is safe to do so with other
|
|
+# linkers.
|
|
+ifdef CONFIG_64BIT
|
|
+ load-ld = $(load-y)
|
|
+else
|
|
+ load-ld = $(subst 0xffffffff,0x,$(load-y))
|
|
+endif
|
|
+
|
|
KBUILD_AFLAGS += $(cflags-y)
|
|
KBUILD_CFLAGS += $(cflags-y)
|
|
-KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y)
|
|
+KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y) -DLINKER_LOAD_ADDRESS=$(load-ld)
|
|
KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)
|
|
|
|
bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) \
|
|
+ LINKER_LOAD_ADDRESS=$(load-ld) \
|
|
VMLINUX_ENTRY_ADDRESS=$(entry-y) \
|
|
PLATFORM="$(platform-y)" \
|
|
ITS_INPUTS="$(its-y)"
|
|
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
|
|
index d859f079b771..378cbfb31ee7 100644
|
|
--- a/arch/mips/boot/compressed/Makefile
|
|
+++ b/arch/mips/boot/compressed/Makefile
|
|
@@ -90,7 +90,7 @@ ifneq ($(zload-y),)
|
|
VMLINUZ_LOAD_ADDRESS := $(zload-y)
|
|
else
|
|
VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \
|
|
- $(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS))
|
|
+ $(obj)/vmlinux.bin $(LINKER_LOAD_ADDRESS))
|
|
endif
|
|
UIMAGE_LOADADDR = $(VMLINUZ_LOAD_ADDRESS)
|
|
|
|
diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig
|
|
index 90ee0084d786..e41f4841cb4d 100644
|
|
--- a/arch/mips/configs/loongson3_defconfig
|
|
+++ b/arch/mips/configs/loongson3_defconfig
|
|
@@ -231,7 +231,7 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y
|
|
CONFIG_MEDIA_USB_SUPPORT=y
|
|
CONFIG_USB_VIDEO_CLASS=m
|
|
CONFIG_DRM=y
|
|
-CONFIG_DRM_RADEON=y
|
|
+CONFIG_DRM_RADEON=m
|
|
CONFIG_FB_RADEON=y
|
|
CONFIG_LCD_CLASS_DEVICE=y
|
|
CONFIG_LCD_PLATFORM=m
|
|
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
|
|
index 983a6a7f43a1..3e26b0c7391b 100644
|
|
--- a/arch/mips/include/asm/cpu-features.h
|
|
+++ b/arch/mips/include/asm/cpu-features.h
|
|
@@ -288,10 +288,12 @@
|
|
# define cpu_has_mips32r6 __isa_ge_or_flag(6, MIPS_CPU_ISA_M32R6)
|
|
#endif
|
|
#ifndef cpu_has_mips64r1
|
|
-# define cpu_has_mips64r1 __isa_range_or_flag(1, 6, MIPS_CPU_ISA_M64R1)
|
|
+# define cpu_has_mips64r1 (cpu_has_64bits && \
|
|
+ __isa_range_or_flag(1, 6, MIPS_CPU_ISA_M64R1))
|
|
#endif
|
|
#ifndef cpu_has_mips64r2
|
|
-# define cpu_has_mips64r2 __isa_range_or_flag(2, 6, MIPS_CPU_ISA_M64R2)
|
|
+# define cpu_has_mips64r2 (cpu_has_64bits && \
|
|
+ __isa_range_or_flag(2, 6, MIPS_CPU_ISA_M64R2))
|
|
#endif
|
|
#ifndef cpu_has_mips64r6
|
|
# define cpu_has_mips64r6 __isa_ge_and_flag(6, MIPS_CPU_ISA_M64R6)
|
|
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
|
|
index bdbdc19a2b8f..3afdb39d092a 100644
|
|
--- a/arch/mips/include/asm/mipsregs.h
|
|
+++ b/arch/mips/include/asm/mipsregs.h
|
|
@@ -750,7 +750,7 @@
|
|
|
|
/* MAAR bit definitions */
|
|
#define MIPS_MAAR_VH (_U64CAST_(1) << 63)
|
|
-#define MIPS_MAAR_ADDR ((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
|
|
+#define MIPS_MAAR_ADDR GENMASK_ULL(55, 12)
|
|
#define MIPS_MAAR_ADDR_SHIFT 12
|
|
#define MIPS_MAAR_S (_ULCAST_(1) << 1)
|
|
#define MIPS_MAAR_VL (_ULCAST_(1) << 0)
|
|
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
|
|
index efde27c99414..9c5f8a5d097f 100644
|
|
--- a/arch/mips/kernel/genex.S
|
|
+++ b/arch/mips/kernel/genex.S
|
|
@@ -474,20 +474,20 @@ NESTED(nmi_handler, PT_SIZE, sp)
|
|
.endm
|
|
|
|
.macro __build_clear_fpe
|
|
+ CLI
|
|
+ TRACE_IRQS_OFF
|
|
.set push
|
|
/* gas fails to assemble cfc1 for some archs (octeon).*/ \
|
|
.set mips1
|
|
SET_HARDFLOAT
|
|
cfc1 a1, fcr31
|
|
.set pop
|
|
- CLI
|
|
- TRACE_IRQS_OFF
|
|
.endm
|
|
|
|
.macro __build_clear_msa_fpe
|
|
- _cfcmsa a1, MSA_CSR
|
|
CLI
|
|
TRACE_IRQS_OFF
|
|
+ _cfcmsa a1, MSA_CSR
|
|
.endm
|
|
|
|
.macro __build_clear_ade
|
|
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
|
|
index e5ea3db23d6b..a9eab83d9148 100644
|
|
--- a/arch/mips/kernel/mips-cm.c
|
|
+++ b/arch/mips/kernel/mips-cm.c
|
|
@@ -119,9 +119,9 @@ static char *cm2_causes[32] = {
|
|
"COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
|
|
"0x08", "0x09", "0x0a", "0x0b",
|
|
"0x0c", "0x0d", "0x0e", "0x0f",
|
|
- "0x10", "0x11", "0x12", "0x13",
|
|
- "0x14", "0x15", "0x16", "INTVN_WR_ERR",
|
|
- "INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
|
|
+ "0x10", "INTVN_WR_ERR", "INTVN_RD_ERR", "0x13",
|
|
+ "0x14", "0x15", "0x16", "0x17",
|
|
+ "0x18", "0x19", "0x1a", "0x1b",
|
|
"0x1c", "0x1d", "0x1e", "0x1f"
|
|
};
|
|
|
|
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
|
|
index 5eec13b8d222..7b06e6ee6817 100644
|
|
--- a/arch/mips/kernel/setup.c
|
|
+++ b/arch/mips/kernel/setup.c
|
|
@@ -653,7 +653,17 @@ static void __init arch_mem_init(char **cmdline_p)
|
|
crashk_res.end - crashk_res.start + 1);
|
|
#endif
|
|
device_tree_init();
|
|
+
|
|
+ /*
|
|
+ * In order to reduce the possibility of kernel panic when failed to
|
|
+ * get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate
|
|
+ * low memory as small as possible before plat_swiotlb_setup(), so
|
|
+ * make sparse_init() using top-down allocation.
|
|
+ */
|
|
+ memblock_set_bottom_up(false);
|
|
sparse_init();
|
|
+ memblock_set_bottom_up(true);
|
|
+
|
|
plat_swiotlb_setup();
|
|
|
|
dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
|
|
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
|
|
index 37e9413a393d..caa01457dce6 100644
|
|
--- a/arch/mips/kernel/time.c
|
|
+++ b/arch/mips/kernel/time.c
|
|
@@ -18,12 +18,82 @@
|
|
#include <linux/smp.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/export.h>
|
|
+#include <linux/cpufreq.h>
|
|
+#include <linux/delay.h>
|
|
|
|
#include <asm/cpu-features.h>
|
|
#include <asm/cpu-type.h>
|
|
#include <asm/div64.h>
|
|
#include <asm/time.h>
|
|
|
|
+#ifdef CONFIG_CPU_FREQ
|
|
+
|
|
+static DEFINE_PER_CPU(unsigned long, pcp_lpj_ref);
|
|
+static DEFINE_PER_CPU(unsigned long, pcp_lpj_ref_freq);
|
|
+static unsigned long glb_lpj_ref;
|
|
+static unsigned long glb_lpj_ref_freq;
|
|
+
|
|
+static int cpufreq_callback(struct notifier_block *nb,
|
|
+ unsigned long val, void *data)
|
|
+{
|
|
+ struct cpufreq_freqs *freq = data;
|
|
+ struct cpumask *cpus = freq->policy->cpus;
|
|
+ unsigned long lpj;
|
|
+ int cpu;
|
|
+
|
|
+ /*
|
|
+ * Skip lpj numbers adjustment if the CPU-freq transition is safe for
|
|
+ * the loops delay. (Is this possible?)
|
|
+ */
|
|
+ if (freq->flags & CPUFREQ_CONST_LOOPS)
|
|
+ return NOTIFY_OK;
|
|
+
|
|
+ /* Save the initial values of the lpjes for future scaling. */
|
|
+ if (!glb_lpj_ref) {
|
|
+ glb_lpj_ref = boot_cpu_data.udelay_val;
|
|
+ glb_lpj_ref_freq = freq->old;
|
|
+
|
|
+ for_each_online_cpu(cpu) {
|
|
+ per_cpu(pcp_lpj_ref, cpu) =
|
|
+ cpu_data[cpu].udelay_val;
|
|
+ per_cpu(pcp_lpj_ref_freq, cpu) = freq->old;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Adjust global lpj variable and per-CPU udelay_val number in
|
|
+ * accordance with the new CPU frequency.
|
|
+ */
|
|
+ if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
|
|
+ (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
|
|
+ loops_per_jiffy = cpufreq_scale(glb_lpj_ref,
|
|
+ glb_lpj_ref_freq,
|
|
+ freq->new);
|
|
+
|
|
+ for_each_cpu(cpu, cpus) {
|
|
+ lpj = cpufreq_scale(per_cpu(pcp_lpj_ref, cpu),
|
|
+ per_cpu(pcp_lpj_ref_freq, cpu),
|
|
+ freq->new);
|
|
+ cpu_data[cpu].udelay_val = (unsigned int)lpj;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return NOTIFY_OK;
|
|
+}
|
|
+
|
|
+static struct notifier_block cpufreq_notifier = {
|
|
+ .notifier_call = cpufreq_callback,
|
|
+};
|
|
+
|
|
+static int __init register_cpufreq_notifier(void)
|
|
+{
|
|
+ return cpufreq_register_notifier(&cpufreq_notifier,
|
|
+ CPUFREQ_TRANSITION_NOTIFIER);
|
|
+}
|
|
+core_initcall(register_cpufreq_notifier);
|
|
+
|
|
+#endif /* CONFIG_CPU_FREQ */
|
|
+
|
|
/*
|
|
* forward reference
|
|
*/
|
|
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
|
|
index 33ee0d18fb0a..eb9d7af93836 100644
|
|
--- a/arch/mips/kernel/vmlinux.lds.S
|
|
+++ b/arch/mips/kernel/vmlinux.lds.S
|
|
@@ -50,7 +50,7 @@ SECTIONS
|
|
/* . = 0xa800000000300000; */
|
|
. = 0xffffffff80300000;
|
|
#endif
|
|
- . = VMLINUX_LOAD_ADDRESS;
|
|
+ . = LINKER_LOAD_ADDRESS;
|
|
/* read-only */
|
|
_text = .; /* Text and read-only data */
|
|
.text : {
|
|
diff --git a/arch/mips/tools/elf-entry.c b/arch/mips/tools/elf-entry.c
|
|
index adde79ce7fc0..dbd14ff05b4c 100644
|
|
--- a/arch/mips/tools/elf-entry.c
|
|
+++ b/arch/mips/tools/elf-entry.c
|
|
@@ -51,11 +51,14 @@ int main(int argc, const char *argv[])
|
|
nread = fread(&hdr, 1, sizeof(hdr), file);
|
|
if (nread != sizeof(hdr)) {
|
|
perror("Unable to read input file");
|
|
+ fclose(file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
- if (memcmp(hdr.ehdr32.e_ident, ELFMAG, SELFMAG))
|
|
+ if (memcmp(hdr.ehdr32.e_ident, ELFMAG, SELFMAG)) {
|
|
+ fclose(file);
|
|
die("Input is not an ELF\n");
|
|
+ }
|
|
|
|
switch (hdr.ehdr32.e_ident[EI_CLASS]) {
|
|
case ELFCLASS32:
|
|
@@ -67,6 +70,7 @@ int main(int argc, const char *argv[])
|
|
entry = be32toh(hdr.ehdr32.e_entry);
|
|
break;
|
|
default:
|
|
+ fclose(file);
|
|
die("Invalid ELF encoding\n");
|
|
}
|
|
|
|
@@ -83,14 +87,17 @@ int main(int argc, const char *argv[])
|
|
entry = be64toh(hdr.ehdr64.e_entry);
|
|
break;
|
|
default:
|
|
+ fclose(file);
|
|
die("Invalid ELF encoding\n");
|
|
}
|
|
break;
|
|
|
|
default:
|
|
+ fclose(file);
|
|
die("Invalid ELF class\n");
|
|
}
|
|
|
|
printf("0x%016" PRIx64 "\n", entry);
|
|
+ fclose(file);
|
|
return EXIT_SUCCESS;
|
|
}
|
|
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
|
|
index 3dc5aecdd853..44431dc06982 100644
|
|
--- a/arch/powerpc/Kconfig
|
|
+++ b/arch/powerpc/Kconfig
|
|
@@ -171,7 +171,7 @@ config PPC
|
|
select HAVE_ARCH_AUDITSYSCALL
|
|
select HAVE_ARCH_HUGE_VMAP if PPC_BOOK3S_64 && PPC_RADIX_MMU
|
|
select HAVE_ARCH_JUMP_LABEL
|
|
- select HAVE_ARCH_KASAN if PPC32
|
|
+ select HAVE_ARCH_KASAN if PPC32 && PPC_PAGE_SHIFT <= 14
|
|
select HAVE_ARCH_KGDB
|
|
select HAVE_ARCH_MMAP_RND_BITS
|
|
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
|
|
diff --git a/arch/powerpc/include/asm/book3s/32/kup.h b/arch/powerpc/include/asm/book3s/32/kup.h
|
|
index 1a2c80e8be84..6eb311eb818b 100644
|
|
--- a/arch/powerpc/include/asm/book3s/32/kup.h
|
|
+++ b/arch/powerpc/include/asm/book3s/32/kup.h
|
|
@@ -2,6 +2,7 @@
|
|
#ifndef _ASM_POWERPC_BOOK3S_32_KUP_H
|
|
#define _ASM_POWERPC_BOOK3S_32_KUP_H
|
|
|
|
+#include <asm/bug.h>
|
|
#include <asm/book3s/32/mmu-hash.h>
|
|
|
|
#ifdef __ASSEMBLY__
|
|
@@ -75,7 +76,7 @@
|
|
|
|
.macro kuap_check current, gpr
|
|
#ifdef CONFIG_PPC_KUAP_DEBUG
|
|
- lwz \gpr, KUAP(thread)
|
|
+ lwz \gpr, THREAD + KUAP(\current)
|
|
999: twnei \gpr, 0
|
|
EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE)
|
|
#endif
|
|
diff --git a/arch/powerpc/include/asm/fadump-internal.h b/arch/powerpc/include/asm/fadump-internal.h
|
|
index c814a2b55389..8d61c8f3fec4 100644
|
|
--- a/arch/powerpc/include/asm/fadump-internal.h
|
|
+++ b/arch/powerpc/include/asm/fadump-internal.h
|
|
@@ -64,12 +64,14 @@ struct fadump_memory_range {
|
|
};
|
|
|
|
/* fadump memory ranges info */
|
|
+#define RNG_NAME_SZ 16
|
|
struct fadump_mrange_info {
|
|
- char name[16];
|
|
+ char name[RNG_NAME_SZ];
|
|
struct fadump_memory_range *mem_ranges;
|
|
u32 mem_ranges_sz;
|
|
u32 mem_range_cnt;
|
|
u32 max_mem_ranges;
|
|
+ bool is_static;
|
|
};
|
|
|
|
/* Platform specific callback functions */
|
|
diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h
|
|
index 296e51c2f066..b68eeff77806 100644
|
|
--- a/arch/powerpc/include/asm/kasan.h
|
|
+++ b/arch/powerpc/include/asm/kasan.h
|
|
@@ -23,17 +23,13 @@
|
|
|
|
#define KASAN_SHADOW_OFFSET ASM_CONST(CONFIG_KASAN_SHADOW_OFFSET)
|
|
|
|
-#define KASAN_SHADOW_END 0UL
|
|
-
|
|
-#define KASAN_SHADOW_SIZE (KASAN_SHADOW_END - KASAN_SHADOW_START)
|
|
+#define KASAN_SHADOW_END (-(-KASAN_SHADOW_START >> KASAN_SHADOW_SCALE_SHIFT))
|
|
|
|
#ifdef CONFIG_KASAN
|
|
void kasan_early_init(void);
|
|
-void kasan_mmu_init(void);
|
|
void kasan_init(void);
|
|
#else
|
|
static inline void kasan_init(void) { }
|
|
-static inline void kasan_mmu_init(void) { }
|
|
#endif
|
|
|
|
#endif /* __ASSEMBLY */
|
|
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
|
|
index 05606025a131..3551f11accf0 100644
|
|
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
|
|
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
|
|
@@ -346,6 +346,14 @@ static int __init feat_enable_dscr(struct dt_cpu_feature *f)
|
|
{
|
|
u64 lpcr;
|
|
|
|
+ /*
|
|
+ * Linux relies on FSCR[DSCR] being clear, so that we can take the
|
|
+ * facility unavailable interrupt and track the task's usage of DSCR.
|
|
+ * See facility_unavailable_exception().
|
|
+ * Clear the bit here so that feat_enable() doesn't set it.
|
|
+ */
|
|
+ f->fscr_bit_nr = -1;
|
|
+
|
|
feat_enable(f);
|
|
|
|
lpcr = mfspr(SPRN_LPCR);
|
|
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
|
|
index ed59855430b9..9b522152d8f0 100644
|
|
--- a/arch/powerpc/kernel/fadump.c
|
|
+++ b/arch/powerpc/kernel/fadump.c
|
|
@@ -38,8 +38,17 @@ static void __init fadump_reserve_crash_area(u64 base);
|
|
|
|
#ifndef CONFIG_PRESERVE_FA_DUMP
|
|
static DEFINE_MUTEX(fadump_mutex);
|
|
-struct fadump_mrange_info crash_mrange_info = { "crash", NULL, 0, 0, 0 };
|
|
-struct fadump_mrange_info reserved_mrange_info = { "reserved", NULL, 0, 0, 0 };
|
|
+struct fadump_mrange_info crash_mrange_info = { "crash", NULL, 0, 0, 0, false };
|
|
+
|
|
+#define RESERVED_RNGS_SZ 16384 /* 16K - 128 entries */
|
|
+#define RESERVED_RNGS_CNT (RESERVED_RNGS_SZ / \
|
|
+ sizeof(struct fadump_memory_range))
|
|
+static struct fadump_memory_range rngs[RESERVED_RNGS_CNT];
|
|
+struct fadump_mrange_info reserved_mrange_info = { "reserved", rngs,
|
|
+ RESERVED_RNGS_SZ, 0,
|
|
+ RESERVED_RNGS_CNT, true };
|
|
+
|
|
+static void __init early_init_dt_scan_reserved_ranges(unsigned long node);
|
|
|
|
#ifdef CONFIG_CMA
|
|
static struct cma *fadump_cma;
|
|
@@ -108,6 +117,11 @@ static int __init fadump_cma_init(void) { return 1; }
|
|
int __init early_init_dt_scan_fw_dump(unsigned long node, const char *uname,
|
|
int depth, void *data)
|
|
{
|
|
+ if (depth == 0) {
|
|
+ early_init_dt_scan_reserved_ranges(node);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
if (depth != 1)
|
|
return 0;
|
|
|
|
@@ -429,10 +443,72 @@ static int __init fadump_get_boot_mem_regions(void)
|
|
return ret;
|
|
}
|
|
|
|
+/*
|
|
+ * Returns true, if the given range overlaps with reserved memory ranges
|
|
+ * starting at idx. Also, updates idx to index of overlapping memory range
|
|
+ * with the given memory range.
|
|
+ * False, otherwise.
|
|
+ */
|
|
+static bool overlaps_reserved_ranges(u64 base, u64 end, int *idx)
|
|
+{
|
|
+ bool ret = false;
|
|
+ int i;
|
|
+
|
|
+ for (i = *idx; i < reserved_mrange_info.mem_range_cnt; i++) {
|
|
+ u64 rbase = reserved_mrange_info.mem_ranges[i].base;
|
|
+ u64 rend = rbase + reserved_mrange_info.mem_ranges[i].size;
|
|
+
|
|
+ if (end <= rbase)
|
|
+ break;
|
|
+
|
|
+ if ((end > rbase) && (base < rend)) {
|
|
+ *idx = i;
|
|
+ ret = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Locate a suitable memory area to reserve memory for FADump. While at it,
|
|
+ * lookup reserved-ranges & avoid overlap with them, as they are used by F/W.
|
|
+ */
|
|
+static u64 __init fadump_locate_reserve_mem(u64 base, u64 size)
|
|
+{
|
|
+ struct fadump_memory_range *mrngs;
|
|
+ phys_addr_t mstart, mend;
|
|
+ int idx = 0;
|
|
+ u64 i, ret = 0;
|
|
+
|
|
+ mrngs = reserved_mrange_info.mem_ranges;
|
|
+ for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
|
|
+ &mstart, &mend, NULL) {
|
|
+ pr_debug("%llu) mstart: %llx, mend: %llx, base: %llx\n",
|
|
+ i, mstart, mend, base);
|
|
+
|
|
+ if (mstart > base)
|
|
+ base = PAGE_ALIGN(mstart);
|
|
+
|
|
+ while ((mend > base) && ((mend - base) >= size)) {
|
|
+ if (!overlaps_reserved_ranges(base, base+size, &idx)) {
|
|
+ ret = base;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ base = mrngs[idx].base + mrngs[idx].size;
|
|
+ base = PAGE_ALIGN(base);
|
|
+ }
|
|
+ }
|
|
+
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int __init fadump_reserve_mem(void)
|
|
{
|
|
- u64 base, size, mem_boundary, bootmem_min, align = PAGE_SIZE;
|
|
- bool is_memblock_bottom_up = memblock_bottom_up();
|
|
+ u64 base, size, mem_boundary, bootmem_min;
|
|
int ret = 1;
|
|
|
|
if (!fw_dump.fadump_enabled)
|
|
@@ -453,9 +529,9 @@ int __init fadump_reserve_mem(void)
|
|
PAGE_ALIGN(fadump_calculate_reserve_size());
|
|
#ifdef CONFIG_CMA
|
|
if (!fw_dump.nocma) {
|
|
- align = FADUMP_CMA_ALIGNMENT;
|
|
fw_dump.boot_memory_size =
|
|
- ALIGN(fw_dump.boot_memory_size, align);
|
|
+ ALIGN(fw_dump.boot_memory_size,
|
|
+ FADUMP_CMA_ALIGNMENT);
|
|
}
|
|
#endif
|
|
|
|
@@ -523,13 +599,9 @@ int __init fadump_reserve_mem(void)
|
|
* Reserve memory at an offset closer to bottom of the RAM to
|
|
* minimize the impact of memory hot-remove operation.
|
|
*/
|
|
- memblock_set_bottom_up(true);
|
|
- base = memblock_find_in_range(base, mem_boundary, size, align);
|
|
+ base = fadump_locate_reserve_mem(base, size);
|
|
|
|
- /* Restore the previous allocation mode */
|
|
- memblock_set_bottom_up(is_memblock_bottom_up);
|
|
-
|
|
- if (!base) {
|
|
+ if (!base || (base + size > mem_boundary)) {
|
|
pr_err("Failed to find memory chunk for reservation!\n");
|
|
goto error_out;
|
|
}
|
|
@@ -726,10 +798,14 @@ void fadump_free_cpu_notes_buf(void)
|
|
|
|
static void fadump_free_mem_ranges(struct fadump_mrange_info *mrange_info)
|
|
{
|
|
+ if (mrange_info->is_static) {
|
|
+ mrange_info->mem_range_cnt = 0;
|
|
+ return;
|
|
+ }
|
|
+
|
|
kfree(mrange_info->mem_ranges);
|
|
- mrange_info->mem_ranges = NULL;
|
|
- mrange_info->mem_ranges_sz = 0;
|
|
- mrange_info->max_mem_ranges = 0;
|
|
+ memset((void *)((u64)mrange_info + RNG_NAME_SZ), 0,
|
|
+ (sizeof(struct fadump_mrange_info) - RNG_NAME_SZ));
|
|
}
|
|
|
|
/*
|
|
@@ -786,6 +862,12 @@ static inline int fadump_add_mem_range(struct fadump_mrange_info *mrange_info,
|
|
if (mrange_info->mem_range_cnt == mrange_info->max_mem_ranges) {
|
|
int ret;
|
|
|
|
+ if (mrange_info->is_static) {
|
|
+ pr_err("Reached array size limit for %s memory ranges\n",
|
|
+ mrange_info->name);
|
|
+ return -ENOSPC;
|
|
+ }
|
|
+
|
|
ret = fadump_alloc_mem_ranges(mrange_info);
|
|
if (ret)
|
|
return ret;
|
|
@@ -1202,20 +1284,19 @@ static void sort_and_merge_mem_ranges(struct fadump_mrange_info *mrange_info)
|
|
* Scan reserved-ranges to consider them while reserving/releasing
|
|
* memory for FADump.
|
|
*/
|
|
-static inline int fadump_scan_reserved_mem_ranges(void)
|
|
+static void __init early_init_dt_scan_reserved_ranges(unsigned long node)
|
|
{
|
|
- struct device_node *root;
|
|
const __be32 *prop;
|
|
int len, ret = -1;
|
|
unsigned long i;
|
|
|
|
- root = of_find_node_by_path("/");
|
|
- if (!root)
|
|
- return ret;
|
|
+ /* reserved-ranges already scanned */
|
|
+ if (reserved_mrange_info.mem_range_cnt != 0)
|
|
+ return;
|
|
|
|
- prop = of_get_property(root, "reserved-ranges", &len);
|
|
+ prop = of_get_flat_dt_prop(node, "reserved-ranges", &len);
|
|
if (!prop)
|
|
- return ret;
|
|
+ return;
|
|
|
|
/*
|
|
* Each reserved range is an (address,size) pair, 2 cells each,
|
|
@@ -1237,7 +1318,8 @@ static inline int fadump_scan_reserved_mem_ranges(void)
|
|
}
|
|
}
|
|
|
|
- return ret;
|
|
+ /* Compact reserved ranges */
|
|
+ sort_and_merge_mem_ranges(&reserved_mrange_info);
|
|
}
|
|
|
|
/*
|
|
@@ -1251,32 +1333,21 @@ static void fadump_release_memory(u64 begin, u64 end)
|
|
u64 ra_start, ra_end, tstart;
|
|
int i, ret;
|
|
|
|
- fadump_scan_reserved_mem_ranges();
|
|
-
|
|
ra_start = fw_dump.reserve_dump_area_start;
|
|
ra_end = ra_start + fw_dump.reserve_dump_area_size;
|
|
|
|
/*
|
|
- * Add reserved dump area to reserved ranges list
|
|
- * and exclude all these ranges while releasing memory.
|
|
+ * If reserved ranges array limit is hit, overwrite the last reserved
|
|
+ * memory range with reserved dump area to ensure it is excluded from
|
|
+ * the memory being released (reused for next FADump registration).
|
|
*/
|
|
- ret = fadump_add_mem_range(&reserved_mrange_info, ra_start, ra_end);
|
|
- if (ret != 0) {
|
|
- /*
|
|
- * Not enough memory to setup reserved ranges but the system is
|
|
- * running shortage of memory. So, release all the memory except
|
|
- * Reserved dump area (reused for next fadump registration).
|
|
- */
|
|
- if (begin < ra_end && end > ra_start) {
|
|
- if (begin < ra_start)
|
|
- fadump_release_reserved_area(begin, ra_start);
|
|
- if (end > ra_end)
|
|
- fadump_release_reserved_area(ra_end, end);
|
|
- } else
|
|
- fadump_release_reserved_area(begin, end);
|
|
+ if (reserved_mrange_info.mem_range_cnt ==
|
|
+ reserved_mrange_info.max_mem_ranges)
|
|
+ reserved_mrange_info.mem_range_cnt--;
|
|
|
|
+ ret = fadump_add_mem_range(&reserved_mrange_info, ra_start, ra_end);
|
|
+ if (ret != 0)
|
|
return;
|
|
- }
|
|
|
|
/* Get the reserved ranges list in order first. */
|
|
sort_and_merge_mem_ranges(&reserved_mrange_info);
|
|
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
|
|
index 6620f37abe73..e13e96e665e0 100644
|
|
--- a/arch/powerpc/kernel/prom.c
|
|
+++ b/arch/powerpc/kernel/prom.c
|
|
@@ -685,6 +685,23 @@ static void __init tm_init(void)
|
|
static void tm_init(void) { }
|
|
#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
|
|
|
|
+#ifdef CONFIG_PPC64
|
|
+static void __init save_fscr_to_task(void)
|
|
+{
|
|
+ /*
|
|
+ * Ensure the init_task (pid 0, aka swapper) uses the value of FSCR we
|
|
+ * have configured via the device tree features or via __init_FSCR().
|
|
+ * That value will then be propagated to pid 1 (init) and all future
|
|
+ * processes.
|
|
+ */
|
|
+ if (early_cpu_has_feature(CPU_FTR_ARCH_207S))
|
|
+ init_task.thread.fscr = mfspr(SPRN_FSCR);
|
|
+}
|
|
+#else
|
|
+static inline void save_fscr_to_task(void) {};
|
|
+#endif
|
|
+
|
|
+
|
|
void __init early_init_devtree(void *params)
|
|
{
|
|
phys_addr_t limit;
|
|
@@ -773,6 +790,8 @@ void __init early_init_devtree(void *params)
|
|
BUG();
|
|
}
|
|
|
|
+ save_fscr_to_task();
|
|
+
|
|
#if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
|
|
/* We'll later wait for secondaries to check in; there are
|
|
* NCPUS-1 non-boot CPUs :-)
|
|
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
|
|
index b04896a88d79..68f7446193d1 100644
|
|
--- a/arch/powerpc/mm/init_32.c
|
|
+++ b/arch/powerpc/mm/init_32.c
|
|
@@ -175,8 +175,6 @@ void __init MMU_init(void)
|
|
btext_unmap();
|
|
#endif
|
|
|
|
- kasan_mmu_init();
|
|
-
|
|
setup_kup();
|
|
|
|
/* Shortly after that, the entire linear mapping will be available */
|
|
diff --git a/arch/powerpc/mm/kasan/kasan_init_32.c b/arch/powerpc/mm/kasan/kasan_init_32.c
|
|
index 1cfe57b51d7e..b01d4b72eccf 100644
|
|
--- a/arch/powerpc/mm/kasan/kasan_init_32.c
|
|
+++ b/arch/powerpc/mm/kasan/kasan_init_32.c
|
|
@@ -129,7 +129,7 @@ static void __init kasan_remap_early_shadow_ro(void)
|
|
flush_tlb_kernel_range(KASAN_SHADOW_START, KASAN_SHADOW_END);
|
|
}
|
|
|
|
-void __init kasan_mmu_init(void)
|
|
+static void __init kasan_mmu_init(void)
|
|
{
|
|
int ret;
|
|
struct memblock_region *reg;
|
|
@@ -156,6 +156,8 @@ void __init kasan_mmu_init(void)
|
|
|
|
void __init kasan_init(void)
|
|
{
|
|
+ kasan_mmu_init();
|
|
+
|
|
kasan_remap_early_shadow_ro();
|
|
|
|
clear_page(kasan_early_shadow_page);
|
|
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
|
|
index 784cae9f5697..da9f722d9f16 100644
|
|
--- a/arch/powerpc/mm/pgtable_32.c
|
|
+++ b/arch/powerpc/mm/pgtable_32.c
|
|
@@ -207,7 +207,7 @@ void mark_initmem_nx(void)
|
|
unsigned long numpages = PFN_UP((unsigned long)_einittext) -
|
|
PFN_DOWN((unsigned long)_sinittext);
|
|
|
|
- if (v_block_mapped((unsigned long)_stext + 1))
|
|
+ if (v_block_mapped((unsigned long)_sinittext))
|
|
mmu_mark_initmem_nx();
|
|
else
|
|
change_page_attr(page, numpages, PAGE_KERNEL);
|
|
@@ -219,7 +219,7 @@ void mark_rodata_ro(void)
|
|
struct page *page;
|
|
unsigned long numpages;
|
|
|
|
- if (v_block_mapped((unsigned long)_sinittext)) {
|
|
+ if (v_block_mapped((unsigned long)_stext + 1)) {
|
|
mmu_mark_rodata_ro();
|
|
ptdump_check_wx();
|
|
return;
|
|
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
|
|
index c0f950a3f4e1..f4a4dfb191e7 100644
|
|
--- a/arch/powerpc/platforms/cell/spufs/file.c
|
|
+++ b/arch/powerpc/platforms/cell/spufs/file.c
|
|
@@ -1978,8 +1978,9 @@ static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
|
|
static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *pos)
|
|
{
|
|
- int ret;
|
|
struct spu_context *ctx = file->private_data;
|
|
+ u32 stat, data;
|
|
+ int ret;
|
|
|
|
if (!access_ok(buf, len))
|
|
return -EFAULT;
|
|
@@ -1988,11 +1989,16 @@ static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
|
|
if (ret)
|
|
return ret;
|
|
spin_lock(&ctx->csa.register_lock);
|
|
- ret = __spufs_mbox_info_read(ctx, buf, len, pos);
|
|
+ stat = ctx->csa.prob.mb_stat_R;
|
|
+ data = ctx->csa.prob.pu_mb_R;
|
|
spin_unlock(&ctx->csa.register_lock);
|
|
spu_release_saved(ctx);
|
|
|
|
- return ret;
|
|
+ /* EOF if there's no entry in the mbox */
|
|
+ if (!(stat & 0x0000ff))
|
|
+ return 0;
|
|
+
|
|
+ return simple_read_from_buffer(buf, len, pos, &data, sizeof(data));
|
|
}
|
|
|
|
static const struct file_operations spufs_mbox_info_fops = {
|
|
@@ -2019,6 +2025,7 @@ static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *pos)
|
|
{
|
|
struct spu_context *ctx = file->private_data;
|
|
+ u32 stat, data;
|
|
int ret;
|
|
|
|
if (!access_ok(buf, len))
|
|
@@ -2028,11 +2035,16 @@ static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf,
|
|
if (ret)
|
|
return ret;
|
|
spin_lock(&ctx->csa.register_lock);
|
|
- ret = __spufs_ibox_info_read(ctx, buf, len, pos);
|
|
+ stat = ctx->csa.prob.mb_stat_R;
|
|
+ data = ctx->csa.priv2.puint_mb_R;
|
|
spin_unlock(&ctx->csa.register_lock);
|
|
spu_release_saved(ctx);
|
|
|
|
- return ret;
|
|
+ /* EOF if there's no entry in the ibox */
|
|
+ if (!(stat & 0xff0000))
|
|
+ return 0;
|
|
+
|
|
+ return simple_read_from_buffer(buf, len, pos, &data, sizeof(data));
|
|
}
|
|
|
|
static const struct file_operations spufs_ibox_info_fops = {
|
|
@@ -2041,6 +2053,11 @@ static const struct file_operations spufs_ibox_info_fops = {
|
|
.llseek = generic_file_llseek,
|
|
};
|
|
|
|
+static size_t spufs_wbox_info_cnt(struct spu_context *ctx)
|
|
+{
|
|
+ return (4 - ((ctx->csa.prob.mb_stat_R & 0x00ff00) >> 8)) * sizeof(u32);
|
|
+}
|
|
+
|
|
static ssize_t __spufs_wbox_info_read(struct spu_context *ctx,
|
|
char __user *buf, size_t len, loff_t *pos)
|
|
{
|
|
@@ -2049,7 +2066,7 @@ static ssize_t __spufs_wbox_info_read(struct spu_context *ctx,
|
|
u32 wbox_stat;
|
|
|
|
wbox_stat = ctx->csa.prob.mb_stat_R;
|
|
- cnt = 4 - ((wbox_stat & 0x00ff00) >> 8);
|
|
+ cnt = spufs_wbox_info_cnt(ctx);
|
|
for (i = 0; i < cnt; i++) {
|
|
data[i] = ctx->csa.spu_mailbox_data[i];
|
|
}
|
|
@@ -2062,7 +2079,8 @@ static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *pos)
|
|
{
|
|
struct spu_context *ctx = file->private_data;
|
|
- int ret;
|
|
+ u32 data[ARRAY_SIZE(ctx->csa.spu_mailbox_data)];
|
|
+ int ret, count;
|
|
|
|
if (!access_ok(buf, len))
|
|
return -EFAULT;
|
|
@@ -2071,11 +2089,13 @@ static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
|
|
if (ret)
|
|
return ret;
|
|
spin_lock(&ctx->csa.register_lock);
|
|
- ret = __spufs_wbox_info_read(ctx, buf, len, pos);
|
|
+ count = spufs_wbox_info_cnt(ctx);
|
|
+ memcpy(&data, &ctx->csa.spu_mailbox_data, sizeof(data));
|
|
spin_unlock(&ctx->csa.register_lock);
|
|
spu_release_saved(ctx);
|
|
|
|
- return ret;
|
|
+ return simple_read_from_buffer(buf, len, pos, &data,
|
|
+ count * sizeof(u32));
|
|
}
|
|
|
|
static const struct file_operations spufs_wbox_info_fops = {
|
|
@@ -2084,27 +2104,33 @@ static const struct file_operations spufs_wbox_info_fops = {
|
|
.llseek = generic_file_llseek,
|
|
};
|
|
|
|
-static ssize_t __spufs_dma_info_read(struct spu_context *ctx,
|
|
- char __user *buf, size_t len, loff_t *pos)
|
|
+static void spufs_get_dma_info(struct spu_context *ctx,
|
|
+ struct spu_dma_info *info)
|
|
{
|
|
- struct spu_dma_info info;
|
|
- struct mfc_cq_sr *qp, *spuqp;
|
|
int i;
|
|
|
|
- info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
|
|
- info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0];
|
|
- info.dma_info_status = ctx->csa.spu_chnldata_RW[24];
|
|
- info.dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25];
|
|
- info.dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27];
|
|
+ info->dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
|
|
+ info->dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0];
|
|
+ info->dma_info_status = ctx->csa.spu_chnldata_RW[24];
|
|
+ info->dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25];
|
|
+ info->dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27];
|
|
for (i = 0; i < 16; i++) {
|
|
- qp = &info.dma_info_command_data[i];
|
|
- spuqp = &ctx->csa.priv2.spuq[i];
|
|
+ struct mfc_cq_sr *qp = &info->dma_info_command_data[i];
|
|
+ struct mfc_cq_sr *spuqp = &ctx->csa.priv2.spuq[i];
|
|
|
|
qp->mfc_cq_data0_RW = spuqp->mfc_cq_data0_RW;
|
|
qp->mfc_cq_data1_RW = spuqp->mfc_cq_data1_RW;
|
|
qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW;
|
|
qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW;
|
|
}
|
|
+}
|
|
+
|
|
+static ssize_t __spufs_dma_info_read(struct spu_context *ctx,
|
|
+ char __user *buf, size_t len, loff_t *pos)
|
|
+{
|
|
+ struct spu_dma_info info;
|
|
+
|
|
+ spufs_get_dma_info(ctx, &info);
|
|
|
|
return simple_read_from_buffer(buf, len, pos, &info,
|
|
sizeof info);
|
|
@@ -2114,6 +2140,7 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *pos)
|
|
{
|
|
struct spu_context *ctx = file->private_data;
|
|
+ struct spu_dma_info info;
|
|
int ret;
|
|
|
|
if (!access_ok(buf, len))
|
|
@@ -2123,11 +2150,12 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
|
|
if (ret)
|
|
return ret;
|
|
spin_lock(&ctx->csa.register_lock);
|
|
- ret = __spufs_dma_info_read(ctx, buf, len, pos);
|
|
+ spufs_get_dma_info(ctx, &info);
|
|
spin_unlock(&ctx->csa.register_lock);
|
|
spu_release_saved(ctx);
|
|
|
|
- return ret;
|
|
+ return simple_read_from_buffer(buf, len, pos, &info,
|
|
+ sizeof(info));
|
|
}
|
|
|
|
static const struct file_operations spufs_dma_info_fops = {
|
|
@@ -2136,13 +2164,31 @@ static const struct file_operations spufs_dma_info_fops = {
|
|
.llseek = no_llseek,
|
|
};
|
|
|
|
+static void spufs_get_proxydma_info(struct spu_context *ctx,
|
|
+ struct spu_proxydma_info *info)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ info->proxydma_info_type = ctx->csa.prob.dma_querytype_RW;
|
|
+ info->proxydma_info_mask = ctx->csa.prob.dma_querymask_RW;
|
|
+ info->proxydma_info_status = ctx->csa.prob.dma_tagstatus_R;
|
|
+
|
|
+ for (i = 0; i < 8; i++) {
|
|
+ struct mfc_cq_sr *qp = &info->proxydma_info_command_data[i];
|
|
+ struct mfc_cq_sr *puqp = &ctx->csa.priv2.puq[i];
|
|
+
|
|
+ qp->mfc_cq_data0_RW = puqp->mfc_cq_data0_RW;
|
|
+ qp->mfc_cq_data1_RW = puqp->mfc_cq_data1_RW;
|
|
+ qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW;
|
|
+ qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW;
|
|
+ }
|
|
+}
|
|
+
|
|
static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
|
|
char __user *buf, size_t len, loff_t *pos)
|
|
{
|
|
struct spu_proxydma_info info;
|
|
- struct mfc_cq_sr *qp, *puqp;
|
|
int ret = sizeof info;
|
|
- int i;
|
|
|
|
if (len < ret)
|
|
return -EINVAL;
|
|
@@ -2150,18 +2196,7 @@ static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
|
|
if (!access_ok(buf, len))
|
|
return -EFAULT;
|
|
|
|
- info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW;
|
|
- info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW;
|
|
- info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R;
|
|
- for (i = 0; i < 8; i++) {
|
|
- qp = &info.proxydma_info_command_data[i];
|
|
- puqp = &ctx->csa.priv2.puq[i];
|
|
-
|
|
- qp->mfc_cq_data0_RW = puqp->mfc_cq_data0_RW;
|
|
- qp->mfc_cq_data1_RW = puqp->mfc_cq_data1_RW;
|
|
- qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW;
|
|
- qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW;
|
|
- }
|
|
+ spufs_get_proxydma_info(ctx, &info);
|
|
|
|
return simple_read_from_buffer(buf, len, pos, &info,
|
|
sizeof info);
|
|
@@ -2171,17 +2206,19 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
|
|
size_t len, loff_t *pos)
|
|
{
|
|
struct spu_context *ctx = file->private_data;
|
|
+ struct spu_proxydma_info info;
|
|
int ret;
|
|
|
|
ret = spu_acquire_saved(ctx);
|
|
if (ret)
|
|
return ret;
|
|
spin_lock(&ctx->csa.register_lock);
|
|
- ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
|
|
+ spufs_get_proxydma_info(ctx, &info);
|
|
spin_unlock(&ctx->csa.register_lock);
|
|
spu_release_saved(ctx);
|
|
|
|
- return ret;
|
|
+ return simple_read_from_buffer(buf, len, pos, &info,
|
|
+ sizeof(info));
|
|
}
|
|
|
|
static const struct file_operations spufs_proxydma_info_fops = {
|
|
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
|
|
index 13e251699346..b2ba3e95bda7 100644
|
|
--- a/arch/powerpc/platforms/powernv/smp.c
|
|
+++ b/arch/powerpc/platforms/powernv/smp.c
|
|
@@ -167,7 +167,6 @@ static void pnv_smp_cpu_kill_self(void)
|
|
/* Standard hot unplug procedure */
|
|
|
|
idle_task_exit();
|
|
- current->active_mm = NULL; /* for sanity */
|
|
cpu = smp_processor_id();
|
|
DBG("CPU%d offline\n", cpu);
|
|
generic_set_cpu_dead(cpu);
|
|
diff --git a/arch/sparc/kernel/ptrace_32.c b/arch/sparc/kernel/ptrace_32.c
|
|
index 16b50afe7b52..60f7205ebe40 100644
|
|
--- a/arch/sparc/kernel/ptrace_32.c
|
|
+++ b/arch/sparc/kernel/ptrace_32.c
|
|
@@ -46,82 +46,79 @@ enum sparc_regset {
|
|
REGSET_FP,
|
|
};
|
|
|
|
+static int regwindow32_get(struct task_struct *target,
|
|
+ const struct pt_regs *regs,
|
|
+ u32 *uregs)
|
|
+{
|
|
+ unsigned long reg_window = regs->u_regs[UREG_I6];
|
|
+ int size = 16 * sizeof(u32);
|
|
+
|
|
+ if (target == current) {
|
|
+ if (copy_from_user(uregs, (void __user *)reg_window, size))
|
|
+ return -EFAULT;
|
|
+ } else {
|
|
+ if (access_process_vm(target, reg_window, uregs, size,
|
|
+ FOLL_FORCE) != size)
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int regwindow32_set(struct task_struct *target,
|
|
+ const struct pt_regs *regs,
|
|
+ u32 *uregs)
|
|
+{
|
|
+ unsigned long reg_window = regs->u_regs[UREG_I6];
|
|
+ int size = 16 * sizeof(u32);
|
|
+
|
|
+ if (target == current) {
|
|
+ if (copy_to_user((void __user *)reg_window, uregs, size))
|
|
+ return -EFAULT;
|
|
+ } else {
|
|
+ if (access_process_vm(target, reg_window, uregs, size,
|
|
+ FOLL_FORCE | FOLL_WRITE) != size)
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int genregs32_get(struct task_struct *target,
|
|
const struct user_regset *regset,
|
|
unsigned int pos, unsigned int count,
|
|
void *kbuf, void __user *ubuf)
|
|
{
|
|
const struct pt_regs *regs = target->thread.kregs;
|
|
- unsigned long __user *reg_window;
|
|
- unsigned long *k = kbuf;
|
|
- unsigned long __user *u = ubuf;
|
|
- unsigned long reg;
|
|
+ u32 uregs[16];
|
|
+ int ret;
|
|
|
|
if (target == current)
|
|
flush_user_windows();
|
|
|
|
- pos /= sizeof(reg);
|
|
- count /= sizeof(reg);
|
|
-
|
|
- if (kbuf) {
|
|
- for (; count > 0 && pos < 16; count--)
|
|
- *k++ = regs->u_regs[pos++];
|
|
-
|
|
- reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
|
|
- reg_window -= 16;
|
|
- for (; count > 0 && pos < 32; count--) {
|
|
- if (get_user(*k++, ®_window[pos++]))
|
|
- return -EFAULT;
|
|
- }
|
|
- } else {
|
|
- for (; count > 0 && pos < 16; count--) {
|
|
- if (put_user(regs->u_regs[pos++], u++))
|
|
- return -EFAULT;
|
|
- }
|
|
-
|
|
- reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
|
|
- reg_window -= 16;
|
|
- for (; count > 0 && pos < 32; count--) {
|
|
- if (get_user(reg, ®_window[pos++]) ||
|
|
- put_user(reg, u++))
|
|
- return -EFAULT;
|
|
- }
|
|
- }
|
|
- while (count > 0) {
|
|
- switch (pos) {
|
|
- case 32: /* PSR */
|
|
- reg = regs->psr;
|
|
- break;
|
|
- case 33: /* PC */
|
|
- reg = regs->pc;
|
|
- break;
|
|
- case 34: /* NPC */
|
|
- reg = regs->npc;
|
|
- break;
|
|
- case 35: /* Y */
|
|
- reg = regs->y;
|
|
- break;
|
|
- case 36: /* WIM */
|
|
- case 37: /* TBR */
|
|
- reg = 0;
|
|
- break;
|
|
- default:
|
|
- goto finish;
|
|
- }
|
|
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
|
+ regs->u_regs,
|
|
+ 0, 16 * sizeof(u32));
|
|
+ if (ret || !count)
|
|
+ return ret;
|
|
|
|
- if (kbuf)
|
|
- *k++ = reg;
|
|
- else if (put_user(reg, u++))
|
|
+ if (pos < 32 * sizeof(u32)) {
|
|
+ if (regwindow32_get(target, regs, uregs))
|
|
return -EFAULT;
|
|
- pos++;
|
|
- count--;
|
|
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
|
+ uregs,
|
|
+ 16 * sizeof(u32), 32 * sizeof(u32));
|
|
+ if (ret || !count)
|
|
+ return ret;
|
|
}
|
|
-finish:
|
|
- pos *= sizeof(reg);
|
|
- count *= sizeof(reg);
|
|
|
|
- return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
|
|
- 38 * sizeof(reg), -1);
|
|
+ uregs[0] = regs->psr;
|
|
+ uregs[1] = regs->pc;
|
|
+ uregs[2] = regs->npc;
|
|
+ uregs[3] = regs->y;
|
|
+ uregs[4] = 0; /* WIM */
|
|
+ uregs[5] = 0; /* TBR */
|
|
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
|
+ uregs,
|
|
+ 32 * sizeof(u32), 38 * sizeof(u32));
|
|
}
|
|
|
|
static int genregs32_set(struct task_struct *target,
|
|
@@ -130,82 +127,53 @@ static int genregs32_set(struct task_struct *target,
|
|
const void *kbuf, const void __user *ubuf)
|
|
{
|
|
struct pt_regs *regs = target->thread.kregs;
|
|
- unsigned long __user *reg_window;
|
|
- const unsigned long *k = kbuf;
|
|
- const unsigned long __user *u = ubuf;
|
|
- unsigned long reg;
|
|
+ u32 uregs[16];
|
|
+ u32 psr;
|
|
+ int ret;
|
|
|
|
if (target == current)
|
|
flush_user_windows();
|
|
|
|
- pos /= sizeof(reg);
|
|
- count /= sizeof(reg);
|
|
-
|
|
- if (kbuf) {
|
|
- for (; count > 0 && pos < 16; count--)
|
|
- regs->u_regs[pos++] = *k++;
|
|
-
|
|
- reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
|
|
- reg_window -= 16;
|
|
- for (; count > 0 && pos < 32; count--) {
|
|
- if (put_user(*k++, ®_window[pos++]))
|
|
- return -EFAULT;
|
|
- }
|
|
- } else {
|
|
- for (; count > 0 && pos < 16; count--) {
|
|
- if (get_user(reg, u++))
|
|
- return -EFAULT;
|
|
- regs->u_regs[pos++] = reg;
|
|
- }
|
|
-
|
|
- reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
|
|
- reg_window -= 16;
|
|
- for (; count > 0 && pos < 32; count--) {
|
|
- if (get_user(reg, u++) ||
|
|
- put_user(reg, ®_window[pos++]))
|
|
- return -EFAULT;
|
|
- }
|
|
- }
|
|
- while (count > 0) {
|
|
- unsigned long psr;
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
|
+ regs->u_regs,
|
|
+ 0, 16 * sizeof(u32));
|
|
+ if (ret || !count)
|
|
+ return ret;
|
|
|
|
- if (kbuf)
|
|
- reg = *k++;
|
|
- else if (get_user(reg, u++))
|
|
+ if (pos < 32 * sizeof(u32)) {
|
|
+ if (regwindow32_get(target, regs, uregs))
|
|
return -EFAULT;
|
|
-
|
|
- switch (pos) {
|
|
- case 32: /* PSR */
|
|
- psr = regs->psr;
|
|
- psr &= ~(PSR_ICC | PSR_SYSCALL);
|
|
- psr |= (reg & (PSR_ICC | PSR_SYSCALL));
|
|
- regs->psr = psr;
|
|
- break;
|
|
- case 33: /* PC */
|
|
- regs->pc = reg;
|
|
- break;
|
|
- case 34: /* NPC */
|
|
- regs->npc = reg;
|
|
- break;
|
|
- case 35: /* Y */
|
|
- regs->y = reg;
|
|
- break;
|
|
- case 36: /* WIM */
|
|
- case 37: /* TBR */
|
|
- break;
|
|
- default:
|
|
- goto finish;
|
|
- }
|
|
-
|
|
- pos++;
|
|
- count--;
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
|
+ uregs,
|
|
+ 16 * sizeof(u32), 32 * sizeof(u32));
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ if (regwindow32_set(target, regs, uregs))
|
|
+ return -EFAULT;
|
|
+ if (!count)
|
|
+ return 0;
|
|
}
|
|
-finish:
|
|
- pos *= sizeof(reg);
|
|
- count *= sizeof(reg);
|
|
-
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
|
+ &psr,
|
|
+ 32 * sizeof(u32), 33 * sizeof(u32));
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ regs->psr = (regs->psr & ~(PSR_ICC | PSR_SYSCALL)) |
|
|
+ (psr & (PSR_ICC | PSR_SYSCALL));
|
|
+ if (!count)
|
|
+ return 0;
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
|
+ ®s->pc,
|
|
+ 33 * sizeof(u32), 34 * sizeof(u32));
|
|
+ if (ret || !count)
|
|
+ return ret;
|
|
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
|
+ ®s->y,
|
|
+ 34 * sizeof(u32), 35 * sizeof(u32));
|
|
+ if (ret || !count)
|
|
+ return ret;
|
|
return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
|
|
- 38 * sizeof(reg), -1);
|
|
+ 35 * sizeof(u32), 38 * sizeof(u32));
|
|
}
|
|
|
|
static int fpregs32_get(struct task_struct *target,
|
|
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
|
|
index c9d41a96468f..3f5930bfab06 100644
|
|
--- a/arch/sparc/kernel/ptrace_64.c
|
|
+++ b/arch/sparc/kernel/ptrace_64.c
|
|
@@ -572,19 +572,13 @@ static int genregs32_get(struct task_struct *target,
|
|
for (; count > 0 && pos < 32; count--) {
|
|
if (access_process_vm(target,
|
|
(unsigned long)
|
|
- ®_window[pos],
|
|
+ ®_window[pos++],
|
|
®, sizeof(reg),
|
|
FOLL_FORCE)
|
|
!= sizeof(reg))
|
|
return -EFAULT;
|
|
- if (access_process_vm(target,
|
|
- (unsigned long) u,
|
|
- ®, sizeof(reg),
|
|
- FOLL_FORCE | FOLL_WRITE)
|
|
- != sizeof(reg))
|
|
+ if (put_user(reg, u++))
|
|
return -EFAULT;
|
|
- pos++;
|
|
- u++;
|
|
}
|
|
}
|
|
}
|
|
@@ -684,12 +678,7 @@ static int genregs32_set(struct task_struct *target,
|
|
}
|
|
} else {
|
|
for (; count > 0 && pos < 32; count--) {
|
|
- if (access_process_vm(target,
|
|
- (unsigned long)
|
|
- u,
|
|
- ®, sizeof(reg),
|
|
- FOLL_FORCE)
|
|
- != sizeof(reg))
|
|
+ if (get_user(reg, u++))
|
|
return -EFAULT;
|
|
if (access_process_vm(target,
|
|
(unsigned long)
|
|
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
|
|
index 70ffce98c568..d7c0fcc1dbf9 100644
|
|
--- a/arch/x86/boot/compressed/head_32.S
|
|
+++ b/arch/x86/boot/compressed/head_32.S
|
|
@@ -49,16 +49,17 @@
|
|
* Position Independent Executable (PIE) so that linker won't optimize
|
|
* R_386_GOT32X relocation to its fixed symbol address. Older
|
|
* linkers generate R_386_32 relocations against locally defined symbols,
|
|
- * _bss, _ebss, _got and _egot, in PIE. It isn't wrong, just less
|
|
+ * _bss, _ebss, _got, _egot and _end, in PIE. It isn't wrong, just less
|
|
* optimal than R_386_RELATIVE. But the x86 kernel fails to properly handle
|
|
* R_386_32 relocations when relocating the kernel. To generate
|
|
- * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
|
|
+ * R_386_RELATIVE relocations, we mark _bss, _ebss, _got, _egot and _end as
|
|
* hidden:
|
|
*/
|
|
.hidden _bss
|
|
.hidden _ebss
|
|
.hidden _got
|
|
.hidden _egot
|
|
+ .hidden _end
|
|
|
|
__HEAD
|
|
ENTRY(startup_32)
|
|
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
|
|
index 07d2002da642..50c9eeb36f0d 100644
|
|
--- a/arch/x86/boot/compressed/head_64.S
|
|
+++ b/arch/x86/boot/compressed/head_64.S
|
|
@@ -42,6 +42,7 @@
|
|
.hidden _ebss
|
|
.hidden _got
|
|
.hidden _egot
|
|
+ .hidden _end
|
|
|
|
__HEAD
|
|
.code32
|
|
diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h
|
|
index 27c47d183f4b..8b58d6975d5d 100644
|
|
--- a/arch/x86/include/asm/smap.h
|
|
+++ b/arch/x86/include/asm/smap.h
|
|
@@ -57,8 +57,10 @@ static __always_inline unsigned long smap_save(void)
|
|
{
|
|
unsigned long flags;
|
|
|
|
- asm volatile (ALTERNATIVE("", "pushf; pop %0; " __ASM_CLAC,
|
|
- X86_FEATURE_SMAP)
|
|
+ asm volatile ("# smap_save\n\t"
|
|
+ ALTERNATIVE("jmp 1f", "", X86_FEATURE_SMAP)
|
|
+ "pushf; pop %0; " __ASM_CLAC "\n\t"
|
|
+ "1:"
|
|
: "=rm" (flags) : : "memory", "cc");
|
|
|
|
return flags;
|
|
@@ -66,7 +68,10 @@ static __always_inline unsigned long smap_save(void)
|
|
|
|
static __always_inline void smap_restore(unsigned long flags)
|
|
{
|
|
- asm volatile (ALTERNATIVE("", "push %0; popf", X86_FEATURE_SMAP)
|
|
+ asm volatile ("# smap_restore\n\t"
|
|
+ ALTERNATIVE("jmp 1f", "", X86_FEATURE_SMAP)
|
|
+ "push %0; popf\n\t"
|
|
+ "1:"
|
|
: : "g" (flags) : "memory", "cc");
|
|
}
|
|
|
|
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
|
|
index 251c795b4eb3..c4bc01da820e 100644
|
|
--- a/arch/x86/kernel/amd_nb.c
|
|
+++ b/arch/x86/kernel/amd_nb.c
|
|
@@ -18,10 +18,13 @@
|
|
#define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450
|
|
#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT 0x15d0
|
|
#define PCI_DEVICE_ID_AMD_17H_M30H_ROOT 0x1480
|
|
+#define PCI_DEVICE_ID_AMD_17H_M60H_ROOT 0x1630
|
|
#define PCI_DEVICE_ID_AMD_17H_DF_F4 0x1464
|
|
#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec
|
|
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F4 0x1494
|
|
+#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F4 0x144c
|
|
#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4 0x1444
|
|
+#define PCI_DEVICE_ID_AMD_19H_DF_F4 0x1654
|
|
|
|
/* Protect the PCI config register pairs used for SMN and DF indirect access. */
|
|
static DEFINE_MUTEX(smn_mutex);
|
|
@@ -32,6 +35,7 @@ static const struct pci_device_id amd_root_ids[] = {
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_ROOT) },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_ROOT) },
|
|
{}
|
|
};
|
|
|
|
@@ -50,8 +54,10 @@ const struct pci_device_id amd_nb_misc_ids[] = {
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) },
|
|
{}
|
|
};
|
|
EXPORT_SYMBOL_GPL(amd_nb_misc_ids);
|
|
@@ -65,7 +71,9 @@ static const struct pci_device_id amd_nb_link_ids[] = {
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F4) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F4) },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F4) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F4) },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F4) },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
|
|
{}
|
|
};
|
|
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
|
|
index 12df3a4abfdd..6b32ab009c19 100644
|
|
--- a/arch/x86/kernel/irq_64.c
|
|
+++ b/arch/x86/kernel/irq_64.c
|
|
@@ -43,7 +43,7 @@ static int map_irq_stack(unsigned int cpu)
|
|
pages[i] = pfn_to_page(pa >> PAGE_SHIFT);
|
|
}
|
|
|
|
- va = vmap(pages, IRQ_STACK_SIZE / PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
|
|
+ va = vmap(pages, IRQ_STACK_SIZE / PAGE_SIZE, VM_MAP, PAGE_KERNEL);
|
|
if (!va)
|
|
return -ENOMEM;
|
|
|
|
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
|
|
index fd10d91a6115..af352e228fa2 100644
|
|
--- a/arch/x86/mm/init.c
|
|
+++ b/arch/x86/mm/init.c
|
|
@@ -121,8 +121,6 @@ __ref void *alloc_low_pages(unsigned int num)
|
|
} else {
|
|
pfn = pgt_buf_end;
|
|
pgt_buf_end += num;
|
|
- printk(KERN_DEBUG "BRK [%#010lx, %#010lx] PGTABLE\n",
|
|
- pfn << PAGE_SHIFT, (pgt_buf_end << PAGE_SHIFT) - 1);
|
|
}
|
|
|
|
for (i = 0; i < num; i++) {
|
|
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
|
|
index d083f7704082..4d2bda812d9b 100644
|
|
--- a/block/blk-iocost.c
|
|
+++ b/block/blk-iocost.c
|
|
@@ -1546,19 +1546,39 @@ skip_surplus_transfers:
|
|
if (rq_wait_pct > RQ_WAIT_BUSY_PCT ||
|
|
missed_ppm[READ] > ppm_rthr ||
|
|
missed_ppm[WRITE] > ppm_wthr) {
|
|
+ /* clearly missing QoS targets, slow down vrate */
|
|
ioc->busy_level = max(ioc->busy_level, 0);
|
|
ioc->busy_level++;
|
|
} else if (rq_wait_pct <= RQ_WAIT_BUSY_PCT * UNBUSY_THR_PCT / 100 &&
|
|
missed_ppm[READ] <= ppm_rthr * UNBUSY_THR_PCT / 100 &&
|
|
missed_ppm[WRITE] <= ppm_wthr * UNBUSY_THR_PCT / 100) {
|
|
- /* take action iff there is contention */
|
|
- if (nr_shortages && !nr_lagging) {
|
|
+ /* QoS targets are being met with >25% margin */
|
|
+ if (nr_shortages) {
|
|
+ /*
|
|
+ * We're throttling while the device has spare
|
|
+ * capacity. If vrate was being slowed down, stop.
|
|
+ */
|
|
ioc->busy_level = min(ioc->busy_level, 0);
|
|
- /* redistribute surpluses first */
|
|
- if (!nr_surpluses)
|
|
+
|
|
+ /*
|
|
+ * If there are IOs spanning multiple periods, wait
|
|
+ * them out before pushing the device harder. If
|
|
+ * there are surpluses, let redistribution work it
|
|
+ * out first.
|
|
+ */
|
|
+ if (!nr_lagging && !nr_surpluses)
|
|
ioc->busy_level--;
|
|
+ } else {
|
|
+ /*
|
|
+ * Nobody is being throttled and the users aren't
|
|
+ * issuing enough IOs to saturate the device. We
|
|
+ * simply don't know how close the device is to
|
|
+ * saturation. Coast.
|
|
+ */
|
|
+ ioc->busy_level = 0;
|
|
}
|
|
} else {
|
|
+ /* inside the hysterisis margin, we're good */
|
|
ioc->busy_level = 0;
|
|
}
|
|
|
|
diff --git a/block/blk-mq.c b/block/blk-mq.c
|
|
index 757c0fd9f0cc..0550366e25d8 100644
|
|
--- a/block/blk-mq.c
|
|
+++ b/block/blk-mq.c
|
|
@@ -2493,18 +2493,6 @@ static void blk_mq_map_swqueue(struct request_queue *q)
|
|
* If the cpu isn't present, the cpu is mapped to first hctx.
|
|
*/
|
|
for_each_possible_cpu(i) {
|
|
- hctx_idx = set->map[HCTX_TYPE_DEFAULT].mq_map[i];
|
|
- /* unmapped hw queue can be remapped after CPU topo changed */
|
|
- if (!set->tags[hctx_idx] &&
|
|
- !__blk_mq_alloc_rq_map(set, hctx_idx)) {
|
|
- /*
|
|
- * If tags initialization fail for some hctx,
|
|
- * that hctx won't be brought online. In this
|
|
- * case, remap the current ctx to hctx[0] which
|
|
- * is guaranteed to always have tags allocated
|
|
- */
|
|
- set->map[HCTX_TYPE_DEFAULT].mq_map[i] = 0;
|
|
- }
|
|
|
|
ctx = per_cpu_ptr(q->queue_ctx, i);
|
|
for (j = 0; j < set->nr_maps; j++) {
|
|
@@ -2513,6 +2501,18 @@ static void blk_mq_map_swqueue(struct request_queue *q)
|
|
HCTX_TYPE_DEFAULT, i);
|
|
continue;
|
|
}
|
|
+ hctx_idx = set->map[j].mq_map[i];
|
|
+ /* unmapped hw queue can be remapped after CPU topo changed */
|
|
+ if (!set->tags[hctx_idx] &&
|
|
+ !__blk_mq_alloc_rq_map(set, hctx_idx)) {
|
|
+ /*
|
|
+ * If tags initialization fail for some hctx,
|
|
+ * that hctx won't be brought online. In this
|
|
+ * case, remap the current ctx to hctx[0] which
|
|
+ * is guaranteed to always have tags allocated
|
|
+ */
|
|
+ set->map[j].mq_map[i] = 0;
|
|
+ }
|
|
|
|
hctx = blk_mq_map_queue_type(q, j, i);
|
|
ctx->hctxs[j] = hctx;
|
|
@@ -3304,8 +3304,8 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
|
|
|
|
prev_nr_hw_queues = set->nr_hw_queues;
|
|
set->nr_hw_queues = nr_hw_queues;
|
|
- blk_mq_update_queue_map(set);
|
|
fallback:
|
|
+ blk_mq_update_queue_map(set);
|
|
list_for_each_entry(q, &set->tag_list, tag_set_list) {
|
|
blk_mq_realloc_hw_ctxs(set, q);
|
|
if (q->nr_hw_queues != set->nr_hw_queues) {
|
|
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
|
|
index 8438e33aa447..fd9028a6bc20 100644
|
|
--- a/drivers/acpi/acpica/dsfield.c
|
|
+++ b/drivers/acpi/acpica/dsfield.c
|
|
@@ -518,13 +518,20 @@ acpi_ds_create_field(union acpi_parse_object *op,
|
|
info.region_node = region_node;
|
|
|
|
status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
|
|
+ if (ACPI_FAILURE(status)) {
|
|
+ return_ACPI_STATUS(status);
|
|
+ }
|
|
+
|
|
if (info.region_node->object->region.space_id ==
|
|
- ACPI_ADR_SPACE_PLATFORM_COMM
|
|
- && !(region_node->object->field.internal_pcc_buffer =
|
|
- ACPI_ALLOCATE_ZEROED(info.region_node->object->region.
|
|
- length))) {
|
|
- return_ACPI_STATUS(AE_NO_MEMORY);
|
|
+ ACPI_ADR_SPACE_PLATFORM_COMM) {
|
|
+ region_node->object->field.internal_pcc_buffer =
|
|
+ ACPI_ALLOCATE_ZEROED(info.region_node->object->region.
|
|
+ length);
|
|
+ if (!region_node->object->field.internal_pcc_buffer) {
|
|
+ return_ACPI_STATUS(AE_NO_MEMORY);
|
|
+ }
|
|
}
|
|
+
|
|
return_ACPI_STATUS(status);
|
|
}
|
|
|
|
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
|
|
index 5a7551d060f2..bc95a5eebd13 100644
|
|
--- a/drivers/acpi/arm64/iort.c
|
|
+++ b/drivers/acpi/arm64/iort.c
|
|
@@ -361,6 +361,7 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
|
|
static int iort_get_id_mapping_index(struct acpi_iort_node *node)
|
|
{
|
|
struct acpi_iort_smmu_v3 *smmu;
|
|
+ struct acpi_iort_pmcg *pmcg;
|
|
|
|
switch (node->type) {
|
|
case ACPI_IORT_NODE_SMMU_V3:
|
|
@@ -388,6 +389,10 @@ static int iort_get_id_mapping_index(struct acpi_iort_node *node)
|
|
|
|
return smmu->id_mapping_index;
|
|
case ACPI_IORT_NODE_PMCG:
|
|
+ pmcg = (struct acpi_iort_pmcg *)node->node_data;
|
|
+ if (pmcg->overflow_gsiv || node->mapping_count == 0)
|
|
+ return -EINVAL;
|
|
+
|
|
return 0;
|
|
default:
|
|
return -EINVAL;
|
|
diff --git a/drivers/acpi/evged.c b/drivers/acpi/evged.c
|
|
index 6d7a522952bf..ccd900690b6f 100644
|
|
--- a/drivers/acpi/evged.c
|
|
+++ b/drivers/acpi/evged.c
|
|
@@ -94,7 +94,7 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
|
|
trigger = p->triggering;
|
|
} else {
|
|
gsi = pext->interrupts[0];
|
|
- trigger = p->triggering;
|
|
+ trigger = pext->triggering;
|
|
}
|
|
|
|
irq = r.start;
|
|
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c
|
|
index f02a4bdc0ca7..dd29d687cd38 100644
|
|
--- a/drivers/bluetooth/btbcm.c
|
|
+++ b/drivers/bluetooth/btbcm.c
|
|
@@ -329,6 +329,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
|
|
{ 0x410e, "BCM43341B0" }, /* 002.001.014 */
|
|
{ 0x4204, "BCM2076B1" }, /* 002.002.004 */
|
|
{ 0x4406, "BCM4324B3" }, /* 002.004.006 */
|
|
+ { 0x4606, "BCM4324B5" }, /* 002.006.006 */
|
|
{ 0x6109, "BCM4335C0" }, /* 003.001.009 */
|
|
{ 0x610c, "BCM4354" }, /* 003.001.012 */
|
|
{ 0x2122, "BCM4343A0" }, /* 001.001.034 */
|
|
@@ -343,6 +344,7 @@ static const struct bcm_subver_table bcm_uart_subver_table[] = {
|
|
};
|
|
|
|
static const struct bcm_subver_table bcm_usb_subver_table[] = {
|
|
+ { 0x2105, "BCM20703A1" }, /* 001.001.005 */
|
|
{ 0x210b, "BCM43142A0" }, /* 001.001.011 */
|
|
{ 0x2112, "BCM4314A0" }, /* 001.001.018 */
|
|
{ 0x2118, "BCM20702A0" }, /* 001.001.024 */
|
|
diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c
|
|
index e11169ad8247..8a81fbca5c9d 100644
|
|
--- a/drivers/bluetooth/btmtkuart.c
|
|
+++ b/drivers/bluetooth/btmtkuart.c
|
|
@@ -1015,7 +1015,7 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
|
if (btmtkuart_is_standalone(bdev)) {
|
|
err = clk_prepare_enable(bdev->osc);
|
|
if (err < 0)
|
|
- return err;
|
|
+ goto err_hci_free_dev;
|
|
|
|
if (bdev->boot) {
|
|
gpiod_set_value_cansleep(bdev->boot, 1);
|
|
@@ -1028,10 +1028,8 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
|
|
|
/* Power on */
|
|
err = regulator_enable(bdev->vcc);
|
|
- if (err < 0) {
|
|
- clk_disable_unprepare(bdev->osc);
|
|
- return err;
|
|
- }
|
|
+ if (err < 0)
|
|
+ goto err_clk_disable_unprepare;
|
|
|
|
/* Reset if the reset-gpios is available otherwise the board
|
|
* -level design should be guaranteed.
|
|
@@ -1063,7 +1061,6 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
|
err = hci_register_dev(hdev);
|
|
if (err < 0) {
|
|
dev_err(&serdev->dev, "Can't register HCI device\n");
|
|
- hci_free_dev(hdev);
|
|
goto err_regulator_disable;
|
|
}
|
|
|
|
@@ -1072,6 +1069,11 @@ static int btmtkuart_probe(struct serdev_device *serdev)
|
|
err_regulator_disable:
|
|
if (btmtkuart_is_standalone(bdev))
|
|
regulator_disable(bdev->vcc);
|
|
+err_clk_disable_unprepare:
|
|
+ if (btmtkuart_is_standalone(bdev))
|
|
+ clk_disable_unprepare(bdev->osc);
|
|
+err_hci_free_dev:
|
|
+ hci_free_dev(hdev);
|
|
|
|
return err;
|
|
}
|
|
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
|
|
index 7646636f2d18..94ed734c1d7e 100644
|
|
--- a/drivers/bluetooth/hci_bcm.c
|
|
+++ b/drivers/bluetooth/hci_bcm.c
|
|
@@ -107,6 +107,7 @@ struct bcm_device {
|
|
u32 oper_speed;
|
|
int irq;
|
|
bool irq_active_low;
|
|
+ bool irq_acquired;
|
|
|
|
#ifdef CONFIG_PM
|
|
struct hci_uart *hu;
|
|
@@ -319,6 +320,8 @@ static int bcm_request_irq(struct bcm_data *bcm)
|
|
goto unlock;
|
|
}
|
|
|
|
+ bdev->irq_acquired = true;
|
|
+
|
|
device_init_wakeup(bdev->dev, true);
|
|
|
|
pm_runtime_set_autosuspend_delay(bdev->dev,
|
|
@@ -487,7 +490,7 @@ static int bcm_close(struct hci_uart *hu)
|
|
}
|
|
|
|
if (bdev) {
|
|
- if (IS_ENABLED(CONFIG_PM) && bdev->irq > 0) {
|
|
+ if (IS_ENABLED(CONFIG_PM) && bdev->irq_acquired) {
|
|
devm_free_irq(bdev->dev, bdev->irq, bdev);
|
|
device_init_wakeup(bdev->dev, false);
|
|
pm_runtime_disable(bdev->dev);
|
|
diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c
|
|
index 76f9cd039195..14e127e9a740 100644
|
|
--- a/drivers/clk/mediatek/clk-mux.c
|
|
+++ b/drivers/clk/mediatek/clk-mux.c
|
|
@@ -160,7 +160,7 @@ struct clk *mtk_clk_register_mux(const struct mtk_mux *mux,
|
|
spinlock_t *lock)
|
|
{
|
|
struct mtk_clk_mux *clk_mux;
|
|
- struct clk_init_data init;
|
|
+ struct clk_init_data init = {};
|
|
struct clk *clk;
|
|
|
|
clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL);
|
|
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
|
|
index 654766538f93..10ce69548f1b 100644
|
|
--- a/drivers/clocksource/dw_apb_timer.c
|
|
+++ b/drivers/clocksource/dw_apb_timer.c
|
|
@@ -222,7 +222,8 @@ static int apbt_next_event(unsigned long delta,
|
|
/**
|
|
* dw_apb_clockevent_init() - use an APB timer as a clock_event_device
|
|
*
|
|
- * @cpu: The CPU the events will be targeted at.
|
|
+ * @cpu: The CPU the events will be targeted at or -1 if CPU affiliation
|
|
+ * isn't required.
|
|
* @name: The name used for the timer and the IRQ for it.
|
|
* @rating: The rating to give the timer.
|
|
* @base: I/O base for the timer registers.
|
|
@@ -257,7 +258,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
|
|
dw_ced->ced.max_delta_ticks = 0x7fffffff;
|
|
dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
|
|
dw_ced->ced.min_delta_ticks = 5000;
|
|
- dw_ced->ced.cpumask = cpumask_of(cpu);
|
|
+ dw_ced->ced.cpumask = cpu < 0 ? cpu_possible_mask : cpumask_of(cpu);
|
|
dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC |
|
|
CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;
|
|
dw_ced->ced.set_state_shutdown = apbt_shutdown;
|
|
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
|
|
index 8c28b127759f..6921b91b61ef 100644
|
|
--- a/drivers/clocksource/dw_apb_timer_of.c
|
|
+++ b/drivers/clocksource/dw_apb_timer_of.c
|
|
@@ -147,10 +147,6 @@ static int num_called;
|
|
static int __init dw_apb_timer_init(struct device_node *timer)
|
|
{
|
|
switch (num_called) {
|
|
- case 0:
|
|
- pr_debug("%s: found clockevent timer\n", __func__);
|
|
- add_clockevent(timer);
|
|
- break;
|
|
case 1:
|
|
pr_debug("%s: found clocksource timer\n", __func__);
|
|
add_clocksource(timer);
|
|
@@ -161,6 +157,8 @@ static int __init dw_apb_timer_init(struct device_node *timer)
|
|
#endif
|
|
break;
|
|
default:
|
|
+ pr_debug("%s: found clockevent timer\n", __func__);
|
|
+ add_clockevent(timer);
|
|
break;
|
|
}
|
|
|
|
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
|
|
index 2bb2683b493c..f8747322b3c7 100644
|
|
--- a/drivers/cpuidle/sysfs.c
|
|
+++ b/drivers/cpuidle/sysfs.c
|
|
@@ -480,7 +480,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
|
|
ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
|
|
&kdev->kobj, "state%d", i);
|
|
if (ret) {
|
|
- kfree(kobj);
|
|
+ kobject_put(&kobj->kobj);
|
|
goto error_state;
|
|
}
|
|
cpuidle_add_s2idle_attr_group(kobj);
|
|
@@ -611,7 +611,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
|
|
ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
|
|
&kdev->kobj, "driver");
|
|
if (ret) {
|
|
- kfree(kdrv);
|
|
+ kobject_put(&kdrv->kobj);
|
|
return ret;
|
|
}
|
|
|
|
@@ -705,7 +705,7 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
|
|
error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
|
|
"cpuidle");
|
|
if (error) {
|
|
- kfree(kdev);
|
|
+ kobject_put(&kdev->kobj);
|
|
return error;
|
|
}
|
|
|
|
diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig
|
|
index 8fec733f567f..63e227adbb13 100644
|
|
--- a/drivers/crypto/ccp/Kconfig
|
|
+++ b/drivers/crypto/ccp/Kconfig
|
|
@@ -10,10 +10,9 @@ config CRYPTO_DEV_CCP_DD
|
|
config CRYPTO_DEV_SP_CCP
|
|
bool "Cryptographic Coprocessor device"
|
|
default y
|
|
- depends on CRYPTO_DEV_CCP_DD
|
|
+ depends on CRYPTO_DEV_CCP_DD && DMADEVICES
|
|
select HW_RANDOM
|
|
select DMA_ENGINE
|
|
- select DMADEVICES
|
|
select CRYPTO_SHA1
|
|
select CRYPTO_SHA256
|
|
help
|
|
diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c
|
|
index 01dd418bdadc..fe2eadc0ce83 100644
|
|
--- a/drivers/crypto/chelsio/chcr_algo.c
|
|
+++ b/drivers/crypto/chelsio/chcr_algo.c
|
|
@@ -2818,7 +2818,7 @@ static void fill_sec_cpl_for_aead(struct cpl_tx_sec_pdu *sec_cpl,
|
|
unsigned int mac_mode = CHCR_SCMD_AUTH_MODE_CBCMAC;
|
|
unsigned int c_id = a_ctx(tfm)->tx_chan_id;
|
|
unsigned int ccm_xtra;
|
|
- unsigned char tag_offset = 0, auth_offset = 0;
|
|
+ unsigned int tag_offset = 0, auth_offset = 0;
|
|
unsigned int assoclen;
|
|
|
|
if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309)
|
|
diff --git a/drivers/crypto/stm32/stm32-crc32.c b/drivers/crypto/stm32/stm32-crc32.c
|
|
index 9e11c3480353..e68b856d03b6 100644
|
|
--- a/drivers/crypto/stm32/stm32-crc32.c
|
|
+++ b/drivers/crypto/stm32/stm32-crc32.c
|
|
@@ -28,8 +28,10 @@
|
|
|
|
/* Registers values */
|
|
#define CRC_CR_RESET BIT(0)
|
|
-#define CRC_CR_REVERSE (BIT(7) | BIT(6) | BIT(5))
|
|
-#define CRC_INIT_DEFAULT 0xFFFFFFFF
|
|
+#define CRC_CR_REV_IN_WORD (BIT(6) | BIT(5))
|
|
+#define CRC_CR_REV_IN_BYTE BIT(5)
|
|
+#define CRC_CR_REV_OUT BIT(7)
|
|
+#define CRC32C_INIT_DEFAULT 0xFFFFFFFF
|
|
|
|
#define CRC_AUTOSUSPEND_DELAY 50
|
|
|
|
@@ -38,8 +40,6 @@ struct stm32_crc {
|
|
struct device *dev;
|
|
void __iomem *regs;
|
|
struct clk *clk;
|
|
- u8 pending_data[sizeof(u32)];
|
|
- size_t nb_pending_bytes;
|
|
};
|
|
|
|
struct stm32_crc_list {
|
|
@@ -59,14 +59,13 @@ struct stm32_crc_ctx {
|
|
|
|
struct stm32_crc_desc_ctx {
|
|
u32 partial; /* crc32c: partial in first 4 bytes of that struct */
|
|
- struct stm32_crc *crc;
|
|
};
|
|
|
|
static int stm32_crc32_cra_init(struct crypto_tfm *tfm)
|
|
{
|
|
struct stm32_crc_ctx *mctx = crypto_tfm_ctx(tfm);
|
|
|
|
- mctx->key = CRC_INIT_DEFAULT;
|
|
+ mctx->key = 0;
|
|
mctx->poly = CRC32_POLY_LE;
|
|
return 0;
|
|
}
|
|
@@ -75,7 +74,7 @@ static int stm32_crc32c_cra_init(struct crypto_tfm *tfm)
|
|
{
|
|
struct stm32_crc_ctx *mctx = crypto_tfm_ctx(tfm);
|
|
|
|
- mctx->key = CRC_INIT_DEFAULT;
|
|
+ mctx->key = CRC32C_INIT_DEFAULT;
|
|
mctx->poly = CRC32C_POLY_LE;
|
|
return 0;
|
|
}
|
|
@@ -94,32 +93,42 @@ static int stm32_crc_setkey(struct crypto_shash *tfm, const u8 *key,
|
|
return 0;
|
|
}
|
|
|
|
+static struct stm32_crc *stm32_crc_get_next_crc(void)
|
|
+{
|
|
+ struct stm32_crc *crc;
|
|
+
|
|
+ spin_lock_bh(&crc_list.lock);
|
|
+ crc = list_first_entry(&crc_list.dev_list, struct stm32_crc, list);
|
|
+ if (crc)
|
|
+ list_move_tail(&crc->list, &crc_list.dev_list);
|
|
+ spin_unlock_bh(&crc_list.lock);
|
|
+
|
|
+ return crc;
|
|
+}
|
|
+
|
|
static int stm32_crc_init(struct shash_desc *desc)
|
|
{
|
|
struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc);
|
|
struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
|
|
struct stm32_crc *crc;
|
|
|
|
- spin_lock_bh(&crc_list.lock);
|
|
- list_for_each_entry(crc, &crc_list.dev_list, list) {
|
|
- ctx->crc = crc;
|
|
- break;
|
|
- }
|
|
- spin_unlock_bh(&crc_list.lock);
|
|
+ crc = stm32_crc_get_next_crc();
|
|
+ if (!crc)
|
|
+ return -ENODEV;
|
|
|
|
- pm_runtime_get_sync(ctx->crc->dev);
|
|
+ pm_runtime_get_sync(crc->dev);
|
|
|
|
/* Reset, set key, poly and configure in bit reverse mode */
|
|
- writel_relaxed(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT);
|
|
- writel_relaxed(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL);
|
|
- writel_relaxed(CRC_CR_RESET | CRC_CR_REVERSE, ctx->crc->regs + CRC_CR);
|
|
+ writel_relaxed(bitrev32(mctx->key), crc->regs + CRC_INIT);
|
|
+ writel_relaxed(bitrev32(mctx->poly), crc->regs + CRC_POL);
|
|
+ writel_relaxed(CRC_CR_RESET | CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
|
|
+ crc->regs + CRC_CR);
|
|
|
|
/* Store partial result */
|
|
- ctx->partial = readl_relaxed(ctx->crc->regs + CRC_DR);
|
|
- ctx->crc->nb_pending_bytes = 0;
|
|
+ ctx->partial = readl_relaxed(crc->regs + CRC_DR);
|
|
|
|
- pm_runtime_mark_last_busy(ctx->crc->dev);
|
|
- pm_runtime_put_autosuspend(ctx->crc->dev);
|
|
+ pm_runtime_mark_last_busy(crc->dev);
|
|
+ pm_runtime_put_autosuspend(crc->dev);
|
|
|
|
return 0;
|
|
}
|
|
@@ -128,31 +137,49 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8,
|
|
unsigned int length)
|
|
{
|
|
struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc);
|
|
- struct stm32_crc *crc = ctx->crc;
|
|
- u32 *d32;
|
|
- unsigned int i;
|
|
+ struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
|
|
+ struct stm32_crc *crc;
|
|
+
|
|
+ crc = stm32_crc_get_next_crc();
|
|
+ if (!crc)
|
|
+ return -ENODEV;
|
|
|
|
pm_runtime_get_sync(crc->dev);
|
|
|
|
- if (unlikely(crc->nb_pending_bytes)) {
|
|
- while (crc->nb_pending_bytes != sizeof(u32) && length) {
|
|
- /* Fill in pending data */
|
|
- crc->pending_data[crc->nb_pending_bytes++] = *(d8++);
|
|
+ /*
|
|
+ * Restore previously calculated CRC for this context as init value
|
|
+ * Restore polynomial configuration
|
|
+ * Configure in register for word input data,
|
|
+ * Configure out register in reversed bit mode data.
|
|
+ */
|
|
+ writel_relaxed(bitrev32(ctx->partial), crc->regs + CRC_INIT);
|
|
+ writel_relaxed(bitrev32(mctx->poly), crc->regs + CRC_POL);
|
|
+ writel_relaxed(CRC_CR_RESET | CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
|
|
+ crc->regs + CRC_CR);
|
|
+
|
|
+ if (d8 != PTR_ALIGN(d8, sizeof(u32))) {
|
|
+ /* Configure for byte data */
|
|
+ writel_relaxed(CRC_CR_REV_IN_BYTE | CRC_CR_REV_OUT,
|
|
+ crc->regs + CRC_CR);
|
|
+ while (d8 != PTR_ALIGN(d8, sizeof(u32)) && length) {
|
|
+ writeb_relaxed(*d8++, crc->regs + CRC_DR);
|
|
length--;
|
|
}
|
|
-
|
|
- if (crc->nb_pending_bytes == sizeof(u32)) {
|
|
- /* Process completed pending data */
|
|
- writel_relaxed(*(u32 *)crc->pending_data,
|
|
- crc->regs + CRC_DR);
|
|
- crc->nb_pending_bytes = 0;
|
|
- }
|
|
+ /* Configure for word data */
|
|
+ writel_relaxed(CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
|
|
+ crc->regs + CRC_CR);
|
|
}
|
|
|
|
- d32 = (u32 *)d8;
|
|
- for (i = 0; i < length >> 2; i++)
|
|
- /* Process 32 bits data */
|
|
- writel_relaxed(*(d32++), crc->regs + CRC_DR);
|
|
+ for (; length >= sizeof(u32); d8 += sizeof(u32), length -= sizeof(u32))
|
|
+ writel_relaxed(*((u32 *)d8), crc->regs + CRC_DR);
|
|
+
|
|
+ if (length) {
|
|
+ /* Configure for byte data */
|
|
+ writel_relaxed(CRC_CR_REV_IN_BYTE | CRC_CR_REV_OUT,
|
|
+ crc->regs + CRC_CR);
|
|
+ while (length--)
|
|
+ writeb_relaxed(*d8++, crc->regs + CRC_DR);
|
|
+ }
|
|
|
|
/* Store partial result */
|
|
ctx->partial = readl_relaxed(crc->regs + CRC_DR);
|
|
@@ -160,22 +187,6 @@ static int stm32_crc_update(struct shash_desc *desc, const u8 *d8,
|
|
pm_runtime_mark_last_busy(crc->dev);
|
|
pm_runtime_put_autosuspend(crc->dev);
|
|
|
|
- /* Check for pending data (non 32 bits) */
|
|
- length &= 3;
|
|
- if (likely(!length))
|
|
- return 0;
|
|
-
|
|
- if ((crc->nb_pending_bytes + length) >= sizeof(u32)) {
|
|
- /* Shall not happen */
|
|
- dev_err(crc->dev, "Pending data overflow\n");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- d8 = (const u8 *)d32;
|
|
- for (i = 0; i < length; i++)
|
|
- /* Store pending data */
|
|
- crc->pending_data[crc->nb_pending_bytes++] = *(d8++);
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -204,6 +215,8 @@ static int stm32_crc_digest(struct shash_desc *desc, const u8 *data,
|
|
return stm32_crc_init(desc) ?: stm32_crc_finup(desc, data, length, out);
|
|
}
|
|
|
|
+static unsigned int refcnt;
|
|
+static DEFINE_MUTEX(refcnt_lock);
|
|
static struct shash_alg algs[] = {
|
|
/* CRC-32 */
|
|
{
|
|
@@ -294,12 +307,18 @@ static int stm32_crc_probe(struct platform_device *pdev)
|
|
list_add(&crc->list, &crc_list.dev_list);
|
|
spin_unlock(&crc_list.lock);
|
|
|
|
- ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
|
|
- if (ret) {
|
|
- dev_err(dev, "Failed to register\n");
|
|
- clk_disable_unprepare(crc->clk);
|
|
- return ret;
|
|
+ mutex_lock(&refcnt_lock);
|
|
+ if (!refcnt) {
|
|
+ ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
|
|
+ if (ret) {
|
|
+ mutex_unlock(&refcnt_lock);
|
|
+ dev_err(dev, "Failed to register\n");
|
|
+ clk_disable_unprepare(crc->clk);
|
|
+ return ret;
|
|
+ }
|
|
}
|
|
+ refcnt++;
|
|
+ mutex_unlock(&refcnt_lock);
|
|
|
|
dev_info(dev, "Initialized\n");
|
|
|
|
@@ -320,7 +339,10 @@ static int stm32_crc_remove(struct platform_device *pdev)
|
|
list_del(&crc->list);
|
|
spin_unlock(&crc_list.lock);
|
|
|
|
- crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
|
|
+ mutex_lock(&refcnt_lock);
|
|
+ if (!--refcnt)
|
|
+ crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
|
|
+ mutex_unlock(&refcnt_lock);
|
|
|
|
pm_runtime_disable(crc->dev);
|
|
pm_runtime_put_noidle(crc->dev);
|
|
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
|
|
index cc5e56d752c8..ad7d2bce91cd 100644
|
|
--- a/drivers/edac/amd64_edac.c
|
|
+++ b/drivers/edac/amd64_edac.c
|
|
@@ -2317,6 +2317,15 @@ static struct amd64_family_type family_types[] = {
|
|
.dbam_to_cs = f17_addr_mask_to_cs_size,
|
|
}
|
|
},
|
|
+ [F17_M60H_CPUS] = {
|
|
+ .ctl_name = "F17h_M60h",
|
|
+ .f0_id = PCI_DEVICE_ID_AMD_17H_M60H_DF_F0,
|
|
+ .f6_id = PCI_DEVICE_ID_AMD_17H_M60H_DF_F6,
|
|
+ .ops = {
|
|
+ .early_channel_count = f17_early_channel_count,
|
|
+ .dbam_to_cs = f17_addr_mask_to_cs_size,
|
|
+ }
|
|
+ },
|
|
[F17_M70H_CPUS] = {
|
|
.ctl_name = "F17h_M70h",
|
|
.f0_id = PCI_DEVICE_ID_AMD_17H_M70H_DF_F0,
|
|
@@ -3366,6 +3375,10 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
|
|
fam_type = &family_types[F17_M30H_CPUS];
|
|
pvt->ops = &family_types[F17_M30H_CPUS].ops;
|
|
break;
|
|
+ } else if (pvt->model >= 0x60 && pvt->model <= 0x6f) {
|
|
+ fam_type = &family_types[F17_M60H_CPUS];
|
|
+ pvt->ops = &family_types[F17_M60H_CPUS].ops;
|
|
+ break;
|
|
} else if (pvt->model >= 0x70 && pvt->model <= 0x7f) {
|
|
fam_type = &family_types[F17_M70H_CPUS];
|
|
pvt->ops = &family_types[F17_M70H_CPUS].ops;
|
|
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
|
|
index 8c3cda81e619..d280b91f97cb 100644
|
|
--- a/drivers/edac/amd64_edac.h
|
|
+++ b/drivers/edac/amd64_edac.h
|
|
@@ -120,6 +120,8 @@
|
|
#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F6 0x15ee
|
|
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F0 0x1490
|
|
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F6 0x1496
|
|
+#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F0 0x1448
|
|
+#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F6 0x144e
|
|
#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F0 0x1440
|
|
#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F6 0x1446
|
|
|
|
@@ -291,6 +293,7 @@ enum amd_families {
|
|
F17_CPUS,
|
|
F17_M10H_CPUS,
|
|
F17_M30H_CPUS,
|
|
+ F17_M60H_CPUS,
|
|
F17_M70H_CPUS,
|
|
NUM_FAMILIES,
|
|
};
|
|
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
|
|
index ee0661ddb25b..8c5b5529dbc0 100644
|
|
--- a/drivers/firmware/efi/libstub/Makefile
|
|
+++ b/drivers/firmware/efi/libstub/Makefile
|
|
@@ -28,6 +28,7 @@ KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \
|
|
-D__NO_FORTIFY \
|
|
$(call cc-option,-ffreestanding) \
|
|
$(call cc-option,-fno-stack-protector) \
|
|
+ $(call cc-option,-fno-addrsig) \
|
|
-D__DISABLE_EXPORTS
|
|
|
|
GCOV_PROFILE := n
|
|
diff --git a/drivers/gnss/sirf.c b/drivers/gnss/sirf.c
|
|
index effed3a8d398..2ecb1d3e8eeb 100644
|
|
--- a/drivers/gnss/sirf.c
|
|
+++ b/drivers/gnss/sirf.c
|
|
@@ -439,14 +439,18 @@ static int sirf_probe(struct serdev_device *serdev)
|
|
|
|
data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff",
|
|
GPIOD_OUT_LOW);
|
|
- if (IS_ERR(data->on_off))
|
|
+ if (IS_ERR(data->on_off)) {
|
|
+ ret = PTR_ERR(data->on_off);
|
|
goto err_put_device;
|
|
+ }
|
|
|
|
if (data->on_off) {
|
|
data->wakeup = devm_gpiod_get_optional(dev, "sirf,wakeup",
|
|
GPIOD_IN);
|
|
- if (IS_ERR(data->wakeup))
|
|
+ if (IS_ERR(data->wakeup)) {
|
|
+ ret = PTR_ERR(data->wakeup);
|
|
goto err_put_device;
|
|
+ }
|
|
|
|
ret = regulator_enable(data->vcc);
|
|
if (ret)
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
|
|
index 8ceb44925947..5fa5158d18ee 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
|
|
@@ -161,16 +161,17 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
|
|
|
struct amdgpu_bo_list_entry vm_pd;
|
|
struct list_head list, duplicates;
|
|
+ struct dma_fence *fence = NULL;
|
|
struct ttm_validate_buffer tv;
|
|
struct ww_acquire_ctx ticket;
|
|
struct amdgpu_bo_va *bo_va;
|
|
- int r;
|
|
+ long r;
|
|
|
|
INIT_LIST_HEAD(&list);
|
|
INIT_LIST_HEAD(&duplicates);
|
|
|
|
tv.bo = &bo->tbo;
|
|
- tv.num_shared = 1;
|
|
+ tv.num_shared = 2;
|
|
list_add(&tv.head, &list);
|
|
|
|
amdgpu_vm_get_pd_bo(vm, &list, &vm_pd);
|
|
@@ -178,28 +179,34 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
|
r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates, false);
|
|
if (r) {
|
|
dev_err(adev->dev, "leaking bo va because "
|
|
- "we fail to reserve bo (%d)\n", r);
|
|
+ "we fail to reserve bo (%ld)\n", r);
|
|
return;
|
|
}
|
|
bo_va = amdgpu_vm_bo_find(vm, bo);
|
|
- if (bo_va && --bo_va->ref_count == 0) {
|
|
- amdgpu_vm_bo_rmv(adev, bo_va);
|
|
-
|
|
- if (amdgpu_vm_ready(vm)) {
|
|
- struct dma_fence *fence = NULL;
|
|
+ if (!bo_va || --bo_va->ref_count)
|
|
+ goto out_unlock;
|
|
|
|
- r = amdgpu_vm_clear_freed(adev, vm, &fence);
|
|
- if (unlikely(r)) {
|
|
- dev_err(adev->dev, "failed to clear page "
|
|
- "tables on GEM object close (%d)\n", r);
|
|
- }
|
|
+ amdgpu_vm_bo_rmv(adev, bo_va);
|
|
+ if (!amdgpu_vm_ready(vm))
|
|
+ goto out_unlock;
|
|
|
|
- if (fence) {
|
|
- amdgpu_bo_fence(bo, fence, true);
|
|
- dma_fence_put(fence);
|
|
- }
|
|
- }
|
|
+ fence = dma_resv_get_excl(bo->tbo.base.resv);
|
|
+ if (fence) {
|
|
+ amdgpu_bo_fence(bo, fence, true);
|
|
+ fence = NULL;
|
|
}
|
|
+
|
|
+ r = amdgpu_vm_clear_freed(adev, vm, &fence);
|
|
+ if (r || !fence)
|
|
+ goto out_unlock;
|
|
+
|
|
+ amdgpu_bo_fence(bo, fence, true);
|
|
+ dma_fence_put(fence);
|
|
+
|
|
+out_unlock:
|
|
+ if (unlikely(r < 0))
|
|
+ dev_err(adev->dev, "failed to clear page "
|
|
+ "tables on GEM object close (%ld)\n", r);
|
|
ttm_eu_backoff_reservation(&ticket, &list);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
|
|
index 51263b8d94b1..d1d2372ab7ca 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
|
|
@@ -370,6 +370,15 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
|
|
if (current_level == level)
|
|
return count;
|
|
|
|
+ if (adev->asic_type == CHIP_RAVEN) {
|
|
+ if (adev->rev_id < 8) {
|
|
+ if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && level == AMD_DPM_FORCED_LEVEL_MANUAL)
|
|
+ amdgpu_gfx_off_ctrl(adev, false);
|
|
+ else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && level != AMD_DPM_FORCED_LEVEL_MANUAL)
|
|
+ amdgpu_gfx_off_ctrl(adev, true);
|
|
+ }
|
|
+ }
|
|
+
|
|
/* profile_exit setting is valid only when current mode is in profile mode */
|
|
if (!(current_level & (AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
|
|
AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
|
|
@@ -416,8 +425,11 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev,
|
|
ret = smu_get_power_num_states(&adev->smu, &data);
|
|
if (ret)
|
|
return ret;
|
|
- } else if (adev->powerplay.pp_funcs->get_pp_num_states)
|
|
+ } else if (adev->powerplay.pp_funcs->get_pp_num_states) {
|
|
amdgpu_dpm_get_pp_num_states(adev, &data);
|
|
+ } else {
|
|
+ memset(&data, 0, sizeof(data));
|
|
+ }
|
|
|
|
buf_len = snprintf(buf, PAGE_SIZE, "states: %d\n", data.nums);
|
|
for (i = 0; i < data.nums; i++)
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
|
index c7514f743409..6335bd4ae374 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
|
|
@@ -2867,10 +2867,17 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm, uns
|
|
WARN_ONCE((vm->use_cpu_for_update && !amdgpu_gmc_vram_full_visible(&adev->gmc)),
|
|
"CPU update of VM recommended only for large BAR system\n");
|
|
|
|
- if (vm->use_cpu_for_update)
|
|
+ if (vm->use_cpu_for_update) {
|
|
+ /* Sync with last SDMA update/clear before switching to CPU */
|
|
+ r = amdgpu_bo_sync_wait(vm->root.base.bo,
|
|
+ AMDGPU_FENCE_OWNER_UNDEFINED, true);
|
|
+ if (r)
|
|
+ goto free_idr;
|
|
+
|
|
vm->update_funcs = &amdgpu_vm_cpu_funcs;
|
|
- else
|
|
+ } else {
|
|
vm->update_funcs = &amdgpu_vm_sdma_funcs;
|
|
+ }
|
|
dma_fence_put(vm->last_update);
|
|
vm->last_update = NULL;
|
|
|
|
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
|
|
index a428185be2c1..d05b3033b510 100644
|
|
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
|
|
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
|
|
@@ -19,13 +19,15 @@ static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
|
|
{
|
|
switch (fs) {
|
|
case 32000:
|
|
- *n = 4096;
|
|
+ case 48000:
|
|
+ case 96000:
|
|
+ case 192000:
|
|
+ *n = fs * 128 / 1000;
|
|
break;
|
|
case 44100:
|
|
- *n = 6272;
|
|
- break;
|
|
- case 48000:
|
|
- *n = 6144;
|
|
+ case 88200:
|
|
+ case 176400:
|
|
+ *n = fs * 128 / 900;
|
|
break;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
|
|
index 35bb825d1918..8c8c92fc82e9 100644
|
|
--- a/drivers/gpu/drm/mcde/mcde_dsi.c
|
|
+++ b/drivers/gpu/drm/mcde/mcde_dsi.c
|
|
@@ -940,10 +940,9 @@ static int mcde_dsi_bind(struct device *dev, struct device *master,
|
|
panel = NULL;
|
|
|
|
bridge = of_drm_find_bridge(child);
|
|
- if (IS_ERR(bridge)) {
|
|
- dev_err(dev, "failed to find bridge (%ld)\n",
|
|
- PTR_ERR(bridge));
|
|
- return PTR_ERR(bridge);
|
|
+ if (!bridge) {
|
|
+ dev_err(dev, "failed to find bridge\n");
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
}
|
|
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
|
|
index be6d95c5ff25..48de07e9059e 100644
|
|
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
|
|
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
|
|
@@ -10,7 +10,9 @@
|
|
#include <linux/kernel.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_device.h>
|
|
+#include <linux/of_gpio.h>
|
|
#include <linux/of_graph.h>
|
|
+#include <linux/pinctrl/consumer.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/types.h>
|
|
|
|
@@ -73,6 +75,9 @@ struct mtk_dpi {
|
|
enum mtk_dpi_out_yc_map yc_map;
|
|
enum mtk_dpi_out_bit_num bit_num;
|
|
enum mtk_dpi_out_channel_swap channel_swap;
|
|
+ struct pinctrl *pinctrl;
|
|
+ struct pinctrl_state *pins_gpio;
|
|
+ struct pinctrl_state *pins_dpi;
|
|
int refcount;
|
|
};
|
|
|
|
@@ -378,6 +383,9 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi)
|
|
if (--dpi->refcount != 0)
|
|
return;
|
|
|
|
+ if (dpi->pinctrl && dpi->pins_gpio)
|
|
+ pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
|
|
+
|
|
mtk_dpi_disable(dpi);
|
|
clk_disable_unprepare(dpi->pixel_clk);
|
|
clk_disable_unprepare(dpi->engine_clk);
|
|
@@ -402,6 +410,9 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
|
|
goto err_pixel;
|
|
}
|
|
|
|
+ if (dpi->pinctrl && dpi->pins_dpi)
|
|
+ pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
|
|
+
|
|
mtk_dpi_enable(dpi);
|
|
return 0;
|
|
|
|
@@ -689,6 +700,26 @@ static int mtk_dpi_probe(struct platform_device *pdev)
|
|
dpi->dev = dev;
|
|
dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);
|
|
|
|
+ dpi->pinctrl = devm_pinctrl_get(&pdev->dev);
|
|
+ if (IS_ERR(dpi->pinctrl)) {
|
|
+ dpi->pinctrl = NULL;
|
|
+ dev_dbg(&pdev->dev, "Cannot find pinctrl!\n");
|
|
+ }
|
|
+ if (dpi->pinctrl) {
|
|
+ dpi->pins_gpio = pinctrl_lookup_state(dpi->pinctrl, "sleep");
|
|
+ if (IS_ERR(dpi->pins_gpio)) {
|
|
+ dpi->pins_gpio = NULL;
|
|
+ dev_dbg(&pdev->dev, "Cannot find pinctrl idle!\n");
|
|
+ }
|
|
+ if (dpi->pins_gpio)
|
|
+ pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
|
|
+
|
|
+ dpi->pins_dpi = pinctrl_lookup_state(dpi->pinctrl, "default");
|
|
+ if (IS_ERR(dpi->pins_dpi)) {
|
|
+ dpi->pins_dpi = NULL;
|
|
+ dev_dbg(&pdev->dev, "Cannot find pinctrl active!\n");
|
|
+ }
|
|
+ }
|
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
dpi->regs = devm_ioremap_resource(dev, mem);
|
|
if (IS_ERR(dpi->regs)) {
|
|
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
|
|
index c6430027169f..a0021fc25b27 100644
|
|
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
|
|
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
|
|
@@ -785,13 +785,15 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
|
|
|
|
drm_plane_create_alpha_property(&plane->plane);
|
|
|
|
- if (type == DRM_PLANE_TYPE_PRIMARY)
|
|
- continue;
|
|
-
|
|
- drm_object_attach_property(&plane->plane.base,
|
|
- rcdu->props.colorkey,
|
|
- RCAR_DU_COLORKEY_NONE);
|
|
- drm_plane_create_zpos_property(&plane->plane, 1, 1, 7);
|
|
+ if (type == DRM_PLANE_TYPE_PRIMARY) {
|
|
+ drm_plane_create_zpos_immutable_property(&plane->plane,
|
|
+ 0);
|
|
+ } else {
|
|
+ drm_object_attach_property(&plane->plane.base,
|
|
+ rcdu->props.colorkey,
|
|
+ RCAR_DU_COLORKEY_NONE);
|
|
+ drm_plane_create_zpos_property(&plane->plane, 1, 1, 7);
|
|
+ }
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
|
|
index 5e4faf258c31..f1a81c9b184d 100644
|
|
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
|
|
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
|
|
@@ -392,12 +392,14 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np,
|
|
drm_plane_helper_add(&plane->plane,
|
|
&rcar_du_vsp_plane_helper_funcs);
|
|
|
|
- if (type == DRM_PLANE_TYPE_PRIMARY)
|
|
- continue;
|
|
-
|
|
- drm_plane_create_alpha_property(&plane->plane);
|
|
- drm_plane_create_zpos_property(&plane->plane, 1, 1,
|
|
- vsp->num_planes - 1);
|
|
+ if (type == DRM_PLANE_TYPE_PRIMARY) {
|
|
+ drm_plane_create_zpos_immutable_property(&plane->plane,
|
|
+ 0);
|
|
+ } else {
|
|
+ drm_plane_create_alpha_property(&plane->plane);
|
|
+ drm_plane_create_zpos_property(&plane->plane, 1, 1,
|
|
+ vsp->num_planes - 1);
|
|
+ }
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
|
|
index 6e4c015783ff..c90d79096e8c 100644
|
|
--- a/drivers/hv/connection.c
|
|
+++ b/drivers/hv/connection.c
|
|
@@ -67,7 +67,6 @@ static __u32 vmbus_get_next_version(__u32 current_version)
|
|
int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version)
|
|
{
|
|
int ret = 0;
|
|
- unsigned int cur_cpu;
|
|
struct vmbus_channel_initiate_contact *msg;
|
|
unsigned long flags;
|
|
|
|
@@ -100,24 +99,7 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version)
|
|
|
|
msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
|
|
msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
|
|
- /*
|
|
- * We want all channel messages to be delivered on CPU 0.
|
|
- * This has been the behavior pre-win8. This is not
|
|
- * perf issue and having all channel messages delivered on CPU 0
|
|
- * would be ok.
|
|
- * For post win8 hosts, we support receiving channel messagges on
|
|
- * all the CPUs. This is needed for kexec to work correctly where
|
|
- * the CPU attempting to connect may not be CPU 0.
|
|
- */
|
|
- if (version >= VERSION_WIN8_1) {
|
|
- cur_cpu = get_cpu();
|
|
- msg->target_vcpu = hv_cpu_number_to_vp_number(cur_cpu);
|
|
- vmbus_connection.connect_cpu = cur_cpu;
|
|
- put_cpu();
|
|
- } else {
|
|
- msg->target_vcpu = 0;
|
|
- vmbus_connection.connect_cpu = 0;
|
|
- }
|
|
+ msg->target_vcpu = hv_cpu_number_to_vp_number(VMBUS_CONNECT_CPU);
|
|
|
|
/*
|
|
* Add to list before we send the request since we may
|
|
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
|
|
index fcc52797c169..d6320022af15 100644
|
|
--- a/drivers/hv/hv.c
|
|
+++ b/drivers/hv/hv.c
|
|
@@ -249,6 +249,13 @@ int hv_synic_cleanup(unsigned int cpu)
|
|
bool channel_found = false;
|
|
unsigned long flags;
|
|
|
|
+ /*
|
|
+ * Hyper-V does not provide a way to change the connect CPU once
|
|
+ * it is set; we must prevent the connect CPU from going offline.
|
|
+ */
|
|
+ if (cpu == VMBUS_CONNECT_CPU)
|
|
+ return -EBUSY;
|
|
+
|
|
/*
|
|
* Search for channels which are bound to the CPU we're about to
|
|
* cleanup. In case we find one and vmbus is still connected we need to
|
|
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
|
|
index af9379a3bf89..cabcb66e7c5e 100644
|
|
--- a/drivers/hv/hyperv_vmbus.h
|
|
+++ b/drivers/hv/hyperv_vmbus.h
|
|
@@ -212,12 +212,13 @@ enum vmbus_connect_state {
|
|
|
|
#define MAX_SIZE_CHANNEL_MESSAGE HV_MESSAGE_PAYLOAD_BYTE_COUNT
|
|
|
|
-struct vmbus_connection {
|
|
- /*
|
|
- * CPU on which the initial host contact was made.
|
|
- */
|
|
- int connect_cpu;
|
|
+/*
|
|
+ * The CPU that Hyper-V will interrupt for VMBUS messages, such as
|
|
+ * CHANNELMSG_OFFERCHANNEL and CHANNELMSG_RESCIND_CHANNELOFFER.
|
|
+ */
|
|
+#define VMBUS_CONNECT_CPU 0
|
|
|
|
+struct vmbus_connection {
|
|
u32 msg_conn_id;
|
|
|
|
atomic_t offer_in_progress;
|
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
|
index 9cdd434bb340..160ff640485b 100644
|
|
--- a/drivers/hv/vmbus_drv.c
|
|
+++ b/drivers/hv/vmbus_drv.c
|
|
@@ -1092,14 +1092,28 @@ void vmbus_on_msg_dpc(unsigned long data)
|
|
/*
|
|
* If we are handling the rescind message;
|
|
* schedule the work on the global work queue.
|
|
+ *
|
|
+ * The OFFER message and the RESCIND message should
|
|
+ * not be handled by the same serialized work queue,
|
|
+ * because the OFFER handler may call vmbus_open(),
|
|
+ * which tries to open the channel by sending an
|
|
+ * OPEN_CHANNEL message to the host and waits for
|
|
+ * the host's response; however, if the host has
|
|
+ * rescinded the channel before it receives the
|
|
+ * OPEN_CHANNEL message, the host just silently
|
|
+ * ignores the OPEN_CHANNEL message; as a result,
|
|
+ * the guest's OFFER handler hangs for ever, if we
|
|
+ * handle the RESCIND message in the same serialized
|
|
+ * work queue: the RESCIND handler can not start to
|
|
+ * run before the OFFER handler finishes.
|
|
*/
|
|
- schedule_work_on(vmbus_connection.connect_cpu,
|
|
+ schedule_work_on(VMBUS_CONNECT_CPU,
|
|
&ctx->work);
|
|
break;
|
|
|
|
case CHANNELMSG_OFFERCHANNEL:
|
|
atomic_inc(&vmbus_connection.offer_in_progress);
|
|
- queue_work_on(vmbus_connection.connect_cpu,
|
|
+ queue_work_on(VMBUS_CONNECT_CPU,
|
|
vmbus_connection.work_queue,
|
|
&ctx->work);
|
|
break;
|
|
@@ -1146,7 +1160,7 @@ static void vmbus_force_channel_rescinded(struct vmbus_channel *channel)
|
|
|
|
INIT_WORK(&ctx->work, vmbus_onmessage_work);
|
|
|
|
- queue_work_on(vmbus_connection.connect_cpu,
|
|
+ queue_work_on(VMBUS_CONNECT_CPU,
|
|
vmbus_connection.work_queue,
|
|
&ctx->work);
|
|
}
|
|
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
|
|
index 5c1dddde193c..f96fd8efb45a 100644
|
|
--- a/drivers/hwmon/k10temp.c
|
|
+++ b/drivers/hwmon/k10temp.c
|
|
@@ -349,6 +349,7 @@ static const struct pci_device_id k10temp_id_table[] = {
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
|
|
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) },
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
|
|
{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
|
|
{}
|
|
diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
|
|
index 4150301a89a5..e8377ce0a95a 100644
|
|
--- a/drivers/macintosh/windfarm_pm112.c
|
|
+++ b/drivers/macintosh/windfarm_pm112.c
|
|
@@ -132,14 +132,6 @@ static int create_cpu_loop(int cpu)
|
|
s32 tmax;
|
|
int fmin;
|
|
|
|
- /* Get PID params from the appropriate SAT */
|
|
- hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL);
|
|
- if (hdr == NULL) {
|
|
- printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n");
|
|
- return -EINVAL;
|
|
- }
|
|
- piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
|
|
-
|
|
/* Get FVT params to get Tmax; if not found, assume default */
|
|
hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL);
|
|
if (hdr) {
|
|
@@ -152,6 +144,16 @@ static int create_cpu_loop(int cpu)
|
|
if (tmax < cpu_all_tmax)
|
|
cpu_all_tmax = tmax;
|
|
|
|
+ kfree(hdr);
|
|
+
|
|
+ /* Get PID params from the appropriate SAT */
|
|
+ hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL);
|
|
+ if (hdr == NULL) {
|
|
+ printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
|
|
+
|
|
/*
|
|
* Darwin has a minimum fan speed of 1000 rpm for the 4-way and
|
|
* 515 for the 2-way. That appears to be overkill, so for now,
|
|
@@ -174,6 +176,9 @@ static int create_cpu_loop(int cpu)
|
|
pid.min = fmin;
|
|
|
|
wf_cpu_pid_init(&cpu_pid[cpu], &pid);
|
|
+
|
|
+ kfree(hdr);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
|
|
index 658b0f4a01f5..68901745eb20 100644
|
|
--- a/drivers/md/bcache/super.c
|
|
+++ b/drivers/md/bcache/super.c
|
|
@@ -789,7 +789,9 @@ static void bcache_device_free(struct bcache_device *d)
|
|
bcache_device_detach(d);
|
|
|
|
if (disk) {
|
|
- if (disk->flags & GENHD_FL_UP)
|
|
+ bool disk_added = (disk->flags & GENHD_FL_UP) != 0;
|
|
+
|
|
+ if (disk_added)
|
|
del_gendisk(disk);
|
|
|
|
if (disk->queue)
|
|
@@ -797,7 +799,8 @@ static void bcache_device_free(struct bcache_device *d)
|
|
|
|
ida_simple_remove(&bcache_device_idx,
|
|
first_minor_to_idx(disk->first_minor));
|
|
- put_disk(disk);
|
|
+ if (disk_added)
|
|
+ put_disk(disk);
|
|
}
|
|
|
|
bioset_exit(&d->bio_split);
|
|
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
|
|
index 492bbe0584d9..ffbda729e26e 100644
|
|
--- a/drivers/md/dm-crypt.c
|
|
+++ b/drivers/md/dm-crypt.c
|
|
@@ -2957,7 +2957,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
|
limits->max_segment_size = PAGE_SIZE;
|
|
|
|
limits->logical_block_size =
|
|
- max_t(unsigned short, limits->logical_block_size, cc->sector_size);
|
|
+ max_t(unsigned, limits->logical_block_size, cc->sector_size);
|
|
limits->physical_block_size =
|
|
max_t(unsigned, limits->physical_block_size, cc->sector_size);
|
|
limits->io_min = max_t(unsigned, limits->io_min, cc->sector_size);
|
|
diff --git a/drivers/md/md.c b/drivers/md/md.c
|
|
index 6b69a12ca2d8..5a378a453a2d 100644
|
|
--- a/drivers/md/md.c
|
|
+++ b/drivers/md/md.c
|
|
@@ -7607,7 +7607,8 @@ static int md_open(struct block_device *bdev, fmode_t mode)
|
|
*/
|
|
mddev_put(mddev);
|
|
/* Wait until bdev->bd_disk is definitely gone */
|
|
- flush_workqueue(md_misc_wq);
|
|
+ if (work_pending(&mddev->del_work))
|
|
+ flush_workqueue(md_misc_wq);
|
|
/* Then retry the open from the top */
|
|
return -ERESTARTSYS;
|
|
}
|
|
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
|
|
index 36cd7c2fbf40..a3cbc9f4fec1 100644
|
|
--- a/drivers/md/raid5.c
|
|
+++ b/drivers/md/raid5.c
|
|
@@ -2228,14 +2228,19 @@ static int grow_stripes(struct r5conf *conf, int num)
|
|
* of the P and Q blocks.
|
|
*/
|
|
static int scribble_alloc(struct raid5_percpu *percpu,
|
|
- int num, int cnt, gfp_t flags)
|
|
+ int num, int cnt)
|
|
{
|
|
size_t obj_size =
|
|
sizeof(struct page *) * (num+2) +
|
|
sizeof(addr_conv_t) * (num+2);
|
|
void *scribble;
|
|
|
|
- scribble = kvmalloc_array(cnt, obj_size, flags);
|
|
+ /*
|
|
+ * If here is in raid array suspend context, it is in memalloc noio
|
|
+ * context as well, there is no potential recursive memory reclaim
|
|
+ * I/Os with the GFP_KERNEL flag.
|
|
+ */
|
|
+ scribble = kvmalloc_array(cnt, obj_size, GFP_KERNEL);
|
|
if (!scribble)
|
|
return -ENOMEM;
|
|
|
|
@@ -2267,8 +2272,7 @@ static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
|
|
|
|
percpu = per_cpu_ptr(conf->percpu, cpu);
|
|
err = scribble_alloc(percpu, new_disks,
|
|
- new_sectors / STRIPE_SECTORS,
|
|
- GFP_NOIO);
|
|
+ new_sectors / STRIPE_SECTORS);
|
|
if (err)
|
|
break;
|
|
}
|
|
@@ -6765,8 +6769,7 @@ static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu
|
|
conf->previous_raid_disks),
|
|
max(conf->chunk_sectors,
|
|
conf->prev_chunk_sectors)
|
|
- / STRIPE_SECTORS,
|
|
- GFP_KERNEL)) {
|
|
+ / STRIPE_SECTORS)) {
|
|
free_scratch_buffer(conf, percpu);
|
|
return -ENOMEM;
|
|
}
|
|
diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c
|
|
index b14c09cd9593..06383b26712b 100644
|
|
--- a/drivers/media/cec/cec-adap.c
|
|
+++ b/drivers/media/cec/cec-adap.c
|
|
@@ -1732,6 +1732,10 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
|
|
unsigned j;
|
|
|
|
log_addrs->log_addr[i] = CEC_LOG_ADDR_INVALID;
|
|
+ if (log_addrs->log_addr_type[i] > CEC_LOG_ADDR_TYPE_UNREGISTERED) {
|
|
+ dprintk(1, "unknown logical address type\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
if (type_mask & (1 << log_addrs->log_addr_type[i])) {
|
|
dprintk(1, "duplicate logical address type\n");
|
|
return -EINVAL;
|
|
@@ -1752,10 +1756,6 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
|
|
dprintk(1, "invalid primary device type\n");
|
|
return -EINVAL;
|
|
}
|
|
- if (log_addrs->log_addr_type[i] > CEC_LOG_ADDR_TYPE_UNREGISTERED) {
|
|
- dprintk(1, "unknown logical address type\n");
|
|
- return -EINVAL;
|
|
- }
|
|
for (j = 0; j < feature_sz; j++) {
|
|
if ((features[j] & 0x80) == 0) {
|
|
if (op_is_dev_features)
|
|
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
|
|
index 917fe034af37..032b6d7dd582 100644
|
|
--- a/drivers/media/dvb-core/dvbdev.c
|
|
+++ b/drivers/media/dvb-core/dvbdev.c
|
|
@@ -707,9 +707,10 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
|
|
}
|
|
|
|
if (ntuner && ndemod) {
|
|
- pad_source = media_get_pad_index(tuner, true,
|
|
+ /* NOTE: first found tuner source pad presumed correct */
|
|
+ pad_source = media_get_pad_index(tuner, false,
|
|
PAD_SIGNAL_ANALOG);
|
|
- if (pad_source)
|
|
+ if (pad_source < 0)
|
|
return -EINVAL;
|
|
ret = media_create_pad_links(mdev,
|
|
MEDIA_ENT_F_TUNER,
|
|
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
|
|
index a398ea81e422..266e947572c1 100644
|
|
--- a/drivers/media/i2c/ov5640.c
|
|
+++ b/drivers/media/i2c/ov5640.c
|
|
@@ -3068,8 +3068,8 @@ static int ov5640_probe(struct i2c_client *client)
|
|
free_ctrls:
|
|
v4l2_ctrl_handler_free(&sensor->ctrls.handler);
|
|
entity_cleanup:
|
|
- mutex_destroy(&sensor->lock);
|
|
media_entity_cleanup(&sensor->sd.entity);
|
|
+ mutex_destroy(&sensor->lock);
|
|
return ret;
|
|
}
|
|
|
|
@@ -3079,9 +3079,9 @@ static int ov5640_remove(struct i2c_client *client)
|
|
struct ov5640_dev *sensor = to_ov5640_dev(sd);
|
|
|
|
v4l2_async_unregister_subdev(&sensor->sd);
|
|
- mutex_destroy(&sensor->lock);
|
|
media_entity_cleanup(&sensor->sd.entity);
|
|
v4l2_ctrl_handler_free(&sensor->ctrls.handler);
|
|
+ mutex_destroy(&sensor->lock);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/media/platform/rcar-fcp.c b/drivers/media/platform/rcar-fcp.c
|
|
index 43c78620c9d8..5c6b00737fe7 100644
|
|
--- a/drivers/media/platform/rcar-fcp.c
|
|
+++ b/drivers/media/platform/rcar-fcp.c
|
|
@@ -8,6 +8,7 @@
|
|
*/
|
|
|
|
#include <linux/device.h>
|
|
+#include <linux/dma-mapping.h>
|
|
#include <linux/list.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mod_devicetable.h>
|
|
@@ -21,6 +22,7 @@
|
|
struct rcar_fcp_device {
|
|
struct list_head list;
|
|
struct device *dev;
|
|
+ struct device_dma_parameters dma_parms;
|
|
};
|
|
|
|
static LIST_HEAD(fcp_devices);
|
|
@@ -136,6 +138,9 @@ static int rcar_fcp_probe(struct platform_device *pdev)
|
|
|
|
fcp->dev = &pdev->dev;
|
|
|
|
+ fcp->dev->dma_parms = &fcp->dma_parms;
|
|
+ dma_set_max_seg_size(fcp->dev, DMA_BIT_MASK(32));
|
|
+
|
|
pm_runtime_enable(&pdev->dev);
|
|
|
|
mutex_lock(&fcp_lock);
|
|
diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c
|
|
index 82350097503e..84ec36156f73 100644
|
|
--- a/drivers/media/platform/vicodec/vicodec-core.c
|
|
+++ b/drivers/media/platform/vicodec/vicodec-core.c
|
|
@@ -2172,16 +2172,19 @@ static int vicodec_probe(struct platform_device *pdev)
|
|
|
|
platform_set_drvdata(pdev, dev);
|
|
|
|
- if (register_instance(dev, &dev->stateful_enc,
|
|
- "stateful-encoder", true))
|
|
+ ret = register_instance(dev, &dev->stateful_enc, "stateful-encoder",
|
|
+ true);
|
|
+ if (ret)
|
|
goto unreg_dev;
|
|
|
|
- if (register_instance(dev, &dev->stateful_dec,
|
|
- "stateful-decoder", false))
|
|
+ ret = register_instance(dev, &dev->stateful_dec, "stateful-decoder",
|
|
+ false);
|
|
+ if (ret)
|
|
goto unreg_sf_enc;
|
|
|
|
- if (register_instance(dev, &dev->stateless_dec,
|
|
- "stateless-decoder", false))
|
|
+ ret = register_instance(dev, &dev->stateless_dec, "stateless-decoder",
|
|
+ false);
|
|
+ if (ret)
|
|
goto unreg_sf_dec;
|
|
|
|
#ifdef CONFIG_MEDIA_CONTROLLER
|
|
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
|
|
index e87040d6eca7..a39e1966816b 100644
|
|
--- a/drivers/media/tuners/si2157.c
|
|
+++ b/drivers/media/tuners/si2157.c
|
|
@@ -75,24 +75,23 @@ static int si2157_init(struct dvb_frontend *fe)
|
|
struct si2157_cmd cmd;
|
|
const struct firmware *fw;
|
|
const char *fw_name;
|
|
- unsigned int uitmp, chip_id;
|
|
+ unsigned int chip_id, xtal_trim;
|
|
|
|
dev_dbg(&client->dev, "\n");
|
|
|
|
- /* Returned IF frequency is garbage when firmware is not running */
|
|
- memcpy(cmd.args, "\x15\x00\x06\x07", 4);
|
|
+ /* Try to get Xtal trim property, to verify tuner still running */
|
|
+ memcpy(cmd.args, "\x15\x00\x04\x02", 4);
|
|
cmd.wlen = 4;
|
|
cmd.rlen = 4;
|
|
ret = si2157_cmd_execute(client, &cmd);
|
|
- if (ret)
|
|
- goto err;
|
|
|
|
- uitmp = cmd.args[2] << 0 | cmd.args[3] << 8;
|
|
- dev_dbg(&client->dev, "if_frequency kHz=%u\n", uitmp);
|
|
+ xtal_trim = cmd.args[2] | (cmd.args[3] << 8);
|
|
|
|
- if (uitmp == dev->if_frequency / 1000)
|
|
+ if (ret == 0 && xtal_trim < 16)
|
|
goto warm;
|
|
|
|
+ dev->if_frequency = 0; /* we no longer know current tuner state */
|
|
+
|
|
/* power up */
|
|
if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
|
|
memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
|
|
diff --git a/drivers/media/usb/dvb-usb/dibusb-mb.c b/drivers/media/usb/dvb-usb/dibusb-mb.c
|
|
index d4ea72bf09c5..5131c8d4c632 100644
|
|
--- a/drivers/media/usb/dvb-usb/dibusb-mb.c
|
|
+++ b/drivers/media/usb/dvb-usb/dibusb-mb.c
|
|
@@ -81,7 +81,7 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap)
|
|
|
|
if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
|
|
err("tuner i2c write failed.");
|
|
- ret = -EREMOTEIO;
|
|
+ return -EREMOTEIO;
|
|
}
|
|
|
|
if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
|
|
diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c
|
|
index b05fa227ffb2..95756cbb722f 100644
|
|
--- a/drivers/media/usb/go7007/snd-go7007.c
|
|
+++ b/drivers/media/usb/go7007/snd-go7007.c
|
|
@@ -236,22 +236,18 @@ int go7007_snd_init(struct go7007 *go)
|
|
gosnd->capturing = 0;
|
|
ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0,
|
|
&gosnd->card);
|
|
- if (ret < 0) {
|
|
- kfree(gosnd);
|
|
- return ret;
|
|
- }
|
|
+ if (ret < 0)
|
|
+ goto free_snd;
|
|
+
|
|
ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go,
|
|
&go7007_snd_device_ops);
|
|
- if (ret < 0) {
|
|
- kfree(gosnd);
|
|
- return ret;
|
|
- }
|
|
+ if (ret < 0)
|
|
+ goto free_card;
|
|
+
|
|
ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm);
|
|
- if (ret < 0) {
|
|
- snd_card_free(gosnd->card);
|
|
- kfree(gosnd);
|
|
- return ret;
|
|
- }
|
|
+ if (ret < 0)
|
|
+ goto free_card;
|
|
+
|
|
strscpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
|
|
strscpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->shortname));
|
|
strscpy(gosnd->card->longname, gosnd->card->shortname,
|
|
@@ -262,11 +258,8 @@ int go7007_snd_init(struct go7007 *go)
|
|
&go7007_snd_capture_ops);
|
|
|
|
ret = snd_card_register(gosnd->card);
|
|
- if (ret < 0) {
|
|
- snd_card_free(gosnd->card);
|
|
- kfree(gosnd);
|
|
- return ret;
|
|
- }
|
|
+ if (ret < 0)
|
|
+ goto free_card;
|
|
|
|
gosnd->substream = NULL;
|
|
go->snd_context = gosnd;
|
|
@@ -274,6 +267,12 @@ int go7007_snd_init(struct go7007 *go)
|
|
++dev;
|
|
|
|
return 0;
|
|
+
|
|
+free_card:
|
|
+ snd_card_free(gosnd->card);
|
|
+free_snd:
|
|
+ kfree(gosnd);
|
|
+ return ret;
|
|
}
|
|
EXPORT_SYMBOL(go7007_snd_init);
|
|
|
|
diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c
|
|
index 999214e8cf2b..360d523132bd 100644
|
|
--- a/drivers/mmc/host/meson-mx-sdio.c
|
|
+++ b/drivers/mmc/host/meson-mx-sdio.c
|
|
@@ -246,6 +246,9 @@ static void meson_mx_mmc_request_done(struct meson_mx_mmc_host *host)
|
|
|
|
mrq = host->mrq;
|
|
|
|
+ if (host->cmd->error)
|
|
+ meson_mx_mmc_soft_reset(host);
|
|
+
|
|
host->mrq = NULL;
|
|
host->cmd = NULL;
|
|
|
|
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
|
|
index dccb4df46512..b03d65222622 100644
|
|
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
|
|
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
|
|
@@ -87,7 +87,7 @@
|
|
#define ESDHC_STD_TUNING_EN (1 << 24)
|
|
/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
|
|
#define ESDHC_TUNING_START_TAP_DEFAULT 0x1
|
|
-#define ESDHC_TUNING_START_TAP_MASK 0xff
|
|
+#define ESDHC_TUNING_START_TAP_MASK 0x7f
|
|
#define ESDHC_TUNING_STEP_MASK 0x00070000
|
|
#define ESDHC_TUNING_STEP_SHIFT 16
|
|
|
|
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
|
|
index 8b2a6a362c60..84cffdef264b 100644
|
|
--- a/drivers/mmc/host/sdhci-msm.c
|
|
+++ b/drivers/mmc/host/sdhci-msm.c
|
|
@@ -1742,7 +1742,9 @@ static const struct sdhci_ops sdhci_msm_ops = {
|
|
static const struct sdhci_pltfm_data sdhci_msm_pdata = {
|
|
.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
|
|
SDHCI_QUIRK_SINGLE_POWER_WRITE |
|
|
- SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
|
|
+ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
|
|
+ SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
|
|
+
|
|
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
|
|
.ops = &sdhci_msm_ops,
|
|
};
|
|
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
|
|
index f4ac064ff471..8d96ecba1b55 100644
|
|
--- a/drivers/mmc/host/via-sdmmc.c
|
|
+++ b/drivers/mmc/host/via-sdmmc.c
|
|
@@ -319,6 +319,8 @@ struct via_crdr_mmc_host {
|
|
/* some devices need a very long delay for power to stabilize */
|
|
#define VIA_CRDR_QUIRK_300MS_PWRDELAY 0x0001
|
|
|
|
+#define VIA_CMD_TIMEOUT_MS 1000
|
|
+
|
|
static const struct pci_device_id via_ids[] = {
|
|
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_9530,
|
|
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
|
|
@@ -551,14 +553,17 @@ static void via_sdc_send_command(struct via_crdr_mmc_host *host,
|
|
{
|
|
void __iomem *addrbase;
|
|
struct mmc_data *data;
|
|
+ unsigned int timeout_ms;
|
|
u32 cmdctrl = 0;
|
|
|
|
WARN_ON(host->cmd);
|
|
|
|
data = cmd->data;
|
|
- mod_timer(&host->timer, jiffies + HZ);
|
|
host->cmd = cmd;
|
|
|
|
+ timeout_ms = cmd->busy_timeout ? cmd->busy_timeout : VIA_CMD_TIMEOUT_MS;
|
|
+ mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout_ms));
|
|
+
|
|
/*Command index*/
|
|
cmdctrl = cmd->opcode << 8;
|
|
|
|
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
|
|
index 15ef30b368a5..4fef20724175 100644
|
|
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
|
|
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
|
|
@@ -1019,11 +1019,14 @@ static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section,
|
|
if (!section) {
|
|
/*
|
|
* Small-page NAND use byte 6 for BBI while large-page
|
|
- * NAND use byte 0.
|
|
+ * NAND use bytes 0 and 1.
|
|
*/
|
|
- if (cfg->page_size > 512)
|
|
- oobregion->offset++;
|
|
- oobregion->length--;
|
|
+ if (cfg->page_size > 512) {
|
|
+ oobregion->offset += 2;
|
|
+ oobregion->length -= 2;
|
|
+ } else {
|
|
+ oobregion->length--;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
|
|
index c0e1a8ebe820..522390b99d3c 100644
|
|
--- a/drivers/mtd/nand/raw/diskonchip.c
|
|
+++ b/drivers/mtd/nand/raw/diskonchip.c
|
|
@@ -1609,13 +1609,10 @@ static int __init doc_probe(unsigned long physadr)
|
|
numchips = doc2001_init(mtd);
|
|
|
|
if ((ret = nand_scan(nand, numchips)) || (ret = doc->late_init(mtd))) {
|
|
- /* DBB note: i believe nand_release is necessary here, as
|
|
+ /* DBB note: i believe nand_cleanup is necessary here, as
|
|
buffers may have been allocated in nand_base. Check with
|
|
Thomas. FIX ME! */
|
|
- /* nand_release will call mtd_device_unregister, but we
|
|
- haven't yet added it. This is handled without incident by
|
|
- mtd_device_unregister, as far as I can tell. */
|
|
- nand_release(nand);
|
|
+ nand_cleanup(nand);
|
|
goto fail;
|
|
}
|
|
|
|
diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
|
|
index 49afebee50db..4b7c399d4f4b 100644
|
|
--- a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
|
|
+++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
|
|
@@ -376,7 +376,7 @@ static int ingenic_nand_init_chip(struct platform_device *pdev,
|
|
|
|
ret = mtd_device_register(mtd, NULL, 0);
|
|
if (ret) {
|
|
- nand_release(chip);
|
|
+ nand_cleanup(chip);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
|
|
index 373d47d1ba4c..08008c844a47 100644
|
|
--- a/drivers/mtd/nand/raw/mtk_nand.c
|
|
+++ b/drivers/mtd/nand/raw/mtk_nand.c
|
|
@@ -1419,7 +1419,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
|
|
ret = mtd_device_register(mtd, NULL, 0);
|
|
if (ret) {
|
|
dev_err(dev, "mtd parse partition error\n");
|
|
- nand_release(nand);
|
|
+ nand_cleanup(nand);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
|
|
index 47c63968fa45..db66c1be6e5f 100644
|
|
--- a/drivers/mtd/nand/raw/nand_base.c
|
|
+++ b/drivers/mtd/nand/raw/nand_base.c
|
|
@@ -731,8 +731,14 @@ EXPORT_SYMBOL_GPL(nand_soft_waitrdy);
|
|
int nand_gpio_waitrdy(struct nand_chip *chip, struct gpio_desc *gpiod,
|
|
unsigned long timeout_ms)
|
|
{
|
|
- /* Wait until R/B pin indicates chip is ready or timeout occurs */
|
|
- timeout_ms = jiffies + msecs_to_jiffies(timeout_ms);
|
|
+
|
|
+ /*
|
|
+ * Wait until R/B pin indicates chip is ready or timeout occurs.
|
|
+ * +1 below is necessary because if we are now in the last fraction
|
|
+ * of jiffy and msecs_to_jiffies is 1 then we will wait only that
|
|
+ * small jiffy fraction - possibly leading to false timeout.
|
|
+ */
|
|
+ timeout_ms = jiffies + msecs_to_jiffies(timeout_ms) + 1;
|
|
do {
|
|
if (gpiod_get_value_cansleep(gpiod))
|
|
return 0;
|
|
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c
|
|
index 0b879bd0a68c..8fe8d7bdd203 100644
|
|
--- a/drivers/mtd/nand/raw/nand_onfi.c
|
|
+++ b/drivers/mtd/nand/raw/nand_onfi.c
|
|
@@ -173,7 +173,7 @@ int nand_onfi_detect(struct nand_chip *chip)
|
|
}
|
|
|
|
if (onfi_crc16(ONFI_CRC_BASE, (u8 *)&p[i], 254) ==
|
|
- le16_to_cpu(p->crc)) {
|
|
+ le16_to_cpu(p[i].crc)) {
|
|
if (i)
|
|
memcpy(p, &p[i], sizeof(*p));
|
|
break;
|
|
diff --git a/drivers/mtd/nand/raw/orion_nand.c b/drivers/mtd/nand/raw/orion_nand.c
|
|
index d27b39a7223c..a3dcdf25f5f2 100644
|
|
--- a/drivers/mtd/nand/raw/orion_nand.c
|
|
+++ b/drivers/mtd/nand/raw/orion_nand.c
|
|
@@ -180,7 +180,7 @@ static int __init orion_nand_probe(struct platform_device *pdev)
|
|
mtd->name = "orion_nand";
|
|
ret = mtd_device_register(mtd, board->parts, board->nr_parts);
|
|
if (ret) {
|
|
- nand_release(nc);
|
|
+ nand_cleanup(nc);
|
|
goto no_dev;
|
|
}
|
|
|
|
diff --git a/drivers/mtd/nand/raw/oxnas_nand.c b/drivers/mtd/nand/raw/oxnas_nand.c
|
|
index c43cb4d92d3d..0429d218fd9f 100644
|
|
--- a/drivers/mtd/nand/raw/oxnas_nand.c
|
|
+++ b/drivers/mtd/nand/raw/oxnas_nand.c
|
|
@@ -140,10 +140,8 @@ static int oxnas_nand_probe(struct platform_device *pdev)
|
|
goto err_release_child;
|
|
|
|
err = mtd_device_register(mtd, NULL, 0);
|
|
- if (err) {
|
|
- nand_release(chip);
|
|
- goto err_release_child;
|
|
- }
|
|
+ if (err)
|
|
+ goto err_cleanup_nand;
|
|
|
|
oxnas->chips[nchips] = chip;
|
|
++nchips;
|
|
@@ -159,6 +157,8 @@ static int oxnas_nand_probe(struct platform_device *pdev)
|
|
|
|
return 0;
|
|
|
|
+err_cleanup_nand:
|
|
+ nand_cleanup(chip);
|
|
err_release_child:
|
|
of_node_put(nand_np);
|
|
err_clk_unprepare:
|
|
diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c
|
|
index 9cfe7395172a..066ff6dc9a23 100644
|
|
--- a/drivers/mtd/nand/raw/pasemi_nand.c
|
|
+++ b/drivers/mtd/nand/raw/pasemi_nand.c
|
|
@@ -146,7 +146,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
|
|
if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) {
|
|
dev_err(dev, "Unable to register MTD device\n");
|
|
err = -ENODEV;
|
|
- goto out_lpc;
|
|
+ goto out_cleanup_nand;
|
|
}
|
|
|
|
dev_info(dev, "PA Semi NAND flash at %pR, control at I/O %x\n", &res,
|
|
@@ -154,6 +154,8 @@ static int pasemi_nand_probe(struct platform_device *ofdev)
|
|
|
|
return 0;
|
|
|
|
+ out_cleanup_nand:
|
|
+ nand_cleanup(chip);
|
|
out_lpc:
|
|
release_region(lpcctl, 4);
|
|
out_ior:
|
|
diff --git a/drivers/mtd/nand/raw/plat_nand.c b/drivers/mtd/nand/raw/plat_nand.c
|
|
index dc0f3074ddbf..3a495b233443 100644
|
|
--- a/drivers/mtd/nand/raw/plat_nand.c
|
|
+++ b/drivers/mtd/nand/raw/plat_nand.c
|
|
@@ -92,7 +92,7 @@ static int plat_nand_probe(struct platform_device *pdev)
|
|
if (!err)
|
|
return err;
|
|
|
|
- nand_release(&data->chip);
|
|
+ nand_cleanup(&data->chip);
|
|
out:
|
|
if (pdata->ctrl.remove)
|
|
pdata->ctrl.remove(pdev);
|
|
diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
|
|
index b47a9eaff89b..d8c52a016080 100644
|
|
--- a/drivers/mtd/nand/raw/sharpsl.c
|
|
+++ b/drivers/mtd/nand/raw/sharpsl.c
|
|
@@ -183,7 +183,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
|
|
return 0;
|
|
|
|
err_add:
|
|
- nand_release(this);
|
|
+ nand_cleanup(this);
|
|
|
|
err_scan:
|
|
iounmap(sharpsl->io);
|
|
diff --git a/drivers/mtd/nand/raw/socrates_nand.c b/drivers/mtd/nand/raw/socrates_nand.c
|
|
index 20f40c0e812c..7c94fc51a611 100644
|
|
--- a/drivers/mtd/nand/raw/socrates_nand.c
|
|
+++ b/drivers/mtd/nand/raw/socrates_nand.c
|
|
@@ -169,7 +169,7 @@ static int socrates_nand_probe(struct platform_device *ofdev)
|
|
if (!res)
|
|
return res;
|
|
|
|
- nand_release(nand_chip);
|
|
+ nand_cleanup(nand_chip);
|
|
|
|
out:
|
|
iounmap(host->io_base);
|
|
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
|
|
index 89773293c64d..45c376fc571a 100644
|
|
--- a/drivers/mtd/nand/raw/sunxi_nand.c
|
|
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
|
|
@@ -2003,7 +2003,7 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
|
|
ret = mtd_device_register(mtd, NULL, 0);
|
|
if (ret) {
|
|
dev_err(dev, "failed to register mtd device: %d\n", ret);
|
|
- nand_release(nand);
|
|
+ nand_cleanup(nand);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
|
|
index db030f1701ee..4e9a6d94f6e8 100644
|
|
--- a/drivers/mtd/nand/raw/tmio_nand.c
|
|
+++ b/drivers/mtd/nand/raw/tmio_nand.c
|
|
@@ -448,7 +448,7 @@ static int tmio_probe(struct platform_device *dev)
|
|
if (!retval)
|
|
return retval;
|
|
|
|
- nand_release(nand_chip);
|
|
+ nand_cleanup(nand_chip);
|
|
|
|
err_irq:
|
|
tmio_hw_stop(dev, tmio);
|
|
diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c
|
|
index 834f794816a9..018311dc8fe1 100644
|
|
--- a/drivers/mtd/nand/raw/xway_nand.c
|
|
+++ b/drivers/mtd/nand/raw/xway_nand.c
|
|
@@ -210,7 +210,7 @@ static int xway_nand_probe(struct platform_device *pdev)
|
|
|
|
err = mtd_device_register(mtd, NULL, 0);
|
|
if (err)
|
|
- nand_release(&data->chip);
|
|
+ nand_cleanup(&data->chip);
|
|
|
|
return err;
|
|
}
|
|
diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c
|
|
index 0537df06a9b5..ff318472a3ee 100644
|
|
--- a/drivers/net/ethernet/allwinner/sun4i-emac.c
|
|
+++ b/drivers/net/ethernet/allwinner/sun4i-emac.c
|
|
@@ -432,7 +432,7 @@ static void emac_timeout(struct net_device *dev)
|
|
/* Hardware start transmission.
|
|
* Send a packet to media from the upper layer.
|
|
*/
|
|
-static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
+static netdev_tx_t emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
{
|
|
struct emac_board_info *db = netdev_priv(dev);
|
|
unsigned long channel;
|
|
@@ -440,7 +440,7 @@ static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
|
channel = db->tx_fifo_stat & 3;
|
|
if (channel == 3)
|
|
- return 1;
|
|
+ return NETDEV_TX_BUSY;
|
|
|
|
channel = (channel == 1 ? 1 : 0);
|
|
|
|
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
|
|
index 48de4bee209e..9225733f4fec 100644
|
|
--- a/drivers/net/ethernet/amazon/ena/ena_com.c
|
|
+++ b/drivers/net/ethernet/amazon/ena/ena_com.c
|
|
@@ -2349,6 +2349,9 @@ int ena_com_get_hash_function(struct ena_com_dev *ena_dev,
|
|
rss->hash_key;
|
|
int rc;
|
|
|
|
+ if (unlikely(!func))
|
|
+ return -EINVAL;
|
|
+
|
|
rc = ena_com_get_feature_ex(ena_dev, &get_resp,
|
|
ENA_ADMIN_RSS_HASH_FUNCTION,
|
|
rss->hash_key_dma_addr,
|
|
@@ -2361,8 +2364,7 @@ int ena_com_get_hash_function(struct ena_com_dev *ena_dev,
|
|
if (rss->hash_func)
|
|
rss->hash_func--;
|
|
|
|
- if (func)
|
|
- *func = rss->hash_func;
|
|
+ *func = rss->hash_func;
|
|
|
|
if (key)
|
|
memcpy(key, hash_key->key, (size_t)(hash_key->keys_num) << 2);
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
index 12949f1ec1ea..145334fb18f4 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
@@ -690,6 +690,9 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p)
|
|
u32 *regs_buff = p;
|
|
int err = 0;
|
|
|
|
+ if (unlikely(!self->aq_hw_ops->hw_get_regs))
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
regs->version = 1;
|
|
|
|
err = self->aq_hw_ops->hw_get_regs(self->aq_hw,
|
|
@@ -704,6 +707,9 @@ err_exit:
|
|
|
|
int aq_nic_get_regs_count(struct aq_nic_s *self)
|
|
{
|
|
+ if (unlikely(!self->aq_hw_ops->hw_get_regs))
|
|
+ return 0;
|
|
+
|
|
return self->aq_nic_cfg.aq_hw_caps->mac_regs_count;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
|
index 6f01f4e03cef..3d3b1005d076 100644
|
|
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
|
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
|
@@ -69,6 +69,9 @@
|
|
#define GENET_RDMA_REG_OFF (priv->hw_params->rdma_offset + \
|
|
TOTAL_DESC * DMA_DESC_SIZE)
|
|
|
|
+/* Forward declarations */
|
|
+static void bcmgenet_set_rx_mode(struct net_device *dev);
|
|
+
|
|
static inline void bcmgenet_writel(u32 value, void __iomem *offset)
|
|
{
|
|
/* MIPS chips strapped for BE will automagically configure the
|
|
@@ -2852,6 +2855,7 @@ static void bcmgenet_netif_start(struct net_device *dev)
|
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
|
|
|
/* Start the network engine */
|
|
+ bcmgenet_set_rx_mode(dev);
|
|
bcmgenet_enable_rx_napi(priv);
|
|
|
|
umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
|
|
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
|
|
index dbc69d8fa05f..5b7c2f9241d0 100644
|
|
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
|
|
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
|
|
@@ -14,6 +14,7 @@
|
|
#include <linux/if_vlan.h>
|
|
#include <linux/phy.h>
|
|
#include <linux/dim.h>
|
|
+#include <linux/ethtool.h>
|
|
|
|
/* total number of Buffer Descriptors, same for Rx/Tx */
|
|
#define TOTAL_DESC 256
|
|
@@ -674,6 +675,7 @@ struct bcmgenet_priv {
|
|
/* WOL */
|
|
struct clk *clk_wol;
|
|
u32 wolopts;
|
|
+ u8 sopass[SOPASS_MAX];
|
|
|
|
struct bcmgenet_mib_counters mib;
|
|
|
|
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
|
|
index ea20d94bd050..a41f82379369 100644
|
|
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
|
|
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
|
|
@@ -41,18 +41,13 @@
|
|
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
|
{
|
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
|
- u32 reg;
|
|
|
|
wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
|
|
wol->wolopts = priv->wolopts;
|
|
memset(wol->sopass, 0, sizeof(wol->sopass));
|
|
|
|
- if (wol->wolopts & WAKE_MAGICSECURE) {
|
|
- reg = bcmgenet_umac_readl(priv, UMAC_MPD_PW_MS);
|
|
- put_unaligned_be16(reg, &wol->sopass[0]);
|
|
- reg = bcmgenet_umac_readl(priv, UMAC_MPD_PW_LS);
|
|
- put_unaligned_be32(reg, &wol->sopass[2]);
|
|
- }
|
|
+ if (wol->wolopts & WAKE_MAGICSECURE)
|
|
+ memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
|
|
}
|
|
|
|
/* ethtool function - set WOL (Wake on LAN) settings.
|
|
@@ -62,7 +57,6 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
|
{
|
|
struct bcmgenet_priv *priv = netdev_priv(dev);
|
|
struct device *kdev = &priv->pdev->dev;
|
|
- u32 reg;
|
|
|
|
if (!device_can_wakeup(kdev))
|
|
return -ENOTSUPP;
|
|
@@ -70,17 +64,8 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
|
if (wol->wolopts & ~(WAKE_MAGIC | WAKE_MAGICSECURE))
|
|
return -EINVAL;
|
|
|
|
- reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
|
- if (wol->wolopts & WAKE_MAGICSECURE) {
|
|
- bcmgenet_umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
|
|
- UMAC_MPD_PW_MS);
|
|
- bcmgenet_umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
|
|
- UMAC_MPD_PW_LS);
|
|
- reg |= MPD_PW_EN;
|
|
- } else {
|
|
- reg &= ~MPD_PW_EN;
|
|
- }
|
|
- bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
|
+ if (wol->wolopts & WAKE_MAGICSECURE)
|
|
+ memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
|
|
|
|
/* Flag the device and relevant IRQ as wakeup capable */
|
|
if (wol->wolopts) {
|
|
@@ -120,6 +105,14 @@ static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv)
|
|
return retries;
|
|
}
|
|
|
|
+static void bcmgenet_set_mpd_password(struct bcmgenet_priv *priv)
|
|
+{
|
|
+ bcmgenet_umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
|
|
+ UMAC_MPD_PW_MS);
|
|
+ bcmgenet_umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
|
|
+ UMAC_MPD_PW_LS);
|
|
+}
|
|
+
|
|
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
|
enum bcmgenet_power_mode mode)
|
|
{
|
|
@@ -140,13 +133,17 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
|
|
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
|
reg |= MPD_EN;
|
|
+ if (priv->wolopts & WAKE_MAGICSECURE) {
|
|
+ bcmgenet_set_mpd_password(priv);
|
|
+ reg |= MPD_PW_EN;
|
|
+ }
|
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
|
|
|
/* Do not leave UniMAC in MPD mode only */
|
|
retries = bcmgenet_poll_wol_status(priv);
|
|
if (retries < 0) {
|
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
|
- reg &= ~MPD_EN;
|
|
+ reg &= ~(MPD_EN | MPD_PW_EN);
|
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
|
return retries;
|
|
}
|
|
@@ -185,7 +182,7 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
|
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
|
if (!(reg & MPD_EN))
|
|
return; /* already powered up so skip the rest */
|
|
- reg &= ~MPD_EN;
|
|
+ reg &= ~(MPD_EN | MPD_PW_EN);
|
|
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
|
|
|
/* Disable CRC Forward */
|
|
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
|
|
index a935b20effa3..3177dd8ede8e 100644
|
|
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
|
|
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
|
|
@@ -1981,7 +1981,7 @@ static int dpaa2_eth_setup_tc(struct net_device *net_dev,
|
|
int i;
|
|
|
|
if (type != TC_SETUP_QDISC_MQPRIO)
|
|
- return -EINVAL;
|
|
+ return -EOPNOTSUPP;
|
|
|
|
mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
|
num_queues = dpaa2_eth_queue_count(priv);
|
|
@@ -1993,7 +1993,7 @@ static int dpaa2_eth_setup_tc(struct net_device *net_dev,
|
|
if (num_tc > dpaa2_eth_tc_count(priv)) {
|
|
netdev_err(net_dev, "Max %d traffic classes supported\n",
|
|
dpaa2_eth_tc_count(priv));
|
|
- return -EINVAL;
|
|
+ return -EOPNOTSUPP;
|
|
}
|
|
|
|
if (!num_tc) {
|
|
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
|
|
index 86493fea56e4..f93ed70709c6 100644
|
|
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
|
|
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
|
|
@@ -3140,8 +3140,9 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|
hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
|
|
if (skb->data_len && hdr_len == len) {
|
|
switch (hw->mac_type) {
|
|
+ case e1000_82544: {
|
|
unsigned int pull_size;
|
|
- case e1000_82544:
|
|
+
|
|
/* Make sure we have room to chop off 4 bytes,
|
|
* and that the end alignment will work out to
|
|
* this hardware's requirements
|
|
@@ -3162,6 +3163,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|
}
|
|
len = skb_headlen(skb);
|
|
break;
|
|
+ }
|
|
default:
|
|
/* do nothing */
|
|
break;
|
|
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
|
|
index 37a2314d3e6b..944abd5eae11 100644
|
|
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
|
|
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
|
|
@@ -576,7 +576,6 @@ static inline u32 __er32(struct e1000_hw *hw, unsigned long reg)
|
|
|
|
#define er32(reg) __er32(hw, E1000_##reg)
|
|
|
|
-s32 __ew32_prepare(struct e1000_hw *hw);
|
|
void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val);
|
|
|
|
#define ew32(reg, val) __ew32(hw, E1000_##reg, (val))
|
|
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
index 8c4507838325..108297a099ed 100644
|
|
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
@@ -119,14 +119,12 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = {
|
|
* has bit 24 set while ME is accessing MAC CSR registers, wait if it is set
|
|
* and try again a number of times.
|
|
**/
|
|
-s32 __ew32_prepare(struct e1000_hw *hw)
|
|
+static void __ew32_prepare(struct e1000_hw *hw)
|
|
{
|
|
s32 i = E1000_ICH_FWSM_PCIM2PCI_COUNT;
|
|
|
|
while ((er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI) && --i)
|
|
udelay(50);
|
|
-
|
|
- return i;
|
|
}
|
|
|
|
void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val)
|
|
@@ -607,11 +605,11 @@ static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i)
|
|
{
|
|
struct e1000_adapter *adapter = rx_ring->adapter;
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
- s32 ret_val = __ew32_prepare(hw);
|
|
|
|
+ __ew32_prepare(hw);
|
|
writel(i, rx_ring->tail);
|
|
|
|
- if (unlikely(!ret_val && (i != readl(rx_ring->tail)))) {
|
|
+ if (unlikely(i != readl(rx_ring->tail))) {
|
|
u32 rctl = er32(RCTL);
|
|
|
|
ew32(RCTL, rctl & ~E1000_RCTL_EN);
|
|
@@ -624,11 +622,11 @@ static void e1000e_update_tdt_wa(struct e1000_ring *tx_ring, unsigned int i)
|
|
{
|
|
struct e1000_adapter *adapter = tx_ring->adapter;
|
|
struct e1000_hw *hw = &adapter->hw;
|
|
- s32 ret_val = __ew32_prepare(hw);
|
|
|
|
+ __ew32_prepare(hw);
|
|
writel(i, tx_ring->tail);
|
|
|
|
- if (unlikely(!ret_val && (i != readl(tx_ring->tail)))) {
|
|
+ if (unlikely(i != readl(tx_ring->tail))) {
|
|
u32 tctl = er32(TCTL);
|
|
|
|
ew32(TCTL, tctl & ~E1000_TCTL_EN);
|
|
@@ -5289,6 +5287,10 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|
/* oops */
|
|
break;
|
|
}
|
|
+ if (hw->mac.type == e1000_pch_spt) {
|
|
+ netdev->features &= ~NETIF_F_TSO;
|
|
+ netdev->features &= ~NETIF_F_TSO6;
|
|
+ }
|
|
}
|
|
|
|
/* enable transmits in the hardware, need to do this
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
|
|
index 171f0b625407..d68b8aa31b19 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_common.c
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
|
|
@@ -436,6 +436,7 @@ static void ice_init_flex_flds(struct ice_hw *hw, enum ice_rxdid prof_id)
|
|
static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
|
|
{
|
|
struct ice_switch_info *sw;
|
|
+ enum ice_status status;
|
|
|
|
hw->switch_info = devm_kzalloc(ice_hw_to_dev(hw),
|
|
sizeof(*hw->switch_info), GFP_KERNEL);
|
|
@@ -446,7 +447,12 @@ static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
|
|
|
|
INIT_LIST_HEAD(&sw->vsi_list_map_head);
|
|
|
|
- return ice_init_def_sw_recp(hw);
|
|
+ status = ice_init_def_sw_recp(hw);
|
|
+ if (status) {
|
|
+ devm_kfree(ice_hw_to_dev(hw), hw->switch_info);
|
|
+ return status;
|
|
+ }
|
|
+ return 0;
|
|
}
|
|
|
|
/**
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.c b/drivers/net/ethernet/intel/ice/ice_controlq.c
|
|
index c68709c7ef81..2e9c97bad3c3 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_controlq.c
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_controlq.c
|
|
@@ -199,7 +199,9 @@ unwind_alloc_rq_bufs:
|
|
cq->rq.r.rq_bi[i].pa = 0;
|
|
cq->rq.r.rq_bi[i].size = 0;
|
|
}
|
|
+ cq->rq.r.rq_bi = NULL;
|
|
devm_kfree(ice_hw_to_dev(hw), cq->rq.dma_head);
|
|
+ cq->rq.dma_head = NULL;
|
|
|
|
return ICE_ERR_NO_MEMORY;
|
|
}
|
|
@@ -245,7 +247,9 @@ unwind_alloc_sq_bufs:
|
|
cq->sq.r.sq_bi[i].pa = 0;
|
|
cq->sq.r.sq_bi[i].size = 0;
|
|
}
|
|
+ cq->sq.r.sq_bi = NULL;
|
|
devm_kfree(ice_hw_to_dev(hw), cq->sq.dma_head);
|
|
+ cq->sq.dma_head = NULL;
|
|
|
|
return ICE_ERR_NO_MEMORY;
|
|
}
|
|
@@ -304,6 +308,28 @@ ice_cfg_rq_regs(struct ice_hw *hw, struct ice_ctl_q_info *cq)
|
|
return 0;
|
|
}
|
|
|
|
+#define ICE_FREE_CQ_BUFS(hw, qi, ring) \
|
|
+do { \
|
|
+ int i; \
|
|
+ /* free descriptors */ \
|
|
+ if ((qi)->ring.r.ring##_bi) \
|
|
+ for (i = 0; i < (qi)->num_##ring##_entries; i++) \
|
|
+ if ((qi)->ring.r.ring##_bi[i].pa) { \
|
|
+ dmam_free_coherent(ice_hw_to_dev(hw), \
|
|
+ (qi)->ring.r.ring##_bi[i].size, \
|
|
+ (qi)->ring.r.ring##_bi[i].va, \
|
|
+ (qi)->ring.r.ring##_bi[i].pa); \
|
|
+ (qi)->ring.r.ring##_bi[i].va = NULL;\
|
|
+ (qi)->ring.r.ring##_bi[i].pa = 0;\
|
|
+ (qi)->ring.r.ring##_bi[i].size = 0;\
|
|
+ } \
|
|
+ /* free the buffer info list */ \
|
|
+ if ((qi)->ring.cmd_buf) \
|
|
+ devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
|
|
+ /* free DMA head */ \
|
|
+ devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head); \
|
|
+} while (0)
|
|
+
|
|
/**
|
|
* ice_init_sq - main initialization routine for Control ATQ
|
|
* @hw: pointer to the hardware structure
|
|
@@ -357,6 +383,7 @@ static enum ice_status ice_init_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
|
|
goto init_ctrlq_exit;
|
|
|
|
init_ctrlq_free_rings:
|
|
+ ICE_FREE_CQ_BUFS(hw, cq, sq);
|
|
ice_free_cq_ring(hw, &cq->sq);
|
|
|
|
init_ctrlq_exit:
|
|
@@ -416,33 +443,13 @@ static enum ice_status ice_init_rq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
|
|
goto init_ctrlq_exit;
|
|
|
|
init_ctrlq_free_rings:
|
|
+ ICE_FREE_CQ_BUFS(hw, cq, rq);
|
|
ice_free_cq_ring(hw, &cq->rq);
|
|
|
|
init_ctrlq_exit:
|
|
return ret_code;
|
|
}
|
|
|
|
-#define ICE_FREE_CQ_BUFS(hw, qi, ring) \
|
|
-do { \
|
|
- int i; \
|
|
- /* free descriptors */ \
|
|
- for (i = 0; i < (qi)->num_##ring##_entries; i++) \
|
|
- if ((qi)->ring.r.ring##_bi[i].pa) { \
|
|
- dmam_free_coherent(ice_hw_to_dev(hw), \
|
|
- (qi)->ring.r.ring##_bi[i].size,\
|
|
- (qi)->ring.r.ring##_bi[i].va,\
|
|
- (qi)->ring.r.ring##_bi[i].pa);\
|
|
- (qi)->ring.r.ring##_bi[i].va = NULL; \
|
|
- (qi)->ring.r.ring##_bi[i].pa = 0; \
|
|
- (qi)->ring.r.ring##_bi[i].size = 0; \
|
|
- } \
|
|
- /* free the buffer info list */ \
|
|
- if ((qi)->ring.cmd_buf) \
|
|
- devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
|
|
- /* free DMA head */ \
|
|
- devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head); \
|
|
-} while (0)
|
|
-
|
|
/**
|
|
* ice_shutdown_sq - shutdown the Control ATQ
|
|
* @hw: pointer to the hardware structure
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
|
|
index 2408f0de95fc..d0ccb7ad447b 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_main.c
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
|
|
@@ -2900,7 +2900,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
|
|
if (err) {
|
|
dev_err(dev, "ice_init_interrupt_scheme failed: %d\n", err);
|
|
err = -EIO;
|
|
- goto err_init_interrupt_unroll;
|
|
+ goto err_init_vsi_unroll;
|
|
}
|
|
|
|
/* Driver is mostly up */
|
|
@@ -2986,6 +2986,7 @@ err_msix_misc_unroll:
|
|
ice_free_irq_msix_misc(pf);
|
|
err_init_interrupt_unroll:
|
|
ice_clear_interrupt_scheme(pf);
|
|
+err_init_vsi_unroll:
|
|
devm_kfree(dev, pf->vsi);
|
|
err_init_pf_unroll:
|
|
ice_deinit_pf(pf);
|
|
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
|
|
index 8959418776f6..f80933320fd3 100644
|
|
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
|
|
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
|
|
@@ -143,7 +143,8 @@ static int igb_get_link_ksettings(struct net_device *netdev,
|
|
u32 speed;
|
|
u32 supported, advertising;
|
|
|
|
- status = rd32(E1000_STATUS);
|
|
+ status = pm_runtime_suspended(&adapter->pdev->dev) ?
|
|
+ 0 : rd32(E1000_STATUS);
|
|
if (hw->phy.media_type == e1000_media_type_copper) {
|
|
|
|
supported = (SUPPORTED_10baseT_Half |
|
|
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
|
|
index 0bd1294ba517..39c5e6fdb72c 100644
|
|
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
|
|
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
|
|
@@ -2243,7 +2243,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw)
|
|
}
|
|
|
|
/* Configure pause time (2 TCs per register) */
|
|
- reg = hw->fc.pause_time * 0x00010001;
|
|
+ reg = hw->fc.pause_time * 0x00010001U;
|
|
for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
|
|
IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
|
|
|
|
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
|
index a26f9fb95ac0..edaa0bffa5c3 100644
|
|
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
|
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
|
|
@@ -2254,7 +2254,8 @@ static void ixgbe_rx_buffer_flip(struct ixgbe_ring *rx_ring,
|
|
rx_buffer->page_offset ^= truesize;
|
|
#else
|
|
unsigned int truesize = ring_uses_build_skb(rx_ring) ?
|
|
- SKB_DATA_ALIGN(IXGBE_SKB_PAD + size) :
|
|
+ SKB_DATA_ALIGN(IXGBE_SKB_PAD + size) +
|
|
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
|
|
SKB_DATA_ALIGN(size);
|
|
|
|
rx_buffer->page_offset += truesize;
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
|
|
index c4eed5bbcd45..066bada4ccd1 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
|
|
@@ -1428,6 +1428,7 @@ out:
|
|
|
|
#ifdef CONFIG_MLX5_CORE_IPOIB
|
|
|
|
+#define MLX5_IB_GRH_SGID_OFFSET 8
|
|
#define MLX5_IB_GRH_DGID_OFFSET 24
|
|
#define MLX5_GID_SIZE 16
|
|
|
|
@@ -1441,6 +1442,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
|
|
struct net_device *netdev;
|
|
struct mlx5e_priv *priv;
|
|
char *pseudo_header;
|
|
+ u32 flags_rqpn;
|
|
u32 qpn;
|
|
u8 *dgid;
|
|
u8 g;
|
|
@@ -1462,7 +1464,8 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
|
|
tstamp = &priv->tstamp;
|
|
stats = &priv->channel_stats[rq->ix].rq;
|
|
|
|
- g = (be32_to_cpu(cqe->flags_rqpn) >> 28) & 3;
|
|
+ flags_rqpn = be32_to_cpu(cqe->flags_rqpn);
|
|
+ g = (flags_rqpn >> 28) & 3;
|
|
dgid = skb->data + MLX5_IB_GRH_DGID_OFFSET;
|
|
if ((!g) || dgid[0] != 0xff)
|
|
skb->pkt_type = PACKET_HOST;
|
|
@@ -1471,9 +1474,15 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
|
|
else
|
|
skb->pkt_type = PACKET_MULTICAST;
|
|
|
|
- /* TODO: IB/ipoib: Allow mcast packets from other VFs
|
|
- * 68996a6e760e5c74654723eeb57bf65628ae87f4
|
|
+ /* Drop packets that this interface sent, ie multicast packets
|
|
+ * that the HCA has replicated.
|
|
*/
|
|
+ if (g && (qpn == (flags_rqpn & 0xffffff)) &&
|
|
+ (memcmp(netdev->dev_addr + 4, skb->data + MLX5_IB_GRH_SGID_OFFSET,
|
|
+ MLX5_GID_SIZE) == 0)) {
|
|
+ skb->dev = NULL;
|
|
+ return;
|
|
+ }
|
|
|
|
skb_pull(skb, MLX5_IB_GRH_BYTES);
|
|
|
|
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
|
|
index 544012a67221..1d59ef367a85 100644
|
|
--- a/drivers/net/ethernet/nxp/lpc_eth.c
|
|
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
|
|
@@ -815,7 +815,8 @@ static int lpc_mii_init(struct netdata_local *pldat)
|
|
if (mdiobus_register(pldat->mii_bus))
|
|
goto err_out_unregister_bus;
|
|
|
|
- if (lpc_mii_probe(pldat->ndev) != 0)
|
|
+ err = lpc_mii_probe(pldat->ndev);
|
|
+ if (err)
|
|
goto err_out_unregister_bus;
|
|
|
|
return 0;
|
|
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
|
|
index 1f27f9866b80..61b5aa3e5b98 100644
|
|
--- a/drivers/net/ethernet/qlogic/qede/qede.h
|
|
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
|
|
@@ -574,12 +574,14 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
|
|
#define RX_RING_SIZE ((u16)BIT(RX_RING_SIZE_POW))
|
|
#define NUM_RX_BDS_MAX (RX_RING_SIZE - 1)
|
|
#define NUM_RX_BDS_MIN 128
|
|
+#define NUM_RX_BDS_KDUMP_MIN 63
|
|
#define NUM_RX_BDS_DEF ((u16)BIT(10) - 1)
|
|
|
|
#define TX_RING_SIZE_POW 13
|
|
#define TX_RING_SIZE ((u16)BIT(TX_RING_SIZE_POW))
|
|
#define NUM_TX_BDS_MAX (TX_RING_SIZE - 1)
|
|
#define NUM_TX_BDS_MIN 128
|
|
+#define NUM_TX_BDS_KDUMP_MIN 63
|
|
#define NUM_TX_BDS_DEF NUM_TX_BDS_MAX
|
|
|
|
#define QEDE_MIN_PKT_LEN 64
|
|
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
|
|
index ba53612ae0df..1da6b5bda80a 100644
|
|
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
|
|
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
|
|
@@ -29,6 +29,7 @@
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
+#include <linux/crash_dump.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/version.h>
|
|
@@ -707,8 +708,14 @@ static struct qede_dev *qede_alloc_etherdev(struct qed_dev *cdev,
|
|
edev->dp_module = dp_module;
|
|
edev->dp_level = dp_level;
|
|
edev->ops = qed_ops;
|
|
- edev->q_num_rx_buffers = NUM_RX_BDS_DEF;
|
|
- edev->q_num_tx_buffers = NUM_TX_BDS_DEF;
|
|
+
|
|
+ if (is_kdump_kernel()) {
|
|
+ edev->q_num_rx_buffers = NUM_RX_BDS_KDUMP_MIN;
|
|
+ edev->q_num_tx_buffers = NUM_TX_BDS_KDUMP_MIN;
|
|
+ } else {
|
|
+ edev->q_num_rx_buffers = NUM_RX_BDS_DEF;
|
|
+ edev->q_num_tx_buffers = NUM_TX_BDS_DEF;
|
|
+ }
|
|
|
|
DP_INFO(edev, "Allocated netdev with %d tx queues and %d rx queues\n",
|
|
info->num_queues, info->num_queues);
|
|
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
|
|
index 38b7f6d35759..702fdc393da0 100644
|
|
--- a/drivers/net/ethernet/ti/davinci_mdio.c
|
|
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
|
|
@@ -397,6 +397,8 @@ static int davinci_mdio_probe(struct platform_device *pdev)
|
|
data->dev = dev;
|
|
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ if (!res)
|
|
+ return -EINVAL;
|
|
data->regs = devm_ioremap(dev, res->start, resource_size(res));
|
|
if (!data->regs)
|
|
return -ENOMEM;
|
|
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
|
|
index 0ce1004a8d0d..9d3209ae41cf 100644
|
|
--- a/drivers/net/macvlan.c
|
|
+++ b/drivers/net/macvlan.c
|
|
@@ -447,6 +447,10 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
|
|
int ret;
|
|
rx_handler_result_t handle_res;
|
|
|
|
+ /* Packets from dev_loopback_xmit() do not have L2 header, bail out */
|
|
+ if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
|
|
+ return RX_HANDLER_PASS;
|
|
+
|
|
port = macvlan_port_get_rcu(skb->dev);
|
|
if (is_multicast_ether_addr(eth->h_dest)) {
|
|
unsigned int hash;
|
|
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
|
|
index 9f3c839f9e5f..88cfd63f08a6 100644
|
|
--- a/drivers/net/veth.c
|
|
+++ b/drivers/net/veth.c
|
|
@@ -510,13 +510,15 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_rq *rq,
|
|
struct veth_xdp_tx_bq *bq)
|
|
{
|
|
void *hard_start = frame->data - frame->headroom;
|
|
- void *head = hard_start - sizeof(struct xdp_frame);
|
|
int len = frame->len, delta = 0;
|
|
struct xdp_frame orig_frame;
|
|
struct bpf_prog *xdp_prog;
|
|
unsigned int headroom;
|
|
struct sk_buff *skb;
|
|
|
|
+ /* bpf_xdp_adjust_head() assures BPF cannot access xdp_frame area */
|
|
+ hard_start -= sizeof(struct xdp_frame);
|
|
+
|
|
rcu_read_lock();
|
|
xdp_prog = rcu_dereference(rq->xdp_prog);
|
|
if (likely(xdp_prog)) {
|
|
@@ -538,7 +540,6 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_rq *rq,
|
|
break;
|
|
case XDP_TX:
|
|
orig_frame = *frame;
|
|
- xdp.data_hard_start = head;
|
|
xdp.rxq->mem = frame->mem;
|
|
if (unlikely(veth_xdp_tx(rq->dev, &xdp, bq) < 0)) {
|
|
trace_xdp_exception(rq->dev, xdp_prog, act);
|
|
@@ -550,7 +551,6 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_rq *rq,
|
|
goto xdp_xmit;
|
|
case XDP_REDIRECT:
|
|
orig_frame = *frame;
|
|
- xdp.data_hard_start = head;
|
|
xdp.rxq->mem = frame->mem;
|
|
if (xdp_do_redirect(rq->dev, &xdp, xdp_prog)) {
|
|
frame = &orig_frame;
|
|
@@ -572,7 +572,7 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_rq *rq,
|
|
rcu_read_unlock();
|
|
|
|
headroom = sizeof(struct xdp_frame) + frame->headroom - delta;
|
|
- skb = veth_build_skb(head, headroom, len, 0);
|
|
+ skb = veth_build_skb(hard_start, headroom, len, 0);
|
|
if (!skb) {
|
|
xdp_return_frame(frame);
|
|
goto err;
|
|
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
|
|
index 0a38c76688ab..5e2571d23ab9 100644
|
|
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
|
|
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
|
|
@@ -702,6 +702,8 @@ vmxnet3_get_rss(struct net_device *netdev, u32 *p, u8 *key, u8 *hfunc)
|
|
*hfunc = ETH_RSS_HASH_TOP;
|
|
if (!p)
|
|
return 0;
|
|
+ if (n > UPT1_RSS_MAX_IND_TABLE_SIZE)
|
|
+ return 0;
|
|
while (n--)
|
|
p[n] = rssConf->indTable[n];
|
|
return 0;
|
|
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
|
|
index 30c080094af1..bd5fa4dbab9c 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/htt.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/htt.h
|
|
@@ -2033,6 +2033,7 @@ struct ath10k_htt_tx_ops {
|
|
int (*htt_h2t_aggr_cfg_msg)(struct ath10k_htt *htt,
|
|
u8 max_subfrms_ampdu,
|
|
u8 max_subfrms_amsdu);
|
|
+ void (*htt_flush_tx)(struct ath10k_htt *htt);
|
|
};
|
|
|
|
static inline int ath10k_htt_send_rx_ring_cfg(struct ath10k_htt *htt)
|
|
@@ -2072,6 +2073,12 @@ static inline int ath10k_htt_tx(struct ath10k_htt *htt,
|
|
return htt->tx_ops->htt_tx(htt, txmode, msdu);
|
|
}
|
|
|
|
+static inline void ath10k_htt_flush_tx(struct ath10k_htt *htt)
|
|
+{
|
|
+ if (htt->tx_ops->htt_flush_tx)
|
|
+ htt->tx_ops->htt_flush_tx(htt);
|
|
+}
|
|
+
|
|
static inline int ath10k_htt_alloc_txbuff(struct ath10k_htt *htt)
|
|
{
|
|
if (!htt->tx_ops->htt_alloc_txbuff)
|
|
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
|
|
index a182c0944cc7..735482877a1f 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
|
|
@@ -529,9 +529,14 @@ void ath10k_htt_tx_destroy(struct ath10k_htt *htt)
|
|
htt->tx_mem_allocated = false;
|
|
}
|
|
|
|
-void ath10k_htt_tx_stop(struct ath10k_htt *htt)
|
|
+static void ath10k_htt_flush_tx_queue(struct ath10k_htt *htt)
|
|
{
|
|
idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
|
|
+}
|
|
+
|
|
+void ath10k_htt_tx_stop(struct ath10k_htt *htt)
|
|
+{
|
|
+ ath10k_htt_flush_tx_queue(htt);
|
|
idr_destroy(&htt->pending_tx);
|
|
}
|
|
|
|
@@ -1774,6 +1779,7 @@ static const struct ath10k_htt_tx_ops htt_tx_ops_hl = {
|
|
.htt_send_frag_desc_bank_cfg = ath10k_htt_send_frag_desc_bank_cfg_32,
|
|
.htt_tx = ath10k_htt_tx_hl,
|
|
.htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_32,
|
|
+ .htt_flush_tx = ath10k_htt_flush_tx_queue,
|
|
};
|
|
|
|
void ath10k_htt_set_tx_ops(struct ath10k_htt *htt)
|
|
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
|
|
index 36d24ea126a2..d373602a8014 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
|
@@ -3911,6 +3911,9 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
|
if (ret) {
|
|
ath10k_warn(ar, "failed to transmit management frame by ref via WMI: %d\n",
|
|
ret);
|
|
+ /* remove this msdu from idr tracking */
|
|
+ ath10k_wmi_cleanup_mgmt_tx_send(ar, skb);
|
|
+
|
|
dma_unmap_single(ar->dev, paddr, skb->len,
|
|
DMA_TO_DEVICE);
|
|
ieee80211_free_txskb(ar->hw, skb);
|
|
@@ -7082,6 +7085,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
ath10k_wmi_peer_flush(ar, arvif->vdev_id,
|
|
arvif->bssid, bitmap);
|
|
}
|
|
+ ath10k_htt_flush_tx(&ar->htt);
|
|
}
|
|
return;
|
|
}
|
|
@@ -8811,7 +8815,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
|
ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
|
|
|
|
if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) {
|
|
- ar->hw->wiphy->max_sched_scan_reqs = 1;
|
|
ar->hw->wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS;
|
|
ar->hw->wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
|
|
ar->hw->wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH;
|
|
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
|
|
index 0a727502d14c..fd49d3419e79 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/pci.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/pci.c
|
|
@@ -2074,6 +2074,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
|
|
ath10k_pci_irq_sync(ar);
|
|
napi_synchronize(&ar->napi);
|
|
napi_disable(&ar->napi);
|
|
+ cancel_work_sync(&ar_pci->dump_work);
|
|
|
|
/* Most likely the device has HTT Rx ring configured. The only way to
|
|
* prevent the device from accessing (and possible corrupting) host
|
|
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
|
|
index 39abf8b12903..f46b9083bbf1 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/txrx.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
|
|
@@ -84,9 +84,11 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
|
wake_up(&htt->empty_tx_wq);
|
|
spin_unlock_bh(&htt->tx_lock);
|
|
|
|
+ rcu_read_lock();
|
|
if (txq && txq->sta && skb_cb->airtime_est)
|
|
ieee80211_sta_register_airtime(txq->sta, txq->tid,
|
|
skb_cb->airtime_est, 0);
|
|
+ rcu_read_unlock();
|
|
|
|
if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
|
|
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
|
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
|
|
index 1491c25518bb..edccabc667e8 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
|
|
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
|
|
@@ -133,6 +133,7 @@ struct wmi_ops {
|
|
struct sk_buff *(*gen_mgmt_tx_send)(struct ath10k *ar,
|
|
struct sk_buff *skb,
|
|
dma_addr_t paddr);
|
|
+ int (*cleanup_mgmt_tx_send)(struct ath10k *ar, struct sk_buff *msdu);
|
|
struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u64 module_enable,
|
|
u32 log_level);
|
|
struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter);
|
|
@@ -441,6 +442,15 @@ ath10k_wmi_get_txbf_conf_scheme(struct ath10k *ar)
|
|
return ar->wmi.ops->get_txbf_conf_scheme(ar);
|
|
}
|
|
|
|
+static inline int
|
|
+ath10k_wmi_cleanup_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu)
|
|
+{
|
|
+ if (!ar->wmi.ops->cleanup_mgmt_tx_send)
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
+ return ar->wmi.ops->cleanup_mgmt_tx_send(ar, msdu);
|
|
+}
|
|
+
|
|
static inline int
|
|
ath10k_wmi_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
|
|
dma_addr_t paddr)
|
|
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
|
|
index eb0c963d9fd5..9d5b9df29c35 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
|
|
@@ -2837,6 +2837,18 @@ ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, u32 stats_mask)
|
|
return skb;
|
|
}
|
|
|
|
+static int
|
|
+ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
|
|
+ struct sk_buff *msdu)
|
|
+{
|
|
+ struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
|
|
+ struct ath10k_wmi *wmi = &ar->wmi;
|
|
+
|
|
+ idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int
|
|
ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb,
|
|
dma_addr_t paddr)
|
|
@@ -2911,6 +2923,8 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
|
|
if (desc_id < 0)
|
|
goto err_free_skb;
|
|
|
|
+ cb->msdu_id = desc_id;
|
|
+
|
|
ptr = (void *)skb->data;
|
|
tlv = ptr;
|
|
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD);
|
|
@@ -4339,6 +4353,7 @@ static const struct wmi_ops wmi_tlv_ops = {
|
|
.gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
|
|
/* .gen_mgmt_tx = not implemented; HTT is used */
|
|
.gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send,
|
|
+ .cleanup_mgmt_tx_send = ath10k_wmi_tlv_op_cleanup_mgmt_tx_send,
|
|
.gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
|
|
.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
|
|
.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
|
|
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
|
|
index 51934d191f33..1ab09e1c9ec5 100644
|
|
--- a/drivers/net/wireless/ath/carl9170/fw.c
|
|
+++ b/drivers/net/wireless/ath/carl9170/fw.c
|
|
@@ -338,9 +338,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
|
|
ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
|
|
|
|
if (SUPP(CARL9170FW_WLANTX_CAB)) {
|
|
- if_comb_types |=
|
|
- BIT(NL80211_IFTYPE_AP) |
|
|
- BIT(NL80211_IFTYPE_P2P_GO);
|
|
+ if_comb_types |= BIT(NL80211_IFTYPE_AP);
|
|
|
|
#ifdef CONFIG_MAC80211_MESH
|
|
if_comb_types |=
|
|
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
|
|
index 40a8054f8aa6..21ca62b06214 100644
|
|
--- a/drivers/net/wireless/ath/carl9170/main.c
|
|
+++ b/drivers/net/wireless/ath/carl9170/main.c
|
|
@@ -582,11 +582,10 @@ static int carl9170_init_interface(struct ar9170 *ar,
|
|
ar->disable_offload |= ((vif->type != NL80211_IFTYPE_STATION) &&
|
|
(vif->type != NL80211_IFTYPE_AP));
|
|
|
|
- /* While the driver supports HW offload in a single
|
|
- * P2P client configuration, it doesn't support HW
|
|
- * offload in the favourit, concurrent P2P GO+CLIENT
|
|
- * configuration. Hence, HW offload will always be
|
|
- * disabled for P2P.
|
|
+ /* The driver used to have P2P GO+CLIENT support,
|
|
+ * but since this was dropped and we don't know if
|
|
+ * there are any gremlins lurking in the shadows,
|
|
+ * so best we keep HW offload disabled for P2P.
|
|
*/
|
|
ar->disable_offload |= vif->p2p;
|
|
|
|
@@ -639,18 +638,6 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
|
|
if (vif->type == NL80211_IFTYPE_STATION)
|
|
break;
|
|
|
|
- /* P2P GO [master] use-case
|
|
- * Because the P2P GO station is selected dynamically
|
|
- * by all participating peers of a WIFI Direct network,
|
|
- * the driver has be able to change the main interface
|
|
- * operating mode on the fly.
|
|
- */
|
|
- if (main_vif->p2p && vif->p2p &&
|
|
- vif->type == NL80211_IFTYPE_AP) {
|
|
- old_main = main_vif;
|
|
- break;
|
|
- }
|
|
-
|
|
err = -EBUSY;
|
|
rcu_read_unlock();
|
|
|
|
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
|
|
index 79998a3ddb7a..ad051f34e65b 100644
|
|
--- a/drivers/net/wireless/ath/wcn36xx/main.c
|
|
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
|
|
@@ -1341,7 +1341,7 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
|
if (addr && ret != ETH_ALEN) {
|
|
wcn36xx_err("invalid local-mac-address\n");
|
|
ret = -EINVAL;
|
|
- goto out_wq;
|
|
+ goto out_destroy_ept;
|
|
} else if (addr) {
|
|
wcn36xx_info("mac address: %pM\n", addr);
|
|
SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
|
|
@@ -1349,7 +1349,7 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
|
|
|
ret = wcn36xx_platform_get_resources(wcn, pdev);
|
|
if (ret)
|
|
- goto out_wq;
|
|
+ goto out_destroy_ept;
|
|
|
|
wcn36xx_init_ieee80211(wcn);
|
|
ret = ieee80211_register_hw(wcn->hw);
|
|
@@ -1361,6 +1361,8 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
|
out_unmap:
|
|
iounmap(wcn->ccu_base);
|
|
iounmap(wcn->dxe_base);
|
|
+out_destroy_ept:
|
|
+ rpmsg_destroy_ept(wcn->smd_channel);
|
|
out_wq:
|
|
ieee80211_free_hw(hw);
|
|
out_err:
|
|
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
|
|
index b85603e91c7a..3432dfe1ddb4 100644
|
|
--- a/drivers/net/wireless/broadcom/b43/main.c
|
|
+++ b/drivers/net/wireless/broadcom/b43/main.c
|
|
@@ -5569,7 +5569,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
|
|
/* fill hw info */
|
|
ieee80211_hw_set(hw, RX_INCLUDES_FCS);
|
|
ieee80211_hw_set(hw, SIGNAL_DBM);
|
|
-
|
|
+ ieee80211_hw_set(hw, MFP_CAPABLE);
|
|
hw->wiphy->interface_modes =
|
|
BIT(NL80211_IFTYPE_AP) |
|
|
BIT(NL80211_IFTYPE_MESH_POINT) |
|
|
diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c
|
|
index 8b6b657c4b85..5208a39fd6f7 100644
|
|
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
|
|
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
|
|
@@ -3801,6 +3801,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
|
|
/* fill hw info */
|
|
ieee80211_hw_set(hw, RX_INCLUDES_FCS);
|
|
ieee80211_hw_set(hw, SIGNAL_DBM);
|
|
+ ieee80211_hw_set(hw, MFP_CAPABLE); /* Allow WPA3 in software */
|
|
|
|
hw->wiphy->interface_modes =
|
|
BIT(NL80211_IFTYPE_AP) |
|
|
diff --git a/drivers/net/wireless/broadcom/b43legacy/xmit.c b/drivers/net/wireless/broadcom/b43legacy/xmit.c
|
|
index e9b23c2e5bd4..efd63f4ce74f 100644
|
|
--- a/drivers/net/wireless/broadcom/b43legacy/xmit.c
|
|
+++ b/drivers/net/wireless/broadcom/b43legacy/xmit.c
|
|
@@ -558,6 +558,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
|
|
default:
|
|
b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
|
|
chanstat);
|
|
+ goto drop;
|
|
}
|
|
|
|
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
index 2c3526aeca6f..545015610cf8 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
|
|
@@ -283,13 +283,14 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
|
|
if (!err)
|
|
ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC);
|
|
|
|
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
|
|
+
|
|
if (drvr->settings->feature_disable) {
|
|
brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
|
|
ifp->drvr->feat_flags,
|
|
drvr->settings->feature_disable);
|
|
ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
|
|
}
|
|
- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
|
|
|
|
brcmf_feat_firmware_overrides(drvr);
|
|
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
|
|
index ad18c2f1a806..524f9dd2323d 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
|
|
@@ -5,10 +5,9 @@
|
|
*
|
|
* GPL LICENSE SUMMARY
|
|
*
|
|
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
|
- * Copyright(c) 2018 - 2019 Intel Corporation
|
|
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of version 2 of the GNU General Public License as
|
|
@@ -28,10 +27,9 @@
|
|
*
|
|
* BSD LICENSE
|
|
*
|
|
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
|
- * Copyright(c) 2018 - 2019 Intel Corporation
|
|
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -478,6 +476,11 @@ static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
|
|
if (kstrtou16(buf, 0, &amsdu_len))
|
|
return -EINVAL;
|
|
|
|
+ /* only change from debug set <-> debug unset */
|
|
+ if ((amsdu_len && mvmsta->orig_amsdu_len) ||
|
|
+ (!!amsdu_len && mvmsta->orig_amsdu_len))
|
|
+ return -EBUSY;
|
|
+
|
|
if (amsdu_len) {
|
|
mvmsta->orig_amsdu_len = sta->max_amsdu_len;
|
|
sta->max_amsdu_len = amsdu_len;
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
|
|
index 6ca087ffd163..ed92a8e8cd51 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
|
|
@@ -1193,14 +1193,13 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
|
|
*/
|
|
flush_work(&mvm->roc_done_wk);
|
|
|
|
+ iwl_mvm_rm_aux_sta(mvm);
|
|
+
|
|
iwl_mvm_stop_device(mvm);
|
|
|
|
iwl_mvm_async_handlers_purge(mvm);
|
|
/* async_handlers_list is empty and will stay empty: HW is stopped */
|
|
|
|
- /* the fw is stopped, the aux sta is dead: clean up driver state */
|
|
- iwl_mvm_del_aux_sta(mvm);
|
|
-
|
|
/*
|
|
* Clear IN_HW_RESTART and HW_RESTART_REQUESTED flag when stopping the
|
|
* hw (as restart_complete() won't be called in this case) and mac80211
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
|
|
index 5b2bd603febf..be8bc0601d7b 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
|
|
@@ -367,14 +367,15 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
|
u16 size = le32_to_cpu(notif->amsdu_size);
|
|
int i;
|
|
|
|
- /*
|
|
- * In debug sta->max_amsdu_len < size
|
|
- * so also check with orig_amsdu_len which holds the original
|
|
- * data before debugfs changed the value
|
|
- */
|
|
- if (WARN_ON(sta->max_amsdu_len < size &&
|
|
- mvmsta->orig_amsdu_len < size))
|
|
+ if (sta->max_amsdu_len < size) {
|
|
+ /*
|
|
+ * In debug sta->max_amsdu_len < size
|
|
+ * so also check with orig_amsdu_len which holds the
|
|
+ * original data before debugfs changed the value
|
|
+ */
|
|
+ WARN_ON(mvmsta->orig_amsdu_len < size);
|
|
goto out;
|
|
+ }
|
|
|
|
mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
|
|
mvmsta->max_amsdu_len = size;
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
|
|
index 71d339e90a9e..41f62793a57c 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
|
|
@@ -2080,16 +2080,24 @@ int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|
return ret;
|
|
}
|
|
|
|
-void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)
|
|
+int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm)
|
|
{
|
|
- iwl_mvm_dealloc_int_sta(mvm, &mvm->snif_sta);
|
|
-}
|
|
+ int ret;
|
|
|
|
-void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm)
|
|
-{
|
|
lockdep_assert_held(&mvm->mutex);
|
|
|
|
+ iwl_mvm_disable_txq(mvm, NULL, mvm->aux_queue, IWL_MAX_TID_COUNT, 0);
|
|
+ ret = iwl_mvm_rm_sta_common(mvm, mvm->aux_sta.sta_id);
|
|
+ if (ret)
|
|
+ IWL_WARN(mvm, "Failed sending remove station\n");
|
|
iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)
|
|
+{
|
|
+ iwl_mvm_dealloc_int_sta(mvm, &mvm->snif_sta);
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
|
|
index 8d70093847cb..da2d1ac01229 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
|
|
@@ -8,7 +8,7 @@
|
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
|
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
|
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
|
- * Copyright(c) 2018 - 2019 Intel Corporation
|
|
+ * Copyright(c) 2018 - 2020 Intel Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of version 2 of the GNU General Public License as
|
|
@@ -31,7 +31,7 @@
|
|
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
|
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
|
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
|
- * Copyright(c) 2018 - 2019 Intel Corporation
|
|
+ * Copyright(c) 2018 - 2020 Intel Corporation
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -541,7 +541,7 @@ int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
|
int tid, u8 queue, bool start);
|
|
|
|
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm);
|
|
-void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm);
|
|
+int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm);
|
|
|
|
int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
|
int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
|
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
|
|
index 25ac9db35dbf..bedc09215088 100644
|
|
--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
|
|
+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
|
|
@@ -247,10 +247,10 @@ static void if_usb_disconnect(struct usb_interface *intf)
|
|
|
|
lbtf_deb_enter(LBTF_DEB_MAIN);
|
|
|
|
- if_usb_reset_device(priv);
|
|
-
|
|
- if (priv)
|
|
+ if (priv) {
|
|
+ if_usb_reset_device(priv);
|
|
lbtf_remove_card(priv);
|
|
+ }
|
|
|
|
/* Unlink and free urb */
|
|
if_usb_free(cardp);
|
|
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
|
|
index d89684168500..9e6dc289ec3e 100644
|
|
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
|
|
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
|
|
@@ -1496,7 +1496,8 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
|
int idx, u8 *mac, struct station_info *sinfo)
|
|
{
|
|
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
|
- static struct mwifiex_sta_node *node;
|
|
+ struct mwifiex_sta_node *node;
|
|
+ int i;
|
|
|
|
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
|
|
priv->media_connected && idx == 0) {
|
|
@@ -1506,13 +1507,10 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
|
|
mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,
|
|
HostCmd_ACT_GEN_GET, 0, NULL, true);
|
|
|
|
- if (node && (&node->list == &priv->sta_list)) {
|
|
- node = NULL;
|
|
- return -ENOENT;
|
|
- }
|
|
-
|
|
- node = list_prepare_entry(node, &priv->sta_list, list);
|
|
- list_for_each_entry_continue(node, &priv->sta_list, list) {
|
|
+ i = 0;
|
|
+ list_for_each_entry(node, &priv->sta_list, list) {
|
|
+ if (i++ != idx)
|
|
+ continue;
|
|
ether_addr_copy(mac, node->mac_addr);
|
|
return mwifiex_dump_station_info(priv, node, sinfo);
|
|
}
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/agg-rx.c b/drivers/net/wireless/mediatek/mt76/agg-rx.c
|
|
index 8f3d36a15e17..cbff0dfc9631 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/agg-rx.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/agg-rx.c
|
|
@@ -143,8 +143,8 @@ void mt76_rx_aggr_reorder(struct sk_buff *skb, struct sk_buff_head *frames)
|
|
struct ieee80211_sta *sta;
|
|
struct mt76_rx_tid *tid;
|
|
bool sn_less;
|
|
- u16 seqno, head, size;
|
|
- u8 ackp, idx;
|
|
+ u16 seqno, head, size, idx;
|
|
+ u8 ackp;
|
|
|
|
__skb_queue_tail(frames, skb);
|
|
|
|
@@ -230,7 +230,7 @@ out:
|
|
}
|
|
|
|
int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno,
|
|
- u16 ssn, u8 size)
|
|
+ u16 ssn, u16 size)
|
|
{
|
|
struct mt76_rx_tid *tid;
|
|
|
|
@@ -254,7 +254,7 @@ EXPORT_SYMBOL_GPL(mt76_rx_aggr_start);
|
|
|
|
static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid)
|
|
{
|
|
- u8 size = tid->size;
|
|
+ u16 size = tid->size;
|
|
int i;
|
|
|
|
cancel_delayed_work(&tid->reorder_work);
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
|
|
index 502814c26b33..52a16b42dfd7 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
|
|
@@ -240,8 +240,8 @@ struct mt76_rx_tid {
|
|
struct delayed_work reorder_work;
|
|
|
|
u16 head;
|
|
- u8 size;
|
|
- u8 nframes;
|
|
+ u16 size;
|
|
+ u16 nframes;
|
|
|
|
u8 started:1, stopped:1, timer_pending:1;
|
|
|
|
@@ -723,7 +723,7 @@ int mt76_get_survey(struct ieee80211_hw *hw, int idx,
|
|
void mt76_set_stream_caps(struct mt76_dev *dev, bool vht);
|
|
|
|
int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid,
|
|
- u16 ssn, u8 size);
|
|
+ u16 ssn, u16 size);
|
|
void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid);
|
|
|
|
void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
|
|
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
|
|
index 348b0072cdd6..c66c6dc00378 100644
|
|
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
|
|
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
|
|
@@ -881,10 +881,8 @@ static struct urb *_rtl_usb_tx_urb_setup(struct ieee80211_hw *hw,
|
|
|
|
WARN_ON(NULL == skb);
|
|
_urb = usb_alloc_urb(0, GFP_ATOMIC);
|
|
- if (!_urb) {
|
|
- kfree_skb(skb);
|
|
+ if (!_urb)
|
|
return NULL;
|
|
- }
|
|
_rtl_install_trx_info(rtlusb, skb, ep_num);
|
|
usb_fill_bulk_urb(_urb, rtlusb->udev, usb_sndbulkpipe(rtlusb->udev,
|
|
ep_num), skb->data, skb->len, _rtl_tx_complete, skb);
|
|
@@ -898,7 +896,6 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|
struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
|
|
u32 ep_num;
|
|
struct urb *_urb = NULL;
|
|
- struct sk_buff *_skb = NULL;
|
|
|
|
WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl);
|
|
if (unlikely(IS_USB_STOP(rtlusb))) {
|
|
@@ -907,8 +904,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|
return;
|
|
}
|
|
ep_num = rtlusb->ep_map.ep_mapping[qnum];
|
|
- _skb = skb;
|
|
- _urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num);
|
|
+ _urb = _rtl_usb_tx_urb_setup(hw, skb, ep_num);
|
|
if (unlikely(!_urb)) {
|
|
pr_err("Can't allocate urb. Drop skb!\n");
|
|
kfree_skb(skb);
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
|
|
index 77a2bdee50fa..4a43c4fa716d 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/pci.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
|
|
@@ -974,6 +974,7 @@ static int rtw_pci_io_mapping(struct rtw_dev *rtwdev,
|
|
len = pci_resource_len(pdev, bar_id);
|
|
rtwpci->mmap = pci_iomap(pdev, bar_id, len);
|
|
if (!rtwpci->mmap) {
|
|
+ pci_release_regions(pdev);
|
|
rtw_err(rtwdev, "failed to map pci memory\n");
|
|
return -ENOMEM;
|
|
}
|
|
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
|
|
index f0e0af3aa714..d4b388793f40 100644
|
|
--- a/drivers/nvme/host/core.c
|
|
+++ b/drivers/nvme/host/core.c
|
|
@@ -1032,6 +1032,19 @@ void nvme_stop_keep_alive(struct nvme_ctrl *ctrl)
|
|
}
|
|
EXPORT_SYMBOL_GPL(nvme_stop_keep_alive);
|
|
|
|
+/*
|
|
+ * In NVMe 1.0 the CNS field was just a binary controller or namespace
|
|
+ * flag, thus sending any new CNS opcodes has a big chance of not working.
|
|
+ * Qemu unfortunately had that bug after reporting a 1.1 version compliance
|
|
+ * (but not for any later version).
|
|
+ */
|
|
+static bool nvme_ctrl_limited_cns(struct nvme_ctrl *ctrl)
|
|
+{
|
|
+ if (ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)
|
|
+ return ctrl->vs < NVME_VS(1, 2, 0);
|
|
+ return ctrl->vs < NVME_VS(1, 1, 0);
|
|
+}
|
|
+
|
|
static int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
|
|
{
|
|
struct nvme_command c = { };
|
|
@@ -3740,8 +3753,7 @@ static void nvme_scan_work(struct work_struct *work)
|
|
|
|
mutex_lock(&ctrl->scan_lock);
|
|
nn = le32_to_cpu(id->nn);
|
|
- if (ctrl->vs >= NVME_VS(1, 1, 0) &&
|
|
- !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
|
|
+ if (!nvme_ctrl_limited_cns(ctrl)) {
|
|
if (!nvme_scan_ns_list(ctrl, nn))
|
|
goto out_free_id;
|
|
}
|
|
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
|
|
index cd64ddb129e5..1c2129493508 100644
|
|
--- a/drivers/nvme/host/pci.c
|
|
+++ b/drivers/nvme/host/pci.c
|
|
@@ -128,6 +128,9 @@ struct nvme_dev {
|
|
dma_addr_t host_mem_descs_dma;
|
|
struct nvme_host_mem_buf_desc *host_mem_descs;
|
|
void **host_mem_desc_bufs;
|
|
+ unsigned int nr_allocated_queues;
|
|
+ unsigned int nr_write_queues;
|
|
+ unsigned int nr_poll_queues;
|
|
};
|
|
|
|
static int io_queue_depth_set(const char *val, const struct kernel_param *kp)
|
|
@@ -210,25 +213,14 @@ struct nvme_iod {
|
|
struct scatterlist *sg;
|
|
};
|
|
|
|
-static unsigned int max_io_queues(void)
|
|
+static inline unsigned int nvme_dbbuf_size(struct nvme_dev *dev)
|
|
{
|
|
- return num_possible_cpus() + write_queues + poll_queues;
|
|
-}
|
|
-
|
|
-static unsigned int max_queue_count(void)
|
|
-{
|
|
- /* IO queues + admin queue */
|
|
- return 1 + max_io_queues();
|
|
-}
|
|
-
|
|
-static inline unsigned int nvme_dbbuf_size(u32 stride)
|
|
-{
|
|
- return (max_queue_count() * 8 * stride);
|
|
+ return dev->nr_allocated_queues * 8 * dev->db_stride;
|
|
}
|
|
|
|
static int nvme_dbbuf_dma_alloc(struct nvme_dev *dev)
|
|
{
|
|
- unsigned int mem_size = nvme_dbbuf_size(dev->db_stride);
|
|
+ unsigned int mem_size = nvme_dbbuf_size(dev);
|
|
|
|
if (dev->dbbuf_dbs)
|
|
return 0;
|
|
@@ -253,7 +245,7 @@ static int nvme_dbbuf_dma_alloc(struct nvme_dev *dev)
|
|
|
|
static void nvme_dbbuf_dma_free(struct nvme_dev *dev)
|
|
{
|
|
- unsigned int mem_size = nvme_dbbuf_size(dev->db_stride);
|
|
+ unsigned int mem_size = nvme_dbbuf_size(dev);
|
|
|
|
if (dev->dbbuf_dbs) {
|
|
dma_free_coherent(dev->dev, mem_size,
|
|
@@ -2030,7 +2022,7 @@ static int nvme_setup_host_mem(struct nvme_dev *dev)
|
|
static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs)
|
|
{
|
|
struct nvme_dev *dev = affd->priv;
|
|
- unsigned int nr_read_queues;
|
|
+ unsigned int nr_read_queues, nr_write_queues = dev->nr_write_queues;
|
|
|
|
/*
|
|
* If there is no interupt available for queues, ensure that
|
|
@@ -2046,12 +2038,12 @@ static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs)
|
|
if (!nrirqs) {
|
|
nrirqs = 1;
|
|
nr_read_queues = 0;
|
|
- } else if (nrirqs == 1 || !write_queues) {
|
|
+ } else if (nrirqs == 1 || !nr_write_queues) {
|
|
nr_read_queues = 0;
|
|
- } else if (write_queues >= nrirqs) {
|
|
+ } else if (nr_write_queues >= nrirqs) {
|
|
nr_read_queues = 1;
|
|
} else {
|
|
- nr_read_queues = nrirqs - write_queues;
|
|
+ nr_read_queues = nrirqs - nr_write_queues;
|
|
}
|
|
|
|
dev->io_queues[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues;
|
|
@@ -2075,7 +2067,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
|
|
* Poll queues don't need interrupts, but we need at least one IO
|
|
* queue left over for non-polled IO.
|
|
*/
|
|
- this_p_queues = poll_queues;
|
|
+ this_p_queues = dev->nr_poll_queues;
|
|
if (this_p_queues >= nr_io_queues) {
|
|
this_p_queues = nr_io_queues - 1;
|
|
irq_queues = 1;
|
|
@@ -2105,14 +2097,25 @@ static void nvme_disable_io_queues(struct nvme_dev *dev)
|
|
__nvme_disable_io_queues(dev, nvme_admin_delete_cq);
|
|
}
|
|
|
|
+static unsigned int nvme_max_io_queues(struct nvme_dev *dev)
|
|
+{
|
|
+ return num_possible_cpus() + dev->nr_write_queues + dev->nr_poll_queues;
|
|
+}
|
|
+
|
|
static int nvme_setup_io_queues(struct nvme_dev *dev)
|
|
{
|
|
struct nvme_queue *adminq = &dev->queues[0];
|
|
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
|
- int result, nr_io_queues;
|
|
+ unsigned int nr_io_queues;
|
|
unsigned long size;
|
|
+ int result;
|
|
|
|
- nr_io_queues = max_io_queues();
|
|
+ /*
|
|
+ * Sample the module parameters once at reset time so that we have
|
|
+ * stable values to work with.
|
|
+ */
|
|
+ dev->nr_write_queues = write_queues;
|
|
+ dev->nr_poll_queues = poll_queues;
|
|
|
|
/*
|
|
* If tags are shared with admin queue (Apple bug), then
|
|
@@ -2120,6 +2123,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
|
|
*/
|
|
if (dev->ctrl.quirks & NVME_QUIRK_SHARED_TAGS)
|
|
nr_io_queues = 1;
|
|
+ else
|
|
+ nr_io_queues = min(nvme_max_io_queues(dev),
|
|
+ dev->nr_allocated_queues - 1);
|
|
|
|
result = nvme_set_queue_count(&dev->ctrl, &nr_io_queues);
|
|
if (result < 0)
|
|
@@ -2794,8 +2800,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
if (!dev)
|
|
return -ENOMEM;
|
|
|
|
- dev->queues = kcalloc_node(max_queue_count(), sizeof(struct nvme_queue),
|
|
- GFP_KERNEL, node);
|
|
+ dev->nr_write_queues = write_queues;
|
|
+ dev->nr_poll_queues = poll_queues;
|
|
+ dev->nr_allocated_queues = nvme_max_io_queues(dev) + 1;
|
|
+ dev->queues = kcalloc_node(dev->nr_allocated_queues,
|
|
+ sizeof(struct nvme_queue), GFP_KERNEL, node);
|
|
if (!dev->queues)
|
|
goto free;
|
|
|
|
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
|
|
index 11e84ed4de36..7900814355c2 100644
|
|
--- a/drivers/nvme/host/tcp.c
|
|
+++ b/drivers/nvme/host/tcp.c
|
|
@@ -784,11 +784,11 @@ static void nvme_tcp_data_ready(struct sock *sk)
|
|
{
|
|
struct nvme_tcp_queue *queue;
|
|
|
|
- read_lock(&sk->sk_callback_lock);
|
|
+ read_lock_bh(&sk->sk_callback_lock);
|
|
queue = sk->sk_user_data;
|
|
if (likely(queue && queue->rd_enabled))
|
|
queue_work_on(queue->io_cpu, nvme_tcp_wq, &queue->io_work);
|
|
- read_unlock(&sk->sk_callback_lock);
|
|
+ read_unlock_bh(&sk->sk_callback_lock);
|
|
}
|
|
|
|
static void nvme_tcp_write_space(struct sock *sk)
|
|
diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
|
|
index a35d3f3996d7..afc1a3d240b5 100644
|
|
--- a/drivers/pci/controller/vmd.c
|
|
+++ b/drivers/pci/controller/vmd.c
|
|
@@ -854,6 +854,8 @@ static const struct pci_device_id vmd_ids[] = {
|
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0),
|
|
.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
|
|
VMD_FEAT_HAS_BUS_RESTRICTIONS,},
|
|
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
|
|
+ .driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
|
|
{0,}
|
|
};
|
|
MODULE_DEVICE_TABLE(pci, vmd_ids);
|
|
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
|
|
index d3033873395d..83d909abc61d 100644
|
|
--- a/drivers/pci/probe.c
|
|
+++ b/drivers/pci/probe.c
|
|
@@ -1777,7 +1777,7 @@ int pci_setup_device(struct pci_dev *dev)
|
|
/* Device class may be changed after fixup */
|
|
class = dev->class >> 8;
|
|
|
|
- if (dev->non_compliant_bars) {
|
|
+ if (dev->non_compliant_bars && !dev->mmio_always_on) {
|
|
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
|
if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
|
|
pci_info(dev, "device has non-compliant BARs; disabling IO/MEM decoding\n");
|
|
@@ -1889,13 +1889,33 @@ static void pci_configure_mps(struct pci_dev *dev)
|
|
struct pci_dev *bridge = pci_upstream_bridge(dev);
|
|
int mps, mpss, p_mps, rc;
|
|
|
|
- if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge))
|
|
+ if (!pci_is_pcie(dev))
|
|
return;
|
|
|
|
/* MPS and MRRS fields are of type 'RsvdP' for VFs, short-circuit out */
|
|
if (dev->is_virtfn)
|
|
return;
|
|
|
|
+ /*
|
|
+ * For Root Complex Integrated Endpoints, program the maximum
|
|
+ * supported value unless limited by the PCIE_BUS_PEER2PEER case.
|
|
+ */
|
|
+ if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) {
|
|
+ if (pcie_bus_config == PCIE_BUS_PEER2PEER)
|
|
+ mps = 128;
|
|
+ else
|
|
+ mps = 128 << dev->pcie_mpss;
|
|
+ rc = pcie_set_mps(dev, mps);
|
|
+ if (rc) {
|
|
+ pci_warn(dev, "can't set Max Payload Size to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
|
|
+ mps);
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!bridge || !pci_is_pcie(bridge))
|
|
+ return;
|
|
+
|
|
mps = pcie_get_mps(dev);
|
|
p_mps = pcie_get_mps(bridge);
|
|
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index 798e52051ecc..a1ec8a1977d3 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -4683,6 +4683,20 @@ static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags)
|
|
PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
|
|
}
|
|
|
|
+static int pci_quirk_rciep_acs(struct pci_dev *dev, u16 acs_flags)
|
|
+{
|
|
+ /*
|
|
+ * Intel RCiEP's are required to allow p2p only on translated
|
|
+ * addresses. Refer to Intel VT-d specification, r3.1, sec 3.16,
|
|
+ * "Root-Complex Peer to Peer Considerations".
|
|
+ */
|
|
+ if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END)
|
|
+ return -ENOTTY;
|
|
+
|
|
+ return pci_acs_ctrl_enabled(acs_flags,
|
|
+ PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
|
|
+}
|
|
+
|
|
static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags)
|
|
{
|
|
/*
|
|
@@ -4765,6 +4779,7 @@ static const struct pci_dev_acs_enabled {
|
|
/* I219 */
|
|
{ PCI_VENDOR_ID_INTEL, 0x15b7, pci_quirk_mf_endpoint_acs },
|
|
{ PCI_VENDOR_ID_INTEL, 0x15b8, pci_quirk_mf_endpoint_acs },
|
|
+ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_rciep_acs },
|
|
/* QCOM QDF2xxx root ports */
|
|
{ PCI_VENDOR_ID_QCOM, 0x0400, pci_quirk_qcom_rp_acs },
|
|
{ PCI_VENDOR_ID_QCOM, 0x0401, pci_quirk_qcom_rp_acs },
|
|
@@ -5130,13 +5145,25 @@ static void quirk_intel_qat_vf_cap(struct pci_dev *pdev)
|
|
}
|
|
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap);
|
|
|
|
-/* FLR may cause some 82579 devices to hang */
|
|
-static void quirk_intel_no_flr(struct pci_dev *dev)
|
|
+/*
|
|
+ * FLR may cause the following to devices to hang:
|
|
+ *
|
|
+ * AMD Starship/Matisse HD Audio Controller 0x1487
|
|
+ * AMD Starship USB 3.0 Host Controller 0x148c
|
|
+ * AMD Matisse USB 3.0 Host Controller 0x149c
|
|
+ * Intel 82579LM Gigabit Ethernet Controller 0x1502
|
|
+ * Intel 82579V Gigabit Ethernet Controller 0x1503
|
|
+ *
|
|
+ */
|
|
+static void quirk_no_flr(struct pci_dev *dev)
|
|
{
|
|
dev->dev_flags |= PCI_DEV_FLAGS_NO_FLR_RESET;
|
|
}
|
|
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_intel_no_flr);
|
|
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1503, quirk_intel_no_flr);
|
|
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x1487, quirk_no_flr);
|
|
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x148c, quirk_no_flr);
|
|
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x149c, quirk_no_flr);
|
|
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_no_flr);
|
|
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1503, quirk_no_flr);
|
|
|
|
static void quirk_no_ext_tags(struct pci_dev *pdev)
|
|
{
|
|
@@ -5551,6 +5578,19 @@ static void pci_fixup_no_d0_pme(struct pci_dev *dev)
|
|
}
|
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x2142, pci_fixup_no_d0_pme);
|
|
|
|
+/*
|
|
+ * Device [12d8:0x400e] and [12d8:0x400f]
|
|
+ * These devices advertise PME# support in all power states but don't
|
|
+ * reliably assert it.
|
|
+ */
|
|
+static void pci_fixup_no_pme(struct pci_dev *dev)
|
|
+{
|
|
+ pci_info(dev, "PME# is unreliable, disabling it\n");
|
|
+ dev->pme_support = 0;
|
|
+}
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_PERICOM, 0x400e, pci_fixup_no_pme);
|
|
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_PERICOM, 0x400f, pci_fixup_no_pme);
|
|
+
|
|
static void apex_pci_fixup_class(struct pci_dev *pdev)
|
|
{
|
|
pdev->class = (PCI_CLASS_SYSTEM_OTHER << 8) | pdev->class;
|
|
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
|
|
index 2f8787276d9b..3269232ff570 100644
|
|
--- a/drivers/perf/arm_smmuv3_pmu.c
|
|
+++ b/drivers/perf/arm_smmuv3_pmu.c
|
|
@@ -815,7 +815,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
|
|
if (err) {
|
|
dev_err(dev, "Error %d registering hotplug, PMU @%pa\n",
|
|
err, &res_0->start);
|
|
- return err;
|
|
+ goto out_clear_affinity;
|
|
}
|
|
|
|
err = perf_pmu_register(&smmu_pmu->pmu, name, -1);
|
|
@@ -834,6 +834,8 @@ static int smmu_pmu_probe(struct platform_device *pdev)
|
|
|
|
out_unregister:
|
|
cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
|
|
+out_clear_affinity:
|
|
+ irq_set_affinity_hint(smmu_pmu->irq, NULL);
|
|
return err;
|
|
}
|
|
|
|
@@ -843,6 +845,7 @@ static int smmu_pmu_remove(struct platform_device *pdev)
|
|
|
|
perf_pmu_unregister(&smmu_pmu->pmu);
|
|
cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
|
|
+ irq_set_affinity_hint(smmu_pmu->irq, NULL);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
|
|
index f28063873e11..0d6325d6a4ec 100644
|
|
--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
|
|
+++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
|
|
@@ -285,7 +285,7 @@ static struct attribute *hisi_hha_pmu_events_attr[] = {
|
|
HISI_PMU_EVENT_ATTR(rx_wbip, 0x05),
|
|
HISI_PMU_EVENT_ATTR(rx_wtistash, 0x11),
|
|
HISI_PMU_EVENT_ATTR(rd_ddr_64b, 0x1c),
|
|
- HISI_PMU_EVENT_ATTR(wr_dr_64b, 0x1d),
|
|
+ HISI_PMU_EVENT_ATTR(wr_ddr_64b, 0x1d),
|
|
HISI_PMU_EVENT_ATTR(rd_ddr_128b, 0x1e),
|
|
HISI_PMU_EVENT_ATTR(wr_ddr_128b, 0x1f),
|
|
HISI_PMU_EVENT_ATTR(spill_num, 0x20),
|
|
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
|
|
index 0599f5127b01..84501c785473 100644
|
|
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
|
|
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
|
|
@@ -40,6 +40,8 @@ struct exynos_irq_chip {
|
|
u32 eint_pend;
|
|
u32 eint_wake_mask_value;
|
|
u32 eint_wake_mask_reg;
|
|
+ void (*set_eint_wakeup_mask)(struct samsung_pinctrl_drv_data *drvdata,
|
|
+ struct exynos_irq_chip *irq_chip);
|
|
};
|
|
|
|
static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
|
|
@@ -265,6 +267,7 @@ struct exynos_eint_gpio_save {
|
|
u32 eint_con;
|
|
u32 eint_fltcon0;
|
|
u32 eint_fltcon1;
|
|
+ u32 eint_mask;
|
|
};
|
|
|
|
/*
|
|
@@ -342,6 +345,47 @@ static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
|
|
return 0;
|
|
}
|
|
|
|
+static void
|
|
+exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
|
|
+ struct exynos_irq_chip *irq_chip)
|
|
+{
|
|
+ struct regmap *pmu_regs;
|
|
+
|
|
+ if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
|
|
+ dev_warn(drvdata->dev,
|
|
+ "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ pmu_regs = drvdata->retention_ctrl->priv;
|
|
+ dev_info(drvdata->dev,
|
|
+ "Setting external wakeup interrupt mask: 0x%x\n",
|
|
+ irq_chip->eint_wake_mask_value);
|
|
+
|
|
+ regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
|
|
+ irq_chip->eint_wake_mask_value);
|
|
+}
|
|
+
|
|
+static void
|
|
+s5pv210_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
|
|
+ struct exynos_irq_chip *irq_chip)
|
|
+
|
|
+{
|
|
+ void __iomem *clk_base;
|
|
+
|
|
+ if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
|
|
+ dev_warn(drvdata->dev,
|
|
+ "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+
|
|
+ clk_base = (void __iomem *) drvdata->retention_ctrl->priv;
|
|
+
|
|
+ __raw_writel(irq_chip->eint_wake_mask_value,
|
|
+ clk_base + irq_chip->eint_wake_mask_reg);
|
|
+}
|
|
+
|
|
/*
|
|
* irq_chip for wakeup interrupts
|
|
*/
|
|
@@ -360,8 +404,9 @@ static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = {
|
|
.eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
|
|
.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
|
|
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
|
- /* Only difference with exynos4210_wkup_irq_chip: */
|
|
+ /* Only differences with exynos4210_wkup_irq_chip: */
|
|
.eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK,
|
|
+ .set_eint_wakeup_mask = s5pv210_pinctrl_set_eint_wakeup_mask,
|
|
};
|
|
|
|
static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
|
|
@@ -380,6 +425,7 @@ static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
|
|
.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
|
|
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
|
.eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK,
|
|
+ .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
|
|
};
|
|
|
|
static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
|
|
@@ -398,6 +444,7 @@ static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
|
|
.eint_pend = EXYNOS7_WKUP_EPEND_OFFSET,
|
|
.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
|
|
.eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
|
|
+ .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
|
|
};
|
|
|
|
/* list of external wakeup controllers supported */
|
|
@@ -574,27 +621,6 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
|
|
return 0;
|
|
}
|
|
|
|
-static void
|
|
-exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
|
|
- struct exynos_irq_chip *irq_chip)
|
|
-{
|
|
- struct regmap *pmu_regs;
|
|
-
|
|
- if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
|
|
- dev_warn(drvdata->dev,
|
|
- "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
|
|
- return;
|
|
- }
|
|
-
|
|
- pmu_regs = drvdata->retention_ctrl->priv;
|
|
- dev_info(drvdata->dev,
|
|
- "Setting external wakeup interrupt mask: 0x%x\n",
|
|
- irq_chip->eint_wake_mask_value);
|
|
-
|
|
- regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
|
|
- irq_chip->eint_wake_mask_value);
|
|
-}
|
|
-
|
|
static void exynos_pinctrl_suspend_bank(
|
|
struct samsung_pinctrl_drv_data *drvdata,
|
|
struct samsung_pin_bank *bank)
|
|
@@ -608,10 +634,13 @@ static void exynos_pinctrl_suspend_bank(
|
|
+ 2 * bank->eint_offset);
|
|
save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
|
|
+ 2 * bank->eint_offset + 4);
|
|
+ save->eint_mask = readl(regs + bank->irq_chip->eint_mask
|
|
+ + bank->eint_offset);
|
|
|
|
pr_debug("%s: save con %#010x\n", bank->name, save->eint_con);
|
|
pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
|
|
pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
|
|
+ pr_debug("%s: save mask %#010x\n", bank->name, save->eint_mask);
|
|
}
|
|
|
|
void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
|
|
@@ -626,8 +655,8 @@ void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
|
|
else if (bank->eint_type == EINT_TYPE_WKUP) {
|
|
if (!irq_chip) {
|
|
irq_chip = bank->irq_chip;
|
|
- exynos_pinctrl_set_eint_wakeup_mask(drvdata,
|
|
- irq_chip);
|
|
+ irq_chip->set_eint_wakeup_mask(drvdata,
|
|
+ irq_chip);
|
|
} else if (bank->irq_chip != irq_chip) {
|
|
dev_warn(drvdata->dev,
|
|
"More than one external wakeup interrupt chip configured (bank: %s). This is not supported by hardware nor by driver.\n",
|
|
@@ -653,6 +682,9 @@ static void exynos_pinctrl_resume_bank(
|
|
pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
|
|
readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
|
|
+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
|
|
+ pr_debug("%s: mask %#010x => %#010x\n", bank->name,
|
|
+ readl(regs + bank->irq_chip->eint_mask
|
|
+ + bank->eint_offset), save->eint_mask);
|
|
|
|
writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
|
|
+ bank->eint_offset);
|
|
@@ -660,6 +692,8 @@ static void exynos_pinctrl_resume_bank(
|
|
+ 2 * bank->eint_offset);
|
|
writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
|
|
+ 2 * bank->eint_offset + 4);
|
|
+ writel(save->eint_mask, regs + bank->irq_chip->eint_mask
|
|
+ + bank->eint_offset);
|
|
}
|
|
|
|
void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
|
|
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
|
|
index 41e28552b2ce..b1f4a31ba1ee 100644
|
|
--- a/drivers/platform/x86/asus-wmi.c
|
|
+++ b/drivers/platform/x86/asus-wmi.c
|
|
@@ -111,6 +111,8 @@ struct bios_args {
|
|
u32 arg0;
|
|
u32 arg1;
|
|
u32 arg2; /* At least TUF Gaming series uses 3 dword input buffer. */
|
|
+ u32 arg4;
|
|
+ u32 arg5;
|
|
} __packed;
|
|
|
|
/*
|
|
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
|
|
index 74e988f839e8..4c1dd1d4e60b 100644
|
|
--- a/drivers/platform/x86/dell-laptop.c
|
|
+++ b/drivers/platform/x86/dell-laptop.c
|
|
@@ -2204,10 +2204,13 @@ static int __init dell_init(void)
|
|
|
|
dell_laptop_register_notifier(&dell_laptop_notifier);
|
|
|
|
- micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
|
|
- ret = led_classdev_register(&platform_device->dev, &micmute_led_cdev);
|
|
- if (ret < 0)
|
|
- goto fail_led;
|
|
+ if (dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE) &&
|
|
+ dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE)) {
|
|
+ micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
|
|
+ ret = led_classdev_register(&platform_device->dev, &micmute_led_cdev);
|
|
+ if (ret < 0)
|
|
+ goto fail_led;
|
|
+ }
|
|
|
|
if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
|
|
return 0;
|
|
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
|
|
index a881b709af25..a44a2ec33287 100644
|
|
--- a/drivers/platform/x86/hp-wmi.c
|
|
+++ b/drivers/platform/x86/hp-wmi.c
|
|
@@ -461,8 +461,14 @@ static ssize_t postcode_show(struct device *dev, struct device_attribute *attr,
|
|
static ssize_t als_store(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
- u32 tmp = simple_strtoul(buf, NULL, 10);
|
|
- int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
|
|
+ u32 tmp;
|
|
+ int ret;
|
|
+
|
|
+ ret = kstrtou32(buf, 10, &tmp);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
|
|
sizeof(tmp), sizeof(tmp));
|
|
if (ret)
|
|
return ret < 0 ? ret : -EINVAL;
|
|
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c
|
|
index ef6d4bd77b1a..7a506c1d0113 100644
|
|
--- a/drivers/platform/x86/intel-hid.c
|
|
+++ b/drivers/platform/x86/intel-hid.c
|
|
@@ -77,6 +77,13 @@ static const struct dmi_system_id button_array_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "Wacom MobileStudio Pro 16"),
|
|
},
|
|
},
|
|
+ {
|
|
+ .ident = "HP Spectre x2 (2015)",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x2 Detachable"),
|
|
+ },
|
|
+ },
|
|
{ }
|
|
};
|
|
|
|
diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c
|
|
index b74932307d69..cb2a80fdd8f4 100644
|
|
--- a/drivers/platform/x86/intel-vbtn.c
|
|
+++ b/drivers/platform/x86/intel-vbtn.c
|
|
@@ -39,28 +39,51 @@ static const struct key_entry intel_vbtn_keymap[] = {
|
|
{ KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */
|
|
{ KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key press */
|
|
{ KE_KEY, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key release */
|
|
+};
|
|
+
|
|
+static const struct key_entry intel_vbtn_switchmap[] = {
|
|
{ KE_SW, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */
|
|
{ KE_SW, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */
|
|
{ KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */
|
|
{ KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */
|
|
- { KE_END },
|
|
};
|
|
|
|
+#define KEYMAP_LEN \
|
|
+ (ARRAY_SIZE(intel_vbtn_keymap) + ARRAY_SIZE(intel_vbtn_switchmap) + 1)
|
|
+
|
|
struct intel_vbtn_priv {
|
|
+ struct key_entry keymap[KEYMAP_LEN];
|
|
struct input_dev *input_dev;
|
|
+ bool has_switches;
|
|
bool wakeup_mode;
|
|
};
|
|
|
|
static int intel_vbtn_input_setup(struct platform_device *device)
|
|
{
|
|
struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
|
|
- int ret;
|
|
+ int ret, keymap_len = 0;
|
|
+
|
|
+ if (true) {
|
|
+ memcpy(&priv->keymap[keymap_len], intel_vbtn_keymap,
|
|
+ ARRAY_SIZE(intel_vbtn_keymap) *
|
|
+ sizeof(struct key_entry));
|
|
+ keymap_len += ARRAY_SIZE(intel_vbtn_keymap);
|
|
+ }
|
|
+
|
|
+ if (priv->has_switches) {
|
|
+ memcpy(&priv->keymap[keymap_len], intel_vbtn_switchmap,
|
|
+ ARRAY_SIZE(intel_vbtn_switchmap) *
|
|
+ sizeof(struct key_entry));
|
|
+ keymap_len += ARRAY_SIZE(intel_vbtn_switchmap);
|
|
+ }
|
|
+
|
|
+ priv->keymap[keymap_len].type = KE_END;
|
|
|
|
priv->input_dev = devm_input_allocate_device(&device->dev);
|
|
if (!priv->input_dev)
|
|
return -ENOMEM;
|
|
|
|
- ret = sparse_keymap_setup(priv->input_dev, intel_vbtn_keymap, NULL);
|
|
+ ret = sparse_keymap_setup(priv->input_dev, priv->keymap, NULL);
|
|
if (ret)
|
|
return ret;
|
|
|
|
@@ -115,31 +138,40 @@ out_unknown:
|
|
|
|
static void detect_tablet_mode(struct platform_device *device)
|
|
{
|
|
- const char *chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
|
|
struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
|
|
acpi_handle handle = ACPI_HANDLE(&device->dev);
|
|
- struct acpi_buffer vgbs_output = { ACPI_ALLOCATE_BUFFER, NULL };
|
|
- union acpi_object *obj;
|
|
+ unsigned long long vgbs;
|
|
acpi_status status;
|
|
int m;
|
|
|
|
- if (!(chassis_type && strcmp(chassis_type, "31") == 0))
|
|
- goto out;
|
|
-
|
|
- status = acpi_evaluate_object(handle, "VGBS", NULL, &vgbs_output);
|
|
+ status = acpi_evaluate_integer(handle, "VGBS", NULL, &vgbs);
|
|
if (ACPI_FAILURE(status))
|
|
- goto out;
|
|
-
|
|
- obj = vgbs_output.pointer;
|
|
- if (!(obj && obj->type == ACPI_TYPE_INTEGER))
|
|
- goto out;
|
|
+ return;
|
|
|
|
- m = !(obj->integer.value & TABLET_MODE_FLAG);
|
|
+ m = !(vgbs & TABLET_MODE_FLAG);
|
|
input_report_switch(priv->input_dev, SW_TABLET_MODE, m);
|
|
- m = (obj->integer.value & DOCK_MODE_FLAG) ? 1 : 0;
|
|
+ m = (vgbs & DOCK_MODE_FLAG) ? 1 : 0;
|
|
input_report_switch(priv->input_dev, SW_DOCK, m);
|
|
-out:
|
|
- kfree(vgbs_output.pointer);
|
|
+}
|
|
+
|
|
+static bool intel_vbtn_has_switches(acpi_handle handle)
|
|
+{
|
|
+ const char *chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
|
|
+ unsigned long long vgbs;
|
|
+ acpi_status status;
|
|
+
|
|
+ /*
|
|
+ * Some normal laptops have a VGBS method despite being non-convertible
|
|
+ * and their VGBS method always returns 0, causing detect_tablet_mode()
|
|
+ * to report SW_TABLET_MODE=1 to userspace, which causes issues.
|
|
+ * These laptops have a DMI chassis_type of 9 ("Laptop"), do not report
|
|
+ * switches on any devices with a DMI chassis_type of 9.
|
|
+ */
|
|
+ if (chassis_type && strcmp(chassis_type, "9") == 0)
|
|
+ return false;
|
|
+
|
|
+ status = acpi_evaluate_integer(handle, "VGBS", NULL, &vgbs);
|
|
+ return ACPI_SUCCESS(status);
|
|
}
|
|
|
|
static int intel_vbtn_probe(struct platform_device *device)
|
|
@@ -160,13 +192,16 @@ static int intel_vbtn_probe(struct platform_device *device)
|
|
return -ENOMEM;
|
|
dev_set_drvdata(&device->dev, priv);
|
|
|
|
+ priv->has_switches = intel_vbtn_has_switches(handle);
|
|
+
|
|
err = intel_vbtn_input_setup(device);
|
|
if (err) {
|
|
pr_err("Failed to setup Intel Virtual Button\n");
|
|
return err;
|
|
}
|
|
|
|
- detect_tablet_mode(device);
|
|
+ if (priv->has_switches)
|
|
+ detect_tablet_mode(device);
|
|
|
|
status = acpi_install_notify_handler(handle,
|
|
ACPI_DEVICE_NOTIFY,
|
|
diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c
|
|
index 90cbaa8341e3..0bf9ab8653ae 100644
|
|
--- a/drivers/power/reset/vexpress-poweroff.c
|
|
+++ b/drivers/power/reset/vexpress-poweroff.c
|
|
@@ -143,6 +143,7 @@ static struct platform_driver vexpress_reset_driver = {
|
|
.driver = {
|
|
.name = "vexpress-reset",
|
|
.of_match_table = vexpress_reset_of_match,
|
|
+ .suppress_bind_attrs = true,
|
|
},
|
|
};
|
|
|
|
diff --git a/drivers/power/supply/power_supply_hwmon.c b/drivers/power/supply/power_supply_hwmon.c
|
|
index 75cf861ba492..2e7e2b73b012 100644
|
|
--- a/drivers/power/supply/power_supply_hwmon.c
|
|
+++ b/drivers/power/supply/power_supply_hwmon.c
|
|
@@ -144,7 +144,7 @@ static int power_supply_hwmon_read_string(struct device *dev,
|
|
u32 attr, int channel,
|
|
const char **str)
|
|
{
|
|
- *str = channel ? "temp" : "temp ambient";
|
|
+ *str = channel ? "temp ambient" : "temp";
|
|
return 0;
|
|
}
|
|
|
|
@@ -304,7 +304,7 @@ int power_supply_add_hwmon_sysfs(struct power_supply *psy)
|
|
goto error;
|
|
}
|
|
|
|
- ret = devm_add_action(dev, power_supply_hwmon_bitmap_free,
|
|
+ ret = devm_add_action_or_reset(dev, power_supply_hwmon_bitmap_free,
|
|
psyhw->props);
|
|
if (ret)
|
|
goto error;
|
|
diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
|
|
index 0246b6f99fb5..f11e4bfbc91b 100644
|
|
--- a/drivers/regulator/qcom-rpmh-regulator.c
|
|
+++ b/drivers/regulator/qcom-rpmh-regulator.c
|
|
@@ -832,11 +832,11 @@ static const struct rpmh_vreg_init_data pm8150_vreg_data[] = {
|
|
RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l2-l10"),
|
|
RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo, "vdd-l1-l8-l11"),
|
|
RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"),
|
|
- RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l13-l6-l17"),
|
|
+ RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l13-l16-l17"),
|
|
RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"),
|
|
RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo_lv, "vdd-l7-l12-l14-l15"),
|
|
- RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l13-l6-l17"),
|
|
- RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l13-l6-l17"),
|
|
+ RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l13-l16-l17"),
|
|
+ RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l13-l16-l17"),
|
|
RPMH_VREG("ldo18", "ldo%s18", &pmic5_nldo, "vdd-l3-l4-l5-l18"),
|
|
{},
|
|
};
|
|
@@ -857,7 +857,7 @@ static const struct rpmh_vreg_init_data pm8150l_vreg_data[] = {
|
|
RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"),
|
|
RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"),
|
|
RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"),
|
|
- RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l1-l8-l11"),
|
|
+ RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l1-l8"),
|
|
RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"),
|
|
RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"),
|
|
RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"),
|
|
diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
|
|
index c8ef05d6b8c7..25df4406ce52 100644
|
|
--- a/drivers/soc/tegra/Kconfig
|
|
+++ b/drivers/soc/tegra/Kconfig
|
|
@@ -130,6 +130,7 @@ config SOC_TEGRA_FLOWCTRL
|
|
|
|
config SOC_TEGRA_PMC
|
|
bool
|
|
+ select GENERIC_PINCONF
|
|
|
|
config SOC_TEGRA_POWERGATE_BPMP
|
|
def_bool y
|
|
diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c
|
|
index 2663bb12d9ce..b07710c76fc9 100644
|
|
--- a/drivers/spi/spi-dw-mid.c
|
|
+++ b/drivers/spi/spi-dw-mid.c
|
|
@@ -147,6 +147,7 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_tx(struct dw_spi *dws,
|
|
if (!xfer->tx_buf)
|
|
return NULL;
|
|
|
|
+ memset(&txconf, 0, sizeof(txconf));
|
|
txconf.direction = DMA_MEM_TO_DEV;
|
|
txconf.dst_addr = dws->dma_addr;
|
|
txconf.dst_maxburst = 16;
|
|
@@ -193,6 +194,7 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws,
|
|
if (!xfer->rx_buf)
|
|
return NULL;
|
|
|
|
+ memset(&rxconf, 0, sizeof(rxconf));
|
|
rxconf.direction = DMA_DEV_TO_MEM;
|
|
rxconf.src_addr = dws->dma_addr;
|
|
rxconf.src_maxburst = 16;
|
|
@@ -218,19 +220,23 @@ static struct dma_async_tx_descriptor *dw_spi_dma_prepare_rx(struct dw_spi *dws,
|
|
|
|
static int mid_spi_dma_setup(struct dw_spi *dws, struct spi_transfer *xfer)
|
|
{
|
|
- u16 dma_ctrl = 0;
|
|
+ u16 imr = 0, dma_ctrl = 0;
|
|
|
|
dw_writel(dws, DW_SPI_DMARDLR, 0xf);
|
|
dw_writel(dws, DW_SPI_DMATDLR, 0x10);
|
|
|
|
- if (xfer->tx_buf)
|
|
+ if (xfer->tx_buf) {
|
|
dma_ctrl |= SPI_DMA_TDMAE;
|
|
- if (xfer->rx_buf)
|
|
+ imr |= SPI_INT_TXOI;
|
|
+ }
|
|
+ if (xfer->rx_buf) {
|
|
dma_ctrl |= SPI_DMA_RDMAE;
|
|
+ imr |= SPI_INT_RXUI | SPI_INT_RXOI;
|
|
+ }
|
|
dw_writel(dws, DW_SPI_DMACR, dma_ctrl);
|
|
|
|
/* Set the interrupt mask */
|
|
- spi_umask_intr(dws, SPI_INT_TXOI | SPI_INT_RXUI | SPI_INT_RXOI);
|
|
+ spi_umask_intr(dws, imr);
|
|
|
|
dws->transfer_handler = dma_transfer;
|
|
|
|
@@ -260,7 +266,7 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer)
|
|
dma_async_issue_pending(dws->txchan);
|
|
}
|
|
|
|
- return 0;
|
|
+ return 1;
|
|
}
|
|
|
|
static void mid_spi_dma_stop(struct dw_spi *dws)
|
|
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
|
|
index 82c5c027ec4c..c2f96941ad04 100644
|
|
--- a/drivers/spi/spi-dw.c
|
|
+++ b/drivers/spi/spi-dw.c
|
|
@@ -381,11 +381,8 @@ static int dw_spi_transfer_one(struct spi_controller *master,
|
|
|
|
spi_enable_chip(dws, 1);
|
|
|
|
- if (dws->dma_mapped) {
|
|
- ret = dws->dma_ops->dma_transfer(dws, transfer);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- }
|
|
+ if (dws->dma_mapped)
|
|
+ return dws->dma_ops->dma_transfer(dws, transfer);
|
|
|
|
if (chip->poll_mode)
|
|
return poll_transfer(dws);
|
|
@@ -529,6 +526,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
|
|
dws->dma_inited = 0;
|
|
} else {
|
|
master->can_dma = dws->dma_ops->can_dma;
|
|
+ master->flags |= SPI_CONTROLLER_MUST_TX;
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
|
|
index 9f0fa9f3116d..de0ba3e5449f 100644
|
|
--- a/drivers/spi/spi-mem.c
|
|
+++ b/drivers/spi/spi-mem.c
|
|
@@ -108,15 +108,17 @@ static int spi_check_buswidth_req(struct spi_mem *mem, u8 buswidth, bool tx)
|
|
return 0;
|
|
|
|
case 2:
|
|
- if ((tx && (mode & (SPI_TX_DUAL | SPI_TX_QUAD))) ||
|
|
- (!tx && (mode & (SPI_RX_DUAL | SPI_RX_QUAD))))
|
|
+ if ((tx &&
|
|
+ (mode & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL))) ||
|
|
+ (!tx &&
|
|
+ (mode & (SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))))
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
- if ((tx && (mode & SPI_TX_QUAD)) ||
|
|
- (!tx && (mode & SPI_RX_QUAD)))
|
|
+ if ((tx && (mode & (SPI_TX_QUAD | SPI_TX_OCTAL))) ||
|
|
+ (!tx && (mode & (SPI_RX_QUAD | SPI_RX_OCTAL))))
|
|
return 0;
|
|
|
|
break;
|
|
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
|
|
index d0d6f1bda1b6..7f4285e2ae68 100644
|
|
--- a/drivers/spi/spi-pxa2xx.c
|
|
+++ b/drivers/spi/spi-pxa2xx.c
|
|
@@ -148,6 +148,7 @@ static const struct lpss_config lpss_platforms[] = {
|
|
.tx_threshold_hi = 48,
|
|
.cs_sel_shift = 8,
|
|
.cs_sel_mask = 3 << 8,
|
|
+ .cs_clk_stays_gated = true,
|
|
},
|
|
{ /* LPSS_CNL_SSP */
|
|
.offset = 0x200,
|
|
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
|
|
index 6bfbf0cfcf63..c6242f0a307f 100644
|
|
--- a/drivers/spi/spi.c
|
|
+++ b/drivers/spi/spi.c
|
|
@@ -1950,6 +1950,7 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
|
|
}
|
|
|
|
lookup->max_speed_hz = sb->connection_speed;
|
|
+ lookup->bits_per_word = sb->data_bit_length;
|
|
|
|
if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
|
|
lookup->mode |= SPI_CPHA;
|
|
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
|
|
index 473b465724f1..0755b11348ed 100644
|
|
--- a/drivers/staging/android/ion/ion_heap.c
|
|
+++ b/drivers/staging/android/ion/ion_heap.c
|
|
@@ -99,12 +99,12 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
|
|
|
|
static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot)
|
|
{
|
|
- void *addr = vm_map_ram(pages, num, -1, pgprot);
|
|
+ void *addr = vmap(pages, num, VM_MAP, pgprot);
|
|
|
|
if (!addr)
|
|
return -ENOMEM;
|
|
memset(addr, 0, PAGE_SIZE * num);
|
|
- vm_unmap_ram(addr, num);
|
|
+ vunmap(addr);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c
|
|
index 68c5718be827..c4b16bb5c1a4 100644
|
|
--- a/drivers/staging/greybus/sdio.c
|
|
+++ b/drivers/staging/greybus/sdio.c
|
|
@@ -411,6 +411,7 @@ static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd)
|
|
struct gb_sdio_command_request request = {0};
|
|
struct gb_sdio_command_response response;
|
|
struct mmc_data *data = host->mrq->data;
|
|
+ unsigned int timeout_ms;
|
|
u8 cmd_flags;
|
|
u8 cmd_type;
|
|
int i;
|
|
@@ -469,9 +470,12 @@ static int gb_sdio_command(struct gb_sdio_host *host, struct mmc_command *cmd)
|
|
request.data_blksz = cpu_to_le16(data->blksz);
|
|
}
|
|
|
|
- ret = gb_operation_sync(host->connection, GB_SDIO_TYPE_COMMAND,
|
|
- &request, sizeof(request), &response,
|
|
- sizeof(response));
|
|
+ timeout_ms = cmd->busy_timeout ? cmd->busy_timeout :
|
|
+ GB_OPERATION_TIMEOUT_DEFAULT;
|
|
+
|
|
+ ret = gb_operation_sync_timeout(host->connection, GB_SDIO_TYPE_COMMAND,
|
|
+ &request, sizeof(request), &response,
|
|
+ sizeof(response), timeout_ms);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
|
|
index 6f628195c4da..021bbd420390 100644
|
|
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
|
|
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
|
|
@@ -657,28 +657,6 @@ static int mipi_csis_init_cfg(struct v4l2_subdev *mipi_sd,
|
|
return 0;
|
|
}
|
|
|
|
-static struct csis_pix_format const *
|
|
-mipi_csis_try_format(struct v4l2_subdev *mipi_sd, struct v4l2_mbus_framefmt *mf)
|
|
-{
|
|
- struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
|
|
- struct csis_pix_format const *csis_fmt;
|
|
-
|
|
- csis_fmt = find_csis_format(mf->code);
|
|
- if (!csis_fmt)
|
|
- csis_fmt = &mipi_csis_formats[0];
|
|
-
|
|
- v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
|
|
- csis_fmt->pix_width_alignment,
|
|
- &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
|
|
- 0);
|
|
-
|
|
- state->format_mbus.code = csis_fmt->code;
|
|
- state->format_mbus.width = mf->width;
|
|
- state->format_mbus.height = mf->height;
|
|
-
|
|
- return csis_fmt;
|
|
-}
|
|
-
|
|
static struct v4l2_mbus_framefmt *
|
|
mipi_csis_get_format(struct csi_state *state,
|
|
struct v4l2_subdev_pad_config *cfg,
|
|
@@ -691,53 +669,67 @@ mipi_csis_get_format(struct csi_state *state,
|
|
return &state->format_mbus;
|
|
}
|
|
|
|
-static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
|
|
+static int mipi_csis_get_fmt(struct v4l2_subdev *mipi_sd,
|
|
struct v4l2_subdev_pad_config *cfg,
|
|
struct v4l2_subdev_format *sdformat)
|
|
{
|
|
struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
|
|
- struct csis_pix_format const *csis_fmt;
|
|
struct v4l2_mbus_framefmt *fmt;
|
|
|
|
- if (sdformat->pad >= CSIS_PADS_NUM)
|
|
- return -EINVAL;
|
|
-
|
|
- fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad);
|
|
-
|
|
mutex_lock(&state->lock);
|
|
- if (sdformat->pad == CSIS_PAD_SOURCE) {
|
|
- sdformat->format = *fmt;
|
|
- goto unlock;
|
|
- }
|
|
-
|
|
- csis_fmt = mipi_csis_try_format(mipi_sd, &sdformat->format);
|
|
-
|
|
+ fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad);
|
|
sdformat->format = *fmt;
|
|
-
|
|
- if (csis_fmt && sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
|
- state->csis_fmt = csis_fmt;
|
|
- else
|
|
- cfg->try_fmt = sdformat->format;
|
|
-
|
|
-unlock:
|
|
mutex_unlock(&state->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
-static int mipi_csis_get_fmt(struct v4l2_subdev *mipi_sd,
|
|
+static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd,
|
|
struct v4l2_subdev_pad_config *cfg,
|
|
struct v4l2_subdev_format *sdformat)
|
|
{
|
|
struct csi_state *state = mipi_sd_to_csis_state(mipi_sd);
|
|
+ struct csis_pix_format const *csis_fmt;
|
|
struct v4l2_mbus_framefmt *fmt;
|
|
|
|
- mutex_lock(&state->lock);
|
|
+ /*
|
|
+ * The CSIS can't transcode in any way, the source format can't be
|
|
+ * modified.
|
|
+ */
|
|
+ if (sdformat->pad == CSIS_PAD_SOURCE)
|
|
+ return mipi_csis_get_fmt(mipi_sd, cfg, sdformat);
|
|
+
|
|
+ if (sdformat->pad != CSIS_PAD_SINK)
|
|
+ return -EINVAL;
|
|
|
|
fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad);
|
|
|
|
+ mutex_lock(&state->lock);
|
|
+
|
|
+ /* Validate the media bus code and clamp the size. */
|
|
+ csis_fmt = find_csis_format(sdformat->format.code);
|
|
+ if (!csis_fmt)
|
|
+ csis_fmt = &mipi_csis_formats[0];
|
|
+
|
|
+ fmt->code = csis_fmt->code;
|
|
+ fmt->width = sdformat->format.width;
|
|
+ fmt->height = sdformat->format.height;
|
|
+
|
|
+ v4l_bound_align_image(&fmt->width, 1, CSIS_MAX_PIX_WIDTH,
|
|
+ csis_fmt->pix_width_alignment,
|
|
+ &fmt->height, 1, CSIS_MAX_PIX_HEIGHT, 1, 0);
|
|
+
|
|
sdformat->format = *fmt;
|
|
|
|
+ /* Propagate the format from sink to source. */
|
|
+ fmt = mipi_csis_get_format(state, cfg, sdformat->which,
|
|
+ CSIS_PAD_SOURCE);
|
|
+ *fmt = sdformat->format;
|
|
+
|
|
+ /* Store the CSIS format descriptor for active formats. */
|
|
+ if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
|
+ state->csis_fmt = csis_fmt;
|
|
+
|
|
mutex_unlock(&state->lock);
|
|
|
|
return 0;
|
|
diff --git a/drivers/staging/media/ipu3/ipu3-mmu.c b/drivers/staging/media/ipu3/ipu3-mmu.c
|
|
index 3d969b0522ab..abcf1f3e5f63 100644
|
|
--- a/drivers/staging/media/ipu3/ipu3-mmu.c
|
|
+++ b/drivers/staging/media/ipu3/ipu3-mmu.c
|
|
@@ -174,8 +174,10 @@ static u32 *imgu_mmu_get_l2pt(struct imgu_mmu *mmu, u32 l1pt_idx)
|
|
spin_lock_irqsave(&mmu->lock, flags);
|
|
|
|
l2pt = mmu->l2pts[l1pt_idx];
|
|
- if (l2pt)
|
|
- goto done;
|
|
+ if (l2pt) {
|
|
+ spin_unlock_irqrestore(&mmu->lock, flags);
|
|
+ return l2pt;
|
|
+ }
|
|
|
|
spin_unlock_irqrestore(&mmu->lock, flags);
|
|
|
|
@@ -190,8 +192,9 @@ static u32 *imgu_mmu_get_l2pt(struct imgu_mmu *mmu, u32 l1pt_idx)
|
|
|
|
l2pt = mmu->l2pts[l1pt_idx];
|
|
if (l2pt) {
|
|
+ spin_unlock_irqrestore(&mmu->lock, flags);
|
|
imgu_mmu_free_page_table(new_l2pt);
|
|
- goto done;
|
|
+ return l2pt;
|
|
}
|
|
|
|
l2pt = new_l2pt;
|
|
@@ -200,7 +203,6 @@ static u32 *imgu_mmu_get_l2pt(struct imgu_mmu *mmu, u32 l1pt_idx)
|
|
pteval = IPU3_ADDR2PTE(virt_to_phys(new_l2pt));
|
|
mmu->l1pt[l1pt_idx] = pteval;
|
|
|
|
-done:
|
|
spin_unlock_irqrestore(&mmu->lock, flags);
|
|
return l2pt;
|
|
}
|
|
diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c
|
|
index 3c7ad1eed434..c764cb55dc8d 100644
|
|
--- a/drivers/staging/media/ipu3/ipu3-v4l2.c
|
|
+++ b/drivers/staging/media/ipu3/ipu3-v4l2.c
|
|
@@ -367,8 +367,10 @@ static void imgu_vb2_buf_queue(struct vb2_buffer *vb)
|
|
|
|
vb2_set_plane_payload(vb, 0, need_bytes);
|
|
|
|
+ mutex_lock(&imgu->streaming_lock);
|
|
if (imgu->streaming)
|
|
imgu_queue_buffers(imgu, false, node->pipe);
|
|
+ mutex_unlock(&imgu->streaming_lock);
|
|
|
|
dev_dbg(&imgu->pci_dev->dev, "%s for pipe %u node %u", __func__,
|
|
node->pipe, node->id);
|
|
@@ -468,10 +470,13 @@ static int imgu_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|
dev_dbg(dev, "%s node name %s pipe %u id %u", __func__,
|
|
node->name, node->pipe, node->id);
|
|
|
|
+ mutex_lock(&imgu->streaming_lock);
|
|
if (imgu->streaming) {
|
|
r = -EBUSY;
|
|
+ mutex_unlock(&imgu->streaming_lock);
|
|
goto fail_return_bufs;
|
|
}
|
|
+ mutex_unlock(&imgu->streaming_lock);
|
|
|
|
if (!node->enabled) {
|
|
dev_err(dev, "IMGU node is not enabled");
|
|
@@ -498,9 +503,11 @@ static int imgu_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|
|
|
/* Start streaming of the whole pipeline now */
|
|
dev_dbg(dev, "IMGU streaming is ready to start");
|
|
+ mutex_lock(&imgu->streaming_lock);
|
|
r = imgu_s_stream(imgu, true);
|
|
if (!r)
|
|
imgu->streaming = true;
|
|
+ mutex_unlock(&imgu->streaming_lock);
|
|
|
|
return 0;
|
|
|
|
@@ -532,6 +539,7 @@ static void imgu_vb2_stop_streaming(struct vb2_queue *vq)
|
|
dev_err(&imgu->pci_dev->dev,
|
|
"failed to stop subdev streaming\n");
|
|
|
|
+ mutex_lock(&imgu->streaming_lock);
|
|
/* Was this the first node with streaming disabled? */
|
|
if (imgu->streaming && imgu_all_nodes_streaming(imgu, node)) {
|
|
/* Yes, really stop streaming now */
|
|
@@ -542,6 +550,8 @@ static void imgu_vb2_stop_streaming(struct vb2_queue *vq)
|
|
}
|
|
|
|
imgu_return_all_buffers(imgu, node, VB2_BUF_STATE_ERROR);
|
|
+ mutex_unlock(&imgu->streaming_lock);
|
|
+
|
|
media_pipeline_stop(&node->vdev.entity);
|
|
}
|
|
|
|
diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c
|
|
index 06a61f31ca50..08eb6791918b 100644
|
|
--- a/drivers/staging/media/ipu3/ipu3.c
|
|
+++ b/drivers/staging/media/ipu3/ipu3.c
|
|
@@ -261,6 +261,7 @@ int imgu_queue_buffers(struct imgu_device *imgu, bool initial, unsigned int pipe
|
|
|
|
ivb = list_first_entry(&imgu_pipe->nodes[node].buffers,
|
|
struct imgu_vb2_buffer, list);
|
|
+ list_del(&ivb->list);
|
|
vb = &ivb->vbb.vb2_buf;
|
|
r = imgu_css_set_parameters(&imgu->css, pipe,
|
|
vb2_plane_vaddr(vb, 0));
|
|
@@ -274,7 +275,6 @@ int imgu_queue_buffers(struct imgu_device *imgu, bool initial, unsigned int pipe
|
|
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
|
|
dev_dbg(&imgu->pci_dev->dev,
|
|
"queue user parameters %d to css.", vb->index);
|
|
- list_del(&ivb->list);
|
|
} else if (imgu_pipe->queue_enabled[node]) {
|
|
struct imgu_css_buffer *buf =
|
|
imgu_queue_getbuf(imgu, node, pipe);
|
|
@@ -663,6 +663,7 @@ static int imgu_pci_probe(struct pci_dev *pci_dev,
|
|
return r;
|
|
|
|
mutex_init(&imgu->lock);
|
|
+ mutex_init(&imgu->streaming_lock);
|
|
atomic_set(&imgu->qbuf_barrier, 0);
|
|
init_waitqueue_head(&imgu->buf_drain_wq);
|
|
|
|
@@ -726,6 +727,7 @@ out_mmu_exit:
|
|
out_css_powerdown:
|
|
imgu_css_set_powerdown(&pci_dev->dev, imgu->base);
|
|
out_mutex_destroy:
|
|
+ mutex_destroy(&imgu->streaming_lock);
|
|
mutex_destroy(&imgu->lock);
|
|
|
|
return r;
|
|
@@ -743,6 +745,7 @@ static void imgu_pci_remove(struct pci_dev *pci_dev)
|
|
imgu_css_set_powerdown(&pci_dev->dev, imgu->base);
|
|
imgu_dmamap_exit(imgu);
|
|
imgu_mmu_exit(imgu->mmu);
|
|
+ mutex_destroy(&imgu->streaming_lock);
|
|
mutex_destroy(&imgu->lock);
|
|
}
|
|
|
|
diff --git a/drivers/staging/media/ipu3/ipu3.h b/drivers/staging/media/ipu3/ipu3.h
|
|
index 73b123b2b8a2..8cd6a0077d99 100644
|
|
--- a/drivers/staging/media/ipu3/ipu3.h
|
|
+++ b/drivers/staging/media/ipu3/ipu3.h
|
|
@@ -146,6 +146,10 @@ struct imgu_device {
|
|
* vid_buf.list and css->queue
|
|
*/
|
|
struct mutex lock;
|
|
+
|
|
+ /* Lock to protect writes to streaming flag in this struct */
|
|
+ struct mutex streaming_lock;
|
|
+
|
|
/* Forbid streaming and buffer queuing during system suspend. */
|
|
atomic_t qbuf_barrier;
|
|
/* Indicate if system suspend take place while imgu is streaming. */
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
|
index 56ca4c9ad01c..47940f02457b 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c
|
|
@@ -65,6 +65,8 @@ void cedrus_device_run(void *priv)
|
|
|
|
v4l2_m2m_buf_copy_metadata(run.src, run.dst, true);
|
|
|
|
+ cedrus_dst_format_set(dev, &ctx->dst_fmt);
|
|
+
|
|
dev->dec_ops[ctx->current_codec]->setup(ctx, &run);
|
|
|
|
/* Complete request(s) controls if needed. */
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
index eeee3efd247b..966f9f3ed9d3 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
@@ -286,7 +286,6 @@ static int cedrus_s_fmt_vid_cap(struct file *file, void *priv,
|
|
struct v4l2_format *f)
|
|
{
|
|
struct cedrus_ctx *ctx = cedrus_file2ctx(file);
|
|
- struct cedrus_dev *dev = ctx->dev;
|
|
struct vb2_queue *vq;
|
|
int ret;
|
|
|
|
@@ -300,8 +299,6 @@ static int cedrus_s_fmt_vid_cap(struct file *file, void *priv,
|
|
|
|
ctx->dst_fmt = f->fmt.pix;
|
|
|
|
- cedrus_dst_format_set(dev, &ctx->dst_fmt);
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
|
|
index 28bdbd7b4ab2..f1d230c5a8ef 100644
|
|
--- a/drivers/tty/serial/8250/8250_core.c
|
|
+++ b/drivers/tty/serial/8250/8250_core.c
|
|
@@ -1026,7 +1026,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|
gpios = mctrl_gpio_init(&uart->port, 0);
|
|
if (IS_ERR(gpios)) {
|
|
ret = PTR_ERR(gpios);
|
|
- goto out_unlock;
|
|
+ goto err;
|
|
} else {
|
|
uart->gpios = gpios;
|
|
}
|
|
@@ -1075,8 +1075,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|
serial8250_apply_quirks(uart);
|
|
ret = uart_add_one_port(&serial8250_reg,
|
|
&uart->port);
|
|
- if (ret == 0)
|
|
- ret = uart->port.line;
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ ret = uart->port.line;
|
|
} else {
|
|
dev_info(uart->port.dev,
|
|
"skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n",
|
|
@@ -1098,10 +1100,14 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|
}
|
|
}
|
|
|
|
-out_unlock:
|
|
mutex_unlock(&serial_mutex);
|
|
|
|
return ret;
|
|
+
|
|
+err:
|
|
+ uart->port.dev = NULL;
|
|
+ mutex_unlock(&serial_mutex);
|
|
+ return ret;
|
|
}
|
|
EXPORT_SYMBOL(serial8250_register_8250_port);
|
|
|
|
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
|
|
index 8a01d034f9d1..7cad66eb39ff 100644
|
|
--- a/drivers/tty/serial/8250/8250_pci.c
|
|
+++ b/drivers/tty/serial/8250/8250_pci.c
|
|
@@ -1871,12 +1871,6 @@ pci_moxa_setup(struct serial_private *priv,
|
|
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
|
|
#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253
|
|
|
|
-#define PCI_VENDOR_ID_PERICOM 0x12D8
|
|
-#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
|
|
-#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
|
|
-#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954
|
|
-#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958
|
|
-
|
|
#define PCI_VENDOR_ID_ACCESIO 0x494f
|
|
#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB 0x1051
|
|
#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S 0x1053
|
|
diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c
|
|
index c7d51b51898f..f5608ad68ae1 100644
|
|
--- a/drivers/tty/serial/kgdboc.c
|
|
+++ b/drivers/tty/serial/kgdboc.c
|
|
@@ -20,6 +20,7 @@
|
|
#include <linux/vt_kern.h>
|
|
#include <linux/input.h>
|
|
#include <linux/module.h>
|
|
+#include <linux/platform_device.h>
|
|
|
|
#define MAX_CONFIG_LEN 40
|
|
|
|
@@ -27,6 +28,7 @@ static struct kgdb_io kgdboc_io_ops;
|
|
|
|
/* -1 = init not run yet, 0 = unconfigured, 1 = configured. */
|
|
static int configured = -1;
|
|
+static DEFINE_MUTEX(config_mutex);
|
|
|
|
static char config[MAX_CONFIG_LEN];
|
|
static struct kparam_string kps = {
|
|
@@ -38,6 +40,8 @@ static int kgdboc_use_kms; /* 1 if we use kernel mode switching */
|
|
static struct tty_driver *kgdb_tty_driver;
|
|
static int kgdb_tty_line;
|
|
|
|
+static struct platform_device *kgdboc_pdev;
|
|
+
|
|
#ifdef CONFIG_KDB_KEYBOARD
|
|
static int kgdboc_reset_connect(struct input_handler *handler,
|
|
struct input_dev *dev,
|
|
@@ -133,11 +137,13 @@ static void kgdboc_unregister_kbd(void)
|
|
|
|
static void cleanup_kgdboc(void)
|
|
{
|
|
+ if (configured != 1)
|
|
+ return;
|
|
+
|
|
if (kgdb_unregister_nmi_console())
|
|
return;
|
|
kgdboc_unregister_kbd();
|
|
- if (configured == 1)
|
|
- kgdb_unregister_io_module(&kgdboc_io_ops);
|
|
+ kgdb_unregister_io_module(&kgdboc_io_ops);
|
|
}
|
|
|
|
static int configure_kgdboc(void)
|
|
@@ -200,20 +206,79 @@ nmi_con_failed:
|
|
kgdb_unregister_io_module(&kgdboc_io_ops);
|
|
noconfig:
|
|
kgdboc_unregister_kbd();
|
|
- config[0] = 0;
|
|
configured = 0;
|
|
- cleanup_kgdboc();
|
|
|
|
return err;
|
|
}
|
|
|
|
+static int kgdboc_probe(struct platform_device *pdev)
|
|
+{
|
|
+ int ret = 0;
|
|
+
|
|
+ mutex_lock(&config_mutex);
|
|
+ if (configured != 1) {
|
|
+ ret = configure_kgdboc();
|
|
+
|
|
+ /* Convert "no device" to "defer" so we'll keep trying */
|
|
+ if (ret == -ENODEV)
|
|
+ ret = -EPROBE_DEFER;
|
|
+ }
|
|
+ mutex_unlock(&config_mutex);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static struct platform_driver kgdboc_platform_driver = {
|
|
+ .probe = kgdboc_probe,
|
|
+ .driver = {
|
|
+ .name = "kgdboc",
|
|
+ .suppress_bind_attrs = true,
|
|
+ },
|
|
+};
|
|
+
|
|
static int __init init_kgdboc(void)
|
|
{
|
|
- /* Already configured? */
|
|
- if (configured == 1)
|
|
+ int ret;
|
|
+
|
|
+ /*
|
|
+ * kgdboc is a little bit of an odd "platform_driver". It can be
|
|
+ * up and running long before the platform_driver object is
|
|
+ * created and thus doesn't actually store anything in it. There's
|
|
+ * only one instance of kgdb so anything is stored as global state.
|
|
+ * The platform_driver is only created so that we can leverage the
|
|
+ * kernel's mechanisms (like -EPROBE_DEFER) to call us when our
|
|
+ * underlying tty is ready. Here we init our platform driver and
|
|
+ * then create the single kgdboc instance.
|
|
+ */
|
|
+ ret = platform_driver_register(&kgdboc_platform_driver);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ kgdboc_pdev = platform_device_alloc("kgdboc", PLATFORM_DEVID_NONE);
|
|
+ if (!kgdboc_pdev) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_did_register;
|
|
+ }
|
|
+
|
|
+ ret = platform_device_add(kgdboc_pdev);
|
|
+ if (!ret)
|
|
return 0;
|
|
|
|
- return configure_kgdboc();
|
|
+ platform_device_put(kgdboc_pdev);
|
|
+
|
|
+err_did_register:
|
|
+ platform_driver_unregister(&kgdboc_platform_driver);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void exit_kgdboc(void)
|
|
+{
|
|
+ mutex_lock(&config_mutex);
|
|
+ cleanup_kgdboc();
|
|
+ mutex_unlock(&config_mutex);
|
|
+
|
|
+ platform_device_unregister(kgdboc_pdev);
|
|
+ platform_driver_unregister(&kgdboc_platform_driver);
|
|
}
|
|
|
|
static int kgdboc_get_char(void)
|
|
@@ -236,24 +301,20 @@ static int param_set_kgdboc_var(const char *kmessage,
|
|
const struct kernel_param *kp)
|
|
{
|
|
size_t len = strlen(kmessage);
|
|
+ int ret = 0;
|
|
|
|
if (len >= MAX_CONFIG_LEN) {
|
|
pr_err("config string too long\n");
|
|
return -ENOSPC;
|
|
}
|
|
|
|
- /* Only copy in the string if the init function has not run yet */
|
|
- if (configured < 0) {
|
|
- strcpy(config, kmessage);
|
|
- return 0;
|
|
- }
|
|
-
|
|
if (kgdb_connected) {
|
|
pr_err("Cannot reconfigure while KGDB is connected.\n");
|
|
-
|
|
return -EBUSY;
|
|
}
|
|
|
|
+ mutex_lock(&config_mutex);
|
|
+
|
|
strcpy(config, kmessage);
|
|
/* Chop out \n char as a result of echo */
|
|
if (len && config[len - 1] == '\n')
|
|
@@ -262,8 +323,30 @@ static int param_set_kgdboc_var(const char *kmessage,
|
|
if (configured == 1)
|
|
cleanup_kgdboc();
|
|
|
|
- /* Go and configure with the new params. */
|
|
- return configure_kgdboc();
|
|
+ /*
|
|
+ * Configure with the new params as long as init already ran.
|
|
+ * Note that we can get called before init if someone loads us
|
|
+ * with "modprobe kgdboc kgdboc=..." or if they happen to use the
|
|
+ * the odd syntax of "kgdboc.kgdboc=..." on the kernel command.
|
|
+ */
|
|
+ if (configured >= 0)
|
|
+ ret = configure_kgdboc();
|
|
+
|
|
+ /*
|
|
+ * If we couldn't configure then clear out the config. Note that
|
|
+ * specifying an invalid config on the kernel command line vs.
|
|
+ * through sysfs have slightly different behaviors. If we fail
|
|
+ * to configure what was specified on the kernel command line
|
|
+ * we'll leave it in the 'config' and return -EPROBE_DEFER from
|
|
+ * our probe. When specified through sysfs userspace is
|
|
+ * responsible for loading the tty driver before setting up.
|
|
+ */
|
|
+ if (ret)
|
|
+ config[0] = '\0';
|
|
+
|
|
+ mutex_unlock(&config_mutex);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int dbg_restore_graphics;
|
|
@@ -326,15 +409,8 @@ __setup("kgdboc=", kgdboc_option_setup);
|
|
/* This is only available if kgdboc is a built in for early debugging */
|
|
static int __init kgdboc_early_init(char *opt)
|
|
{
|
|
- /* save the first character of the config string because the
|
|
- * init routine can destroy it.
|
|
- */
|
|
- char save_ch;
|
|
-
|
|
kgdboc_option_setup(opt);
|
|
- save_ch = config[0];
|
|
- init_kgdboc();
|
|
- config[0] = save_ch;
|
|
+ configure_kgdboc();
|
|
return 0;
|
|
}
|
|
|
|
@@ -342,7 +418,7 @@ early_param("ekgdboc", kgdboc_early_init);
|
|
#endif /* CONFIG_KGDB_SERIAL_CONSOLE */
|
|
|
|
module_init(init_kgdboc);
|
|
-module_exit(cleanup_kgdboc);
|
|
+module_exit(exit_kgdboc);
|
|
module_param_call(kgdboc, param_set_kgdboc_var, param_get_string, &kps, 0644);
|
|
MODULE_PARM_DESC(kgdboc, "<serial_device>[,baud]");
|
|
MODULE_DESCRIPTION("KGDB Console TTY Driver");
|
|
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
|
|
index 4164045866b3..6bac5c18cf6d 100644
|
|
--- a/drivers/w1/masters/omap_hdq.c
|
|
+++ b/drivers/w1/masters/omap_hdq.c
|
|
@@ -176,7 +176,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)
|
|
/* check irqstatus */
|
|
if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) {
|
|
dev_dbg(hdq_data->dev, "timeout waiting for"
|
|
- " TXCOMPLETE/RXCOMPLETE, %x", *status);
|
|
+ " TXCOMPLETE/RXCOMPLETE, %x\n", *status);
|
|
ret = -ETIMEDOUT;
|
|
goto out;
|
|
}
|
|
@@ -187,7 +187,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)
|
|
OMAP_HDQ_FLAG_CLEAR, &tmp_status);
|
|
if (ret) {
|
|
dev_dbg(hdq_data->dev, "timeout waiting GO bit"
|
|
- " return to zero, %x", tmp_status);
|
|
+ " return to zero, %x\n", tmp_status);
|
|
}
|
|
|
|
out:
|
|
@@ -203,7 +203,7 @@ static irqreturn_t hdq_isr(int irq, void *_hdq)
|
|
spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
|
|
hdq_data->hdq_irqstatus = hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
|
|
spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
|
|
- dev_dbg(hdq_data->dev, "hdq_isr: %x", hdq_data->hdq_irqstatus);
|
|
+ dev_dbg(hdq_data->dev, "hdq_isr: %x\n", hdq_data->hdq_irqstatus);
|
|
|
|
if (hdq_data->hdq_irqstatus &
|
|
(OMAP_HDQ_INT_STATUS_TXCOMPLETE | OMAP_HDQ_INT_STATUS_RXCOMPLETE
|
|
@@ -311,7 +311,7 @@ static int omap_hdq_break(struct hdq_data *hdq_data)
|
|
tmp_status = hdq_data->hdq_irqstatus;
|
|
/* check irqstatus */
|
|
if (!(tmp_status & OMAP_HDQ_INT_STATUS_TIMEOUT)) {
|
|
- dev_dbg(hdq_data->dev, "timeout waiting for TIMEOUT, %x",
|
|
+ dev_dbg(hdq_data->dev, "timeout waiting for TIMEOUT, %x\n",
|
|
tmp_status);
|
|
ret = -ETIMEDOUT;
|
|
goto out;
|
|
@@ -338,7 +338,7 @@ static int omap_hdq_break(struct hdq_data *hdq_data)
|
|
&tmp_status);
|
|
if (ret)
|
|
dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits"
|
|
- " return to zero, %x", tmp_status);
|
|
+ " return to zero, %x\n", tmp_status);
|
|
|
|
out:
|
|
mutex_unlock(&hdq_data->hdq_mutex);
|
|
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
|
|
index 2fead6c3c687..c2dd94e1b274 100644
|
|
--- a/fs/btrfs/block-group.c
|
|
+++ b/fs/btrfs/block-group.c
|
|
@@ -1167,7 +1167,7 @@ struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
|
|
free_extent_map(em);
|
|
|
|
return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root,
|
|
- num_items, 1);
|
|
+ num_items);
|
|
}
|
|
|
|
/*
|
|
diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c
|
|
index d07bd41a7c1e..343400d49bd1 100644
|
|
--- a/fs/btrfs/block-rsv.c
|
|
+++ b/fs/btrfs/block-rsv.c
|
|
@@ -5,6 +5,7 @@
|
|
#include "block-rsv.h"
|
|
#include "space-info.h"
|
|
#include "transaction.h"
|
|
+#include "block-group.h"
|
|
|
|
static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
|
|
struct btrfs_block_rsv *block_rsv,
|
|
@@ -313,6 +314,8 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
|
|
else
|
|
block_rsv->full = 0;
|
|
|
|
+ if (block_rsv->size >= sinfo->total_bytes)
|
|
+ sinfo->force_alloc = CHUNK_ALLOC_FORCE;
|
|
spin_unlock(&block_rsv->lock);
|
|
spin_unlock(&sinfo->lock);
|
|
}
|
|
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
|
|
index 169075550a5a..6d2c277c6e0a 100644
|
|
--- a/fs/btrfs/ctree.h
|
|
+++ b/fs/btrfs/ctree.h
|
|
@@ -2465,6 +2465,7 @@ enum btrfs_reserve_flush_enum {
|
|
BTRFS_RESERVE_FLUSH_LIMIT,
|
|
BTRFS_RESERVE_FLUSH_EVICT,
|
|
BTRFS_RESERVE_FLUSH_ALL,
|
|
+ BTRFS_RESERVE_FLUSH_ALL_STEAL,
|
|
};
|
|
|
|
enum btrfs_flush_state {
|
|
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
|
|
index f62a179f85bb..2b8f29c07668 100644
|
|
--- a/fs/btrfs/file-item.c
|
|
+++ b/fs/btrfs/file-item.c
|
|
@@ -798,10 +798,12 @@ again:
|
|
nritems = btrfs_header_nritems(path->nodes[0]);
|
|
if (!nritems || (path->slots[0] >= nritems - 1)) {
|
|
ret = btrfs_next_leaf(root, path);
|
|
- if (ret == 1)
|
|
+ if (ret < 0) {
|
|
+ goto out;
|
|
+ } else if (ret > 0) {
|
|
found_next = 1;
|
|
- if (ret != 0)
|
|
goto insert;
|
|
+ }
|
|
slot = path->slots[0];
|
|
}
|
|
btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot);
|
|
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
|
|
index 94b0df3fb3c8..127cdecbe872 100644
|
|
--- a/fs/btrfs/inode.c
|
|
+++ b/fs/btrfs/inode.c
|
|
@@ -49,6 +49,7 @@
|
|
#include "qgroup.h"
|
|
#include "delalloc-space.h"
|
|
#include "block-group.h"
|
|
+#include "space-info.h"
|
|
|
|
struct btrfs_iget_args {
|
|
struct btrfs_key *location;
|
|
@@ -1132,7 +1133,7 @@ out_unlock:
|
|
*/
|
|
if (extent_reserved) {
|
|
extent_clear_unlock_delalloc(inode, start,
|
|
- start + cur_alloc_size,
|
|
+ start + cur_alloc_size - 1,
|
|
locked_page,
|
|
clear_bits,
|
|
page_ops);
|
|
@@ -1322,6 +1323,66 @@ static noinline int csum_exist_in_range(struct btrfs_fs_info *fs_info,
|
|
return 1;
|
|
}
|
|
|
|
+static int fallback_to_cow(struct inode *inode, struct page *locked_page,
|
|
+ const u64 start, const u64 end,
|
|
+ int *page_started, unsigned long *nr_written)
|
|
+{
|
|
+ const bool is_space_ino = btrfs_is_free_space_inode(BTRFS_I(inode));
|
|
+ const u64 range_bytes = end + 1 - start;
|
|
+ struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
|
|
+ u64 range_start = start;
|
|
+ u64 count;
|
|
+
|
|
+ /*
|
|
+ * If EXTENT_NORESERVE is set it means that when the buffered write was
|
|
+ * made we had not enough available data space and therefore we did not
|
|
+ * reserve data space for it, since we though we could do NOCOW for the
|
|
+ * respective file range (either there is prealloc extent or the inode
|
|
+ * has the NOCOW bit set).
|
|
+ *
|
|
+ * However when we need to fallback to COW mode (because for example the
|
|
+ * block group for the corresponding extent was turned to RO mode by a
|
|
+ * scrub or relocation) we need to do the following:
|
|
+ *
|
|
+ * 1) We increment the bytes_may_use counter of the data space info.
|
|
+ * If COW succeeds, it allocates a new data extent and after doing
|
|
+ * that it decrements the space info's bytes_may_use counter and
|
|
+ * increments its bytes_reserved counter by the same amount (we do
|
|
+ * this at btrfs_add_reserved_bytes()). So we need to increment the
|
|
+ * bytes_may_use counter to compensate (when space is reserved at
|
|
+ * buffered write time, the bytes_may_use counter is incremented);
|
|
+ *
|
|
+ * 2) We clear the EXTENT_NORESERVE bit from the range. We do this so
|
|
+ * that if the COW path fails for any reason, it decrements (through
|
|
+ * extent_clear_unlock_delalloc()) the bytes_may_use counter of the
|
|
+ * data space info, which we incremented in the step above.
|
|
+ *
|
|
+ * If we need to fallback to cow and the inode corresponds to a free
|
|
+ * space cache inode, we must also increment bytes_may_use of the data
|
|
+ * space_info for the same reason. Space caches always get a prealloc
|
|
+ * extent for them, however scrub or balance may have set the block
|
|
+ * group that contains that extent to RO mode.
|
|
+ */
|
|
+ count = count_range_bits(io_tree, &range_start, end, range_bytes,
|
|
+ EXTENT_NORESERVE, 0);
|
|
+ if (count > 0 || is_space_ino) {
|
|
+ const u64 bytes = is_space_ino ? range_bytes : count;
|
|
+ struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
|
|
+ struct btrfs_space_info *sinfo = fs_info->data_sinfo;
|
|
+
|
|
+ spin_lock(&sinfo->lock);
|
|
+ btrfs_space_info_update_bytes_may_use(fs_info, sinfo, bytes);
|
|
+ spin_unlock(&sinfo->lock);
|
|
+
|
|
+ if (count > 0)
|
|
+ clear_extent_bit(io_tree, start, end, EXTENT_NORESERVE,
|
|
+ 0, 0, NULL);
|
|
+ }
|
|
+
|
|
+ return cow_file_range(inode, locked_page, start, end, page_started,
|
|
+ nr_written, 1);
|
|
+}
|
|
+
|
|
/*
|
|
* when nowcow writeback call back. This checks for snapshots or COW copies
|
|
* of the extents that exist in the file, and COWs the file as required.
|
|
@@ -1569,9 +1630,9 @@ out_check:
|
|
* NOCOW, following one which needs to be COW'ed
|
|
*/
|
|
if (cow_start != (u64)-1) {
|
|
- ret = cow_file_range(inode, locked_page,
|
|
- cow_start, found_key.offset - 1,
|
|
- page_started, nr_written, 1);
|
|
+ ret = fallback_to_cow(inode, locked_page, cow_start,
|
|
+ found_key.offset - 1,
|
|
+ page_started, nr_written);
|
|
if (ret) {
|
|
if (nocow)
|
|
btrfs_dec_nocow_writers(fs_info,
|
|
@@ -1660,8 +1721,8 @@ out_check:
|
|
|
|
if (cow_start != (u64)-1) {
|
|
cur_offset = end;
|
|
- ret = cow_file_range(inode, locked_page, cow_start, end,
|
|
- page_started, nr_written, 1);
|
|
+ ret = fallback_to_cow(inode, locked_page, cow_start, end,
|
|
+ page_started, nr_written);
|
|
if (ret)
|
|
goto error;
|
|
}
|
|
@@ -4250,7 +4311,7 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir)
|
|
* 1 for the inode ref
|
|
* 1 for the inode
|
|
*/
|
|
- return btrfs_start_transaction_fallback_global_rsv(root, 5, 5);
|
|
+ return btrfs_start_transaction_fallback_global_rsv(root, 5);
|
|
}
|
|
|
|
static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
|
|
@@ -8534,7 +8595,6 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip)
|
|
|
|
/* bio split */
|
|
ASSERT(geom.len <= INT_MAX);
|
|
- atomic_inc(&dip->pending_bios);
|
|
do {
|
|
clone_len = min_t(int, submit_len, geom.len);
|
|
|
|
@@ -8584,7 +8644,8 @@ submit:
|
|
if (!status)
|
|
return 0;
|
|
|
|
- bio_put(bio);
|
|
+ if (bio != orig_bio)
|
|
+ bio_put(bio);
|
|
out_err:
|
|
dip->errors = 1;
|
|
/*
|
|
@@ -8625,7 +8686,7 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
|
|
bio->bi_private = dip;
|
|
dip->orig_bio = bio;
|
|
dip->dio_bio = dio_bio;
|
|
- atomic_set(&dip->pending_bios, 0);
|
|
+ atomic_set(&dip->pending_bios, 1);
|
|
io_bio = btrfs_io_bio(bio);
|
|
io_bio->logical = file_offset;
|
|
|
|
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
|
|
index 590defdf8860..b94f6f99e90d 100644
|
|
--- a/fs/btrfs/qgroup.c
|
|
+++ b/fs/btrfs/qgroup.c
|
|
@@ -2636,6 +2636,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
|
|
struct btrfs_root *quota_root;
|
|
struct btrfs_qgroup *srcgroup;
|
|
struct btrfs_qgroup *dstgroup;
|
|
+ bool need_rescan = false;
|
|
u32 level_size = 0;
|
|
u64 nums;
|
|
|
|
@@ -2779,6 +2780,13 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
|
|
goto unlock;
|
|
}
|
|
++i_qgroups;
|
|
+
|
|
+ /*
|
|
+ * If we're doing a snapshot, and adding the snapshot to a new
|
|
+ * qgroup, the numbers are guaranteed to be incorrect.
|
|
+ */
|
|
+ if (srcid)
|
|
+ need_rescan = true;
|
|
}
|
|
|
|
for (i = 0; i < inherit->num_ref_copies; ++i, i_qgroups += 2) {
|
|
@@ -2798,6 +2806,9 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
|
|
|
|
dst->rfer = src->rfer - level_size;
|
|
dst->rfer_cmpr = src->rfer_cmpr - level_size;
|
|
+
|
|
+ /* Manually tweaking numbers certainly needs a rescan */
|
|
+ need_rescan = true;
|
|
}
|
|
for (i = 0; i < inherit->num_excl_copies; ++i, i_qgroups += 2) {
|
|
struct btrfs_qgroup *src;
|
|
@@ -2816,6 +2827,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
|
|
|
|
dst->excl = src->excl + level_size;
|
|
dst->excl_cmpr = src->excl_cmpr + level_size;
|
|
+ need_rescan = true;
|
|
}
|
|
|
|
unlock:
|
|
@@ -2823,6 +2835,8 @@ unlock:
|
|
out:
|
|
if (!committing)
|
|
mutex_unlock(&fs_info->qgroup_ioctl_lock);
|
|
+ if (need_rescan)
|
|
+ fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
|
|
index 3eb0fec2488a..6ad216e8178e 100644
|
|
--- a/fs/btrfs/send.c
|
|
+++ b/fs/btrfs/send.c
|
|
@@ -23,6 +23,7 @@
|
|
#include "btrfs_inode.h"
|
|
#include "transaction.h"
|
|
#include "compression.h"
|
|
+#include "xattr.h"
|
|
|
|
/*
|
|
* Maximum number of references an extent can have in order for us to attempt to
|
|
@@ -4536,6 +4537,10 @@ static int __process_new_xattr(int num, struct btrfs_key *di_key,
|
|
struct fs_path *p;
|
|
struct posix_acl_xattr_header dummy_acl;
|
|
|
|
+ /* Capabilities are emitted by finish_inode_if_needed */
|
|
+ if (!strncmp(name, XATTR_NAME_CAPS, name_len))
|
|
+ return 0;
|
|
+
|
|
p = fs_path_alloc();
|
|
if (!p)
|
|
return -ENOMEM;
|
|
@@ -5098,6 +5103,64 @@ static int send_extent_data(struct send_ctx *sctx,
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Search for a capability xattr related to sctx->cur_ino. If the capability is
|
|
+ * found, call send_set_xattr function to emit it.
|
|
+ *
|
|
+ * Return 0 if there isn't a capability, or when the capability was emitted
|
|
+ * successfully, or < 0 if an error occurred.
|
|
+ */
|
|
+static int send_capabilities(struct send_ctx *sctx)
|
|
+{
|
|
+ struct fs_path *fspath = NULL;
|
|
+ struct btrfs_path *path;
|
|
+ struct btrfs_dir_item *di;
|
|
+ struct extent_buffer *leaf;
|
|
+ unsigned long data_ptr;
|
|
+ char *buf = NULL;
|
|
+ int buf_len;
|
|
+ int ret = 0;
|
|
+
|
|
+ path = alloc_path_for_send();
|
|
+ if (!path)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ di = btrfs_lookup_xattr(NULL, sctx->send_root, path, sctx->cur_ino,
|
|
+ XATTR_NAME_CAPS, strlen(XATTR_NAME_CAPS), 0);
|
|
+ if (!di) {
|
|
+ /* There is no xattr for this inode */
|
|
+ goto out;
|
|
+ } else if (IS_ERR(di)) {
|
|
+ ret = PTR_ERR(di);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ leaf = path->nodes[0];
|
|
+ buf_len = btrfs_dir_data_len(leaf, di);
|
|
+
|
|
+ fspath = fs_path_alloc();
|
|
+ buf = kmalloc(buf_len, GFP_KERNEL);
|
|
+ if (!fspath || !buf) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, fspath);
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
+
|
|
+ data_ptr = (unsigned long)(di + 1) + btrfs_dir_name_len(leaf, di);
|
|
+ read_extent_buffer(leaf, buf, data_ptr, buf_len);
|
|
+
|
|
+ ret = send_set_xattr(sctx, fspath, XATTR_NAME_CAPS,
|
|
+ strlen(XATTR_NAME_CAPS), buf, buf_len);
|
|
+out:
|
|
+ kfree(buf);
|
|
+ fs_path_free(fspath);
|
|
+ btrfs_free_path(path);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int clone_range(struct send_ctx *sctx,
|
|
struct clone_root *clone_root,
|
|
const u64 disk_byte,
|
|
@@ -6001,6 +6064,10 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
|
|
goto out;
|
|
}
|
|
|
|
+ ret = send_capabilities(sctx);
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
+
|
|
/*
|
|
* If other directory inodes depended on our current directory
|
|
* inode's move/rename, now do their move/rename operations.
|
|
diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
|
|
index e8a4b0ebe97f..7889a59a57fa 100644
|
|
--- a/fs/btrfs/space-info.c
|
|
+++ b/fs/btrfs/space-info.c
|
|
@@ -462,6 +462,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
|
|
struct reserve_ticket *ticket = NULL;
|
|
struct btrfs_block_rsv *delayed_rsv = &fs_info->delayed_block_rsv;
|
|
struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv;
|
|
+ struct btrfs_block_rsv *trans_rsv = &fs_info->trans_block_rsv;
|
|
struct btrfs_trans_handle *trans;
|
|
u64 bytes_needed;
|
|
u64 reclaim_bytes = 0;
|
|
@@ -524,6 +525,11 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
|
|
spin_lock(&delayed_refs_rsv->lock);
|
|
reclaim_bytes += delayed_refs_rsv->reserved;
|
|
spin_unlock(&delayed_refs_rsv->lock);
|
|
+
|
|
+ spin_lock(&trans_rsv->lock);
|
|
+ reclaim_bytes += trans_rsv->reserved;
|
|
+ spin_unlock(&trans_rsv->lock);
|
|
+
|
|
if (reclaim_bytes >= bytes_needed)
|
|
goto commit;
|
|
bytes_needed -= reclaim_bytes;
|
|
@@ -683,6 +689,34 @@ static inline int need_do_async_reclaim(struct btrfs_fs_info *fs_info,
|
|
!test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state));
|
|
}
|
|
|
|
+static bool steal_from_global_rsv(struct btrfs_fs_info *fs_info,
|
|
+ struct btrfs_space_info *space_info,
|
|
+ struct reserve_ticket *ticket)
|
|
+{
|
|
+ struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
|
|
+ u64 min_bytes;
|
|
+
|
|
+ if (global_rsv->space_info != space_info)
|
|
+ return false;
|
|
+
|
|
+ spin_lock(&global_rsv->lock);
|
|
+ min_bytes = div_factor(global_rsv->size, 5);
|
|
+ if (global_rsv->reserved < min_bytes + ticket->bytes) {
|
|
+ spin_unlock(&global_rsv->lock);
|
|
+ return false;
|
|
+ }
|
|
+ global_rsv->reserved -= ticket->bytes;
|
|
+ ticket->bytes = 0;
|
|
+ list_del_init(&ticket->list);
|
|
+ wake_up(&ticket->wait);
|
|
+ space_info->tickets_id++;
|
|
+ if (global_rsv->reserved < global_rsv->size)
|
|
+ global_rsv->full = 0;
|
|
+ spin_unlock(&global_rsv->lock);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
/*
|
|
* maybe_fail_all_tickets - we've exhausted our flushing, start failing tickets
|
|
* @fs_info - fs_info for this fs
|
|
@@ -715,6 +749,10 @@ static bool maybe_fail_all_tickets(struct btrfs_fs_info *fs_info,
|
|
ticket = list_first_entry(&space_info->tickets,
|
|
struct reserve_ticket, list);
|
|
|
|
+ if (ticket->steal &&
|
|
+ steal_from_global_rsv(fs_info, space_info, ticket))
|
|
+ return true;
|
|
+
|
|
/*
|
|
* may_commit_transaction will avoid committing the transaction
|
|
* if it doesn't feel like the space reclaimed by the commit
|
|
@@ -934,6 +972,7 @@ static int handle_reserve_ticket(struct btrfs_fs_info *fs_info,
|
|
|
|
switch (flush) {
|
|
case BTRFS_RESERVE_FLUSH_ALL:
|
|
+ case BTRFS_RESERVE_FLUSH_ALL_STEAL:
|
|
wait_reserve_ticket(fs_info, space_info, ticket);
|
|
break;
|
|
case BTRFS_RESERVE_FLUSH_LIMIT:
|
|
@@ -1033,7 +1072,9 @@ static int __reserve_metadata_bytes(struct btrfs_fs_info *fs_info,
|
|
ticket.bytes = orig_bytes;
|
|
ticket.error = 0;
|
|
init_waitqueue_head(&ticket.wait);
|
|
- if (flush == BTRFS_RESERVE_FLUSH_ALL) {
|
|
+ ticket.steal = (flush == BTRFS_RESERVE_FLUSH_ALL_STEAL);
|
|
+ if (flush == BTRFS_RESERVE_FLUSH_ALL ||
|
|
+ flush == BTRFS_RESERVE_FLUSH_ALL_STEAL) {
|
|
list_add_tail(&ticket.list, &space_info->tickets);
|
|
if (!space_info->flush) {
|
|
space_info->flush = 1;
|
|
diff --git a/fs/btrfs/space-info.h b/fs/btrfs/space-info.h
|
|
index 8867e84aa33d..8b9a1d8fefcb 100644
|
|
--- a/fs/btrfs/space-info.h
|
|
+++ b/fs/btrfs/space-info.h
|
|
@@ -72,6 +72,7 @@ struct btrfs_space_info {
|
|
struct reserve_ticket {
|
|
u64 bytes;
|
|
int error;
|
|
+ bool steal;
|
|
struct list_head list;
|
|
wait_queue_head_t wait;
|
|
};
|
|
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
|
|
index cdca0f656594..54589e940f9a 100644
|
|
--- a/fs/btrfs/transaction.c
|
|
+++ b/fs/btrfs/transaction.c
|
|
@@ -21,6 +21,7 @@
|
|
#include "dev-replace.h"
|
|
#include "qgroup.h"
|
|
#include "block-group.h"
|
|
+#include "space-info.h"
|
|
|
|
#define BTRFS_ROOT_TRANS_TAG 0
|
|
|
|
@@ -451,6 +452,7 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
|
|
u64 num_bytes = 0;
|
|
u64 qgroup_reserved = 0;
|
|
bool reloc_reserved = false;
|
|
+ bool do_chunk_alloc = false;
|
|
int ret;
|
|
|
|
/* Send isn't supposed to start transactions. */
|
|
@@ -491,7 +493,8 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
|
|
* refill that amount for whatever is missing in the reserve.
|
|
*/
|
|
num_bytes = btrfs_calc_insert_metadata_size(fs_info, num_items);
|
|
- if (delayed_refs_rsv->full == 0) {
|
|
+ if (flush == BTRFS_RESERVE_FLUSH_ALL &&
|
|
+ delayed_refs_rsv->full == 0) {
|
|
delayed_refs_bytes = num_bytes;
|
|
num_bytes <<= 1;
|
|
}
|
|
@@ -512,6 +515,9 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
|
|
delayed_refs_bytes);
|
|
num_bytes -= delayed_refs_bytes;
|
|
}
|
|
+
|
|
+ if (rsv->space_info->force_alloc)
|
|
+ do_chunk_alloc = true;
|
|
} else if (num_items == 0 && flush == BTRFS_RESERVE_FLUSH_ALL &&
|
|
!delayed_refs_rsv->full) {
|
|
/*
|
|
@@ -593,6 +599,19 @@ got_it:
|
|
if (!current->journal_info)
|
|
current->journal_info = h;
|
|
|
|
+ /*
|
|
+ * If the space_info is marked ALLOC_FORCE then we'll get upgraded to
|
|
+ * ALLOC_FORCE the first run through, and then we won't allocate for
|
|
+ * anybody else who races in later. We don't care about the return
|
|
+ * value here.
|
|
+ */
|
|
+ if (do_chunk_alloc && num_bytes) {
|
|
+ u64 flags = h->block_rsv->space_info->flags;
|
|
+
|
|
+ btrfs_chunk_alloc(h, btrfs_get_alloc_profile(fs_info, flags),
|
|
+ CHUNK_ALLOC_NO_FORCE);
|
|
+ }
|
|
+
|
|
/*
|
|
* btrfs_record_root_in_trans() needs to alloc new extents, and may
|
|
* call btrfs_join_transaction() while we're also starting a
|
|
@@ -627,43 +646,10 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
|
|
|
|
struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
|
|
struct btrfs_root *root,
|
|
- unsigned int num_items,
|
|
- int min_factor)
|
|
+ unsigned int num_items)
|
|
{
|
|
- struct btrfs_fs_info *fs_info = root->fs_info;
|
|
- struct btrfs_trans_handle *trans;
|
|
- u64 num_bytes;
|
|
- int ret;
|
|
-
|
|
- /*
|
|
- * We have two callers: unlink and block group removal. The
|
|
- * former should succeed even if we will temporarily exceed
|
|
- * quota and the latter operates on the extent root so
|
|
- * qgroup enforcement is ignored anyway.
|
|
- */
|
|
- trans = start_transaction(root, num_items, TRANS_START,
|
|
- BTRFS_RESERVE_FLUSH_ALL, false);
|
|
- if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC)
|
|
- return trans;
|
|
-
|
|
- trans = btrfs_start_transaction(root, 0);
|
|
- if (IS_ERR(trans))
|
|
- return trans;
|
|
-
|
|
- num_bytes = btrfs_calc_insert_metadata_size(fs_info, num_items);
|
|
- ret = btrfs_cond_migrate_bytes(fs_info, &fs_info->trans_block_rsv,
|
|
- num_bytes, min_factor);
|
|
- if (ret) {
|
|
- btrfs_end_transaction(trans);
|
|
- return ERR_PTR(ret);
|
|
- }
|
|
-
|
|
- trans->block_rsv = &fs_info->trans_block_rsv;
|
|
- trans->bytes_reserved = num_bytes;
|
|
- trace_btrfs_space_reservation(fs_info, "transaction",
|
|
- trans->transid, num_bytes, 1);
|
|
-
|
|
- return trans;
|
|
+ return start_transaction(root, num_items, TRANS_START,
|
|
+ BTRFS_RESERVE_FLUSH_ALL_STEAL, false);
|
|
}
|
|
|
|
struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root)
|
|
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
|
|
index 2c5a6f6e5bb0..b15c31d23148 100644
|
|
--- a/fs/btrfs/transaction.h
|
|
+++ b/fs/btrfs/transaction.h
|
|
@@ -181,8 +181,7 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
|
|
unsigned int num_items);
|
|
struct btrfs_trans_handle *btrfs_start_transaction_fallback_global_rsv(
|
|
struct btrfs_root *root,
|
|
- unsigned int num_items,
|
|
- int min_factor);
|
|
+ unsigned int num_items);
|
|
struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root);
|
|
struct btrfs_trans_handle *btrfs_join_transaction_nolock(struct btrfs_root *root);
|
|
struct btrfs_trans_handle *btrfs_join_transaction_nostart(struct btrfs_root *root);
|
|
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
|
|
index 3e64f49c394b..c8b0e5005f02 100644
|
|
--- a/fs/btrfs/volumes.c
|
|
+++ b/fs/btrfs/volumes.c
|
|
@@ -1223,6 +1223,8 @@ again:
|
|
&device->dev_state)) {
|
|
if (!test_bit(BTRFS_DEV_STATE_REPLACE_TGT,
|
|
&device->dev_state) &&
|
|
+ !test_bit(BTRFS_DEV_STATE_MISSING,
|
|
+ &device->dev_state) &&
|
|
(!latest_dev ||
|
|
device->generation > latest_dev->generation)) {
|
|
latest_dev = device;
|
|
@@ -2769,8 +2771,18 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
|
|
ret = btrfs_commit_transaction(trans);
|
|
}
|
|
|
|
- /* Update ctime/mtime for libblkid */
|
|
+ /*
|
|
+ * Now that we have written a new super block to this device, check all
|
|
+ * other fs_devices list if device_path alienates any other scanned
|
|
+ * device.
|
|
+ * We can ignore the return value as it typically returns -EINVAL and
|
|
+ * only succeeds if the device was an alien.
|
|
+ */
|
|
+ btrfs_forget_devices(device_path);
|
|
+
|
|
+ /* Update ctime/mtime for blkid or udev */
|
|
update_dev_time(device_path);
|
|
+
|
|
return ret;
|
|
|
|
error_sysfs:
|
|
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
|
|
index 98bd0e9ee7df..ca78fd709845 100644
|
|
--- a/fs/ext4/ext4_extents.h
|
|
+++ b/fs/ext4/ext4_extents.h
|
|
@@ -170,10 +170,13 @@ struct partial_cluster {
|
|
(EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
|
|
#define EXT_LAST_INDEX(__hdr__) \
|
|
(EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
|
|
-#define EXT_MAX_EXTENT(__hdr__) \
|
|
- (EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
|
|
+#define EXT_MAX_EXTENT(__hdr__) \
|
|
+ ((le16_to_cpu((__hdr__)->eh_max)) ? \
|
|
+ ((EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) \
|
|
+ : 0)
|
|
#define EXT_MAX_INDEX(__hdr__) \
|
|
- (EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)
|
|
+ ((le16_to_cpu((__hdr__)->eh_max)) ? \
|
|
+ ((EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) : 0)
|
|
|
|
static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
|
|
{
|
|
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c
|
|
index 5508baa11bb6..8a28d47bd502 100644
|
|
--- a/fs/ext4/fsync.c
|
|
+++ b/fs/ext4/fsync.c
|
|
@@ -44,30 +44,28 @@
|
|
*/
|
|
static int ext4_sync_parent(struct inode *inode)
|
|
{
|
|
- struct dentry *dentry = NULL;
|
|
- struct inode *next;
|
|
+ struct dentry *dentry, *next;
|
|
int ret = 0;
|
|
|
|
if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
|
|
return 0;
|
|
- inode = igrab(inode);
|
|
+ dentry = d_find_any_alias(inode);
|
|
+ if (!dentry)
|
|
+ return 0;
|
|
while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
|
|
ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
|
|
- dentry = d_find_any_alias(inode);
|
|
- if (!dentry)
|
|
- break;
|
|
- next = igrab(d_inode(dentry->d_parent));
|
|
+
|
|
+ next = dget_parent(dentry);
|
|
dput(dentry);
|
|
- if (!next)
|
|
- break;
|
|
- iput(inode);
|
|
- inode = next;
|
|
+ dentry = next;
|
|
+ inode = dentry->d_inode;
|
|
+
|
|
/*
|
|
* The directory inode may have gone through rmdir by now. But
|
|
* the inode itself and its blocks are still allocated (we hold
|
|
- * a reference to the inode so it didn't go through
|
|
- * ext4_evict_inode()) and so we are safe to flush metadata
|
|
- * blocks and the inode.
|
|
+ * a reference to the inode via its dentry), so it didn't go
|
|
+ * through ext4_evict_inode()) and so we are safe to flush
|
|
+ * metadata blocks and the inode.
|
|
*/
|
|
ret = sync_mapping_buffers(inode->i_mapping);
|
|
if (ret)
|
|
@@ -76,7 +74,7 @@ static int ext4_sync_parent(struct inode *inode)
|
|
if (ret)
|
|
break;
|
|
}
|
|
- iput(inode);
|
|
+ dput(dentry);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
|
|
index 491f9ee4040e..894a61010ae9 100644
|
|
--- a/fs/ext4/xattr.c
|
|
+++ b/fs/ext4/xattr.c
|
|
@@ -1820,8 +1820,11 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
|
|
if (EXT4_I(inode)->i_file_acl) {
|
|
/* The inode already has an extended attribute block. */
|
|
bs->bh = ext4_sb_bread(sb, EXT4_I(inode)->i_file_acl, REQ_PRIO);
|
|
- if (IS_ERR(bs->bh))
|
|
- return PTR_ERR(bs->bh);
|
|
+ if (IS_ERR(bs->bh)) {
|
|
+ error = PTR_ERR(bs->bh);
|
|
+ bs->bh = NULL;
|
|
+ return error;
|
|
+ }
|
|
ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
|
|
atomic_read(&(bs->bh->b_count)),
|
|
le32_to_cpu(BHDR(bs->bh)->h_refcount));
|
|
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
|
|
index 3edde3d6d089..a26ea1e6ba88 100644
|
|
--- a/fs/f2fs/f2fs.h
|
|
+++ b/fs/f2fs/f2fs.h
|
|
@@ -138,6 +138,7 @@ struct f2fs_mount_info {
|
|
int alloc_mode; /* segment allocation policy */
|
|
int fsync_mode; /* fsync policy */
|
|
bool test_dummy_encryption; /* test dummy encryption */
|
|
+ block_t unusable_cap_perc; /* percentage for cap */
|
|
block_t unusable_cap; /* Amount of space allowed to be
|
|
* unusable when disabling checkpoint
|
|
*/
|
|
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
|
|
index 5e1d4d9243a9..e36543c9f2b7 100644
|
|
--- a/fs/f2fs/super.c
|
|
+++ b/fs/f2fs/super.c
|
|
@@ -277,6 +277,22 @@ static inline void limit_reserve_root(struct f2fs_sb_info *sbi)
|
|
F2FS_OPTION(sbi).s_resgid));
|
|
}
|
|
|
|
+static inline void adjust_unusable_cap_perc(struct f2fs_sb_info *sbi)
|
|
+{
|
|
+ if (!F2FS_OPTION(sbi).unusable_cap_perc)
|
|
+ return;
|
|
+
|
|
+ if (F2FS_OPTION(sbi).unusable_cap_perc == 100)
|
|
+ F2FS_OPTION(sbi).unusable_cap = sbi->user_block_count;
|
|
+ else
|
|
+ F2FS_OPTION(sbi).unusable_cap = (sbi->user_block_count / 100) *
|
|
+ F2FS_OPTION(sbi).unusable_cap_perc;
|
|
+
|
|
+ f2fs_info(sbi, "Adjust unusable cap for checkpoint=disable = %u / %u%%",
|
|
+ F2FS_OPTION(sbi).unusable_cap,
|
|
+ F2FS_OPTION(sbi).unusable_cap_perc);
|
|
+}
|
|
+
|
|
static void init_once(void *foo)
|
|
{
|
|
struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
|
|
@@ -790,12 +806,7 @@ static int parse_options(struct super_block *sb, char *options)
|
|
return -EINVAL;
|
|
if (arg < 0 || arg > 100)
|
|
return -EINVAL;
|
|
- if (arg == 100)
|
|
- F2FS_OPTION(sbi).unusable_cap =
|
|
- sbi->user_block_count;
|
|
- else
|
|
- F2FS_OPTION(sbi).unusable_cap =
|
|
- (sbi->user_block_count / 100) * arg;
|
|
+ F2FS_OPTION(sbi).unusable_cap_perc = arg;
|
|
set_opt(sbi, DISABLE_CHECKPOINT);
|
|
break;
|
|
case Opt_checkpoint_disable_cap:
|
|
@@ -1735,6 +1746,7 @@ skip:
|
|
(test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0);
|
|
|
|
limit_reserve_root(sbi);
|
|
+ adjust_unusable_cap_perc(sbi);
|
|
*flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
|
|
return 0;
|
|
restore_gc:
|
|
@@ -3397,6 +3409,7 @@ try_onemore:
|
|
sbi->reserved_blocks = 0;
|
|
sbi->current_reserved_blocks = 0;
|
|
limit_reserve_root(sbi);
|
|
+ adjust_unusable_cap_perc(sbi);
|
|
|
|
for (i = 0; i < NR_INODE_TYPE; i++) {
|
|
INIT_LIST_HEAD(&sbi->inode_list[i]);
|
|
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
|
|
index 4f443703065e..0c71acc1b831 100644
|
|
--- a/fs/xfs/xfs_bmap_util.c
|
|
+++ b/fs/xfs/xfs_bmap_util.c
|
|
@@ -1760,7 +1760,7 @@ xfs_swap_extents(
|
|
if (xfs_inode_has_cow_data(tip)) {
|
|
error = xfs_reflink_cancel_cow_range(tip, 0, NULLFILEOFF, true);
|
|
if (error)
|
|
- return error;
|
|
+ goto out_unlock;
|
|
}
|
|
|
|
/*
|
|
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
|
|
index 0abba171aa89..1264ac63e4e5 100644
|
|
--- a/fs/xfs/xfs_buf.c
|
|
+++ b/fs/xfs/xfs_buf.c
|
|
@@ -1162,8 +1162,10 @@ xfs_buf_ioend(
|
|
bp->b_ops->verify_read(bp);
|
|
}
|
|
|
|
- if (!bp->b_error)
|
|
+ if (!bp->b_error) {
|
|
+ bp->b_flags &= ~XBF_WRITE_FAIL;
|
|
bp->b_flags |= XBF_DONE;
|
|
+ }
|
|
|
|
if (bp->b_iodone)
|
|
(*(bp->b_iodone))(bp);
|
|
@@ -1223,7 +1225,7 @@ xfs_bwrite(
|
|
|
|
bp->b_flags |= XBF_WRITE;
|
|
bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q |
|
|
- XBF_WRITE_FAIL | XBF_DONE);
|
|
+ XBF_DONE);
|
|
|
|
error = xfs_buf_submit(bp);
|
|
if (error)
|
|
@@ -1929,7 +1931,7 @@ xfs_buf_delwri_submit_buffers(
|
|
* synchronously. Otherwise, drop the buffer from the delwri
|
|
* queue and submit async.
|
|
*/
|
|
- bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_WRITE_FAIL);
|
|
+ bp->b_flags &= ~_XBF_DELWRI_Q;
|
|
bp->b_flags |= XBF_WRITE;
|
|
if (wait_list) {
|
|
bp->b_flags &= ~XBF_ASYNC;
|
|
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
|
|
index aeb95e7391c1..3cbf248af51f 100644
|
|
--- a/fs/xfs/xfs_dquot.c
|
|
+++ b/fs/xfs/xfs_dquot.c
|
|
@@ -1116,13 +1116,12 @@ xfs_qm_dqflush(
|
|
dqb = bp->b_addr + dqp->q_bufoffset;
|
|
ddqp = &dqb->dd_diskdq;
|
|
|
|
- /*
|
|
- * A simple sanity check in case we got a corrupted dquot.
|
|
- */
|
|
- fa = xfs_dqblk_verify(mp, dqb, be32_to_cpu(ddqp->d_id), 0);
|
|
+ /* sanity check the in-core structure before we flush */
|
|
+ fa = xfs_dquot_verify(mp, &dqp->q_core, be32_to_cpu(dqp->q_core.d_id),
|
|
+ 0);
|
|
if (fa) {
|
|
xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
|
|
- be32_to_cpu(ddqp->d_id), fa);
|
|
+ be32_to_cpu(dqp->q_core.d_id), fa);
|
|
xfs_buf_relse(bp);
|
|
xfs_dqfunlock(dqp);
|
|
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
|
|
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
|
|
index b072aeb1fd78..4d6fe87fd38f 100644
|
|
--- a/include/linux/kgdb.h
|
|
+++ b/include/linux/kgdb.h
|
|
@@ -323,7 +323,7 @@ extern void gdbstub_exit(int status);
|
|
extern int kgdb_single_step;
|
|
extern atomic_t kgdb_active;
|
|
#define in_dbg_master() \
|
|
- (raw_smp_processor_id() == atomic_read(&kgdb_active))
|
|
+ (irqs_disabled() && (smp_processor_id() == atomic_read(&kgdb_active)))
|
|
extern bool dbg_is_early;
|
|
extern void __init dbg_late_init(void);
|
|
extern void kgdb_panic(const char *msg);
|
|
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
|
|
index 8b5f758942a2..85804ba62215 100644
|
|
--- a/include/linux/mmzone.h
|
|
+++ b/include/linux/mmzone.h
|
|
@@ -709,6 +709,8 @@ typedef struct pglist_data {
|
|
/*
|
|
* Must be held any time you expect node_start_pfn,
|
|
* node_present_pages, node_spanned_pages or nr_zones to stay constant.
|
|
+ * Also synchronizes pgdat->first_deferred_pfn during deferred page
|
|
+ * init.
|
|
*
|
|
* pgdat_resize_lock() and pgdat_resize_unlock() are provided to
|
|
* manipulate node_size_lock without checking for CONFIG_MEMORY_HOTPLUG
|
|
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
|
|
index 228f66347620..0ad57693f392 100644
|
|
--- a/include/linux/pci_ids.h
|
|
+++ b/include/linux/pci_ids.h
|
|
@@ -148,6 +148,8 @@
|
|
|
|
/* Vendors and devices. Sort key: vendor first, device next. */
|
|
|
|
+#define PCI_VENDOR_ID_LOONGSON 0x0014
|
|
+
|
|
#define PCI_VENDOR_ID_TTTECH 0x0357
|
|
#define PCI_DEVICE_ID_TTTECH_MC322 0x000a
|
|
|
|
@@ -548,7 +550,9 @@
|
|
#define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463
|
|
#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F3 0x15eb
|
|
#define PCI_DEVICE_ID_AMD_17H_M30H_DF_F3 0x1493
|
|
+#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F3 0x144b
|
|
#define PCI_DEVICE_ID_AMD_17H_M70H_DF_F3 0x1443
|
|
+#define PCI_DEVICE_ID_AMD_19H_DF_F3 0x1653
|
|
#define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703
|
|
#define PCI_DEVICE_ID_AMD_LANCE 0x2000
|
|
#define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001
|
|
@@ -1829,6 +1833,12 @@
|
|
#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
|
|
#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
|
|
|
|
+#define PCI_VENDOR_ID_PERICOM 0x12D8
|
|
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
|
|
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
|
|
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954
|
|
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958
|
|
+
|
|
#define PCI_SUBVENDOR_ID_CHASE_PCIFAST 0x12E0
|
|
#define PCI_SUBDEVICE_ID_CHASE_PCIFAST4 0x0031
|
|
#define PCI_SUBDEVICE_ID_CHASE_PCIFAST8 0x0021
|
|
@@ -3008,6 +3018,7 @@
|
|
#define PCI_DEVICE_ID_INTEL_84460GX 0x84ea
|
|
#define PCI_DEVICE_ID_INTEL_IXP4XX 0x8500
|
|
#define PCI_DEVICE_ID_INTEL_IXP2800 0x9004
|
|
+#define PCI_DEVICE_ID_INTEL_VMD_9A0B 0x9a0b
|
|
#define PCI_DEVICE_ID_INTEL_S21152BB 0xb152
|
|
|
|
#define PCI_VENDOR_ID_SCALEMP 0x8686
|
|
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
|
|
index c49257a3b510..a132d875d351 100644
|
|
--- a/include/linux/sched/mm.h
|
|
+++ b/include/linux/sched/mm.h
|
|
@@ -49,6 +49,8 @@ static inline void mmdrop(struct mm_struct *mm)
|
|
__mmdrop(mm);
|
|
}
|
|
|
|
+void mmdrop(struct mm_struct *mm);
|
|
+
|
|
/*
|
|
* This has to be called after a get_task_mm()/mmget_not_zero()
|
|
* followed by taking the mmap_sem for writing before modifying the
|
|
diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
|
|
index a3adbe593505..4bdb5e4bbd6a 100644
|
|
--- a/include/linux/skmsg.h
|
|
+++ b/include/linux/skmsg.h
|
|
@@ -457,4 +457,12 @@ static inline void psock_progs_drop(struct sk_psock_progs *progs)
|
|
psock_set_prog(&progs->skb_verdict, NULL);
|
|
}
|
|
|
|
+int sk_psock_tls_strp_read(struct sk_psock *psock, struct sk_buff *skb);
|
|
+
|
|
+static inline bool sk_psock_strp_enabled(struct sk_psock *psock)
|
|
+{
|
|
+ if (!psock)
|
|
+ return false;
|
|
+ return psock->parser.enabled;
|
|
+}
|
|
#endif /* _LINUX_SKMSG_H */
|
|
diff --git a/include/linux/string.h b/include/linux/string.h
|
|
index b6ccdc2c7f02..b2264355272d 100644
|
|
--- a/include/linux/string.h
|
|
+++ b/include/linux/string.h
|
|
@@ -269,6 +269,31 @@ void __read_overflow3(void) __compiletime_error("detected read beyond size of ob
|
|
void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
|
|
|
|
#if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
|
|
+
|
|
+#ifdef CONFIG_KASAN
|
|
+extern void *__underlying_memchr(const void *p, int c, __kernel_size_t size) __RENAME(memchr);
|
|
+extern int __underlying_memcmp(const void *p, const void *q, __kernel_size_t size) __RENAME(memcmp);
|
|
+extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy);
|
|
+extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove);
|
|
+extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset);
|
|
+extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat);
|
|
+extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy);
|
|
+extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen);
|
|
+extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat);
|
|
+extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy);
|
|
+#else
|
|
+#define __underlying_memchr __builtin_memchr
|
|
+#define __underlying_memcmp __builtin_memcmp
|
|
+#define __underlying_memcpy __builtin_memcpy
|
|
+#define __underlying_memmove __builtin_memmove
|
|
+#define __underlying_memset __builtin_memset
|
|
+#define __underlying_strcat __builtin_strcat
|
|
+#define __underlying_strcpy __builtin_strcpy
|
|
+#define __underlying_strlen __builtin_strlen
|
|
+#define __underlying_strncat __builtin_strncat
|
|
+#define __underlying_strncpy __builtin_strncpy
|
|
+#endif
|
|
+
|
|
__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
|
|
{
|
|
size_t p_size = __builtin_object_size(p, 0);
|
|
@@ -276,14 +301,14 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
|
|
__write_overflow();
|
|
if (p_size < size)
|
|
fortify_panic(__func__);
|
|
- return __builtin_strncpy(p, q, size);
|
|
+ return __underlying_strncpy(p, q, size);
|
|
}
|
|
|
|
__FORTIFY_INLINE char *strcat(char *p, const char *q)
|
|
{
|
|
size_t p_size = __builtin_object_size(p, 0);
|
|
if (p_size == (size_t)-1)
|
|
- return __builtin_strcat(p, q);
|
|
+ return __underlying_strcat(p, q);
|
|
if (strlcat(p, q, p_size) >= p_size)
|
|
fortify_panic(__func__);
|
|
return p;
|
|
@@ -297,7 +322,7 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
|
|
/* Work around gcc excess stack consumption issue */
|
|
if (p_size == (size_t)-1 ||
|
|
(__builtin_constant_p(p[p_size - 1]) && p[p_size - 1] == '\0'))
|
|
- return __builtin_strlen(p);
|
|
+ return __underlying_strlen(p);
|
|
ret = strnlen(p, p_size);
|
|
if (p_size <= ret)
|
|
fortify_panic(__func__);
|
|
@@ -330,7 +355,7 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
|
|
__write_overflow();
|
|
if (len >= p_size)
|
|
fortify_panic(__func__);
|
|
- __builtin_memcpy(p, q, len);
|
|
+ __underlying_memcpy(p, q, len);
|
|
p[len] = '\0';
|
|
}
|
|
return ret;
|
|
@@ -343,12 +368,12 @@ __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
|
|
size_t p_size = __builtin_object_size(p, 0);
|
|
size_t q_size = __builtin_object_size(q, 0);
|
|
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
|
- return __builtin_strncat(p, q, count);
|
|
+ return __underlying_strncat(p, q, count);
|
|
p_len = strlen(p);
|
|
copy_len = strnlen(q, count);
|
|
if (p_size < p_len + copy_len + 1)
|
|
fortify_panic(__func__);
|
|
- __builtin_memcpy(p + p_len, q, copy_len);
|
|
+ __underlying_memcpy(p + p_len, q, copy_len);
|
|
p[p_len + copy_len] = '\0';
|
|
return p;
|
|
}
|
|
@@ -360,7 +385,7 @@ __FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size)
|
|
__write_overflow();
|
|
if (p_size < size)
|
|
fortify_panic(__func__);
|
|
- return __builtin_memset(p, c, size);
|
|
+ return __underlying_memset(p, c, size);
|
|
}
|
|
|
|
__FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
|
|
@@ -375,7 +400,7 @@ __FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size)
|
|
}
|
|
if (p_size < size || q_size < size)
|
|
fortify_panic(__func__);
|
|
- return __builtin_memcpy(p, q, size);
|
|
+ return __underlying_memcpy(p, q, size);
|
|
}
|
|
|
|
__FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)
|
|
@@ -390,7 +415,7 @@ __FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size)
|
|
}
|
|
if (p_size < size || q_size < size)
|
|
fortify_panic(__func__);
|
|
- return __builtin_memmove(p, q, size);
|
|
+ return __underlying_memmove(p, q, size);
|
|
}
|
|
|
|
extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
|
|
@@ -416,7 +441,7 @@ __FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size)
|
|
}
|
|
if (p_size < size || q_size < size)
|
|
fortify_panic(__func__);
|
|
- return __builtin_memcmp(p, q, size);
|
|
+ return __underlying_memcmp(p, q, size);
|
|
}
|
|
|
|
__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
|
|
@@ -426,7 +451,7 @@ __FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size)
|
|
__read_overflow();
|
|
if (p_size < size)
|
|
fortify_panic(__func__);
|
|
- return __builtin_memchr(p, c, size);
|
|
+ return __underlying_memchr(p, c, size);
|
|
}
|
|
|
|
void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);
|
|
@@ -457,11 +482,22 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q)
|
|
size_t p_size = __builtin_object_size(p, 0);
|
|
size_t q_size = __builtin_object_size(q, 0);
|
|
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
|
- return __builtin_strcpy(p, q);
|
|
+ return __underlying_strcpy(p, q);
|
|
memcpy(p, q, strlen(q) + 1);
|
|
return p;
|
|
}
|
|
|
|
+/* Don't use these outside the FORITFY_SOURCE implementation */
|
|
+#undef __underlying_memchr
|
|
+#undef __underlying_memcmp
|
|
+#undef __underlying_memcpy
|
|
+#undef __underlying_memmove
|
|
+#undef __underlying_memset
|
|
+#undef __underlying_strcat
|
|
+#undef __underlying_strcpy
|
|
+#undef __underlying_strlen
|
|
+#undef __underlying_strncat
|
|
+#undef __underlying_strncpy
|
|
#endif
|
|
|
|
/**
|
|
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
|
|
index d4326d6662a4..b5a4eb14f809 100644
|
|
--- a/include/linux/sunrpc/gss_api.h
|
|
+++ b/include/linux/sunrpc/gss_api.h
|
|
@@ -85,6 +85,7 @@ struct pf_desc {
|
|
u32 service;
|
|
char *name;
|
|
char *auth_domain_name;
|
|
+ struct auth_domain *domain;
|
|
bool datatouch;
|
|
};
|
|
|
|
diff --git a/include/linux/sunrpc/svcauth_gss.h b/include/linux/sunrpc/svcauth_gss.h
|
|
index a4528b26c8aa..d229d27ab19e 100644
|
|
--- a/include/linux/sunrpc/svcauth_gss.h
|
|
+++ b/include/linux/sunrpc/svcauth_gss.h
|
|
@@ -21,7 +21,8 @@ int gss_svc_init(void);
|
|
void gss_svc_shutdown(void);
|
|
int gss_svc_init_net(struct net *net);
|
|
void gss_svc_shutdown_net(struct net *net);
|
|
-int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
|
|
+struct auth_domain *svcauth_gss_register_pseudoflavor(u32 pseudoflavor,
|
|
+ char *name);
|
|
u32 svcauth_gss_flavor(struct auth_domain *dom);
|
|
|
|
#endif /* __KERNEL__ */
|
|
diff --git a/include/net/tls.h b/include/net/tls.h
|
|
index db26e3ec918f..0a065bdffa39 100644
|
|
--- a/include/net/tls.h
|
|
+++ b/include/net/tls.h
|
|
@@ -590,6 +590,15 @@ static inline bool tls_sw_has_ctx_tx(const struct sock *sk)
|
|
return !!tls_sw_ctx_tx(ctx);
|
|
}
|
|
|
|
+static inline bool tls_sw_has_ctx_rx(const struct sock *sk)
|
|
+{
|
|
+ struct tls_context *ctx = tls_get_ctx(sk);
|
|
+
|
|
+ if (!ctx)
|
|
+ return false;
|
|
+ return !!tls_sw_ctx_rx(ctx);
|
|
+}
|
|
+
|
|
void tls_sw_write_space(struct sock *sk, struct tls_context *ctx);
|
|
void tls_device_write_space(struct sock *sk, struct tls_context *ctx);
|
|
|
|
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
|
|
index 52641d8ca9e8..e735bc4075dc 100644
|
|
--- a/include/uapi/linux/kvm.h
|
|
+++ b/include/uapi/linux/kvm.h
|
|
@@ -189,9 +189,11 @@ struct kvm_hyperv_exit {
|
|
#define KVM_EXIT_HYPERV_SYNIC 1
|
|
#define KVM_EXIT_HYPERV_HCALL 2
|
|
__u32 type;
|
|
+ __u32 pad1;
|
|
union {
|
|
struct {
|
|
__u32 msr;
|
|
+ __u32 pad2;
|
|
__u64 control;
|
|
__u64 evt_page;
|
|
__u64 msg_page;
|
|
diff --git a/kernel/audit.c b/kernel/audit.c
|
|
index fcfbb3476ccd..05ae208ad442 100644
|
|
--- a/kernel/audit.c
|
|
+++ b/kernel/audit.c
|
|
@@ -879,7 +879,7 @@ main_queue:
|
|
return 0;
|
|
}
|
|
|
|
-int audit_send_list(void *_dest)
|
|
+int audit_send_list_thread(void *_dest)
|
|
{
|
|
struct audit_netlink_list *dest = _dest;
|
|
struct sk_buff *skb;
|
|
@@ -923,19 +923,30 @@ out_kfree_skb:
|
|
return NULL;
|
|
}
|
|
|
|
+static void audit_free_reply(struct audit_reply *reply)
|
|
+{
|
|
+ if (!reply)
|
|
+ return;
|
|
+
|
|
+ if (reply->skb)
|
|
+ kfree_skb(reply->skb);
|
|
+ if (reply->net)
|
|
+ put_net(reply->net);
|
|
+ kfree(reply);
|
|
+}
|
|
+
|
|
static int audit_send_reply_thread(void *arg)
|
|
{
|
|
struct audit_reply *reply = (struct audit_reply *)arg;
|
|
- struct sock *sk = audit_get_sk(reply->net);
|
|
|
|
audit_ctl_lock();
|
|
audit_ctl_unlock();
|
|
|
|
/* Ignore failure. It'll only happen if the sender goes away,
|
|
because our timeout is set to infinite. */
|
|
- netlink_unicast(sk, reply->skb, reply->portid, 0);
|
|
- put_net(reply->net);
|
|
- kfree(reply);
|
|
+ netlink_unicast(audit_get_sk(reply->net), reply->skb, reply->portid, 0);
|
|
+ reply->skb = NULL;
|
|
+ audit_free_reply(reply);
|
|
return 0;
|
|
}
|
|
|
|
@@ -949,35 +960,32 @@ static int audit_send_reply_thread(void *arg)
|
|
* @payload: payload data
|
|
* @size: payload size
|
|
*
|
|
- * Allocates an skb, builds the netlink message, and sends it to the port id.
|
|
- * No failure notifications.
|
|
+ * Allocates a skb, builds the netlink message, and sends it to the port id.
|
|
*/
|
|
static void audit_send_reply(struct sk_buff *request_skb, int seq, int type, int done,
|
|
int multi, const void *payload, int size)
|
|
{
|
|
- struct net *net = sock_net(NETLINK_CB(request_skb).sk);
|
|
- struct sk_buff *skb;
|
|
struct task_struct *tsk;
|
|
- struct audit_reply *reply = kmalloc(sizeof(struct audit_reply),
|
|
- GFP_KERNEL);
|
|
+ struct audit_reply *reply;
|
|
|
|
+ reply = kzalloc(sizeof(*reply), GFP_KERNEL);
|
|
if (!reply)
|
|
return;
|
|
|
|
- skb = audit_make_reply(seq, type, done, multi, payload, size);
|
|
- if (!skb)
|
|
- goto out;
|
|
-
|
|
- reply->net = get_net(net);
|
|
+ reply->skb = audit_make_reply(seq, type, done, multi, payload, size);
|
|
+ if (!reply->skb)
|
|
+ goto err;
|
|
+ reply->net = get_net(sock_net(NETLINK_CB(request_skb).sk));
|
|
reply->portid = NETLINK_CB(request_skb).portid;
|
|
- reply->skb = skb;
|
|
|
|
tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
|
|
- if (!IS_ERR(tsk))
|
|
- return;
|
|
- kfree_skb(skb);
|
|
-out:
|
|
- kfree(reply);
|
|
+ if (IS_ERR(tsk))
|
|
+ goto err;
|
|
+
|
|
+ return;
|
|
+
|
|
+err:
|
|
+ audit_free_reply(reply);
|
|
}
|
|
|
|
/*
|
|
diff --git a/kernel/audit.h b/kernel/audit.h
|
|
index 6fb7160412d4..ddc22878433d 100644
|
|
--- a/kernel/audit.h
|
|
+++ b/kernel/audit.h
|
|
@@ -229,7 +229,7 @@ struct audit_netlink_list {
|
|
struct sk_buff_head q;
|
|
};
|
|
|
|
-int audit_send_list(void *_dest);
|
|
+int audit_send_list_thread(void *_dest);
|
|
|
|
extern int selinux_audit_rule_update(void);
|
|
|
|
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
|
|
index 026e34da4ace..a10e2997aa6c 100644
|
|
--- a/kernel/auditfilter.c
|
|
+++ b/kernel/auditfilter.c
|
|
@@ -1161,11 +1161,8 @@ int audit_rule_change(int type, int seq, void *data, size_t datasz)
|
|
*/
|
|
int audit_list_rules_send(struct sk_buff *request_skb, int seq)
|
|
{
|
|
- u32 portid = NETLINK_CB(request_skb).portid;
|
|
- struct net *net = sock_net(NETLINK_CB(request_skb).sk);
|
|
struct task_struct *tsk;
|
|
struct audit_netlink_list *dest;
|
|
- int err = 0;
|
|
|
|
/* We can't just spew out the rules here because we might fill
|
|
* the available socket buffer space and deadlock waiting for
|
|
@@ -1173,25 +1170,26 @@ int audit_list_rules_send(struct sk_buff *request_skb, int seq)
|
|
* happen if we're actually running in the context of auditctl
|
|
* trying to _send_ the stuff */
|
|
|
|
- dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
|
|
+ dest = kmalloc(sizeof(*dest), GFP_KERNEL);
|
|
if (!dest)
|
|
return -ENOMEM;
|
|
- dest->net = get_net(net);
|
|
- dest->portid = portid;
|
|
+ dest->net = get_net(sock_net(NETLINK_CB(request_skb).sk));
|
|
+ dest->portid = NETLINK_CB(request_skb).portid;
|
|
skb_queue_head_init(&dest->q);
|
|
|
|
mutex_lock(&audit_filter_mutex);
|
|
audit_list_rules(seq, &dest->q);
|
|
mutex_unlock(&audit_filter_mutex);
|
|
|
|
- tsk = kthread_run(audit_send_list, dest, "audit_send_list");
|
|
+ tsk = kthread_run(audit_send_list_thread, dest, "audit_send_list");
|
|
if (IS_ERR(tsk)) {
|
|
skb_queue_purge(&dest->q);
|
|
+ put_net(dest->net);
|
|
kfree(dest);
|
|
- err = PTR_ERR(tsk);
|
|
+ return PTR_ERR(tsk);
|
|
}
|
|
|
|
- return err;
|
|
+ return 0;
|
|
}
|
|
|
|
int audit_comparator(u32 left, u32 op, u32 right)
|
|
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
|
|
index 946cfdd3b2cc..e7af1ac69d75 100644
|
|
--- a/kernel/bpf/syscall.c
|
|
+++ b/kernel/bpf/syscall.c
|
|
@@ -1118,7 +1118,8 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
|
|
map = __bpf_map_get(f);
|
|
if (IS_ERR(map))
|
|
return PTR_ERR(map);
|
|
- if (!(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
|
|
+ if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ) ||
|
|
+ !(map_get_sys_perms(map, f) & FMODE_CAN_WRITE)) {
|
|
err = -EPERM;
|
|
goto err_put;
|
|
}
|
|
diff --git a/kernel/cpu.c b/kernel/cpu.c
|
|
index d7890c1285bf..7527825ac7da 100644
|
|
--- a/kernel/cpu.c
|
|
+++ b/kernel/cpu.c
|
|
@@ -3,6 +3,7 @@
|
|
*
|
|
* This code is licenced under the GPL.
|
|
*/
|
|
+#include <linux/sched/mm.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/init.h>
|
|
@@ -564,6 +565,21 @@ static int bringup_cpu(unsigned int cpu)
|
|
return bringup_wait_for_ap(cpu);
|
|
}
|
|
|
|
+static int finish_cpu(unsigned int cpu)
|
|
+{
|
|
+ struct task_struct *idle = idle_thread_get(cpu);
|
|
+ struct mm_struct *mm = idle->active_mm;
|
|
+
|
|
+ /*
|
|
+ * idle_task_exit() will have switched to &init_mm, now
|
|
+ * clean up any remaining active_mm state.
|
|
+ */
|
|
+ if (mm != &init_mm)
|
|
+ idle->active_mm = &init_mm;
|
|
+ mmdrop(mm);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* Hotplug state machine related functions
|
|
*/
|
|
@@ -1434,7 +1450,7 @@ static struct cpuhp_step cpuhp_hp_states[] = {
|
|
[CPUHP_BRINGUP_CPU] = {
|
|
.name = "cpu:bringup",
|
|
.startup.single = bringup_cpu,
|
|
- .teardown.single = NULL,
|
|
+ .teardown.single = finish_cpu,
|
|
.cant_stop = true,
|
|
},
|
|
/* Final state before CPU kills itself */
|
|
diff --git a/kernel/cpu_pm.c b/kernel/cpu_pm.c
|
|
index cbca6879ab7d..44a259338e33 100644
|
|
--- a/kernel/cpu_pm.c
|
|
+++ b/kernel/cpu_pm.c
|
|
@@ -80,7 +80,7 @@ EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier);
|
|
*/
|
|
int cpu_pm_enter(void)
|
|
{
|
|
- int nr_calls;
|
|
+ int nr_calls = 0;
|
|
int ret = 0;
|
|
|
|
ret = cpu_pm_notify(CPU_PM_ENTER, -1, &nr_calls);
|
|
@@ -131,7 +131,7 @@ EXPORT_SYMBOL_GPL(cpu_pm_exit);
|
|
*/
|
|
int cpu_cluster_pm_enter(void)
|
|
{
|
|
- int nr_calls;
|
|
+ int nr_calls = 0;
|
|
int ret = 0;
|
|
|
|
ret = cpu_pm_notify(CPU_CLUSTER_PM_ENTER, -1, &nr_calls);
|
|
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
|
|
index f76d6f77dd5e..7d54c7c28054 100644
|
|
--- a/kernel/debug/debug_core.c
|
|
+++ b/kernel/debug/debug_core.c
|
|
@@ -501,6 +501,7 @@ static int kgdb_reenter_check(struct kgdb_state *ks)
|
|
|
|
if (exception_level > 1) {
|
|
dump_stack();
|
|
+ kgdb_io_module_registered = false;
|
|
panic("Recursive entry to debugger");
|
|
}
|
|
|
|
@@ -634,6 +635,8 @@ return_normal:
|
|
if (kgdb_skipexception(ks->ex_vector, ks->linux_regs))
|
|
goto kgdb_restore;
|
|
|
|
+ atomic_inc(&ignore_console_lock_warning);
|
|
+
|
|
/* Call the I/O driver's pre_exception routine */
|
|
if (dbg_io_ops->pre_exception)
|
|
dbg_io_ops->pre_exception();
|
|
@@ -706,6 +709,8 @@ cpu_master_loop:
|
|
if (dbg_io_ops->post_exception)
|
|
dbg_io_ops->post_exception();
|
|
|
|
+ atomic_dec(&ignore_console_lock_warning);
|
|
+
|
|
if (!kgdb_single_step) {
|
|
raw_spin_unlock(&dbg_slave_lock);
|
|
/* Wait till all the CPUs have quit from the debugger. */
|
|
diff --git a/kernel/exit.c b/kernel/exit.c
|
|
index 22dfaac9e48c..fa46977b9c07 100644
|
|
--- a/kernel/exit.c
|
|
+++ b/kernel/exit.c
|
|
@@ -713,8 +713,12 @@ void __noreturn do_exit(long code)
|
|
struct task_struct *tsk = current;
|
|
int group_dead;
|
|
|
|
- profile_task_exit(tsk);
|
|
- kcov_task_exit(tsk);
|
|
+ /*
|
|
+ * We can get here from a kernel oops, sometimes with preemption off.
|
|
+ * Start by checking for critical errors.
|
|
+ * Then fix up important state like USER_DS and preemption.
|
|
+ * Then do everything else.
|
|
+ */
|
|
|
|
WARN_ON(blk_needs_flush_plug(tsk));
|
|
|
|
@@ -732,6 +736,16 @@ void __noreturn do_exit(long code)
|
|
*/
|
|
set_fs(USER_DS);
|
|
|
|
+ if (unlikely(in_atomic())) {
|
|
+ pr_info("note: %s[%d] exited with preempt_count %d\n",
|
|
+ current->comm, task_pid_nr(current),
|
|
+ preempt_count());
|
|
+ preempt_count_set(PREEMPT_ENABLED);
|
|
+ }
|
|
+
|
|
+ profile_task_exit(tsk);
|
|
+ kcov_task_exit(tsk);
|
|
+
|
|
ptrace_event(PTRACE_EVENT_EXIT, code);
|
|
|
|
validate_creds_for_do_exit(tsk);
|
|
@@ -749,13 +763,6 @@ void __noreturn do_exit(long code)
|
|
|
|
exit_signals(tsk); /* sets PF_EXITING */
|
|
|
|
- if (unlikely(in_atomic())) {
|
|
- pr_info("note: %s[%d] exited with preempt_count %d\n",
|
|
- current->comm, task_pid_nr(current),
|
|
- preempt_count());
|
|
- preempt_count_set(PREEMPT_ENABLED);
|
|
- }
|
|
-
|
|
/* sync mm's RSS info before statistics gathering */
|
|
if (tsk->mm)
|
|
sync_mm_rss(tsk->mm);
|
|
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
|
index e99d326fa569..361cbc2dc966 100644
|
|
--- a/kernel/sched/core.c
|
|
+++ b/kernel/sched/core.c
|
|
@@ -6177,13 +6177,14 @@ void idle_task_exit(void)
|
|
struct mm_struct *mm = current->active_mm;
|
|
|
|
BUG_ON(cpu_online(smp_processor_id()));
|
|
+ BUG_ON(current != this_rq()->idle);
|
|
|
|
if (mm != &init_mm) {
|
|
switch_mm(mm, &init_mm, current);
|
|
- current->active_mm = &init_mm;
|
|
finish_arch_post_lock_switch();
|
|
}
|
|
- mmdrop(mm);
|
|
+
|
|
+ /* finish_cpu(), as ran on the BP, will clean up the active_mm state */
|
|
}
|
|
|
|
/*
|
|
@@ -7373,6 +7374,8 @@ static DEFINE_MUTEX(cfs_constraints_mutex);
|
|
|
|
const u64 max_cfs_quota_period = 1 * NSEC_PER_SEC; /* 1s */
|
|
static const u64 min_cfs_quota_period = 1 * NSEC_PER_MSEC; /* 1ms */
|
|
+/* More than 203 days if BW_SHIFT equals 20. */
|
|
+static const u64 max_cfs_runtime = MAX_BW * NSEC_PER_USEC;
|
|
|
|
static int __cfs_schedulable(struct task_group *tg, u64 period, u64 runtime);
|
|
|
|
@@ -7400,6 +7403,12 @@ static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota)
|
|
if (period > max_cfs_quota_period)
|
|
return -EINVAL;
|
|
|
|
+ /*
|
|
+ * Bound quota to defend quota against overflow during bandwidth shift.
|
|
+ */
|
|
+ if (quota != RUNTIME_INF && quota > max_cfs_runtime)
|
|
+ return -EINVAL;
|
|
+
|
|
/*
|
|
* Prevent race between setting of cfs_rq->runtime_enabled and
|
|
* unthrottle_offline_cfs_rqs().
|
|
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
|
index 8a0e6bdba50d..2f81e4ae844e 100644
|
|
--- a/kernel/sched/fair.c
|
|
+++ b/kernel/sched/fair.c
|
|
@@ -4942,6 +4942,8 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
|
|
if (!overrun)
|
|
break;
|
|
|
|
+ idle = do_sched_cfs_period_timer(cfs_b, overrun, flags);
|
|
+
|
|
if (++count > 3) {
|
|
u64 new, old = ktime_to_ns(cfs_b->period);
|
|
|
|
@@ -4971,8 +4973,6 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
|
|
/* reset count so we don't come right back in here */
|
|
count = 0;
|
|
}
|
|
-
|
|
- idle = do_sched_cfs_period_timer(cfs_b, overrun, flags);
|
|
}
|
|
if (idle)
|
|
cfs_b->period_active = 0;
|
|
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
|
|
index 7bf917e4d63a..5b04bba4500d 100644
|
|
--- a/kernel/sched/rt.c
|
|
+++ b/kernel/sched/rt.c
|
|
@@ -9,6 +9,8 @@
|
|
|
|
int sched_rr_timeslice = RR_TIMESLICE;
|
|
int sysctl_sched_rr_timeslice = (MSEC_PER_SEC / HZ) * RR_TIMESLICE;
|
|
+/* More than 4 hours if BW_SHIFT equals 20. */
|
|
+static const u64 max_rt_runtime = MAX_BW;
|
|
|
|
static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun);
|
|
|
|
@@ -2513,6 +2515,12 @@ static int tg_set_rt_bandwidth(struct task_group *tg,
|
|
if (rt_period == 0)
|
|
return -EINVAL;
|
|
|
|
+ /*
|
|
+ * Bound quota to defend quota against overflow during bandwidth shift.
|
|
+ */
|
|
+ if (rt_runtime != RUNTIME_INF && rt_runtime > max_rt_runtime)
|
|
+ return -EINVAL;
|
|
+
|
|
mutex_lock(&rt_constraints_mutex);
|
|
read_lock(&tasklist_lock);
|
|
err = __rt_schedulable(tg, rt_period, rt_runtime);
|
|
@@ -2634,7 +2642,9 @@ static int sched_rt_global_validate(void)
|
|
return -EINVAL;
|
|
|
|
if ((sysctl_sched_rt_runtime != RUNTIME_INF) &&
|
|
- (sysctl_sched_rt_runtime > sysctl_sched_rt_period))
|
|
+ ((sysctl_sched_rt_runtime > sysctl_sched_rt_period) ||
|
|
+ ((u64)sysctl_sched_rt_runtime *
|
|
+ NSEC_PER_USEC > max_rt_runtime)))
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
|
|
index c7e7481968bf..570659f1c6e2 100644
|
|
--- a/kernel/sched/sched.h
|
|
+++ b/kernel/sched/sched.h
|
|
@@ -1889,6 +1889,8 @@ extern void init_dl_rq_bw_ratio(struct dl_rq *dl_rq);
|
|
#define BW_SHIFT 20
|
|
#define BW_UNIT (1 << BW_SHIFT)
|
|
#define RATIO_SHIFT 8
|
|
+#define MAX_BW_BITS (64 - BW_SHIFT)
|
|
+#define MAX_BW ((1ULL << MAX_BW_BITS) - 1)
|
|
unsigned long to_ratio(u64 period, u64 runtime);
|
|
|
|
extern void init_entity_runnable_average(struct sched_entity *se);
|
|
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h
|
|
index 891e1c3549c4..afbd99987cf8 100644
|
|
--- a/lib/mpi/longlong.h
|
|
+++ b/lib/mpi/longlong.h
|
|
@@ -653,7 +653,7 @@ do { \
|
|
************** MIPS/64 **************
|
|
***************************************/
|
|
#if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
|
|
-#if defined(__mips_isa_rev) && __mips_isa_rev >= 6
|
|
+#if defined(__mips_isa_rev) && __mips_isa_rev >= 6 && defined(CONFIG_CC_IS_GCC)
|
|
/*
|
|
* GCC ends up emitting a __multi3 intrinsic call for MIPS64r6 with the plain C
|
|
* code below, so we special case MIPS64r6 until the compiler can do better.
|
|
diff --git a/lib/test_kasan.c b/lib/test_kasan.c
|
|
index bd3d9ef7d39e..83344c9c38f4 100644
|
|
--- a/lib/test_kasan.c
|
|
+++ b/lib/test_kasan.c
|
|
@@ -22,6 +22,14 @@
|
|
|
|
#include <asm/page.h>
|
|
|
|
+/*
|
|
+ * We assign some test results to these globals to make sure the tests
|
|
+ * are not eliminated as dead code.
|
|
+ */
|
|
+
|
|
+int kasan_int_result;
|
|
+void *kasan_ptr_result;
|
|
+
|
|
/*
|
|
* Note: test functions are marked noinline so that their names appear in
|
|
* reports.
|
|
@@ -603,7 +611,7 @@ static noinline void __init kasan_memchr(void)
|
|
if (!ptr)
|
|
return;
|
|
|
|
- memchr(ptr, '1', size + 1);
|
|
+ kasan_ptr_result = memchr(ptr, '1', size + 1);
|
|
kfree(ptr);
|
|
}
|
|
|
|
@@ -619,7 +627,7 @@ static noinline void __init kasan_memcmp(void)
|
|
return;
|
|
|
|
memset(arr, 0, sizeof(arr));
|
|
- memcmp(ptr, arr, size+1);
|
|
+ kasan_int_result = memcmp(ptr, arr, size + 1);
|
|
kfree(ptr);
|
|
}
|
|
|
|
@@ -642,22 +650,22 @@ static noinline void __init kasan_strings(void)
|
|
* will likely point to zeroed byte.
|
|
*/
|
|
ptr += 16;
|
|
- strchr(ptr, '1');
|
|
+ kasan_ptr_result = strchr(ptr, '1');
|
|
|
|
pr_info("use-after-free in strrchr\n");
|
|
- strrchr(ptr, '1');
|
|
+ kasan_ptr_result = strrchr(ptr, '1');
|
|
|
|
pr_info("use-after-free in strcmp\n");
|
|
- strcmp(ptr, "2");
|
|
+ kasan_int_result = strcmp(ptr, "2");
|
|
|
|
pr_info("use-after-free in strncmp\n");
|
|
- strncmp(ptr, "2", 1);
|
|
+ kasan_int_result = strncmp(ptr, "2", 1);
|
|
|
|
pr_info("use-after-free in strlen\n");
|
|
- strlen(ptr);
|
|
+ kasan_int_result = strlen(ptr);
|
|
|
|
pr_info("use-after-free in strnlen\n");
|
|
- strnlen(ptr, 1);
|
|
+ kasan_int_result = strnlen(ptr, 1);
|
|
}
|
|
|
|
static noinline void __init kasan_bitops(void)
|
|
@@ -724,11 +732,12 @@ static noinline void __init kasan_bitops(void)
|
|
__test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits);
|
|
|
|
pr_info("out-of-bounds in test_bit\n");
|
|
- (void)test_bit(BITS_PER_LONG + BITS_PER_BYTE, bits);
|
|
+ kasan_int_result = test_bit(BITS_PER_LONG + BITS_PER_BYTE, bits);
|
|
|
|
#if defined(clear_bit_unlock_is_negative_byte)
|
|
pr_info("out-of-bounds in clear_bit_unlock_is_negative_byte\n");
|
|
- clear_bit_unlock_is_negative_byte(BITS_PER_LONG + BITS_PER_BYTE, bits);
|
|
+ kasan_int_result = clear_bit_unlock_is_negative_byte(BITS_PER_LONG +
|
|
+ BITS_PER_BYTE, bits);
|
|
#endif
|
|
kfree(bits);
|
|
}
|
|
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
|
|
index 7ec5710afc99..da9040a6838f 100644
|
|
--- a/mm/huge_memory.c
|
|
+++ b/mm/huge_memory.c
|
|
@@ -2301,6 +2301,8 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
|
|
{
|
|
spinlock_t *ptl;
|
|
struct mmu_notifier_range range;
|
|
+ bool was_locked = false;
|
|
+ pmd_t _pmd;
|
|
|
|
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm,
|
|
address & HPAGE_PMD_MASK,
|
|
@@ -2313,11 +2315,32 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
|
|
* pmd against. Otherwise we can end up replacing wrong page.
|
|
*/
|
|
VM_BUG_ON(freeze && !page);
|
|
- if (page && page != pmd_page(*pmd))
|
|
- goto out;
|
|
+ if (page) {
|
|
+ VM_WARN_ON_ONCE(!PageLocked(page));
|
|
+ was_locked = true;
|
|
+ if (page != pmd_page(*pmd))
|
|
+ goto out;
|
|
+ }
|
|
|
|
+repeat:
|
|
if (pmd_trans_huge(*pmd)) {
|
|
- page = pmd_page(*pmd);
|
|
+ if (!page) {
|
|
+ page = pmd_page(*pmd);
|
|
+ if (unlikely(!trylock_page(page))) {
|
|
+ get_page(page);
|
|
+ _pmd = *pmd;
|
|
+ spin_unlock(ptl);
|
|
+ lock_page(page);
|
|
+ spin_lock(ptl);
|
|
+ if (unlikely(!pmd_same(*pmd, _pmd))) {
|
|
+ unlock_page(page);
|
|
+ put_page(page);
|
|
+ page = NULL;
|
|
+ goto repeat;
|
|
+ }
|
|
+ put_page(page);
|
|
+ }
|
|
+ }
|
|
if (PageMlocked(page))
|
|
clear_page_mlock(page);
|
|
} else if (!(pmd_devmap(*pmd) || is_pmd_migration_entry(*pmd)))
|
|
@@ -2325,6 +2348,8 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
|
|
__split_huge_pmd_locked(vma, pmd, range.start, freeze);
|
|
out:
|
|
spin_unlock(ptl);
|
|
+ if (!was_locked && page)
|
|
+ unlock_page(page);
|
|
/*
|
|
* No need to double call mmu_notifier->invalidate_range() callback.
|
|
* They are 3 cases to consider inside __split_huge_pmd_locked():
|
|
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
|
|
index 98d5c940facd..8686fe760f34 100644
|
|
--- a/mm/page_alloc.c
|
|
+++ b/mm/page_alloc.c
|
|
@@ -1640,7 +1640,6 @@ static void __init deferred_free_pages(unsigned long pfn,
|
|
} else if (!(pfn & nr_pgmask)) {
|
|
deferred_free_range(pfn - nr_free, nr_free);
|
|
nr_free = 1;
|
|
- touch_nmi_watchdog();
|
|
} else {
|
|
nr_free++;
|
|
}
|
|
@@ -1670,7 +1669,6 @@ static unsigned long __init deferred_init_pages(struct zone *zone,
|
|
continue;
|
|
} else if (!page || !(pfn & nr_pgmask)) {
|
|
page = pfn_to_page(pfn);
|
|
- touch_nmi_watchdog();
|
|
} else {
|
|
page++;
|
|
}
|
|
@@ -1793,6 +1791,13 @@ static int __init deferred_init_memmap(void *data)
|
|
BUG_ON(pgdat->first_deferred_pfn > pgdat_end_pfn(pgdat));
|
|
pgdat->first_deferred_pfn = ULONG_MAX;
|
|
|
|
+ /*
|
|
+ * Once we unlock here, the zone cannot be grown anymore, thus if an
|
|
+ * interrupt thread must allocate this early in boot, zone must be
|
|
+ * pre-grown prior to start of deferred page initialization.
|
|
+ */
|
|
+ pgdat_resize_unlock(pgdat, &flags);
|
|
+
|
|
/* Only the highest zone is deferred so find it */
|
|
for (zid = 0; zid < MAX_NR_ZONES; zid++) {
|
|
zone = pgdat->node_zones + zid;
|
|
@@ -1810,11 +1815,11 @@ static int __init deferred_init_memmap(void *data)
|
|
* that we can avoid introducing any issues with the buddy
|
|
* allocator.
|
|
*/
|
|
- while (spfn < epfn)
|
|
+ while (spfn < epfn) {
|
|
nr_pages += deferred_init_maxorder(&i, zone, &spfn, &epfn);
|
|
+ cond_resched();
|
|
+ }
|
|
zone_empty:
|
|
- pgdat_resize_unlock(pgdat, &flags);
|
|
-
|
|
/* Sanity check that the next zone really is unpopulated */
|
|
WARN_ON(++zid < MAX_NR_ZONES && populated_zone(++zone));
|
|
|
|
@@ -1856,17 +1861,6 @@ deferred_grow_zone(struct zone *zone, unsigned int order)
|
|
|
|
pgdat_resize_lock(pgdat, &flags);
|
|
|
|
- /*
|
|
- * If deferred pages have been initialized while we were waiting for
|
|
- * the lock, return true, as the zone was grown. The caller will retry
|
|
- * this zone. We won't return to this function since the caller also
|
|
- * has this static branch.
|
|
- */
|
|
- if (!static_branch_unlikely(&deferred_pages)) {
|
|
- pgdat_resize_unlock(pgdat, &flags);
|
|
- return true;
|
|
- }
|
|
-
|
|
/*
|
|
* If someone grew this zone while we were waiting for spinlock, return
|
|
* true, as there might be enough pages already.
|
|
@@ -1895,6 +1889,7 @@ deferred_grow_zone(struct zone *zone, unsigned int order)
|
|
first_deferred_pfn = spfn;
|
|
|
|
nr_pages += deferred_init_maxorder(&i, zone, &spfn, &epfn);
|
|
+ touch_nmi_watchdog();
|
|
|
|
/* We should only stop along section boundaries */
|
|
if ((first_deferred_pfn ^ spfn) < PAGES_PER_SECTION)
|
|
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
|
|
index 2614a9caee00..a39af0eefad3 100644
|
|
--- a/net/batman-adv/bat_v_elp.c
|
|
+++ b/net/batman-adv/bat_v_elp.c
|
|
@@ -120,20 +120,7 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
|
rtnl_lock();
|
|
ret = __ethtool_get_link_ksettings(hard_iface->net_dev, &link_settings);
|
|
rtnl_unlock();
|
|
-
|
|
- /* Virtual interface drivers such as tun / tap interfaces, VLAN, etc
|
|
- * tend to initialize the interface throughput with some value for the
|
|
- * sake of having a throughput number to export via ethtool. This
|
|
- * exported throughput leaves batman-adv to conclude the interface
|
|
- * throughput is genuine (reflecting reality), thus no measurements
|
|
- * are necessary.
|
|
- *
|
|
- * Based on the observation that those interface types also tend to set
|
|
- * the link auto-negotiation to 'off', batman-adv shall check this
|
|
- * setting to differentiate between genuine link throughput information
|
|
- * and placeholders installed by virtual interfaces.
|
|
- */
|
|
- if (ret == 0 && link_settings.base.autoneg == AUTONEG_ENABLE) {
|
|
+ if (ret == 0) {
|
|
/* link characteristics might change over time */
|
|
if (link_settings.base.duplex == DUPLEX_FULL)
|
|
hard_iface->bat_v.flags |= BATADV_FULL_DUPLEX;
|
|
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
|
|
index c1d3a303d97f..88cd410e5728 100644
|
|
--- a/net/bluetooth/hci_event.c
|
|
+++ b/net/bluetooth/hci_event.c
|
|
@@ -4216,6 +4216,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
|
|
case 0x11: /* Unsupported Feature or Parameter Value */
|
|
case 0x1c: /* SCO interval rejected */
|
|
case 0x1a: /* Unsupported Remote Feature */
|
|
+ case 0x1e: /* Invalid LMP Parameters */
|
|
case 0x1f: /* Unspecified error */
|
|
case 0x20: /* Unsupported LMP Parameter value */
|
|
if (conn->out) {
|
|
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
|
|
index ded2d5227678..0536ea9298e4 100644
|
|
--- a/net/core/skmsg.c
|
|
+++ b/net/core/skmsg.c
|
|
@@ -7,6 +7,7 @@
|
|
|
|
#include <net/sock.h>
|
|
#include <net/tcp.h>
|
|
+#include <net/tls.h>
|
|
|
|
static bool sk_msg_try_coalesce_ok(struct sk_msg *msg, int elem_first_coalesce)
|
|
{
|
|
@@ -686,13 +687,75 @@ static struct sk_psock *sk_psock_from_strp(struct strparser *strp)
|
|
return container_of(parser, struct sk_psock, parser);
|
|
}
|
|
|
|
-static void sk_psock_verdict_apply(struct sk_psock *psock,
|
|
- struct sk_buff *skb, int verdict)
|
|
+static void sk_psock_skb_redirect(struct sk_psock *psock, struct sk_buff *skb)
|
|
{
|
|
struct sk_psock *psock_other;
|
|
struct sock *sk_other;
|
|
bool ingress;
|
|
|
|
+ sk_other = tcp_skb_bpf_redirect_fetch(skb);
|
|
+ if (unlikely(!sk_other)) {
|
|
+ kfree_skb(skb);
|
|
+ return;
|
|
+ }
|
|
+ psock_other = sk_psock(sk_other);
|
|
+ if (!psock_other || sock_flag(sk_other, SOCK_DEAD) ||
|
|
+ !sk_psock_test_state(psock_other, SK_PSOCK_TX_ENABLED)) {
|
|
+ kfree_skb(skb);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ingress = tcp_skb_bpf_ingress(skb);
|
|
+ if ((!ingress && sock_writeable(sk_other)) ||
|
|
+ (ingress &&
|
|
+ atomic_read(&sk_other->sk_rmem_alloc) <=
|
|
+ sk_other->sk_rcvbuf)) {
|
|
+ if (!ingress)
|
|
+ skb_set_owner_w(skb, sk_other);
|
|
+ skb_queue_tail(&psock_other->ingress_skb, skb);
|
|
+ schedule_work(&psock_other->work);
|
|
+ } else {
|
|
+ kfree_skb(skb);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void sk_psock_tls_verdict_apply(struct sk_psock *psock,
|
|
+ struct sk_buff *skb, int verdict)
|
|
+{
|
|
+ switch (verdict) {
|
|
+ case __SK_REDIRECT:
|
|
+ sk_psock_skb_redirect(psock, skb);
|
|
+ break;
|
|
+ case __SK_PASS:
|
|
+ case __SK_DROP:
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+int sk_psock_tls_strp_read(struct sk_psock *psock, struct sk_buff *skb)
|
|
+{
|
|
+ struct bpf_prog *prog;
|
|
+ int ret = __SK_PASS;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ prog = READ_ONCE(psock->progs.skb_verdict);
|
|
+ if (likely(prog)) {
|
|
+ tcp_skb_bpf_redirect_clear(skb);
|
|
+ ret = sk_psock_bpf_run(psock, prog, skb);
|
|
+ ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb));
|
|
+ }
|
|
+ rcu_read_unlock();
|
|
+ sk_psock_tls_verdict_apply(psock, skb, ret);
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(sk_psock_tls_strp_read);
|
|
+
|
|
+static void sk_psock_verdict_apply(struct sk_psock *psock,
|
|
+ struct sk_buff *skb, int verdict)
|
|
+{
|
|
+ struct sock *sk_other;
|
|
+
|
|
switch (verdict) {
|
|
case __SK_PASS:
|
|
sk_other = psock->sk;
|
|
@@ -711,25 +774,8 @@ static void sk_psock_verdict_apply(struct sk_psock *psock,
|
|
}
|
|
goto out_free;
|
|
case __SK_REDIRECT:
|
|
- sk_other = tcp_skb_bpf_redirect_fetch(skb);
|
|
- if (unlikely(!sk_other))
|
|
- goto out_free;
|
|
- psock_other = sk_psock(sk_other);
|
|
- if (!psock_other || sock_flag(sk_other, SOCK_DEAD) ||
|
|
- !sk_psock_test_state(psock_other, SK_PSOCK_TX_ENABLED))
|
|
- goto out_free;
|
|
- ingress = tcp_skb_bpf_ingress(skb);
|
|
- if ((!ingress && sock_writeable(sk_other)) ||
|
|
- (ingress &&
|
|
- atomic_read(&sk_other->sk_rmem_alloc) <=
|
|
- sk_other->sk_rcvbuf)) {
|
|
- if (!ingress)
|
|
- skb_set_owner_w(skb, sk_other);
|
|
- skb_queue_tail(&psock_other->ingress_skb, skb);
|
|
- schedule_work(&psock_other->work);
|
|
- break;
|
|
- }
|
|
- /* fall-through */
|
|
+ sk_psock_skb_redirect(psock, skb);
|
|
+ break;
|
|
case __SK_DROP:
|
|
/* fall-through */
|
|
default:
|
|
@@ -783,9 +829,13 @@ static void sk_psock_strp_data_ready(struct sock *sk)
|
|
rcu_read_lock();
|
|
psock = sk_psock(sk);
|
|
if (likely(psock)) {
|
|
- write_lock_bh(&sk->sk_callback_lock);
|
|
- strp_data_ready(&psock->parser.strp);
|
|
- write_unlock_bh(&sk->sk_callback_lock);
|
|
+ if (tls_sw_has_ctx_rx(sk)) {
|
|
+ psock->parser.saved_data_ready(sk);
|
|
+ } else {
|
|
+ write_lock_bh(&sk->sk_callback_lock);
|
|
+ strp_data_ready(&psock->parser.strp);
|
|
+ write_unlock_bh(&sk->sk_callback_lock);
|
|
+ }
|
|
}
|
|
rcu_read_unlock();
|
|
}
|
|
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
|
|
index c3c93e95b46e..243e8107f456 100644
|
|
--- a/net/netfilter/nft_nat.c
|
|
+++ b/net/netfilter/nft_nat.c
|
|
@@ -129,7 +129,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
|
priv->type = NF_NAT_MANIP_DST;
|
|
break;
|
|
default:
|
|
- return -EINVAL;
|
|
+ return -EOPNOTSUPP;
|
|
}
|
|
|
|
if (tb[NFTA_NAT_FAMILY] == NULL)
|
|
@@ -196,7 +196,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
|
if (tb[NFTA_NAT_FLAGS]) {
|
|
priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS]));
|
|
if (priv->flags & ~NF_NAT_RANGE_MASK)
|
|
- return -EINVAL;
|
|
+ return -EOPNOTSUPP;
|
|
}
|
|
|
|
return nf_ct_netns_get(ctx->net, family);
|
|
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
|
|
index 8fa924c8e282..9314999bf095 100644
|
|
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
|
|
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
|
|
@@ -36,6 +36,8 @@ gss_mech_free(struct gss_api_mech *gm)
|
|
|
|
for (i = 0; i < gm->gm_pf_num; i++) {
|
|
pf = &gm->gm_pfs[i];
|
|
+ if (pf->domain)
|
|
+ auth_domain_put(pf->domain);
|
|
kfree(pf->auth_domain_name);
|
|
pf->auth_domain_name = NULL;
|
|
}
|
|
@@ -58,6 +60,7 @@ make_auth_domain_name(char *name)
|
|
static int
|
|
gss_mech_svc_setup(struct gss_api_mech *gm)
|
|
{
|
|
+ struct auth_domain *dom;
|
|
struct pf_desc *pf;
|
|
int i, status;
|
|
|
|
@@ -67,10 +70,13 @@ gss_mech_svc_setup(struct gss_api_mech *gm)
|
|
status = -ENOMEM;
|
|
if (pf->auth_domain_name == NULL)
|
|
goto out;
|
|
- status = svcauth_gss_register_pseudoflavor(pf->pseudoflavor,
|
|
- pf->auth_domain_name);
|
|
- if (status)
|
|
+ dom = svcauth_gss_register_pseudoflavor(
|
|
+ pf->pseudoflavor, pf->auth_domain_name);
|
|
+ if (IS_ERR(dom)) {
|
|
+ status = PTR_ERR(dom);
|
|
goto out;
|
|
+ }
|
|
+ pf->domain = dom;
|
|
}
|
|
return 0;
|
|
out:
|
|
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
|
|
index d9f7439e2431..fd91274e834d 100644
|
|
--- a/net/sunrpc/auth_gss/svcauth_gss.c
|
|
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
|
|
@@ -800,7 +800,7 @@ u32 svcauth_gss_flavor(struct auth_domain *dom)
|
|
|
|
EXPORT_SYMBOL_GPL(svcauth_gss_flavor);
|
|
|
|
-int
|
|
+struct auth_domain *
|
|
svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
|
|
{
|
|
struct gss_domain *new;
|
|
@@ -817,21 +817,23 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
|
|
new->h.flavour = &svcauthops_gss;
|
|
new->pseudoflavor = pseudoflavor;
|
|
|
|
- stat = 0;
|
|
test = auth_domain_lookup(name, &new->h);
|
|
- if (test != &new->h) { /* Duplicate registration */
|
|
+ if (test != &new->h) {
|
|
+ pr_warn("svc: duplicate registration of gss pseudo flavour %s.\n",
|
|
+ name);
|
|
+ stat = -EADDRINUSE;
|
|
auth_domain_put(test);
|
|
- kfree(new->h.name);
|
|
- goto out_free_dom;
|
|
+ goto out_free_name;
|
|
}
|
|
- return 0;
|
|
+ return test;
|
|
|
|
+out_free_name:
|
|
+ kfree(new->h.name);
|
|
out_free_dom:
|
|
kfree(new);
|
|
out:
|
|
- return stat;
|
|
+ return ERR_PTR(stat);
|
|
}
|
|
-
|
|
EXPORT_SYMBOL_GPL(svcauth_gss_register_pseudoflavor);
|
|
|
|
static inline int
|
|
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
|
|
index fbf6a496ee8b..70b203e5d5fd 100644
|
|
--- a/net/tls/tls_sw.c
|
|
+++ b/net/tls/tls_sw.c
|
|
@@ -1737,6 +1737,7 @@ int tls_sw_recvmsg(struct sock *sk,
|
|
long timeo;
|
|
bool is_kvec = iov_iter_is_kvec(&msg->msg_iter);
|
|
bool is_peek = flags & MSG_PEEK;
|
|
+ bool bpf_strp_enabled;
|
|
int num_async = 0;
|
|
int pending;
|
|
|
|
@@ -1747,6 +1748,7 @@ int tls_sw_recvmsg(struct sock *sk,
|
|
|
|
psock = sk_psock_get(sk);
|
|
lock_sock(sk);
|
|
+ bpf_strp_enabled = sk_psock_strp_enabled(psock);
|
|
|
|
/* Process pending decrypted records. It must be non-zero-copy */
|
|
err = process_rx_list(ctx, msg, &control, &cmsg, 0, len, false,
|
|
@@ -1800,11 +1802,12 @@ int tls_sw_recvmsg(struct sock *sk,
|
|
|
|
if (to_decrypt <= len && !is_kvec && !is_peek &&
|
|
ctx->control == TLS_RECORD_TYPE_DATA &&
|
|
- prot->version != TLS_1_3_VERSION)
|
|
+ prot->version != TLS_1_3_VERSION &&
|
|
+ !bpf_strp_enabled)
|
|
zc = true;
|
|
|
|
/* Do not use async mode if record is non-data */
|
|
- if (ctx->control == TLS_RECORD_TYPE_DATA)
|
|
+ if (ctx->control == TLS_RECORD_TYPE_DATA && !bpf_strp_enabled)
|
|
async_capable = ctx->async_capable;
|
|
else
|
|
async_capable = false;
|
|
@@ -1854,6 +1857,19 @@ int tls_sw_recvmsg(struct sock *sk,
|
|
goto pick_next_record;
|
|
|
|
if (!zc) {
|
|
+ if (bpf_strp_enabled) {
|
|
+ err = sk_psock_tls_strp_read(psock, skb);
|
|
+ if (err != __SK_PASS) {
|
|
+ rxm->offset = rxm->offset + rxm->full_len;
|
|
+ rxm->full_len = 0;
|
|
+ if (err == __SK_DROP)
|
|
+ consume_skb(skb);
|
|
+ ctx->recv_pkt = NULL;
|
|
+ __strp_unpause(&ctx->strp);
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (rxm->full_len > len) {
|
|
retain_skb = true;
|
|
chunk = len;
|
|
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
|
|
index fbc2ee6d46fc..ee6bd945f3d6 100644
|
|
--- a/security/integrity/evm/evm_crypto.c
|
|
+++ b/security/integrity/evm/evm_crypto.c
|
|
@@ -243,7 +243,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
|
|
|
|
/* Portable EVM signatures must include an IMA hash */
|
|
if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present)
|
|
- return -EPERM;
|
|
+ error = -EPERM;
|
|
out:
|
|
kfree(xattr_value);
|
|
kfree(desc);
|
|
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
|
|
index 3689081aaf38..be469fce19e1 100644
|
|
--- a/security/integrity/ima/ima.h
|
|
+++ b/security/integrity/ima/ima.h
|
|
@@ -36,7 +36,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
|
|
#define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE
|
|
#define IMA_EVENT_NAME_LEN_MAX 255
|
|
|
|
-#define IMA_HASH_BITS 9
|
|
+#define IMA_HASH_BITS 10
|
|
#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
|
|
|
|
#define IMA_TEMPLATE_FIELD_ID_MAX_LEN 16
|
|
@@ -52,6 +52,7 @@ extern int ima_policy_flag;
|
|
extern int ima_hash_algo;
|
|
extern int ima_appraise;
|
|
extern struct tpm_chip *ima_tpm_chip;
|
|
+extern const char boot_aggregate_name[];
|
|
|
|
/* IMA event related data */
|
|
struct ima_event_data {
|
|
@@ -140,7 +141,7 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,
|
|
int ima_calc_field_array_hash(struct ima_field_data *field_data,
|
|
struct ima_template_desc *desc, int num_fields,
|
|
struct ima_digest_data *hash);
|
|
-int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
|
|
+int ima_calc_boot_aggregate(struct ima_digest_data *hash);
|
|
void ima_add_violation(struct file *file, const unsigned char *filename,
|
|
struct integrity_iint_cache *iint,
|
|
const char *op, const char *cause);
|
|
@@ -175,9 +176,10 @@ struct ima_h_table {
|
|
};
|
|
extern struct ima_h_table ima_htable;
|
|
|
|
-static inline unsigned long ima_hash_key(u8 *digest)
|
|
+static inline unsigned int ima_hash_key(u8 *digest)
|
|
{
|
|
- return hash_long(*digest, IMA_HASH_BITS);
|
|
+ /* there is no point in taking a hash of part of a digest */
|
|
+ return (digest[0] | digest[1] << 8) % IMA_MEASURE_HTABLE_SIZE;
|
|
}
|
|
|
|
#define __ima_hooks(hook) \
|
|
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
|
|
index ad6cbbccc8d9..d5ad7b2539c7 100644
|
|
--- a/security/integrity/ima/ima_crypto.c
|
|
+++ b/security/integrity/ima/ima_crypto.c
|
|
@@ -645,7 +645,7 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,
|
|
return calc_buffer_shash(buf, len, hash);
|
|
}
|
|
|
|
-static void __init ima_pcrread(u32 idx, struct tpm_digest *d)
|
|
+static void ima_pcrread(u32 idx, struct tpm_digest *d)
|
|
{
|
|
if (!ima_tpm_chip)
|
|
return;
|
|
@@ -655,18 +655,29 @@ static void __init ima_pcrread(u32 idx, struct tpm_digest *d)
|
|
}
|
|
|
|
/*
|
|
- * Calculate the boot aggregate hash
|
|
+ * The boot_aggregate is a cumulative hash over TPM registers 0 - 7. With
|
|
+ * TPM 1.2 the boot_aggregate was based on reading the SHA1 PCRs, but with
|
|
+ * TPM 2.0 hash agility, TPM chips could support multiple TPM PCR banks,
|
|
+ * allowing firmware to configure and enable different banks.
|
|
+ *
|
|
+ * Knowing which TPM bank is read to calculate the boot_aggregate digest
|
|
+ * needs to be conveyed to a verifier. For this reason, use the same
|
|
+ * hash algorithm for reading the TPM PCRs as for calculating the boot
|
|
+ * aggregate digest as stored in the measurement list.
|
|
*/
|
|
-static int __init ima_calc_boot_aggregate_tfm(char *digest,
|
|
- struct crypto_shash *tfm)
|
|
+static int ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id,
|
|
+ struct crypto_shash *tfm)
|
|
{
|
|
- struct tpm_digest d = { .alg_id = TPM_ALG_SHA1, .digest = {0} };
|
|
+ struct tpm_digest d = { .alg_id = alg_id, .digest = {0} };
|
|
int rc;
|
|
u32 i;
|
|
SHASH_DESC_ON_STACK(shash, tfm);
|
|
|
|
shash->tfm = tfm;
|
|
|
|
+ pr_devel("calculating the boot-aggregate based on TPM bank: %04x\n",
|
|
+ d.alg_id);
|
|
+
|
|
rc = crypto_shash_init(shash);
|
|
if (rc != 0)
|
|
return rc;
|
|
@@ -675,24 +686,48 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest,
|
|
for (i = TPM_PCR0; i < TPM_PCR8; i++) {
|
|
ima_pcrread(i, &d);
|
|
/* now accumulate with current aggregate */
|
|
- rc = crypto_shash_update(shash, d.digest, TPM_DIGEST_SIZE);
|
|
+ rc = crypto_shash_update(shash, d.digest,
|
|
+ crypto_shash_digestsize(tfm));
|
|
}
|
|
if (!rc)
|
|
crypto_shash_final(shash, digest);
|
|
return rc;
|
|
}
|
|
|
|
-int __init ima_calc_boot_aggregate(struct ima_digest_data *hash)
|
|
+int ima_calc_boot_aggregate(struct ima_digest_data *hash)
|
|
{
|
|
struct crypto_shash *tfm;
|
|
- int rc;
|
|
+ u16 crypto_id, alg_id;
|
|
+ int rc, i, bank_idx = -1;
|
|
+
|
|
+ for (i = 0; i < ima_tpm_chip->nr_allocated_banks; i++) {
|
|
+ crypto_id = ima_tpm_chip->allocated_banks[i].crypto_id;
|
|
+ if (crypto_id == hash->algo) {
|
|
+ bank_idx = i;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (crypto_id == HASH_ALGO_SHA256)
|
|
+ bank_idx = i;
|
|
+
|
|
+ if (bank_idx == -1 && crypto_id == HASH_ALGO_SHA1)
|
|
+ bank_idx = i;
|
|
+ }
|
|
+
|
|
+ if (bank_idx == -1) {
|
|
+ pr_err("No suitable TPM algorithm for boot aggregate\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ hash->algo = ima_tpm_chip->allocated_banks[bank_idx].crypto_id;
|
|
|
|
tfm = ima_alloc_tfm(hash->algo);
|
|
if (IS_ERR(tfm))
|
|
return PTR_ERR(tfm);
|
|
|
|
hash->length = crypto_shash_digestsize(tfm);
|
|
- rc = ima_calc_boot_aggregate_tfm(hash->digest, tfm);
|
|
+ alg_id = ima_tpm_chip->allocated_banks[bank_idx].alg_id;
|
|
+ rc = ima_calc_boot_aggregate_tfm(hash->digest, alg_id, tfm);
|
|
|
|
ima_free_tfm(tfm);
|
|
|
|
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
|
|
index 5d55ade5f3b9..a94177042eaa 100644
|
|
--- a/security/integrity/ima/ima_init.c
|
|
+++ b/security/integrity/ima/ima_init.c
|
|
@@ -21,13 +21,13 @@
|
|
#include "ima.h"
|
|
|
|
/* name for boot aggregate entry */
|
|
-static const char boot_aggregate_name[] = "boot_aggregate";
|
|
+const char boot_aggregate_name[] = "boot_aggregate";
|
|
struct tpm_chip *ima_tpm_chip;
|
|
|
|
/* Add the boot aggregate to the IMA measurement list and extend
|
|
* the PCR register.
|
|
*
|
|
- * Calculate the boot aggregate, a SHA1 over tpm registers 0-7,
|
|
+ * Calculate the boot aggregate, a hash over tpm registers 0-7,
|
|
* assuming a TPM chip exists, and zeroes if the TPM chip does not
|
|
* exist. Add the boot aggregate measurement to the measurement
|
|
* list and extend the PCR register.
|
|
@@ -51,15 +51,27 @@ static int __init ima_add_boot_aggregate(void)
|
|
int violation = 0;
|
|
struct {
|
|
struct ima_digest_data hdr;
|
|
- char digest[TPM_DIGEST_SIZE];
|
|
+ char digest[TPM_MAX_DIGEST_SIZE];
|
|
} hash;
|
|
|
|
memset(iint, 0, sizeof(*iint));
|
|
memset(&hash, 0, sizeof(hash));
|
|
iint->ima_hash = &hash.hdr;
|
|
- iint->ima_hash->algo = HASH_ALGO_SHA1;
|
|
- iint->ima_hash->length = SHA1_DIGEST_SIZE;
|
|
-
|
|
+ iint->ima_hash->algo = ima_hash_algo;
|
|
+ iint->ima_hash->length = hash_digest_size[ima_hash_algo];
|
|
+
|
|
+ /*
|
|
+ * With TPM 2.0 hash agility, TPM chips could support multiple TPM
|
|
+ * PCR banks, allowing firmware to configure and enable different
|
|
+ * banks. The SHA1 bank is not necessarily enabled.
|
|
+ *
|
|
+ * Use the same hash algorithm for reading the TPM PCRs as for
|
|
+ * calculating the boot aggregate digest. Preference is given to
|
|
+ * the configured IMA default hash algorithm. Otherwise, use the
|
|
+ * TCG required banks - SHA256 for TPM 2.0, SHA1 for TPM 1.2.
|
|
+ * Ultimately select SHA1 also for TPM 2.0 if the SHA256 PCR bank
|
|
+ * is not found.
|
|
+ */
|
|
if (ima_tpm_chip) {
|
|
result = ima_calc_boot_aggregate(&hash.hdr);
|
|
if (result < 0) {
|
|
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
|
|
index 60027c643ecd..a768f37a0a4d 100644
|
|
--- a/security/integrity/ima/ima_main.c
|
|
+++ b/security/integrity/ima/ima_main.c
|
|
@@ -712,6 +712,9 @@ static int __init init_ima(void)
|
|
error = ima_init();
|
|
}
|
|
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
error = register_blocking_lsm_notifier(&ima_lsm_policy_notifier);
|
|
if (error)
|
|
pr_warn("Couldn't register LSM notifier, error %d\n", error);
|
|
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
|
|
index ee9aec5e98f0..558a7607bf93 100644
|
|
--- a/security/integrity/ima/ima_policy.c
|
|
+++ b/security/integrity/ima/ima_policy.c
|
|
@@ -204,7 +204,7 @@ static struct ima_rule_entry *arch_policy_entry __ro_after_init;
|
|
static LIST_HEAD(ima_default_rules);
|
|
static LIST_HEAD(ima_policy_rules);
|
|
static LIST_HEAD(ima_temp_rules);
|
|
-static struct list_head *ima_rules;
|
|
+static struct list_head *ima_rules = &ima_default_rules;
|
|
|
|
static int ima_policy __initdata;
|
|
|
|
@@ -591,9 +591,12 @@ static void add_rules(struct ima_rule_entry *entries, int count,
|
|
list_add_tail(&entry->list, &ima_policy_rules);
|
|
}
|
|
if (entries[i].action == APPRAISE) {
|
|
- temp_ima_appraise |= ima_appraise_flag(entries[i].func);
|
|
- if (entries[i].func == POLICY_CHECK)
|
|
- temp_ima_appraise |= IMA_APPRAISE_POLICY;
|
|
+ if (entries != build_appraise_rules)
|
|
+ temp_ima_appraise |=
|
|
+ ima_appraise_flag(entries[i].func);
|
|
+ else
|
|
+ build_ima_appraise |=
|
|
+ ima_appraise_flag(entries[i].func);
|
|
}
|
|
}
|
|
}
|
|
@@ -712,7 +715,6 @@ void __init ima_init_policy(void)
|
|
ARRAY_SIZE(default_appraise_rules),
|
|
IMA_DEFAULT_POLICY);
|
|
|
|
- ima_rules = &ima_default_rules;
|
|
ima_update_policy_flag();
|
|
}
|
|
|
|
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
|
|
index 32ae05d88257..1be146e17d9f 100644
|
|
--- a/security/integrity/ima/ima_template_lib.c
|
|
+++ b/security/integrity/ima/ima_template_lib.c
|
|
@@ -288,6 +288,24 @@ int ima_eventdigest_init(struct ima_event_data *event_data,
|
|
goto out;
|
|
}
|
|
|
|
+ if ((const char *)event_data->filename == boot_aggregate_name) {
|
|
+ if (ima_tpm_chip) {
|
|
+ hash.hdr.algo = HASH_ALGO_SHA1;
|
|
+ result = ima_calc_boot_aggregate(&hash.hdr);
|
|
+
|
|
+ /* algo can change depending on available PCR banks */
|
|
+ if (!result && hash.hdr.algo != HASH_ALGO_SHA1)
|
|
+ result = -EINVAL;
|
|
+
|
|
+ if (result < 0)
|
|
+ memset(&hash, 0, sizeof(hash));
|
|
+ }
|
|
+
|
|
+ cur_digest = hash.hdr.digest;
|
|
+ cur_digestsize = hash_digest_size[HASH_ALGO_SHA1];
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
if (!event_data->file) /* missing info to re-calculate the digest */
|
|
return -EINVAL;
|
|
|
|
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
|
|
index b2f87015d6e9..3f38583bed06 100644
|
|
--- a/security/lockdown/lockdown.c
|
|
+++ b/security/lockdown/lockdown.c
|
|
@@ -177,7 +177,7 @@ static int __init lockdown_secfs_init(void)
|
|
{
|
|
struct dentry *dentry;
|
|
|
|
- dentry = securityfs_create_file("lockdown", 0600, NULL, NULL,
|
|
+ dentry = securityfs_create_file("lockdown", 0644, NULL, NULL,
|
|
&lockdown_ops);
|
|
return PTR_ERR_OR_ZERO(dentry);
|
|
}
|
|
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
|
|
index 1260f5fb766e..dd7aabd94a92 100644
|
|
--- a/security/selinux/ss/policydb.c
|
|
+++ b/security/selinux/ss/policydb.c
|
|
@@ -2496,6 +2496,7 @@ int policydb_read(struct policydb *p, void *fp)
|
|
if (rc)
|
|
goto bad;
|
|
|
|
+ rc = -ENOMEM;
|
|
p->type_attr_map_array = kvcalloc(p->p_types.nprim,
|
|
sizeof(*p->type_attr_map_array),
|
|
GFP_KERNEL);
|
|
diff --git a/tools/cgroup/iocost_monitor.py b/tools/cgroup/iocost_monitor.py
|
|
index 7e344a78a627..b8c082c9fd7d 100644
|
|
--- a/tools/cgroup/iocost_monitor.py
|
|
+++ b/tools/cgroup/iocost_monitor.py
|
|
@@ -112,14 +112,14 @@ class IocStat:
|
|
|
|
def dict(self, now):
|
|
return { 'device' : devname,
|
|
- 'timestamp' : str(now),
|
|
- 'enabled' : str(int(self.enabled)),
|
|
- 'running' : str(int(self.running)),
|
|
- 'period_ms' : str(self.period_ms),
|
|
- 'period_at' : str(self.period_at),
|
|
- 'period_vtime_at' : str(self.vperiod_at),
|
|
- 'busy_level' : str(self.busy_level),
|
|
- 'vrate_pct' : str(self.vrate_pct), }
|
|
+ 'timestamp' : now,
|
|
+ 'enabled' : self.enabled,
|
|
+ 'running' : self.running,
|
|
+ 'period_ms' : self.period_ms,
|
|
+ 'period_at' : self.period_at,
|
|
+ 'period_vtime_at' : self.vperiod_at,
|
|
+ 'busy_level' : self.busy_level,
|
|
+ 'vrate_pct' : self.vrate_pct, }
|
|
|
|
def table_preamble_str(self):
|
|
state = ('RUN' if self.running else 'IDLE') if self.enabled else 'OFF'
|
|
@@ -179,19 +179,19 @@ class IocgStat:
|
|
|
|
def dict(self, now, path):
|
|
out = { 'cgroup' : path,
|
|
- 'timestamp' : str(now),
|
|
- 'is_active' : str(int(self.is_active)),
|
|
- 'weight' : str(self.weight),
|
|
- 'weight_active' : str(self.active),
|
|
- 'weight_inuse' : str(self.inuse),
|
|
- 'hweight_active_pct' : str(self.hwa_pct),
|
|
- 'hweight_inuse_pct' : str(self.hwi_pct),
|
|
- 'inflight_pct' : str(self.inflight_pct),
|
|
- 'debt_ms' : str(self.debt_ms),
|
|
- 'use_delay' : str(self.use_delay),
|
|
- 'delay_ms' : str(self.delay_ms),
|
|
- 'usage_pct' : str(self.usage),
|
|
- 'address' : str(hex(self.address)) }
|
|
+ 'timestamp' : now,
|
|
+ 'is_active' : self.is_active,
|
|
+ 'weight' : self.weight,
|
|
+ 'weight_active' : self.active,
|
|
+ 'weight_inuse' : self.inuse,
|
|
+ 'hweight_active_pct' : self.hwa_pct,
|
|
+ 'hweight_inuse_pct' : self.hwi_pct,
|
|
+ 'inflight_pct' : self.inflight_pct,
|
|
+ 'debt_ms' : self.debt_ms,
|
|
+ 'use_delay' : self.use_delay,
|
|
+ 'delay_ms' : self.delay_ms,
|
|
+ 'usage_pct' : self.usage,
|
|
+ 'address' : self.address }
|
|
for i in range(len(self.usages)):
|
|
out[f'usage_pct_{i}'] = str(self.usages[i])
|
|
return out
|
|
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
|
|
index bd021a0eeef8..4cc69675c2a9 100644
|
|
--- a/tools/lib/api/fs/fs.c
|
|
+++ b/tools/lib/api/fs/fs.c
|
|
@@ -90,6 +90,7 @@ struct fs {
|
|
const char * const *mounts;
|
|
char path[PATH_MAX];
|
|
bool found;
|
|
+ bool checked;
|
|
long magic;
|
|
};
|
|
|
|
@@ -111,31 +112,37 @@ static struct fs fs__entries[] = {
|
|
.name = "sysfs",
|
|
.mounts = sysfs__fs_known_mountpoints,
|
|
.magic = SYSFS_MAGIC,
|
|
+ .checked = false,
|
|
},
|
|
[FS__PROCFS] = {
|
|
.name = "proc",
|
|
.mounts = procfs__known_mountpoints,
|
|
.magic = PROC_SUPER_MAGIC,
|
|
+ .checked = false,
|
|
},
|
|
[FS__DEBUGFS] = {
|
|
.name = "debugfs",
|
|
.mounts = debugfs__known_mountpoints,
|
|
.magic = DEBUGFS_MAGIC,
|
|
+ .checked = false,
|
|
},
|
|
[FS__TRACEFS] = {
|
|
.name = "tracefs",
|
|
.mounts = tracefs__known_mountpoints,
|
|
.magic = TRACEFS_MAGIC,
|
|
+ .checked = false,
|
|
},
|
|
[FS__HUGETLBFS] = {
|
|
.name = "hugetlbfs",
|
|
.mounts = hugetlbfs__known_mountpoints,
|
|
.magic = HUGETLBFS_MAGIC,
|
|
+ .checked = false,
|
|
},
|
|
[FS__BPF_FS] = {
|
|
.name = "bpf",
|
|
.mounts = bpf_fs__known_mountpoints,
|
|
.magic = BPF_FS_MAGIC,
|
|
+ .checked = false,
|
|
},
|
|
};
|
|
|
|
@@ -158,6 +165,7 @@ static bool fs__read_mounts(struct fs *fs)
|
|
}
|
|
|
|
fclose(fp);
|
|
+ fs->checked = true;
|
|
return fs->found = found;
|
|
}
|
|
|
|
@@ -220,6 +228,7 @@ static bool fs__env_override(struct fs *fs)
|
|
return false;
|
|
|
|
fs->found = true;
|
|
+ fs->checked = true;
|
|
strncpy(fs->path, override_path, sizeof(fs->path) - 1);
|
|
fs->path[sizeof(fs->path) - 1] = '\0';
|
|
return true;
|
|
@@ -246,6 +255,14 @@ static const char *fs__mountpoint(int idx)
|
|
if (fs->found)
|
|
return (const char *)fs->path;
|
|
|
|
+ /* the mount point was already checked for the mount point
|
|
+ * but and did not exist, so return NULL to avoid scanning again.
|
|
+ * This makes the found and not found paths cost equivalent
|
|
+ * in case of multiple calls.
|
|
+ */
|
|
+ if (fs->checked)
|
|
+ return NULL;
|
|
+
|
|
return fs__get_mountpoint(fs);
|
|
}
|
|
|
|
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
|
|
index 92d03b8396b1..3b70003e7cfb 100644
|
|
--- a/tools/lib/api/fs/fs.h
|
|
+++ b/tools/lib/api/fs/fs.h
|
|
@@ -18,6 +18,18 @@
|
|
const char *name##__mount(void); \
|
|
bool name##__configured(void); \
|
|
|
|
+/*
|
|
+ * The xxxx__mountpoint() entry points find the first match mount point for each
|
|
+ * filesystems listed below, where xxxx is the filesystem type.
|
|
+ *
|
|
+ * The interface is as follows:
|
|
+ *
|
|
+ * - If a mount point is found on first call, it is cached and used for all
|
|
+ * subsequent calls.
|
|
+ *
|
|
+ * - If a mount point is not found, NULL is returned on first call and all
|
|
+ * subsequent calls.
|
|
+ */
|
|
FS(sysfs)
|
|
FS(procfs)
|
|
FS(debugfs)
|
|
diff --git a/tools/lib/bpf/hashmap.c b/tools/lib/bpf/hashmap.c
|
|
index 6122272943e6..9ef9f6201d8b 100644
|
|
--- a/tools/lib/bpf/hashmap.c
|
|
+++ b/tools/lib/bpf/hashmap.c
|
|
@@ -56,7 +56,14 @@ struct hashmap *hashmap__new(hashmap_hash_fn hash_fn,
|
|
|
|
void hashmap__clear(struct hashmap *map)
|
|
{
|
|
+ struct hashmap_entry *cur, *tmp;
|
|
+ int bkt;
|
|
+
|
|
+ hashmap__for_each_entry_safe(map, cur, tmp, bkt) {
|
|
+ free(cur);
|
|
+ }
|
|
free(map->buckets);
|
|
+ map->buckets = NULL;
|
|
map->cap = map->cap_bits = map->sz = 0;
|
|
}
|
|
|
|
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
|
|
index 281cc65276e0..2a1dbf52fc9a 100644
|
|
--- a/tools/lib/bpf/libbpf.c
|
|
+++ b/tools/lib/bpf/libbpf.c
|
|
@@ -5358,9 +5358,12 @@ void perf_buffer__free(struct perf_buffer *pb)
|
|
if (!pb)
|
|
return;
|
|
if (pb->cpu_bufs) {
|
|
- for (i = 0; i < pb->cpu_cnt && pb->cpu_bufs[i]; i++) {
|
|
+ for (i = 0; i < pb->cpu_cnt; i++) {
|
|
struct perf_cpu_buf *cpu_buf = pb->cpu_bufs[i];
|
|
|
|
+ if (!cpu_buf)
|
|
+ continue;
|
|
+
|
|
bpf_map_delete_elem(pb->map_fd, &cpu_buf->map_key);
|
|
perf_buffer__free_cpu_buf(pb, cpu_buf);
|
|
}
|
|
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
|
|
index fcc6cd404f56..48b234d8f251 100644
|
|
--- a/tools/objtool/check.c
|
|
+++ b/tools/objtool/check.c
|
|
@@ -865,6 +865,12 @@ static int add_special_section_alts(struct objtool_file *file)
|
|
}
|
|
|
|
if (special_alt->group) {
|
|
+ if (!special_alt->orig_len) {
|
|
+ WARN_FUNC("empty alternative entry",
|
|
+ orig_insn->sec, orig_insn->offset);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
ret = handle_group_alt(file, special_alt, orig_insn,
|
|
&new_insn);
|
|
if (ret)
|
|
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
|
|
index 26bc5923e6b5..2f05f59e9758 100644
|
|
--- a/tools/perf/builtin-probe.c
|
|
+++ b/tools/perf/builtin-probe.c
|
|
@@ -364,6 +364,9 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
|
|
|
|
for (k = 0; k < pev->ntevs; k++) {
|
|
struct probe_trace_event *tev = &pev->tevs[k];
|
|
+ /* Skipped events have no event name */
|
|
+ if (!tev->event)
|
|
+ continue;
|
|
|
|
/* We use tev's name for showing new events */
|
|
show_perf_probe_event(tev->group, tev->event, pev,
|
|
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
|
|
index e11ddf86f2b3..ab2e130dc07a 100644
|
|
--- a/tools/perf/util/dso.c
|
|
+++ b/tools/perf/util/dso.c
|
|
@@ -47,6 +47,7 @@ char dso__symtab_origin(const struct dso *dso)
|
|
[DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO] = 'D',
|
|
[DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
|
|
[DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
|
|
+ [DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO] = 'x',
|
|
[DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
|
|
[DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
|
|
[DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
|
|
@@ -129,6 +130,21 @@ int dso__read_binary_type_filename(const struct dso *dso,
|
|
snprintf(filename + len, size - len, "%s", dso->long_name);
|
|
break;
|
|
|
|
+ case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
|
|
+ /*
|
|
+ * Ubuntu can mixup /usr/lib with /lib, putting debuginfo in
|
|
+ * /usr/lib/debug/lib when it is expected to be in
|
|
+ * /usr/lib/debug/usr/lib
|
|
+ */
|
|
+ if (strlen(dso->long_name) < 9 ||
|
|
+ strncmp(dso->long_name, "/usr/lib/", 9)) {
|
|
+ ret = -1;
|
|
+ break;
|
|
+ }
|
|
+ len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
|
|
+ snprintf(filename + len, size - len, "%s", dso->long_name + 4);
|
|
+ break;
|
|
+
|
|
case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
|
|
{
|
|
const char *last_slash;
|
|
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
|
|
index e4dddb76770d..69bb77d19164 100644
|
|
--- a/tools/perf/util/dso.h
|
|
+++ b/tools/perf/util/dso.h
|
|
@@ -30,6 +30,7 @@ enum dso_binary_type {
|
|
DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO,
|
|
DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
|
|
DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
|
|
+ DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
|
|
DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
|
|
DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
|
|
DSO_BINARY_TYPE__GUEST_KMODULE,
|
|
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
|
|
index 92b07be0b48b..a5cb1a3a1064 100644
|
|
--- a/tools/perf/util/probe-event.c
|
|
+++ b/tools/perf/util/probe-event.c
|
|
@@ -102,7 +102,7 @@ void exit_probe_symbol_maps(void)
|
|
symbol__exit();
|
|
}
|
|
|
|
-static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
|
|
+static struct ref_reloc_sym *kernel_get_ref_reloc_sym(struct map **pmap)
|
|
{
|
|
/* kmap->ref_reloc_sym should be set if host_machine is initialized */
|
|
struct kmap *kmap;
|
|
@@ -114,6 +114,10 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
|
|
kmap = map__kmap(map);
|
|
if (!kmap)
|
|
return NULL;
|
|
+
|
|
+ if (pmap)
|
|
+ *pmap = map;
|
|
+
|
|
return kmap->ref_reloc_sym;
|
|
}
|
|
|
|
@@ -125,7 +129,7 @@ static int kernel_get_symbol_address_by_name(const char *name, u64 *addr,
|
|
struct map *map;
|
|
|
|
/* ref_reloc_sym is just a label. Need a special fix*/
|
|
- reloc_sym = kernel_get_ref_reloc_sym();
|
|
+ reloc_sym = kernel_get_ref_reloc_sym(NULL);
|
|
if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
|
|
*addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
|
|
else {
|
|
@@ -232,21 +236,22 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
|
|
static bool kprobe_blacklist__listed(unsigned long address);
|
|
static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
|
|
{
|
|
- u64 etext_addr = 0;
|
|
- int ret;
|
|
-
|
|
- /* Get the address of _etext for checking non-probable text symbol */
|
|
- ret = kernel_get_symbol_address_by_name("_etext", &etext_addr,
|
|
- false, false);
|
|
+ struct map *map;
|
|
+ bool ret = false;
|
|
|
|
- if (ret == 0 && etext_addr < address)
|
|
- pr_warning("%s is out of .text, skip it.\n", symbol);
|
|
- else if (kprobe_blacklist__listed(address))
|
|
+ map = kernel_get_module_map(NULL);
|
|
+ if (map) {
|
|
+ ret = address <= map->start || map->end < address;
|
|
+ if (ret)
|
|
+ pr_warning("%s is out of .text, skip it.\n", symbol);
|
|
+ map__put(map);
|
|
+ }
|
|
+ if (!ret && kprobe_blacklist__listed(address)) {
|
|
pr_warning("%s is blacklisted function, skip it.\n", symbol);
|
|
- else
|
|
- return false;
|
|
+ ret = true;
|
|
+ }
|
|
|
|
- return true;
|
|
+ return ret;
|
|
}
|
|
|
|
/*
|
|
@@ -745,6 +750,7 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
|
|
int ntevs)
|
|
{
|
|
struct ref_reloc_sym *reloc_sym;
|
|
+ struct map *map;
|
|
char *tmp;
|
|
int i, skipped = 0;
|
|
|
|
@@ -753,7 +759,7 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
|
|
return post_process_offline_probe_trace_events(tevs, ntevs,
|
|
symbol_conf.vmlinux_name);
|
|
|
|
- reloc_sym = kernel_get_ref_reloc_sym();
|
|
+ reloc_sym = kernel_get_ref_reloc_sym(&map);
|
|
if (!reloc_sym) {
|
|
pr_warning("Relocated base symbol is not found!\n");
|
|
return -EINVAL;
|
|
@@ -764,9 +770,13 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
|
|
continue;
|
|
if (tevs[i].point.retprobe && !kretprobe_offset_is_supported())
|
|
continue;
|
|
- /* If we found a wrong one, mark it by NULL symbol */
|
|
+ /*
|
|
+ * If we found a wrong one, mark it by NULL symbol.
|
|
+ * Since addresses in debuginfo is same as objdump, we need
|
|
+ * to convert it to addresses on memory.
|
|
+ */
|
|
if (kprobe_warn_out_range(tevs[i].point.symbol,
|
|
- tevs[i].point.address)) {
|
|
+ map__objdump_2mem(map, tevs[i].point.address))) {
|
|
tmp = NULL;
|
|
skipped++;
|
|
} else {
|
|
@@ -2922,7 +2932,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
|
|
/* Note that the symbols in the kmodule are not relocated */
|
|
if (!pev->uprobes && !pev->target &&
|
|
(!pp->retprobe || kretprobe_offset_is_supported())) {
|
|
- reloc_sym = kernel_get_ref_reloc_sym();
|
|
+ reloc_sym = kernel_get_ref_reloc_sym(NULL);
|
|
if (!reloc_sym) {
|
|
pr_warning("Relocated base symbol is not found!\n");
|
|
ret = -EINVAL;
|
|
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
|
|
index aaf3b24fffa4..dc9d495e3d6a 100644
|
|
--- a/tools/perf/util/probe-finder.c
|
|
+++ b/tools/perf/util/probe-finder.c
|
|
@@ -101,6 +101,7 @@ enum dso_binary_type distro_dwarf_types[] = {
|
|
DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
|
|
DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
|
|
DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
|
|
+ DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
|
|
DSO_BINARY_TYPE__NOT_FOUND,
|
|
};
|
|
|
|
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
|
|
index a8f80e427674..901ad7f6f4dc 100644
|
|
--- a/tools/perf/util/symbol.c
|
|
+++ b/tools/perf/util/symbol.c
|
|
@@ -79,6 +79,7 @@ static enum dso_binary_type binary_type_symtab[] = {
|
|
DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
|
|
DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
|
|
DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
|
|
+ DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
|
|
DSO_BINARY_TYPE__NOT_FOUND,
|
|
};
|
|
|
|
@@ -1220,6 +1221,7 @@ int map_groups__merge_in(struct map_groups *kmaps, struct map *new_map)
|
|
|
|
m->end = old_map->start;
|
|
list_add_tail(&m->node, &merged);
|
|
+ new_map->pgoff += old_map->end - new_map->start;
|
|
new_map->start = old_map->end;
|
|
}
|
|
} else {
|
|
@@ -1240,6 +1242,7 @@ int map_groups__merge_in(struct map_groups *kmaps, struct map *new_map)
|
|
* |new......| -> |new...|
|
|
* |old....| -> |old....|
|
|
*/
|
|
+ new_map->pgoff += old_map->end - new_map->start;
|
|
new_map->start = old_map->end;
|
|
}
|
|
}
|
|
@@ -1530,6 +1533,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
|
|
case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
|
|
case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
|
|
case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
|
|
+ case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
|
|
case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
|
|
case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
|
|
return !kmod && dso->kernel == DSO_TYPE_USER;
|
|
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
|
|
index 5dc109f4c097..b9601f13cf03 100644
|
|
--- a/tools/testing/selftests/bpf/config
|
|
+++ b/tools/testing/selftests/bpf/config
|
|
@@ -25,6 +25,7 @@ CONFIG_XDP_SOCKETS=y
|
|
CONFIG_FTRACE_SYSCALLS=y
|
|
CONFIG_IPV6_TUNNEL=y
|
|
CONFIG_IPV6_GRE=y
|
|
+CONFIG_IPV6_SEG6_BPF=y
|
|
CONFIG_NET_FOU=m
|
|
CONFIG_NET_FOU_IP_TUNNELS=y
|
|
CONFIG_IPV6_FOU=m
|
|
diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
|
|
index 92563898867c..9f3634c9971d 100644
|
|
--- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
|
|
+++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
|
|
@@ -523,6 +523,7 @@ void test_flow_dissector(void)
|
|
CHECK_ATTR(err, tests[i].name, "bpf_map_delete_elem %d\n", err);
|
|
}
|
|
|
|
+ close(tap_fd);
|
|
bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR);
|
|
bpf_object__close(obj);
|
|
}
|
|
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
|
|
index 3bf18364c67c..8cb3469dd11f 100644
|
|
--- a/tools/testing/selftests/bpf/test_progs.c
|
|
+++ b/tools/testing/selftests/bpf/test_progs.c
|
|
@@ -293,6 +293,7 @@ int extract_build_id(char *build_id, size_t size)
|
|
len = size;
|
|
memcpy(build_id, line, len);
|
|
build_id[len] = '\0';
|
|
+ free(line);
|
|
return 0;
|
|
err:
|
|
fclose(fp);
|