21068 lines
696 KiB
Diff
21068 lines
696 KiB
Diff
diff --git a/Documentation/ABI/testing/evm b/Documentation/ABI/testing/evm
|
|
index 3c477ba48a312..2243b72e41107 100644
|
|
--- a/Documentation/ABI/testing/evm
|
|
+++ b/Documentation/ABI/testing/evm
|
|
@@ -49,8 +49,30 @@ Description:
|
|
modification of EVM-protected metadata and
|
|
disable all further modification of policy
|
|
|
|
- Note that once a key has been loaded, it will no longer be
|
|
- possible to enable metadata modification.
|
|
+ Echoing a value is additive, the new value is added to the
|
|
+ existing initialization flags.
|
|
+
|
|
+ For example, after::
|
|
+
|
|
+ echo 2 ><securityfs>/evm
|
|
+
|
|
+ another echo can be performed::
|
|
+
|
|
+ echo 1 ><securityfs>/evm
|
|
+
|
|
+ and the resulting value will be 3.
|
|
+
|
|
+ Note that once an HMAC key has been loaded, it will no longer
|
|
+ be possible to enable metadata modification. Signaling that an
|
|
+ HMAC key has been loaded will clear the corresponding flag.
|
|
+ For example, if the current value is 6 (2 and 4 set)::
|
|
+
|
|
+ echo 1 ><securityfs>/evm
|
|
+
|
|
+ will set the new value to 3 (4 cleared).
|
|
+
|
|
+ Loading an HMAC key is the only way to disable metadata
|
|
+ modification.
|
|
|
|
Until key loading has been signaled EVM can not create
|
|
or validate the 'security.evm' xattr, but returns
|
|
diff --git a/Documentation/ABI/testing/sysfs-bus-papr-pmem b/Documentation/ABI/testing/sysfs-bus-papr-pmem
|
|
index 8316c33862a04..0aa02bf2bde5c 100644
|
|
--- a/Documentation/ABI/testing/sysfs-bus-papr-pmem
|
|
+++ b/Documentation/ABI/testing/sysfs-bus-papr-pmem
|
|
@@ -39,9 +39,11 @@ KernelVersion: v5.9
|
|
Contact: linuxppc-dev <linuxppc-dev@lists.ozlabs.org>, linux-nvdimm@lists.01.org,
|
|
Description:
|
|
(RO) Report various performance stats related to papr-scm NVDIMM
|
|
- device. Each stat is reported on a new line with each line
|
|
- composed of a stat-identifier followed by it value. Below are
|
|
- currently known dimm performance stats which are reported:
|
|
+ device. This attribute is only available for NVDIMM devices
|
|
+ that support reporting NVDIMM performance stats. Each stat is
|
|
+ reported on a new line with each line composed of a
|
|
+ stat-identifier followed by it value. Below are currently known
|
|
+ dimm performance stats which are reported:
|
|
|
|
* "CtlResCt" : Controller Reset Count
|
|
* "CtlResTm" : Controller Reset Elapsed Time
|
|
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
|
|
index 26bfe7ae711b8..f103667d3727f 100644
|
|
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
@@ -577,6 +577,12 @@
|
|
loops can be debugged more effectively on production
|
|
systems.
|
|
|
|
+ clocksource.max_cswd_read_retries= [KNL]
|
|
+ Number of clocksource_watchdog() retries due to
|
|
+ external delays before the clock will be marked
|
|
+ unstable. Defaults to three retries, that is,
|
|
+ four attempts to read the clock under test.
|
|
+
|
|
clearcpuid=BITNUM[,BITNUM...] [X86]
|
|
Disable CPUID feature X for the kernel. See
|
|
arch/x86/include/asm/cpufeatures.h for the valid bit
|
|
diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst
|
|
index f301385d8cef3..7b097c3b9b908 100644
|
|
--- a/Documentation/hwmon/max31790.rst
|
|
+++ b/Documentation/hwmon/max31790.rst
|
|
@@ -38,6 +38,7 @@ Sysfs entries
|
|
fan[1-12]_input RO fan tachometer speed in RPM
|
|
fan[1-12]_fault RO fan experienced fault
|
|
fan[1-6]_target RW desired fan speed in RPM
|
|
-pwm[1-6]_enable RW regulator mode, 0=disabled, 1=manual mode, 2=rpm mode
|
|
-pwm[1-6] RW fan target duty cycle (0-255)
|
|
+pwm[1-6]_enable RW regulator mode, 0=disabled (duty cycle=0%), 1=manual mode, 2=rpm mode
|
|
+pwm[1-6] RW read: current pwm duty cycle,
|
|
+ write: target pwm duty cycle (0-255)
|
|
================== === =======================================================
|
|
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
index ce728c757eaf8..b864869b42bc8 100644
|
|
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst
|
|
@@ -4030,7 +4030,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
|
|
:stub-columns: 0
|
|
:widths: 1 1 2
|
|
|
|
- * - ``V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT``
|
|
+ * - ``V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED``
|
|
- 0x00000001
|
|
-
|
|
* - ``V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT``
|
|
@@ -4238,6 +4238,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
|
|
* - ``V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED``
|
|
- 0x00000100
|
|
-
|
|
+ * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT``
|
|
+ - 0x00000200
|
|
+ -
|
|
|
|
.. c:type:: v4l2_hevc_dpb_entry
|
|
|
|
diff --git a/Documentation/vm/arch_pgtable_helpers.rst b/Documentation/vm/arch_pgtable_helpers.rst
|
|
index f3591ee3aaa89..552567d863b86 100644
|
|
--- a/Documentation/vm/arch_pgtable_helpers.rst
|
|
+++ b/Documentation/vm/arch_pgtable_helpers.rst
|
|
@@ -50,7 +50,7 @@ PTE Page Table Helpers
|
|
+---------------------------+--------------------------------------------------+
|
|
| pte_mkwrite | Creates a writable PTE |
|
|
+---------------------------+--------------------------------------------------+
|
|
-| pte_mkwrprotect | Creates a write protected PTE |
|
|
+| pte_wrprotect | Creates a write protected PTE |
|
|
+---------------------------+--------------------------------------------------+
|
|
| pte_mkspecial | Creates a special PTE |
|
|
+---------------------------+--------------------------------------------------+
|
|
@@ -120,7 +120,7 @@ PMD Page Table Helpers
|
|
+---------------------------+--------------------------------------------------+
|
|
| pmd_mkwrite | Creates a writable PMD |
|
|
+---------------------------+--------------------------------------------------+
|
|
-| pmd_mkwrprotect | Creates a write protected PMD |
|
|
+| pmd_wrprotect | Creates a write protected PMD |
|
|
+---------------------------+--------------------------------------------------+
|
|
| pmd_mkspecial | Creates a special PMD |
|
|
+---------------------------+--------------------------------------------------+
|
|
@@ -186,7 +186,7 @@ PUD Page Table Helpers
|
|
+---------------------------+--------------------------------------------------+
|
|
| pud_mkwrite | Creates a writable PUD |
|
|
+---------------------------+--------------------------------------------------+
|
|
-| pud_mkwrprotect | Creates a write protected PUD |
|
|
+| pud_wrprotect | Creates a write protected PUD |
|
|
+---------------------------+--------------------------------------------------+
|
|
| pud_mkdevmap | Creates a ZONE_DEVICE mapped PUD |
|
|
+---------------------------+--------------------------------------------------+
|
|
@@ -224,7 +224,7 @@ HugeTLB Page Table Helpers
|
|
+---------------------------+--------------------------------------------------+
|
|
| huge_pte_mkwrite | Creates a writable HugeTLB |
|
|
+---------------------------+--------------------------------------------------+
|
|
-| huge_pte_mkwrprotect | Creates a write protected HugeTLB |
|
|
+| huge_pte_wrprotect | Creates a write protected HugeTLB |
|
|
+---------------------------+--------------------------------------------------+
|
|
| huge_ptep_get_and_clear | Clears a HugeTLB |
|
|
+---------------------------+--------------------------------------------------+
|
|
diff --git a/Makefile b/Makefile
|
|
index c51b73455ea33..695f8e739a91b 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 5
|
|
PATCHLEVEL = 10
|
|
-SUBLEVEL = 49
|
|
+SUBLEVEL = 50
|
|
EXTRAVERSION =
|
|
NAME = Dare mighty things
|
|
|
|
@@ -978,7 +978,7 @@ LDFLAGS_vmlinux += $(call ld-option, -X,)
|
|
endif
|
|
|
|
ifeq ($(CONFIG_RELR),y)
|
|
-LDFLAGS_vmlinux += --pack-dyn-relocs=relr
|
|
+LDFLAGS_vmlinux += --pack-dyn-relocs=relr --use-android-relr-tags
|
|
endif
|
|
|
|
# We never want expected sections to be placed heuristically by the
|
|
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
|
|
index f4dd9f3f30010..4b2575f936d46 100644
|
|
--- a/arch/alpha/kernel/smp.c
|
|
+++ b/arch/alpha/kernel/smp.c
|
|
@@ -166,7 +166,6 @@ smp_callin(void)
|
|
DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n",
|
|
cpuid, current, current->active_mm));
|
|
|
|
- preempt_disable();
|
|
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
|
|
}
|
|
|
|
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
|
|
index 52906d3145371..db0e104d68355 100644
|
|
--- a/arch/arc/kernel/smp.c
|
|
+++ b/arch/arc/kernel/smp.c
|
|
@@ -189,7 +189,6 @@ void start_kernel_secondary(void)
|
|
pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
|
|
|
|
local_irq_enable();
|
|
- preempt_disable();
|
|
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
|
|
}
|
|
|
|
diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi
|
|
index 04f24cf752d34..e5c2c52013e3e 100644
|
|
--- a/arch/arm/boot/dts/sama5d4.dtsi
|
|
+++ b/arch/arm/boot/dts/sama5d4.dtsi
|
|
@@ -809,7 +809,7 @@
|
|
0xffffffff 0x3ffcfe7c 0x1c010101 /* pioA */
|
|
0x7fffffff 0xfffccc3a 0x3f00cc3a /* pioB */
|
|
0xffffffff 0x3ff83fff 0xff00ffff /* pioC */
|
|
- 0x0003ff00 0x8002a800 0x00000000 /* pioD */
|
|
+ 0xb003ff00 0x8002a800 0x00000000 /* pioD */
|
|
0xffffffff 0x7fffffff 0x76fff1bf /* pioE */
|
|
>;
|
|
|
|
diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi
|
|
index ff47cbf6ed3b7..359c1219b0bab 100644
|
|
--- a/arch/arm/boot/dts/ste-href.dtsi
|
|
+++ b/arch/arm/boot/dts/ste-href.dtsi
|
|
@@ -4,6 +4,7 @@
|
|
*/
|
|
|
|
#include <dt-bindings/interrupt-controller/irq.h>
|
|
+#include <dt-bindings/leds/common.h>
|
|
#include "ste-href-family-pinctrl.dtsi"
|
|
|
|
/ {
|
|
@@ -64,17 +65,20 @@
|
|
reg = <0>;
|
|
led-cur = /bits/ 8 <0x2f>;
|
|
max-cur = /bits/ 8 <0x5f>;
|
|
+ color = <LED_COLOR_ID_BLUE>;
|
|
linux,default-trigger = "heartbeat";
|
|
};
|
|
chan@1 {
|
|
reg = <1>;
|
|
led-cur = /bits/ 8 <0x2f>;
|
|
max-cur = /bits/ 8 <0x5f>;
|
|
+ color = <LED_COLOR_ID_BLUE>;
|
|
};
|
|
chan@2 {
|
|
reg = <2>;
|
|
led-cur = /bits/ 8 <0x2f>;
|
|
max-cur = /bits/ 8 <0x5f>;
|
|
+ color = <LED_COLOR_ID_BLUE>;
|
|
};
|
|
};
|
|
lp5521@34 {
|
|
@@ -88,16 +92,19 @@
|
|
reg = <0>;
|
|
led-cur = /bits/ 8 <0x2f>;
|
|
max-cur = /bits/ 8 <0x5f>;
|
|
+ color = <LED_COLOR_ID_BLUE>;
|
|
};
|
|
chan@1 {
|
|
reg = <1>;
|
|
led-cur = /bits/ 8 <0x2f>;
|
|
max-cur = /bits/ 8 <0x5f>;
|
|
+ color = <LED_COLOR_ID_BLUE>;
|
|
};
|
|
chan@2 {
|
|
reg = <2>;
|
|
led-cur = /bits/ 8 <0x2f>;
|
|
max-cur = /bits/ 8 <0x5f>;
|
|
+ color = <LED_COLOR_ID_BLUE>;
|
|
};
|
|
};
|
|
bh1780@29 {
|
|
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
|
|
index 2924d7910b106..eb2190477da10 100644
|
|
--- a/arch/arm/kernel/perf_event_v7.c
|
|
+++ b/arch/arm/kernel/perf_event_v7.c
|
|
@@ -773,10 +773,10 @@ static inline void armv7pmu_write_counter(struct perf_event *event, u64 value)
|
|
pr_err("CPU%u writing wrong counter %d\n",
|
|
smp_processor_id(), idx);
|
|
} else if (idx == ARMV7_IDX_CYCLE_COUNTER) {
|
|
- asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
|
|
+ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" ((u32)value));
|
|
} else {
|
|
armv7_pmnc_select_counter(idx);
|
|
- asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value));
|
|
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" ((u32)value));
|
|
}
|
|
}
|
|
|
|
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
|
|
index 48099c6e1e4a6..8aa7fa949c232 100644
|
|
--- a/arch/arm/kernel/smp.c
|
|
+++ b/arch/arm/kernel/smp.c
|
|
@@ -432,7 +432,6 @@ asmlinkage void secondary_start_kernel(void)
|
|
#endif
|
|
pr_debug("CPU%u: Booted secondary processor\n", cpu);
|
|
|
|
- preempt_disable();
|
|
trace_hardirqs_off();
|
|
|
|
/*
|
|
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
|
index a89e47d95eef2..879115dfdf828 100644
|
|
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
|
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
|
|
@@ -134,7 +134,7 @@
|
|
|
|
uart0: serial@12000 {
|
|
compatible = "marvell,armada-3700-uart";
|
|
- reg = <0x12000 0x200>;
|
|
+ reg = <0x12000 0x18>;
|
|
clocks = <&xtalclk>;
|
|
interrupts =
|
|
<GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
|
|
diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h
|
|
index f68a0e64482a1..5ef624fef44a2 100644
|
|
--- a/arch/arm64/include/asm/asm-uaccess.h
|
|
+++ b/arch/arm64/include/asm/asm-uaccess.h
|
|
@@ -15,10 +15,10 @@
|
|
.macro __uaccess_ttbr0_disable, tmp1
|
|
mrs \tmp1, ttbr1_el1 // swapper_pg_dir
|
|
bic \tmp1, \tmp1, #TTBR_ASID_MASK
|
|
- sub \tmp1, \tmp1, #RESERVED_TTBR0_SIZE // reserved_ttbr0 just before swapper_pg_dir
|
|
+ sub \tmp1, \tmp1, #PAGE_SIZE // reserved_pg_dir just before swapper_pg_dir
|
|
msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1
|
|
isb
|
|
- add \tmp1, \tmp1, #RESERVED_TTBR0_SIZE
|
|
+ add \tmp1, \tmp1, #PAGE_SIZE
|
|
msr ttbr1_el1, \tmp1 // set reserved ASID
|
|
isb
|
|
.endm
|
|
diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
|
|
index 19ca76ea60d98..587c504a4c8b2 100644
|
|
--- a/arch/arm64/include/asm/kernel-pgtable.h
|
|
+++ b/arch/arm64/include/asm/kernel-pgtable.h
|
|
@@ -89,12 +89,6 @@
|
|
#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end))
|
|
#define IDMAP_DIR_SIZE (IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
|
|
|
|
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
|
-#define RESERVED_TTBR0_SIZE (PAGE_SIZE)
|
|
-#else
|
|
-#define RESERVED_TTBR0_SIZE (0)
|
|
-#endif
|
|
-
|
|
/* Initial memory map size */
|
|
#if ARM64_SWAPPER_USES_SECTION_MAPS
|
|
#define SWAPPER_BLOCK_SHIFT SECTION_SHIFT
|
|
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
|
|
index 4e2ba94778450..5a54a5ab5f928 100644
|
|
--- a/arch/arm64/include/asm/mmu_context.h
|
|
+++ b/arch/arm64/include/asm/mmu_context.h
|
|
@@ -36,11 +36,11 @@ static inline void contextidr_thread_switch(struct task_struct *next)
|
|
}
|
|
|
|
/*
|
|
- * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0.
|
|
+ * Set TTBR0 to reserved_pg_dir. No translations will be possible via TTBR0.
|
|
*/
|
|
static inline void cpu_set_reserved_ttbr0(void)
|
|
{
|
|
- unsigned long ttbr = phys_to_ttbr(__pa_symbol(empty_zero_page));
|
|
+ unsigned long ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
|
|
|
|
write_sysreg(ttbr, ttbr0_el1);
|
|
isb();
|
|
@@ -192,9 +192,9 @@ static inline void update_saved_ttbr0(struct task_struct *tsk,
|
|
return;
|
|
|
|
if (mm == &init_mm)
|
|
- ttbr = __pa_symbol(empty_zero_page);
|
|
+ ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
|
|
else
|
|
- ttbr = virt_to_phys(mm->pgd) | ASID(mm) << 48;
|
|
+ ttbr = phys_to_ttbr(virt_to_phys(mm->pgd)) | ASID(mm) << 48;
|
|
|
|
WRITE_ONCE(task_thread_info(tsk)->ttbr0, ttbr);
|
|
}
|
|
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
|
|
index 717f13d52ecc5..10ffbc96ac31f 100644
|
|
--- a/arch/arm64/include/asm/pgtable.h
|
|
+++ b/arch/arm64/include/asm/pgtable.h
|
|
@@ -530,6 +530,7 @@ 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 pgd_t reserved_pg_dir[PTRS_PER_PGD];
|
|
|
|
extern void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd);
|
|
|
|
diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h
|
|
index 80e946b2abee2..e83f0982b99c1 100644
|
|
--- a/arch/arm64/include/asm/preempt.h
|
|
+++ b/arch/arm64/include/asm/preempt.h
|
|
@@ -23,7 +23,7 @@ static inline void preempt_count_set(u64 pc)
|
|
} while (0)
|
|
|
|
#define init_idle_preempt_count(p, cpu) do { \
|
|
- task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \
|
|
+ task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \
|
|
} while (0)
|
|
|
|
static inline void set_preempt_need_resched(void)
|
|
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
|
|
index 991dd5f031e46..385a189f7d39e 100644
|
|
--- a/arch/arm64/include/asm/uaccess.h
|
|
+++ b/arch/arm64/include/asm/uaccess.h
|
|
@@ -113,8 +113,8 @@ static inline void __uaccess_ttbr0_disable(void)
|
|
local_irq_save(flags);
|
|
ttbr = read_sysreg(ttbr1_el1);
|
|
ttbr &= ~TTBR_ASID_MASK;
|
|
- /* reserved_ttbr0 placed before swapper_pg_dir */
|
|
- write_sysreg(ttbr - RESERVED_TTBR0_SIZE, ttbr0_el1);
|
|
+ /* reserved_pg_dir placed before swapper_pg_dir */
|
|
+ write_sysreg(ttbr - PAGE_SIZE, ttbr0_el1);
|
|
isb();
|
|
/* Set reserved ASID */
|
|
write_sysreg(ttbr, ttbr1_el1);
|
|
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
|
|
index 60d3991233600..fe83d6d67ec3d 100644
|
|
--- a/arch/arm64/kernel/entry.S
|
|
+++ b/arch/arm64/kernel/entry.S
|
|
@@ -770,9 +770,10 @@ SYM_CODE_END(ret_to_user)
|
|
*/
|
|
.pushsection ".entry.tramp.text", "ax"
|
|
|
|
+ // Move from tramp_pg_dir to swapper_pg_dir
|
|
.macro tramp_map_kernel, tmp
|
|
mrs \tmp, ttbr1_el1
|
|
- add \tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
|
|
+ add \tmp, \tmp, #(2 * PAGE_SIZE)
|
|
bic \tmp, \tmp, #USER_ASID_FLAG
|
|
msr ttbr1_el1, \tmp
|
|
#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
|
|
@@ -789,9 +790,10 @@ alternative_else_nop_endif
|
|
#endif /* CONFIG_QCOM_FALKOR_ERRATUM_1003 */
|
|
.endm
|
|
|
|
+ // Move from swapper_pg_dir to tramp_pg_dir
|
|
.macro tramp_unmap_kernel, tmp
|
|
mrs \tmp, ttbr1_el1
|
|
- sub \tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
|
|
+ sub \tmp, \tmp, #(2 * PAGE_SIZE)
|
|
orr \tmp, \tmp, #USER_ASID_FLAG
|
|
msr ttbr1_el1, \tmp
|
|
/*
|
|
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
|
|
index 11852e05ee32a..cdb3d4549b3a9 100644
|
|
--- a/arch/arm64/kernel/perf_event.c
|
|
+++ b/arch/arm64/kernel/perf_event.c
|
|
@@ -312,7 +312,7 @@ static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
|
|
struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu);
|
|
u32 slots = cpu_pmu->reg_pmmir & ARMV8_PMU_SLOTS_MASK;
|
|
|
|
- return snprintf(page, PAGE_SIZE, "0x%08x\n", slots);
|
|
+ return sysfs_emit(page, "0x%08x\n", slots);
|
|
}
|
|
|
|
static DEVICE_ATTR_RO(slots);
|
|
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
|
|
index 133257ffd8591..eb4b24652c105 100644
|
|
--- a/arch/arm64/kernel/setup.c
|
|
+++ b/arch/arm64/kernel/setup.c
|
|
@@ -366,7 +366,7 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
|
|
* faults in case uaccess_enable() is inadvertently called by the init
|
|
* thread.
|
|
*/
|
|
- init_task.thread_info.ttbr0 = __pa_symbol(empty_zero_page);
|
|
+ init_task.thread_info.ttbr0 = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
|
|
#endif
|
|
|
|
if (boot_args[1] || boot_args[2] || boot_args[3]) {
|
|
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
|
|
index 18e9727d3f645..feee5a3cd1288 100644
|
|
--- a/arch/arm64/kernel/smp.c
|
|
+++ b/arch/arm64/kernel/smp.c
|
|
@@ -223,7 +223,6 @@ asmlinkage notrace void secondary_start_kernel(void)
|
|
init_gic_priority_masking();
|
|
|
|
rcu_cpu_starting(cpu);
|
|
- preempt_disable();
|
|
trace_hardirqs_off();
|
|
|
|
/*
|
|
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
|
|
index 1bda604f4c704..30c1029789427 100644
|
|
--- a/arch/arm64/kernel/vmlinux.lds.S
|
|
+++ b/arch/arm64/kernel/vmlinux.lds.S
|
|
@@ -164,13 +164,11 @@ SECTIONS
|
|
. += PAGE_SIZE;
|
|
#endif
|
|
|
|
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
|
- reserved_ttbr0 = .;
|
|
- . += RESERVED_TTBR0_SIZE;
|
|
-#endif
|
|
+ reserved_pg_dir = .;
|
|
+ . += PAGE_SIZE;
|
|
+
|
|
swapper_pg_dir = .;
|
|
. += PAGE_SIZE;
|
|
- swapper_pg_end = .;
|
|
|
|
. = ALIGN(SEGMENT_ALIGN);
|
|
__init_begin = .;
|
|
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
|
|
index 2dd164bb1c5a9..4b30260e1abf4 100644
|
|
--- a/arch/arm64/kvm/pmu-emul.c
|
|
+++ b/arch/arm64/kvm/pmu-emul.c
|
|
@@ -578,6 +578,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
|
|
kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0);
|
|
|
|
if (val & ARMV8_PMU_PMCR_P) {
|
|
+ mask &= ~BIT(ARMV8_PMU_CYCLE_IDX);
|
|
for_each_set_bit(i, &mask, 32)
|
|
kvm_pmu_set_counter_value(vcpu, i, 0);
|
|
}
|
|
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
|
|
index a14927360be26..aacc7eab9b2ff 100644
|
|
--- a/arch/arm64/mm/proc.S
|
|
+++ b/arch/arm64/mm/proc.S
|
|
@@ -168,7 +168,7 @@ SYM_FUNC_END(cpu_do_resume)
|
|
.pushsection ".idmap.text", "awx"
|
|
|
|
.macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2
|
|
- adrp \tmp1, empty_zero_page
|
|
+ adrp \tmp1, reserved_pg_dir
|
|
phys_to_ttbr \tmp2, \tmp1
|
|
offset_ttbr1 \tmp2, \tmp1
|
|
msr ttbr1_el1, \tmp2
|
|
diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c
|
|
index 041d0de6a1b67..1a8d7eaf1ff71 100644
|
|
--- a/arch/csky/kernel/smp.c
|
|
+++ b/arch/csky/kernel/smp.c
|
|
@@ -282,7 +282,6 @@ void csky_start_secondary(void)
|
|
pr_info("CPU%u Online: %s...\n", cpu, __func__);
|
|
|
|
local_irq_enable();
|
|
- preempt_disable();
|
|
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
|
|
}
|
|
|
|
diff --git a/arch/csky/mm/syscache.c b/arch/csky/mm/syscache.c
|
|
index ffade2f9a4c87..cd847ad62c7ee 100644
|
|
--- a/arch/csky/mm/syscache.c
|
|
+++ b/arch/csky/mm/syscache.c
|
|
@@ -12,14 +12,17 @@ SYSCALL_DEFINE3(cacheflush,
|
|
int, cache)
|
|
{
|
|
switch (cache) {
|
|
- case ICACHE:
|
|
case BCACHE:
|
|
- flush_icache_mm_range(current->mm,
|
|
- (unsigned long)addr,
|
|
- (unsigned long)addr + bytes);
|
|
case DCACHE:
|
|
dcache_wb_range((unsigned long)addr,
|
|
(unsigned long)addr + bytes);
|
|
+ if (cache != BCACHE)
|
|
+ break;
|
|
+ fallthrough;
|
|
+ case ICACHE:
|
|
+ flush_icache_mm_range(current->mm,
|
|
+ (unsigned long)addr,
|
|
+ (unsigned long)addr + bytes);
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
|
|
index 4d0ab323dee8c..2a40268c3d494 100644
|
|
--- a/arch/ia64/kernel/mca_drv.c
|
|
+++ b/arch/ia64/kernel/mca_drv.c
|
|
@@ -343,7 +343,7 @@ init_record_index_pools(void)
|
|
|
|
/* - 2 - */
|
|
sect_min_size = sal_log_sect_min_sizes[0];
|
|
- for (i = 1; i < sizeof sal_log_sect_min_sizes/sizeof(size_t); i++)
|
|
+ for (i = 1; i < ARRAY_SIZE(sal_log_sect_min_sizes); i++)
|
|
if (sect_min_size > sal_log_sect_min_sizes[i])
|
|
sect_min_size = sal_log_sect_min_sizes[i];
|
|
|
|
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
|
|
index 093040f7e626a..0cad990385c04 100644
|
|
--- a/arch/ia64/kernel/smpboot.c
|
|
+++ b/arch/ia64/kernel/smpboot.c
|
|
@@ -440,7 +440,6 @@ start_secondary (void *unused)
|
|
#endif
|
|
efi_map_pal_code();
|
|
cpu_init();
|
|
- preempt_disable();
|
|
smp_callin();
|
|
|
|
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
|
|
diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
|
|
index 17e8c3a292d77..e161a4e1493b4 100644
|
|
--- a/arch/m68k/Kconfig.machine
|
|
+++ b/arch/m68k/Kconfig.machine
|
|
@@ -23,6 +23,9 @@ config ATARI
|
|
this kernel on an Atari, say Y here and browse the material
|
|
available in <file:Documentation/m68k>; otherwise say N.
|
|
|
|
+config ATARI_KBD_CORE
|
|
+ bool
|
|
+
|
|
config MAC
|
|
bool "Macintosh support"
|
|
depends on MMU
|
|
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
|
|
index f1f788b571666..9f021cf51aa71 100644
|
|
--- a/arch/mips/include/asm/highmem.h
|
|
+++ b/arch/mips/include/asm/highmem.h
|
|
@@ -36,7 +36,7 @@ extern pte_t *pkmap_page_table;
|
|
* easily, subsequent pte tables have to be allocated in one physical
|
|
* chunk of RAM.
|
|
*/
|
|
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
|
+#if defined(CONFIG_PHYS_ADDR_T_64BIT) || defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
|
|
#define LAST_PKMAP 512
|
|
#else
|
|
#define LAST_PKMAP 1024
|
|
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
|
|
index 48d84d5fcc361..ff25926c5458c 100644
|
|
--- a/arch/mips/kernel/smp.c
|
|
+++ b/arch/mips/kernel/smp.c
|
|
@@ -348,7 +348,6 @@ asmlinkage void start_secondary(void)
|
|
*/
|
|
|
|
calibrate_delay();
|
|
- preempt_disable();
|
|
cpu = smp_processor_id();
|
|
cpu_data[cpu].udelay_val = loops_per_jiffy;
|
|
|
|
diff --git a/arch/openrisc/kernel/smp.c b/arch/openrisc/kernel/smp.c
|
|
index 29c82ef2e207c..e4dad76066aed 100644
|
|
--- a/arch/openrisc/kernel/smp.c
|
|
+++ b/arch/openrisc/kernel/smp.c
|
|
@@ -134,8 +134,6 @@ asmlinkage __init void secondary_start_kernel(void)
|
|
set_cpu_online(cpu, true);
|
|
|
|
local_irq_enable();
|
|
-
|
|
- preempt_disable();
|
|
/*
|
|
* OK, it's off to the idle thread for us
|
|
*/
|
|
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
|
|
index 10227f667c8a6..1405b603b91b6 100644
|
|
--- a/arch/parisc/kernel/smp.c
|
|
+++ b/arch/parisc/kernel/smp.c
|
|
@@ -302,7 +302,6 @@ void __init smp_callin(unsigned long pdce_proc)
|
|
#endif
|
|
|
|
smp_cpu_init(slave_id);
|
|
- preempt_disable();
|
|
|
|
flush_cache_all_local(); /* start with known state */
|
|
flush_tlb_all_local(NULL);
|
|
diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h
|
|
index 98c8bd155bf9d..b167186aaee4a 100644
|
|
--- a/arch/powerpc/include/asm/cputhreads.h
|
|
+++ b/arch/powerpc/include/asm/cputhreads.h
|
|
@@ -98,6 +98,36 @@ static inline int cpu_last_thread_sibling(int cpu)
|
|
return cpu | (threads_per_core - 1);
|
|
}
|
|
|
|
+/*
|
|
+ * tlb_thread_siblings are siblings which share a TLB. This is not
|
|
+ * architected, is not something a hypervisor could emulate and a future
|
|
+ * CPU may change behaviour even in compat mode, so this should only be
|
|
+ * used on PowerNV, and only with care.
|
|
+ */
|
|
+static inline int cpu_first_tlb_thread_sibling(int cpu)
|
|
+{
|
|
+ if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
|
|
+ return cpu & ~0x6; /* Big Core */
|
|
+ else
|
|
+ return cpu_first_thread_sibling(cpu);
|
|
+}
|
|
+
|
|
+static inline int cpu_last_tlb_thread_sibling(int cpu)
|
|
+{
|
|
+ if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
|
|
+ return cpu | 0x6; /* Big Core */
|
|
+ else
|
|
+ return cpu_last_thread_sibling(cpu);
|
|
+}
|
|
+
|
|
+static inline int cpu_tlb_thread_sibling_step(void)
|
|
+{
|
|
+ if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
|
|
+ return 2; /* Big Core */
|
|
+ else
|
|
+ return 1;
|
|
+}
|
|
+
|
|
static inline u32 get_tensr(void)
|
|
{
|
|
#ifdef CONFIG_BOOKE
|
|
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
|
|
index b7e173754a2e9..ea8b002820cec 100644
|
|
--- a/arch/powerpc/kernel/mce_power.c
|
|
+++ b/arch/powerpc/kernel/mce_power.c
|
|
@@ -475,12 +475,11 @@ static int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr,
|
|
return -1;
|
|
}
|
|
|
|
-static int mce_handle_ierror(struct pt_regs *regs,
|
|
+static int mce_handle_ierror(struct pt_regs *regs, unsigned long srr1,
|
|
const struct mce_ierror_table table[],
|
|
struct mce_error_info *mce_err, uint64_t *addr,
|
|
uint64_t *phys_addr)
|
|
{
|
|
- uint64_t srr1 = regs->msr;
|
|
int handled = 0;
|
|
int i;
|
|
|
|
@@ -683,19 +682,19 @@ static long mce_handle_ue_error(struct pt_regs *regs,
|
|
}
|
|
|
|
static long mce_handle_error(struct pt_regs *regs,
|
|
+ unsigned long srr1,
|
|
const struct mce_derror_table dtable[],
|
|
const struct mce_ierror_table itable[])
|
|
{
|
|
struct mce_error_info mce_err = { 0 };
|
|
uint64_t addr, phys_addr = ULONG_MAX;
|
|
- uint64_t srr1 = regs->msr;
|
|
long handled;
|
|
|
|
if (SRR1_MC_LOADSTORE(srr1))
|
|
handled = mce_handle_derror(regs, dtable, &mce_err, &addr,
|
|
&phys_addr);
|
|
else
|
|
- handled = mce_handle_ierror(regs, itable, &mce_err, &addr,
|
|
+ handled = mce_handle_ierror(regs, srr1, itable, &mce_err, &addr,
|
|
&phys_addr);
|
|
|
|
if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE)
|
|
@@ -711,16 +710,20 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs)
|
|
/* P7 DD1 leaves top bits of DSISR undefined */
|
|
regs->dsisr &= 0x0000ffff;
|
|
|
|
- return mce_handle_error(regs, mce_p7_derror_table, mce_p7_ierror_table);
|
|
+ return mce_handle_error(regs, regs->msr,
|
|
+ mce_p7_derror_table, mce_p7_ierror_table);
|
|
}
|
|
|
|
long __machine_check_early_realmode_p8(struct pt_regs *regs)
|
|
{
|
|
- return mce_handle_error(regs, mce_p8_derror_table, mce_p8_ierror_table);
|
|
+ return mce_handle_error(regs, regs->msr,
|
|
+ mce_p8_derror_table, mce_p8_ierror_table);
|
|
}
|
|
|
|
long __machine_check_early_realmode_p9(struct pt_regs *regs)
|
|
{
|
|
+ unsigned long srr1 = regs->msr;
|
|
+
|
|
/*
|
|
* On POWER9 DD2.1 and below, it's possible to get a machine check
|
|
* caused by a paste instruction where only DSISR bit 25 is set. This
|
|
@@ -734,10 +737,39 @@ long __machine_check_early_realmode_p9(struct pt_regs *regs)
|
|
if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000)
|
|
return 1;
|
|
|
|
- return mce_handle_error(regs, mce_p9_derror_table, mce_p9_ierror_table);
|
|
+ /*
|
|
+ * Async machine check due to bad real address from store or foreign
|
|
+ * link time out comes with the load/store bit (PPC bit 42) set in
|
|
+ * SRR1, but the cause comes in SRR1 not DSISR. Clear bit 42 so we're
|
|
+ * directed to the ierror table so it will find the cause (which
|
|
+ * describes it correctly as a store error).
|
|
+ */
|
|
+ if (SRR1_MC_LOADSTORE(srr1) &&
|
|
+ ((srr1 & 0x081c0000) == 0x08140000 ||
|
|
+ (srr1 & 0x081c0000) == 0x08180000)) {
|
|
+ srr1 &= ~PPC_BIT(42);
|
|
+ }
|
|
+
|
|
+ return mce_handle_error(regs, srr1,
|
|
+ mce_p9_derror_table, mce_p9_ierror_table);
|
|
}
|
|
|
|
long __machine_check_early_realmode_p10(struct pt_regs *regs)
|
|
{
|
|
- return mce_handle_error(regs, mce_p10_derror_table, mce_p10_ierror_table);
|
|
+ unsigned long srr1 = regs->msr;
|
|
+
|
|
+ /*
|
|
+ * Async machine check due to bad real address from store comes with
|
|
+ * the load/store bit (PPC bit 42) set in SRR1, but the cause comes in
|
|
+ * SRR1 not DSISR. Clear bit 42 so we're directed to the ierror table
|
|
+ * so it will find the cause (which describes it correctly as a store
|
|
+ * error).
|
|
+ */
|
|
+ if (SRR1_MC_LOADSTORE(srr1) &&
|
|
+ (srr1 & 0x081c0000) == 0x08140000) {
|
|
+ srr1 &= ~PPC_BIT(42);
|
|
+ }
|
|
+
|
|
+ return mce_handle_error(regs, srr1,
|
|
+ mce_p10_derror_table, mce_p10_ierror_table);
|
|
}
|
|
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
|
|
index 1a1d2657fe8dd..3064694afea17 100644
|
|
--- a/arch/powerpc/kernel/process.c
|
|
+++ b/arch/powerpc/kernel/process.c
|
|
@@ -1227,6 +1227,19 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
|
__flush_tlb_pending(batch);
|
|
batch->active = 0;
|
|
}
|
|
+
|
|
+ /*
|
|
+ * On POWER9 the copy-paste buffer can only paste into
|
|
+ * foreign real addresses, so unprivileged processes can not
|
|
+ * see the data or use it in any way unless they have
|
|
+ * foreign real mappings. If the new process has the foreign
|
|
+ * real address mappings, we must issue a cp_abort to clear
|
|
+ * any state and prevent snooping, corruption or a covert
|
|
+ * channel. ISA v3.1 supports paste into local memory.
|
|
+ */
|
|
+ if (new->mm && (cpu_has_feature(CPU_FTR_ARCH_31) ||
|
|
+ atomic_read(&new->mm->context.vas_windows)))
|
|
+ asm volatile(PPC_CP_ABORT);
|
|
#endif /* CONFIG_PPC_BOOK3S_64 */
|
|
|
|
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
|
|
@@ -1272,30 +1285,33 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
|
|
|
last = _switch(old_thread, new_thread);
|
|
|
|
+ /*
|
|
+ * Nothing after _switch will be run for newly created tasks,
|
|
+ * because they switch directly to ret_from_fork/ret_from_kernel_thread
|
|
+ * etc. Code added here should have a comment explaining why that is
|
|
+ * okay.
|
|
+ */
|
|
+
|
|
#ifdef CONFIG_PPC_BOOK3S_64
|
|
+ /*
|
|
+ * This applies to a process that was context switched while inside
|
|
+ * arch_enter_lazy_mmu_mode(), to re-activate the batch that was
|
|
+ * deactivated above, before _switch(). This will never be the case
|
|
+ * for new tasks.
|
|
+ */
|
|
if (current_thread_info()->local_flags & _TLF_LAZY_MMU) {
|
|
current_thread_info()->local_flags &= ~_TLF_LAZY_MMU;
|
|
batch = this_cpu_ptr(&ppc64_tlb_batch);
|
|
batch->active = 1;
|
|
}
|
|
|
|
- if (current->thread.regs) {
|
|
+ /*
|
|
+ * Math facilities are masked out of the child MSR in copy_thread.
|
|
+ * A new task does not need to restore_math because it will
|
|
+ * demand fault them.
|
|
+ */
|
|
+ if (current->thread.regs)
|
|
restore_math(current->thread.regs);
|
|
-
|
|
- /*
|
|
- * On POWER9 the copy-paste buffer can only paste into
|
|
- * foreign real addresses, so unprivileged processes can not
|
|
- * see the data or use it in any way unless they have
|
|
- * foreign real mappings. If the new process has the foreign
|
|
- * real address mappings, we must issue a cp_abort to clear
|
|
- * any state and prevent snooping, corruption or a covert
|
|
- * channel. ISA v3.1 supports paste into local memory.
|
|
- */
|
|
- if (current->mm &&
|
|
- (cpu_has_feature(CPU_FTR_ARCH_31) ||
|
|
- atomic_read(¤t->mm->context.vas_windows)))
|
|
- asm volatile(PPC_CP_ABORT);
|
|
- }
|
|
#endif /* CONFIG_PPC_BOOK3S_64 */
|
|
|
|
return last;
|
|
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
|
|
index db7ac77bea3a7..26a028a9233af 100644
|
|
--- a/arch/powerpc/kernel/smp.c
|
|
+++ b/arch/powerpc/kernel/smp.c
|
|
@@ -600,6 +600,8 @@ static void nmi_stop_this_cpu(struct pt_regs *regs)
|
|
/*
|
|
* IRQs are already hard disabled by the smp_handle_nmi_ipi.
|
|
*/
|
|
+ set_cpu_online(smp_processor_id(), false);
|
|
+
|
|
spin_begin();
|
|
while (1)
|
|
spin_cpu_relax();
|
|
@@ -615,6 +617,15 @@ void smp_send_stop(void)
|
|
static void stop_this_cpu(void *dummy)
|
|
{
|
|
hard_irq_disable();
|
|
+
|
|
+ /*
|
|
+ * Offlining CPUs in stop_this_cpu can result in scheduler warnings,
|
|
+ * (see commit de6e5d38417e), but printk_safe_flush_on_panic() wants
|
|
+ * to know other CPUs are offline before it breaks locks to flush
|
|
+ * printk buffers, in case we panic()ed while holding the lock.
|
|
+ */
|
|
+ set_cpu_online(smp_processor_id(), false);
|
|
+
|
|
spin_begin();
|
|
while (1)
|
|
spin_cpu_relax();
|
|
@@ -1426,7 +1437,6 @@ void start_secondary(void *unused)
|
|
smp_store_cpu_info(cpu);
|
|
set_dec(tb_ticks_per_jiffy);
|
|
rcu_cpu_starting(cpu);
|
|
- preempt_disable();
|
|
cpu_callin_map[cpu] = 1;
|
|
|
|
if (smp_ops->setup_cpu)
|
|
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
|
|
index b6440657ef92d..2f926ea9b7b94 100644
|
|
--- a/arch/powerpc/kernel/stacktrace.c
|
|
+++ b/arch/powerpc/kernel/stacktrace.c
|
|
@@ -19,6 +19,7 @@
|
|
#include <asm/ptrace.h>
|
|
#include <asm/processor.h>
|
|
#include <linux/ftrace.h>
|
|
+#include <linux/delay.h>
|
|
#include <asm/kprobes.h>
|
|
|
|
#include <asm/paca.h>
|
|
@@ -230,17 +231,31 @@ static void handle_backtrace_ipi(struct pt_regs *regs)
|
|
|
|
static void raise_backtrace_ipi(cpumask_t *mask)
|
|
{
|
|
+ struct paca_struct *p;
|
|
unsigned int cpu;
|
|
+ u64 delay_us;
|
|
|
|
for_each_cpu(cpu, mask) {
|
|
- if (cpu == smp_processor_id())
|
|
+ if (cpu == smp_processor_id()) {
|
|
handle_backtrace_ipi(NULL);
|
|
- else
|
|
- smp_send_safe_nmi_ipi(cpu, handle_backtrace_ipi, 5 * USEC_PER_SEC);
|
|
- }
|
|
+ continue;
|
|
+ }
|
|
|
|
- for_each_cpu(cpu, mask) {
|
|
- struct paca_struct *p = paca_ptrs[cpu];
|
|
+ delay_us = 5 * USEC_PER_SEC;
|
|
+
|
|
+ if (smp_send_safe_nmi_ipi(cpu, handle_backtrace_ipi, delay_us)) {
|
|
+ // Now wait up to 5s for the other CPU to do its backtrace
|
|
+ while (cpumask_test_cpu(cpu, mask) && delay_us) {
|
|
+ udelay(1);
|
|
+ delay_us--;
|
|
+ }
|
|
+
|
|
+ // Other CPU cleared itself from the mask
|
|
+ if (delay_us)
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ p = paca_ptrs[cpu];
|
|
|
|
cpumask_clear_cpu(cpu, mask);
|
|
|
|
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
|
|
index 965b702208d85..2325b7a6e95f8 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv.c
|
|
+++ b/arch/powerpc/kvm/book3s_hv.c
|
|
@@ -2578,7 +2578,7 @@ static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu)
|
|
cpumask_t *cpu_in_guest;
|
|
int i;
|
|
|
|
- cpu = cpu_first_thread_sibling(cpu);
|
|
+ cpu = cpu_first_tlb_thread_sibling(cpu);
|
|
if (nested) {
|
|
cpumask_set_cpu(cpu, &nested->need_tlb_flush);
|
|
cpu_in_guest = &nested->cpu_in_guest;
|
|
@@ -2592,9 +2592,10 @@ static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu)
|
|
* the other side is the first smp_mb() in kvmppc_run_core().
|
|
*/
|
|
smp_mb();
|
|
- for (i = 0; i < threads_per_core; ++i)
|
|
- if (cpumask_test_cpu(cpu + i, cpu_in_guest))
|
|
- smp_call_function_single(cpu + i, do_nothing, NULL, 1);
|
|
+ for (i = cpu; i <= cpu_last_tlb_thread_sibling(cpu);
|
|
+ i += cpu_tlb_thread_sibling_step())
|
|
+ if (cpumask_test_cpu(i, cpu_in_guest))
|
|
+ smp_call_function_single(i, do_nothing, NULL, 1);
|
|
}
|
|
|
|
static void kvmppc_prepare_radix_vcpu(struct kvm_vcpu *vcpu, int pcpu)
|
|
@@ -2625,8 +2626,8 @@ static void kvmppc_prepare_radix_vcpu(struct kvm_vcpu *vcpu, int pcpu)
|
|
*/
|
|
if (prev_cpu != pcpu) {
|
|
if (prev_cpu >= 0 &&
|
|
- cpu_first_thread_sibling(prev_cpu) !=
|
|
- cpu_first_thread_sibling(pcpu))
|
|
+ cpu_first_tlb_thread_sibling(prev_cpu) !=
|
|
+ cpu_first_tlb_thread_sibling(pcpu))
|
|
radix_flush_cpu(kvm, prev_cpu, vcpu);
|
|
if (nested)
|
|
nested->prev_cpu[vcpu->arch.nested_vcpu_id] = pcpu;
|
|
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
|
|
index 8f58dd20b362a..4621905bdd9ea 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
|
|
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
|
|
@@ -893,7 +893,7 @@ void kvmppc_check_need_tlb_flush(struct kvm *kvm, int pcpu,
|
|
* Thus we make all 4 threads use the same bit.
|
|
*/
|
|
if (cpu_has_feature(CPU_FTR_ARCH_300))
|
|
- pcpu = cpu_first_thread_sibling(pcpu);
|
|
+ pcpu = cpu_first_tlb_thread_sibling(pcpu);
|
|
|
|
if (nested)
|
|
need_tlb_flush = &nested->need_tlb_flush;
|
|
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
|
|
index 33b58549a9aaf..065738819db9b 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv_nested.c
|
|
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
|
|
@@ -51,7 +51,8 @@ void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
|
|
hr->ppr = vcpu->arch.ppr;
|
|
}
|
|
|
|
-static void byteswap_pt_regs(struct pt_regs *regs)
|
|
+/* Use noinline_for_stack due to https://bugs.llvm.org/show_bug.cgi?id=49610 */
|
|
+static noinline_for_stack void byteswap_pt_regs(struct pt_regs *regs)
|
|
{
|
|
unsigned long *addr = (unsigned long *) regs;
|
|
|
|
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
|
|
index 88da2764c1bb9..3ddc83d2e8493 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
|
|
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
|
|
@@ -67,7 +67,7 @@ static int global_invalidates(struct kvm *kvm)
|
|
* so use the bit for the first thread to represent the core.
|
|
*/
|
|
if (cpu_has_feature(CPU_FTR_ARCH_300))
|
|
- cpu = cpu_first_thread_sibling(cpu);
|
|
+ cpu = cpu_first_tlb_thread_sibling(cpu);
|
|
cpumask_clear_cpu(cpu, &kvm->arch.need_tlb_flush);
|
|
}
|
|
|
|
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
|
|
index c855a0aeb49cc..d7ab868aab54a 100644
|
|
--- a/arch/powerpc/platforms/cell/smp.c
|
|
+++ b/arch/powerpc/platforms/cell/smp.c
|
|
@@ -78,9 +78,6 @@ static inline int smp_startup_cpu(unsigned int lcpu)
|
|
|
|
pcpu = get_hard_smp_processor_id(lcpu);
|
|
|
|
- /* Fixup atomic count: it exited inside IRQ handler. */
|
|
- task_thread_info(paca_ptrs[lcpu]->__current)->preempt_count = 0;
|
|
-
|
|
/*
|
|
* If the RTAS start-cpu token does not exist then presume the
|
|
* cpu is already spinning.
|
|
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
|
|
index 835163f54244a..057acbb9116dd 100644
|
|
--- a/arch/powerpc/platforms/pseries/papr_scm.c
|
|
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
|
|
@@ -18,6 +18,7 @@
|
|
#include <asm/plpar_wrappers.h>
|
|
#include <asm/papr_pdsm.h>
|
|
#include <asm/mce.h>
|
|
+#include <asm/unaligned.h>
|
|
|
|
#define BIND_ANY_ADDR (~0ul)
|
|
|
|
@@ -867,6 +868,20 @@ static ssize_t flags_show(struct device *dev,
|
|
}
|
|
DEVICE_ATTR_RO(flags);
|
|
|
|
+static umode_t papr_nd_attribute_visible(struct kobject *kobj,
|
|
+ struct attribute *attr, int n)
|
|
+{
|
|
+ struct device *dev = kobj_to_dev(kobj);
|
|
+ struct nvdimm *nvdimm = to_nvdimm(dev);
|
|
+ struct papr_scm_priv *p = nvdimm_provider_data(nvdimm);
|
|
+
|
|
+ /* For if perf-stats not available remove perf_stats sysfs */
|
|
+ if (attr == &dev_attr_perf_stats.attr && p->stat_buffer_len == 0)
|
|
+ return 0;
|
|
+
|
|
+ return attr->mode;
|
|
+}
|
|
+
|
|
/* papr_scm specific dimm attributes */
|
|
static struct attribute *papr_nd_attributes[] = {
|
|
&dev_attr_flags.attr,
|
|
@@ -876,6 +891,7 @@ static struct attribute *papr_nd_attributes[] = {
|
|
|
|
static struct attribute_group papr_nd_attribute_group = {
|
|
.name = "papr",
|
|
+ .is_visible = papr_nd_attribute_visible,
|
|
.attrs = papr_nd_attributes,
|
|
};
|
|
|
|
@@ -891,7 +907,6 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
|
|
struct nd_region_desc ndr_desc;
|
|
unsigned long dimm_flags;
|
|
int target_nid, online_nid;
|
|
- ssize_t stat_size;
|
|
|
|
p->bus_desc.ndctl = papr_scm_ndctl;
|
|
p->bus_desc.module = THIS_MODULE;
|
|
@@ -962,16 +977,6 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
|
|
list_add_tail(&p->region_list, &papr_nd_regions);
|
|
mutex_unlock(&papr_ndr_lock);
|
|
|
|
- /* Try retriving the stat buffer and see if its supported */
|
|
- stat_size = drc_pmem_query_stats(p, NULL, 0);
|
|
- if (stat_size > 0) {
|
|
- p->stat_buffer_len = stat_size;
|
|
- dev_dbg(&p->pdev->dev, "Max perf-stat size %lu-bytes\n",
|
|
- p->stat_buffer_len);
|
|
- } else {
|
|
- dev_info(&p->pdev->dev, "Dimm performance stats unavailable\n");
|
|
- }
|
|
-
|
|
return 0;
|
|
|
|
err: nvdimm_bus_unregister(p->bus);
|
|
@@ -1047,8 +1052,10 @@ static int papr_scm_probe(struct platform_device *pdev)
|
|
u32 drc_index, metadata_size;
|
|
u64 blocks, block_size;
|
|
struct papr_scm_priv *p;
|
|
+ u8 uuid_raw[UUID_SIZE];
|
|
const char *uuid_str;
|
|
- u64 uuid[2];
|
|
+ ssize_t stat_size;
|
|
+ uuid_t uuid;
|
|
int rc;
|
|
|
|
/* check we have all the required DT properties */
|
|
@@ -1090,16 +1097,23 @@ static int papr_scm_probe(struct platform_device *pdev)
|
|
p->is_volatile = !of_property_read_bool(dn, "ibm,cache-flush-required");
|
|
|
|
/* We just need to ensure that set cookies are unique across */
|
|
- uuid_parse(uuid_str, (uuid_t *) uuid);
|
|
+ uuid_parse(uuid_str, &uuid);
|
|
+
|
|
/*
|
|
- * cookie1 and cookie2 are not really little endian
|
|
- * we store a little endian representation of the
|
|
- * uuid str so that we can compare this with the label
|
|
- * area cookie irrespective of the endian config with which
|
|
- * the kernel is built.
|
|
+ * The cookie1 and cookie2 are not really little endian.
|
|
+ * We store a raw buffer representation of the
|
|
+ * uuid string so that we can compare this with the label
|
|
+ * area cookie irrespective of the endian configuration
|
|
+ * with which the kernel is built.
|
|
+ *
|
|
+ * Historically we stored the cookie in the below format.
|
|
+ * for a uuid string 72511b67-0b3b-42fd-8d1d-5be3cae8bcaa
|
|
+ * cookie1 was 0xfd423b0b671b5172
|
|
+ * cookie2 was 0xaabce8cae35b1d8d
|
|
*/
|
|
- p->nd_set.cookie1 = cpu_to_le64(uuid[0]);
|
|
- p->nd_set.cookie2 = cpu_to_le64(uuid[1]);
|
|
+ export_uuid(uuid_raw, &uuid);
|
|
+ p->nd_set.cookie1 = get_unaligned_le64(&uuid_raw[0]);
|
|
+ p->nd_set.cookie2 = get_unaligned_le64(&uuid_raw[8]);
|
|
|
|
/* might be zero */
|
|
p->metadata_size = metadata_size;
|
|
@@ -1124,6 +1138,14 @@ static int papr_scm_probe(struct platform_device *pdev)
|
|
p->res.name = pdev->name;
|
|
p->res.flags = IORESOURCE_MEM;
|
|
|
|
+ /* Try retrieving the stat buffer and see if its supported */
|
|
+ stat_size = drc_pmem_query_stats(p, NULL, 0);
|
|
+ if (stat_size > 0) {
|
|
+ p->stat_buffer_len = stat_size;
|
|
+ dev_dbg(&p->pdev->dev, "Max perf-stat size %lu-bytes\n",
|
|
+ p->stat_buffer_len);
|
|
+ }
|
|
+
|
|
rc = papr_scm_nvdimm_init(p);
|
|
if (rc)
|
|
goto err2;
|
|
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
|
|
index 92922491a81c6..624e80b00eb18 100644
|
|
--- a/arch/powerpc/platforms/pseries/smp.c
|
|
+++ b/arch/powerpc/platforms/pseries/smp.c
|
|
@@ -104,9 +104,6 @@ static inline int smp_startup_cpu(unsigned int lcpu)
|
|
return 1;
|
|
}
|
|
|
|
- /* Fixup atomic count: it exited inside IRQ handler. */
|
|
- task_thread_info(paca_ptrs[lcpu]->__current)->preempt_count = 0;
|
|
-
|
|
/*
|
|
* If the RTAS start-cpu token does not exist then presume the
|
|
* cpu is already spinning.
|
|
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
|
|
index 96167d55ed984..0b04e0eae3ab5 100644
|
|
--- a/arch/riscv/kernel/smpboot.c
|
|
+++ b/arch/riscv/kernel/smpboot.c
|
|
@@ -166,7 +166,6 @@ asmlinkage __visible void smp_callin(void)
|
|
* Disable preemption before enabling interrupts, so we don't try to
|
|
* schedule a CPU that hasn't actually started yet.
|
|
*/
|
|
- preempt_disable();
|
|
local_irq_enable();
|
|
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
|
|
}
|
|
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
|
|
index 4a2a12be04c96..896b68e541b2e 100644
|
|
--- a/arch/s390/Kconfig
|
|
+++ b/arch/s390/Kconfig
|
|
@@ -154,6 +154,8 @@ config S390
|
|
select HAVE_FUTEX_CMPXCHG if FUTEX
|
|
select HAVE_GCC_PLUGINS
|
|
select HAVE_GENERIC_VDSO
|
|
+ select HAVE_IOREMAP_PROT if PCI
|
|
+ select HAVE_IRQ_EXIT_ON_IRQ_STACK
|
|
select HAVE_KERNEL_BZIP2
|
|
select HAVE_KERNEL_GZIP
|
|
select HAVE_KERNEL_LZ4
|
|
@@ -856,7 +858,7 @@ config CMM_IUCV
|
|
config APPLDATA_BASE
|
|
def_bool n
|
|
prompt "Linux - VM Monitor Stream, base infrastructure"
|
|
- depends on PROC_FS
|
|
+ depends on PROC_SYSCTL
|
|
help
|
|
This provides a kernel interface for creating and updating z/VM APPLDATA
|
|
monitor records. The monitor records are updated at certain time
|
|
diff --git a/arch/s390/boot/uv.c b/arch/s390/boot/uv.c
|
|
index 87641dd65ccf9..b3501ea5039e4 100644
|
|
--- a/arch/s390/boot/uv.c
|
|
+++ b/arch/s390/boot/uv.c
|
|
@@ -36,6 +36,7 @@ void uv_query_info(void)
|
|
uv_info.max_sec_stor_addr = ALIGN(uvcb.max_guest_stor_addr, PAGE_SIZE);
|
|
uv_info.max_num_sec_conf = uvcb.max_num_sec_conf;
|
|
uv_info.max_guest_cpu_id = uvcb.max_guest_cpu_id;
|
|
+ uv_info.uv_feature_indications = uvcb.uv_feature_indications;
|
|
}
|
|
|
|
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
|
|
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
|
|
index b5dbae78969b9..2338345912a31 100644
|
|
--- a/arch/s390/include/asm/pgtable.h
|
|
+++ b/arch/s390/include/asm/pgtable.h
|
|
@@ -864,6 +864,25 @@ static inline int pte_unused(pte_t pte)
|
|
return pte_val(pte) & _PAGE_UNUSED;
|
|
}
|
|
|
|
+/*
|
|
+ * Extract the pgprot value from the given pte while at the same time making it
|
|
+ * usable for kernel address space mappings where fault driven dirty and
|
|
+ * young/old accounting is not supported, i.e _PAGE_PROTECT and _PAGE_INVALID
|
|
+ * must not be set.
|
|
+ */
|
|
+static inline pgprot_t pte_pgprot(pte_t pte)
|
|
+{
|
|
+ unsigned long pte_flags = pte_val(pte) & _PAGE_CHG_MASK;
|
|
+
|
|
+ if (pte_write(pte))
|
|
+ pte_flags |= pgprot_val(PAGE_KERNEL);
|
|
+ else
|
|
+ pte_flags |= pgprot_val(PAGE_KERNEL_RO);
|
|
+ pte_flags |= pte_val(pte) & mio_wb_bit_mask;
|
|
+
|
|
+ return __pgprot(pte_flags);
|
|
+}
|
|
+
|
|
/*
|
|
* pgd/pmd/pte modification functions
|
|
*/
|
|
diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h
|
|
index 6ede29907fbf7..b5f545db461a4 100644
|
|
--- a/arch/s390/include/asm/preempt.h
|
|
+++ b/arch/s390/include/asm/preempt.h
|
|
@@ -29,12 +29,6 @@ static inline void preempt_count_set(int pc)
|
|
old, new) != old);
|
|
}
|
|
|
|
-#define init_task_preempt_count(p) do { } while (0)
|
|
-
|
|
-#define init_idle_preempt_count(p, cpu) do { \
|
|
- S390_lowcore.preempt_count = PREEMPT_ENABLED; \
|
|
-} while (0)
|
|
-
|
|
static inline void set_preempt_need_resched(void)
|
|
{
|
|
__atomic_and(~PREEMPT_NEED_RESCHED, &S390_lowcore.preempt_count);
|
|
@@ -88,12 +82,6 @@ static inline void preempt_count_set(int pc)
|
|
S390_lowcore.preempt_count = pc;
|
|
}
|
|
|
|
-#define init_task_preempt_count(p) do { } while (0)
|
|
-
|
|
-#define init_idle_preempt_count(p, cpu) do { \
|
|
- S390_lowcore.preempt_count = PREEMPT_ENABLED; \
|
|
-} while (0)
|
|
-
|
|
static inline void set_preempt_need_resched(void)
|
|
{
|
|
}
|
|
@@ -130,6 +118,10 @@ static inline bool should_resched(int preempt_offset)
|
|
|
|
#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
|
|
|
|
+#define init_task_preempt_count(p) do { } while (0)
|
|
+/* Deferred to CPU bringup time */
|
|
+#define init_idle_preempt_count(p, cpu) do { } while (0)
|
|
+
|
|
#ifdef CONFIG_PREEMPTION
|
|
extern asmlinkage void preempt_schedule(void);
|
|
#define __preempt_schedule() preempt_schedule()
|
|
diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h
|
|
index 7b98d4caee779..12c5f006c1364 100644
|
|
--- a/arch/s390/include/asm/uv.h
|
|
+++ b/arch/s390/include/asm/uv.h
|
|
@@ -73,6 +73,10 @@ enum uv_cmds_inst {
|
|
BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22,
|
|
};
|
|
|
|
+enum uv_feat_ind {
|
|
+ BIT_UV_FEAT_MISC = 0,
|
|
+};
|
|
+
|
|
struct uv_cb_header {
|
|
u16 len;
|
|
u16 cmd; /* Command Code */
|
|
@@ -97,7 +101,8 @@ struct uv_cb_qui {
|
|
u64 max_guest_stor_addr;
|
|
u8 reserved88[158 - 136];
|
|
u16 max_guest_cpu_id;
|
|
- u8 reserveda0[200 - 160];
|
|
+ u64 uv_feature_indications;
|
|
+ u8 reserveda0[200 - 168];
|
|
} __packed __aligned(8);
|
|
|
|
/* Initialize Ultravisor */
|
|
@@ -274,6 +279,7 @@ struct uv_info {
|
|
unsigned long max_sec_stor_addr;
|
|
unsigned int max_num_sec_conf;
|
|
unsigned short max_guest_cpu_id;
|
|
+ unsigned long uv_feature_indications;
|
|
};
|
|
|
|
extern struct uv_info uv_info;
|
|
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
|
|
index e83ce909686c5..83a3f346e5bd9 100644
|
|
--- a/arch/s390/kernel/setup.c
|
|
+++ b/arch/s390/kernel/setup.c
|
|
@@ -454,6 +454,7 @@ static void __init setup_lowcore_dat_off(void)
|
|
lc->br_r1_trampoline = 0x07f1; /* br %r1 */
|
|
lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW);
|
|
lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW);
|
|
+ lc->preempt_count = PREEMPT_DISABLED;
|
|
|
|
set_prefix((u32)(unsigned long) lc);
|
|
lowcore_ptr[0] = lc;
|
|
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
|
|
index 791bc373418bd..5674792726cd9 100644
|
|
--- a/arch/s390/kernel/smp.c
|
|
+++ b/arch/s390/kernel/smp.c
|
|
@@ -215,6 +215,7 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
|
|
lc->br_r1_trampoline = 0x07f1; /* br %r1 */
|
|
lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW);
|
|
lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW);
|
|
+ lc->preempt_count = PREEMPT_DISABLED;
|
|
if (nmi_alloc_per_cpu(lc))
|
|
goto out_async;
|
|
if (vdso_alloc_per_cpu(lc))
|
|
@@ -863,7 +864,6 @@ static void smp_init_secondary(void)
|
|
set_cpu_flag(CIF_ASCE_SECONDARY);
|
|
cpu_init();
|
|
rcu_cpu_starting(cpu);
|
|
- preempt_disable();
|
|
init_cpu_timer();
|
|
vtime_init();
|
|
pfault_init();
|
|
diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c
|
|
index b2d2ad1530676..c811b2313100b 100644
|
|
--- a/arch/s390/kernel/uv.c
|
|
+++ b/arch/s390/kernel/uv.c
|
|
@@ -364,6 +364,15 @@ static ssize_t uv_query_facilities(struct kobject *kobj,
|
|
static struct kobj_attribute uv_query_facilities_attr =
|
|
__ATTR(facilities, 0444, uv_query_facilities, NULL);
|
|
|
|
+static ssize_t uv_query_feature_indications(struct kobject *kobj,
|
|
+ struct kobj_attribute *attr, char *buf)
|
|
+{
|
|
+ return sysfs_emit(buf, "%lx\n", uv_info.uv_feature_indications);
|
|
+}
|
|
+
|
|
+static struct kobj_attribute uv_query_feature_indications_attr =
|
|
+ __ATTR(feature_indications, 0444, uv_query_feature_indications, NULL);
|
|
+
|
|
static ssize_t uv_query_max_guest_cpus(struct kobject *kobj,
|
|
struct kobj_attribute *attr, char *page)
|
|
{
|
|
@@ -396,6 +405,7 @@ static struct kobj_attribute uv_query_max_guest_addr_attr =
|
|
|
|
static struct attribute *uv_query_attrs[] = {
|
|
&uv_query_facilities_attr.attr,
|
|
+ &uv_query_feature_indications_attr.attr,
|
|
&uv_query_max_guest_cpus_attr.attr,
|
|
&uv_query_max_guest_vms_attr.attr,
|
|
&uv_query_max_guest_addr_attr.attr,
|
|
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
|
|
index 20afffd6b9820..f94b4f78d4dab 100644
|
|
--- a/arch/s390/kvm/kvm-s390.c
|
|
+++ b/arch/s390/kvm/kvm-s390.c
|
|
@@ -327,31 +327,31 @@ static void allow_cpu_feat(unsigned long nr)
|
|
|
|
static inline int plo_test_bit(unsigned char nr)
|
|
{
|
|
- register unsigned long r0 asm("0") = (unsigned long) nr | 0x100;
|
|
+ unsigned long function = (unsigned long)nr | 0x100;
|
|
int cc;
|
|
|
|
asm volatile(
|
|
+ " lgr 0,%[function]\n"
|
|
/* Parameter registers are ignored for "test bit" */
|
|
" plo 0,0,0,0(0)\n"
|
|
" ipm %0\n"
|
|
" srl %0,28\n"
|
|
: "=d" (cc)
|
|
- : "d" (r0)
|
|
- : "cc");
|
|
+ : [function] "d" (function)
|
|
+ : "cc", "0");
|
|
return cc == 0;
|
|
}
|
|
|
|
static __always_inline void __insn32_query(unsigned int opcode, u8 *query)
|
|
{
|
|
- register unsigned long r0 asm("0") = 0; /* query function */
|
|
- register unsigned long r1 asm("1") = (unsigned long) query;
|
|
-
|
|
asm volatile(
|
|
- /* Parameter regs are ignored */
|
|
+ " lghi 0,0\n"
|
|
+ " lgr 1,%[query]\n"
|
|
+ /* Parameter registers are ignored */
|
|
" .insn rrf,%[opc] << 16,2,4,6,0\n"
|
|
:
|
|
- : "d" (r0), "a" (r1), [opc] "i" (opcode)
|
|
- : "cc", "memory");
|
|
+ : [query] "d" ((unsigned long)query), [opc] "i" (opcode)
|
|
+ : "cc", "memory", "0", "1");
|
|
}
|
|
|
|
#define INSN_SORTL 0xb938
|
|
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
|
|
index 996884dcc9fdb..ed517fad0d035 100644
|
|
--- a/arch/s390/mm/fault.c
|
|
+++ b/arch/s390/mm/fault.c
|
|
@@ -805,6 +805,32 @@ void do_secure_storage_access(struct pt_regs *regs)
|
|
struct page *page;
|
|
int rc;
|
|
|
|
+ /*
|
|
+ * bit 61 tells us if the address is valid, if it's not we
|
|
+ * have a major problem and should stop the kernel or send a
|
|
+ * SIGSEGV to the process. Unfortunately bit 61 is not
|
|
+ * reliable without the misc UV feature so we need to check
|
|
+ * for that as well.
|
|
+ */
|
|
+ if (test_bit_inv(BIT_UV_FEAT_MISC, &uv_info.uv_feature_indications) &&
|
|
+ !test_bit_inv(61, ®s->int_parm_long)) {
|
|
+ /*
|
|
+ * When this happens, userspace did something that it
|
|
+ * was not supposed to do, e.g. branching into secure
|
|
+ * memory. Trigger a segmentation fault.
|
|
+ */
|
|
+ if (user_mode(regs)) {
|
|
+ send_sig(SIGSEGV, current, 0);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * The kernel should never run into this case and we
|
|
+ * have no way out of this situation.
|
|
+ */
|
|
+ panic("Unexpected PGM 0x3d with TEID bit 61=0");
|
|
+ }
|
|
+
|
|
switch (get_fault_type(regs)) {
|
|
case USER_FAULT:
|
|
mm = current->mm;
|
|
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
|
|
index 372acdc9033eb..65924d9ec2459 100644
|
|
--- a/arch/sh/kernel/smp.c
|
|
+++ b/arch/sh/kernel/smp.c
|
|
@@ -186,8 +186,6 @@ asmlinkage void start_secondary(void)
|
|
|
|
per_cpu_trap_init();
|
|
|
|
- preempt_disable();
|
|
-
|
|
notify_cpu_starting(cpu);
|
|
|
|
local_irq_enable();
|
|
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
|
|
index 50c127ab46d5b..22b148e5a5f88 100644
|
|
--- a/arch/sparc/kernel/smp_32.c
|
|
+++ b/arch/sparc/kernel/smp_32.c
|
|
@@ -348,7 +348,6 @@ static void sparc_start_secondary(void *arg)
|
|
*/
|
|
arch_cpu_pre_starting(arg);
|
|
|
|
- preempt_disable();
|
|
cpu = smp_processor_id();
|
|
|
|
notify_cpu_starting(cpu);
|
|
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
|
|
index e38d8bf454e86..ae5faa1d989d2 100644
|
|
--- a/arch/sparc/kernel/smp_64.c
|
|
+++ b/arch/sparc/kernel/smp_64.c
|
|
@@ -138,9 +138,6 @@ void smp_callin(void)
|
|
|
|
set_cpu_online(cpuid, true);
|
|
|
|
- /* idle thread is expected to have preempt disabled */
|
|
- preempt_disable();
|
|
-
|
|
local_irq_enable();
|
|
|
|
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
|
|
diff --git a/arch/x86/crypto/curve25519-x86_64.c b/arch/x86/crypto/curve25519-x86_64.c
|
|
index 5af8021b98cea..11b4c83c715e3 100644
|
|
--- a/arch/x86/crypto/curve25519-x86_64.c
|
|
+++ b/arch/x86/crypto/curve25519-x86_64.c
|
|
@@ -1500,7 +1500,7 @@ static int __init curve25519_mod_init(void)
|
|
static void __exit curve25519_mod_exit(void)
|
|
{
|
|
if (IS_REACHABLE(CONFIG_CRYPTO_KPP) &&
|
|
- (boot_cpu_has(X86_FEATURE_BMI2) || boot_cpu_has(X86_FEATURE_ADX)))
|
|
+ static_branch_likely(&curve25519_use_bmi2_adx))
|
|
crypto_unregister_kpp(&curve25519_alg);
|
|
}
|
|
|
|
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
|
|
index cad08703c4ad7..f18f3932e971a 100644
|
|
--- a/arch/x86/entry/entry_64.S
|
|
+++ b/arch/x86/entry/entry_64.S
|
|
@@ -508,7 +508,7 @@ SYM_CODE_START(\asmsym)
|
|
|
|
movq %rsp, %rdi /* pt_regs pointer */
|
|
|
|
- call \cfunc
|
|
+ call kernel_\cfunc
|
|
|
|
/*
|
|
* No need to switch back to the IST stack. The current stack is either
|
|
@@ -519,7 +519,7 @@ SYM_CODE_START(\asmsym)
|
|
|
|
/* Switch to the regular task stack */
|
|
.Lfrom_usermode_switch_stack_\@:
|
|
- idtentry_body safe_stack_\cfunc, has_error_code=1
|
|
+ idtentry_body user_\cfunc, has_error_code=1
|
|
|
|
_ASM_NOKPROBE(\asmsym)
|
|
SYM_CODE_END(\asmsym)
|
|
diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
|
|
index 0e3325790f3a9..dc2a8b1657f4a 100644
|
|
--- a/arch/x86/include/asm/idtentry.h
|
|
+++ b/arch/x86/include/asm/idtentry.h
|
|
@@ -315,8 +315,8 @@ static __always_inline void __##func(struct pt_regs *regs)
|
|
*/
|
|
#define DECLARE_IDTENTRY_VC(vector, func) \
|
|
DECLARE_IDTENTRY_RAW_ERRORCODE(vector, func); \
|
|
- __visible noinstr void ist_##func(struct pt_regs *regs, unsigned long error_code); \
|
|
- __visible noinstr void safe_stack_##func(struct pt_regs *regs, unsigned long error_code)
|
|
+ __visible noinstr void kernel_##func(struct pt_regs *regs, unsigned long error_code); \
|
|
+ __visible noinstr void user_##func(struct pt_regs *regs, unsigned long error_code)
|
|
|
|
/**
|
|
* DEFINE_IDTENTRY_IST - Emit code for IST entry points
|
|
@@ -358,33 +358,24 @@ static __always_inline void __##func(struct pt_regs *regs)
|
|
DEFINE_IDTENTRY_RAW_ERRORCODE(func)
|
|
|
|
/**
|
|
- * DEFINE_IDTENTRY_VC_SAFE_STACK - Emit code for VMM communication handler
|
|
- which runs on a safe stack.
|
|
+ * DEFINE_IDTENTRY_VC_KERNEL - Emit code for VMM communication handler
|
|
+ when raised from kernel mode
|
|
* @func: Function name of the entry point
|
|
*
|
|
* Maps to DEFINE_IDTENTRY_RAW_ERRORCODE
|
|
*/
|
|
-#define DEFINE_IDTENTRY_VC_SAFE_STACK(func) \
|
|
- DEFINE_IDTENTRY_RAW_ERRORCODE(safe_stack_##func)
|
|
+#define DEFINE_IDTENTRY_VC_KERNEL(func) \
|
|
+ DEFINE_IDTENTRY_RAW_ERRORCODE(kernel_##func)
|
|
|
|
/**
|
|
- * DEFINE_IDTENTRY_VC_IST - Emit code for VMM communication handler
|
|
- which runs on the VC fall-back stack
|
|
+ * DEFINE_IDTENTRY_VC_USER - Emit code for VMM communication handler
|
|
+ when raised from user mode
|
|
* @func: Function name of the entry point
|
|
*
|
|
* Maps to DEFINE_IDTENTRY_RAW_ERRORCODE
|
|
*/
|
|
-#define DEFINE_IDTENTRY_VC_IST(func) \
|
|
- DEFINE_IDTENTRY_RAW_ERRORCODE(ist_##func)
|
|
-
|
|
-/**
|
|
- * DEFINE_IDTENTRY_VC - Emit code for VMM communication handler
|
|
- * @func: Function name of the entry point
|
|
- *
|
|
- * Maps to DEFINE_IDTENTRY_RAW_ERRORCODE
|
|
- */
|
|
-#define DEFINE_IDTENTRY_VC(func) \
|
|
- DEFINE_IDTENTRY_RAW_ERRORCODE(func)
|
|
+#define DEFINE_IDTENTRY_VC_USER(func) \
|
|
+ DEFINE_IDTENTRY_RAW_ERRORCODE(user_##func)
|
|
|
|
#else /* CONFIG_X86_64 */
|
|
|
|
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
|
|
index d1ac2de41ea8a..b1cd8334db11a 100644
|
|
--- a/arch/x86/include/asm/kvm_host.h
|
|
+++ b/arch/x86/include/asm/kvm_host.h
|
|
@@ -84,7 +84,7 @@
|
|
#define KVM_REQ_APICV_UPDATE \
|
|
KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
|
|
#define KVM_REQ_TLB_FLUSH_CURRENT KVM_ARCH_REQ(26)
|
|
-#define KVM_REQ_HV_TLB_FLUSH \
|
|
+#define KVM_REQ_TLB_FLUSH_GUEST \
|
|
KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_NO_WAKEUP)
|
|
#define KVM_REQ_APF_READY KVM_ARCH_REQ(28)
|
|
#define KVM_REQ_MSR_FILTER_CHANGED KVM_ARCH_REQ(29)
|
|
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
|
|
index 69485ca13665f..a334dd0d7c42c 100644
|
|
--- a/arch/x86/include/asm/preempt.h
|
|
+++ b/arch/x86/include/asm/preempt.h
|
|
@@ -43,7 +43,7 @@ static __always_inline void preempt_count_set(int pc)
|
|
#define init_task_preempt_count(p) do { } while (0)
|
|
|
|
#define init_idle_preempt_count(p, cpu) do { \
|
|
- per_cpu(__preempt_count, (cpu)) = PREEMPT_ENABLED; \
|
|
+ per_cpu(__preempt_count, (cpu)) = PREEMPT_DISABLED; \
|
|
} while (0)
|
|
|
|
/*
|
|
diff --git a/arch/x86/include/uapi/asm/hwcap2.h b/arch/x86/include/uapi/asm/hwcap2.h
|
|
index 5fdfcb47000f9..054604aba9f00 100644
|
|
--- a/arch/x86/include/uapi/asm/hwcap2.h
|
|
+++ b/arch/x86/include/uapi/asm/hwcap2.h
|
|
@@ -2,10 +2,12 @@
|
|
#ifndef _ASM_X86_HWCAP2_H
|
|
#define _ASM_X86_HWCAP2_H
|
|
|
|
+#include <linux/const.h>
|
|
+
|
|
/* MONITOR/MWAIT enabled in Ring 3 */
|
|
-#define HWCAP2_RING3MWAIT (1 << 0)
|
|
+#define HWCAP2_RING3MWAIT _BITUL(0)
|
|
|
|
/* Kernel allows FSGSBASE instructions available in Ring 3 */
|
|
-#define HWCAP2_FSGSBASE BIT(1)
|
|
+#define HWCAP2_FSGSBASE _BITUL(1)
|
|
|
|
#endif
|
|
diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c
|
|
index e0cdab7cb632b..f3202b2e3c157 100644
|
|
--- a/arch/x86/kernel/sev-es.c
|
|
+++ b/arch/x86/kernel/sev-es.c
|
|
@@ -12,7 +12,6 @@
|
|
#include <linux/sched/debug.h> /* For show_regs() */
|
|
#include <linux/percpu-defs.h>
|
|
#include <linux/mem_encrypt.h>
|
|
-#include <linux/lockdep.h>
|
|
#include <linux/printk.h>
|
|
#include <linux/mm_types.h>
|
|
#include <linux/set_memory.h>
|
|
@@ -180,11 +179,19 @@ void noinstr __sev_es_ist_exit(void)
|
|
this_cpu_write(cpu_tss_rw.x86_tss.ist[IST_INDEX_VC], *(unsigned long *)ist);
|
|
}
|
|
|
|
-static __always_inline struct ghcb *sev_es_get_ghcb(struct ghcb_state *state)
|
|
+/*
|
|
+ * Nothing shall interrupt this code path while holding the per-CPU
|
|
+ * GHCB. The backup GHCB is only for NMIs interrupting this path.
|
|
+ *
|
|
+ * Callers must disable local interrupts around it.
|
|
+ */
|
|
+static noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state)
|
|
{
|
|
struct sev_es_runtime_data *data;
|
|
struct ghcb *ghcb;
|
|
|
|
+ WARN_ON(!irqs_disabled());
|
|
+
|
|
data = this_cpu_read(runtime_data);
|
|
ghcb = &data->ghcb_page;
|
|
|
|
@@ -201,7 +208,9 @@ static __always_inline struct ghcb *sev_es_get_ghcb(struct ghcb_state *state)
|
|
data->ghcb_active = false;
|
|
data->backup_ghcb_active = false;
|
|
|
|
+ instrumentation_begin();
|
|
panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use");
|
|
+ instrumentation_end();
|
|
}
|
|
|
|
/* Mark backup_ghcb active before writing to it */
|
|
@@ -452,11 +461,13 @@ static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt
|
|
/* Include code shared with pre-decompression boot stage */
|
|
#include "sev-es-shared.c"
|
|
|
|
-static __always_inline void sev_es_put_ghcb(struct ghcb_state *state)
|
|
+static noinstr void __sev_put_ghcb(struct ghcb_state *state)
|
|
{
|
|
struct sev_es_runtime_data *data;
|
|
struct ghcb *ghcb;
|
|
|
|
+ WARN_ON(!irqs_disabled());
|
|
+
|
|
data = this_cpu_read(runtime_data);
|
|
ghcb = &data->ghcb_page;
|
|
|
|
@@ -480,7 +491,7 @@ void noinstr __sev_es_nmi_complete(void)
|
|
struct ghcb_state state;
|
|
struct ghcb *ghcb;
|
|
|
|
- ghcb = sev_es_get_ghcb(&state);
|
|
+ ghcb = __sev_get_ghcb(&state);
|
|
|
|
vc_ghcb_invalidate(ghcb);
|
|
ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_NMI_COMPLETE);
|
|
@@ -490,7 +501,7 @@ void noinstr __sev_es_nmi_complete(void)
|
|
sev_es_wr_ghcb_msr(__pa_nodebug(ghcb));
|
|
VMGEXIT();
|
|
|
|
- sev_es_put_ghcb(&state);
|
|
+ __sev_put_ghcb(&state);
|
|
}
|
|
|
|
static u64 get_jump_table_addr(void)
|
|
@@ -502,7 +513,7 @@ static u64 get_jump_table_addr(void)
|
|
|
|
local_irq_save(flags);
|
|
|
|
- ghcb = sev_es_get_ghcb(&state);
|
|
+ ghcb = __sev_get_ghcb(&state);
|
|
|
|
vc_ghcb_invalidate(ghcb);
|
|
ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_AP_JUMP_TABLE);
|
|
@@ -516,7 +527,7 @@ static u64 get_jump_table_addr(void)
|
|
ghcb_sw_exit_info_2_is_valid(ghcb))
|
|
ret = ghcb->save.sw_exit_info_2;
|
|
|
|
- sev_es_put_ghcb(&state);
|
|
+ __sev_put_ghcb(&state);
|
|
|
|
local_irq_restore(flags);
|
|
|
|
@@ -641,7 +652,7 @@ static void sev_es_ap_hlt_loop(void)
|
|
struct ghcb_state state;
|
|
struct ghcb *ghcb;
|
|
|
|
- ghcb = sev_es_get_ghcb(&state);
|
|
+ ghcb = __sev_get_ghcb(&state);
|
|
|
|
while (true) {
|
|
vc_ghcb_invalidate(ghcb);
|
|
@@ -658,7 +669,7 @@ static void sev_es_ap_hlt_loop(void)
|
|
break;
|
|
}
|
|
|
|
- sev_es_put_ghcb(&state);
|
|
+ __sev_put_ghcb(&state);
|
|
}
|
|
|
|
/*
|
|
@@ -748,7 +759,7 @@ void __init sev_es_init_vc_handling(void)
|
|
sev_es_setup_play_dead();
|
|
|
|
/* Secondary CPUs use the runtime #VC handler */
|
|
- initial_vc_handler = (unsigned long)safe_stack_exc_vmm_communication;
|
|
+ initial_vc_handler = (unsigned long)kernel_exc_vmm_communication;
|
|
}
|
|
|
|
static void __init vc_early_forward_exception(struct es_em_ctxt *ctxt)
|
|
@@ -1186,14 +1197,6 @@ static enum es_result vc_handle_trap_ac(struct ghcb *ghcb,
|
|
return ES_EXCEPTION;
|
|
}
|
|
|
|
-static __always_inline void vc_handle_trap_db(struct pt_regs *regs)
|
|
-{
|
|
- if (user_mode(regs))
|
|
- noist_exc_debug(regs);
|
|
- else
|
|
- exc_debug(regs);
|
|
-}
|
|
-
|
|
static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt,
|
|
struct ghcb *ghcb,
|
|
unsigned long exit_code)
|
|
@@ -1289,44 +1292,15 @@ static __always_inline bool on_vc_fallback_stack(struct pt_regs *regs)
|
|
return (sp >= __this_cpu_ist_bottom_va(VC2) && sp < __this_cpu_ist_top_va(VC2));
|
|
}
|
|
|
|
-/*
|
|
- * Main #VC exception handler. It is called when the entry code was able to
|
|
- * switch off the IST to a safe kernel stack.
|
|
- *
|
|
- * With the current implementation it is always possible to switch to a safe
|
|
- * stack because #VC exceptions only happen at known places, like intercepted
|
|
- * instructions or accesses to MMIO areas/IO ports. They can also happen with
|
|
- * code instrumentation when the hypervisor intercepts #DB, but the critical
|
|
- * paths are forbidden to be instrumented, so #DB exceptions currently also
|
|
- * only happen in safe places.
|
|
- */
|
|
-DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
|
|
+static bool vc_raw_handle_exception(struct pt_regs *regs, unsigned long error_code)
|
|
{
|
|
- irqentry_state_t irq_state;
|
|
struct ghcb_state state;
|
|
struct es_em_ctxt ctxt;
|
|
enum es_result result;
|
|
struct ghcb *ghcb;
|
|
+ bool ret = true;
|
|
|
|
- /*
|
|
- * Handle #DB before calling into !noinstr code to avoid recursive #DB.
|
|
- */
|
|
- if (error_code == SVM_EXIT_EXCP_BASE + X86_TRAP_DB) {
|
|
- vc_handle_trap_db(regs);
|
|
- return;
|
|
- }
|
|
-
|
|
- irq_state = irqentry_nmi_enter(regs);
|
|
- lockdep_assert_irqs_disabled();
|
|
- instrumentation_begin();
|
|
-
|
|
- /*
|
|
- * This is invoked through an interrupt gate, so IRQs are disabled. The
|
|
- * code below might walk page-tables for user or kernel addresses, so
|
|
- * keep the IRQs disabled to protect us against concurrent TLB flushes.
|
|
- */
|
|
-
|
|
- ghcb = sev_es_get_ghcb(&state);
|
|
+ ghcb = __sev_get_ghcb(&state);
|
|
|
|
vc_ghcb_invalidate(ghcb);
|
|
result = vc_init_em_ctxt(&ctxt, regs, error_code);
|
|
@@ -1334,7 +1308,7 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
|
|
if (result == ES_OK)
|
|
result = vc_handle_exitcode(&ctxt, ghcb, error_code);
|
|
|
|
- sev_es_put_ghcb(&state);
|
|
+ __sev_put_ghcb(&state);
|
|
|
|
/* Done - now check the result */
|
|
switch (result) {
|
|
@@ -1344,15 +1318,18 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
|
|
case ES_UNSUPPORTED:
|
|
pr_err_ratelimited("Unsupported exit-code 0x%02lx in early #VC exception (IP: 0x%lx)\n",
|
|
error_code, regs->ip);
|
|
- goto fail;
|
|
+ ret = false;
|
|
+ break;
|
|
case ES_VMM_ERROR:
|
|
pr_err_ratelimited("Failure in communication with VMM (exit-code 0x%02lx IP: 0x%lx)\n",
|
|
error_code, regs->ip);
|
|
- goto fail;
|
|
+ ret = false;
|
|
+ break;
|
|
case ES_DECODE_FAILED:
|
|
pr_err_ratelimited("Failed to decode instruction (exit-code 0x%02lx IP: 0x%lx)\n",
|
|
error_code, regs->ip);
|
|
- goto fail;
|
|
+ ret = false;
|
|
+ break;
|
|
case ES_EXCEPTION:
|
|
vc_forward_exception(&ctxt);
|
|
break;
|
|
@@ -1368,24 +1345,52 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
|
|
BUG();
|
|
}
|
|
|
|
-out:
|
|
- instrumentation_end();
|
|
- irqentry_nmi_exit(regs, irq_state);
|
|
+ return ret;
|
|
+}
|
|
|
|
- return;
|
|
+static __always_inline bool vc_is_db(unsigned long error_code)
|
|
+{
|
|
+ return error_code == SVM_EXIT_EXCP_BASE + X86_TRAP_DB;
|
|
+}
|
|
|
|
-fail:
|
|
- if (user_mode(regs)) {
|
|
- /*
|
|
- * Do not kill the machine if user-space triggered the
|
|
- * exception. Send SIGBUS instead and let user-space deal with
|
|
- * it.
|
|
- */
|
|
- force_sig_fault(SIGBUS, BUS_OBJERR, (void __user *)0);
|
|
- } else {
|
|
- pr_emerg("PANIC: Unhandled #VC exception in kernel space (result=%d)\n",
|
|
- result);
|
|
+/*
|
|
+ * Runtime #VC exception handler when raised from kernel mode. Runs in NMI mode
|
|
+ * and will panic when an error happens.
|
|
+ */
|
|
+DEFINE_IDTENTRY_VC_KERNEL(exc_vmm_communication)
|
|
+{
|
|
+ irqentry_state_t irq_state;
|
|
|
|
+ /*
|
|
+ * With the current implementation it is always possible to switch to a
|
|
+ * safe stack because #VC exceptions only happen at known places, like
|
|
+ * intercepted instructions or accesses to MMIO areas/IO ports. They can
|
|
+ * also happen with code instrumentation when the hypervisor intercepts
|
|
+ * #DB, but the critical paths are forbidden to be instrumented, so #DB
|
|
+ * exceptions currently also only happen in safe places.
|
|
+ *
|
|
+ * But keep this here in case the noinstr annotations are violated due
|
|
+ * to bug elsewhere.
|
|
+ */
|
|
+ if (unlikely(on_vc_fallback_stack(regs))) {
|
|
+ instrumentation_begin();
|
|
+ panic("Can't handle #VC exception from unsupported context\n");
|
|
+ instrumentation_end();
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Handle #DB before calling into !noinstr code to avoid recursive #DB.
|
|
+ */
|
|
+ if (vc_is_db(error_code)) {
|
|
+ exc_debug(regs);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ irq_state = irqentry_nmi_enter(regs);
|
|
+
|
|
+ instrumentation_begin();
|
|
+
|
|
+ if (!vc_raw_handle_exception(regs, error_code)) {
|
|
/* Show some debug info */
|
|
show_regs(regs);
|
|
|
|
@@ -1396,23 +1401,38 @@ fail:
|
|
panic("Returned from Terminate-Request to Hypervisor\n");
|
|
}
|
|
|
|
- goto out;
|
|
+ instrumentation_end();
|
|
+ irqentry_nmi_exit(regs, irq_state);
|
|
}
|
|
|
|
-/* This handler runs on the #VC fall-back stack. It can cause further #VC exceptions */
|
|
-DEFINE_IDTENTRY_VC_IST(exc_vmm_communication)
|
|
+/*
|
|
+ * Runtime #VC exception handler when raised from user mode. Runs in IRQ mode
|
|
+ * and will kill the current task with SIGBUS when an error happens.
|
|
+ */
|
|
+DEFINE_IDTENTRY_VC_USER(exc_vmm_communication)
|
|
{
|
|
+ /*
|
|
+ * Handle #DB before calling into !noinstr code to avoid recursive #DB.
|
|
+ */
|
|
+ if (vc_is_db(error_code)) {
|
|
+ noist_exc_debug(regs);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ irqentry_enter_from_user_mode(regs);
|
|
instrumentation_begin();
|
|
- panic("Can't handle #VC exception from unsupported context\n");
|
|
- instrumentation_end();
|
|
-}
|
|
|
|
-DEFINE_IDTENTRY_VC(exc_vmm_communication)
|
|
-{
|
|
- if (likely(!on_vc_fallback_stack(regs)))
|
|
- safe_stack_exc_vmm_communication(regs, error_code);
|
|
- else
|
|
- ist_exc_vmm_communication(regs, error_code);
|
|
+ if (!vc_raw_handle_exception(regs, error_code)) {
|
|
+ /*
|
|
+ * Do not kill the machine if user-space triggered the
|
|
+ * exception. Send SIGBUS instead and let user-space deal with
|
|
+ * it.
|
|
+ */
|
|
+ force_sig_fault(SIGBUS, BUS_OBJERR, (void __user *)0);
|
|
+ }
|
|
+
|
|
+ instrumentation_end();
|
|
+ irqentry_exit_to_user_mode(regs);
|
|
}
|
|
|
|
bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
|
|
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
|
|
index 582387fc939f4..8baff500914ea 100644
|
|
--- a/arch/x86/kernel/smpboot.c
|
|
+++ b/arch/x86/kernel/smpboot.c
|
|
@@ -230,7 +230,6 @@ static void notrace start_secondary(void *unused)
|
|
cpu_init_exception_handling();
|
|
cpu_init();
|
|
x86_cpuinit.early_percpu_clock_init();
|
|
- preempt_disable();
|
|
smp_callin();
|
|
|
|
enable_start_cpu0 = 0;
|
|
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
|
|
index f70dffc2771f5..56289170753c5 100644
|
|
--- a/arch/x86/kernel/tsc.c
|
|
+++ b/arch/x86/kernel/tsc.c
|
|
@@ -1151,7 +1151,8 @@ static struct clocksource clocksource_tsc = {
|
|
.mask = CLOCKSOURCE_MASK(64),
|
|
.flags = CLOCK_SOURCE_IS_CONTINUOUS |
|
|
CLOCK_SOURCE_VALID_FOR_HRES |
|
|
- CLOCK_SOURCE_MUST_VERIFY,
|
|
+ CLOCK_SOURCE_MUST_VERIFY |
|
|
+ CLOCK_SOURCE_VERIFY_PERCPU,
|
|
.vdso_clock_mode = VDSO_CLOCKMODE_TSC,
|
|
.enable = tsc_cs_enable,
|
|
.resume = tsc_resume,
|
|
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
|
|
index 5c7c4060b45cb..bb39f493447cf 100644
|
|
--- a/arch/x86/kvm/hyperv.c
|
|
+++ b/arch/x86/kvm/hyperv.c
|
|
@@ -1564,7 +1564,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa,
|
|
* vcpu->arch.cr3 may not be up-to-date for running vCPUs so we can't
|
|
* analyze it here, flush TLB regardless of the specified address space.
|
|
*/
|
|
- kvm_make_vcpus_request_mask(kvm, KVM_REQ_HV_TLB_FLUSH,
|
|
+ kvm_make_vcpus_request_mask(kvm, KVM_REQ_TLB_FLUSH_GUEST,
|
|
NULL, vcpu_mask, &hv_vcpu->tlb_flush);
|
|
|
|
ret_success:
|
|
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
|
|
index f2eeaf197294d..7e6dc454ea28d 100644
|
|
--- a/arch/x86/kvm/mmu/mmu.c
|
|
+++ b/arch/x86/kvm/mmu/mmu.c
|
|
@@ -4133,7 +4133,15 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
|
|
void
|
|
reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
|
|
{
|
|
- bool uses_nx = context->nx ||
|
|
+ /*
|
|
+ * KVM uses NX when TDP is disabled to handle a variety of scenarios,
|
|
+ * notably for huge SPTEs if iTLB multi-hit mitigation is enabled and
|
|
+ * to generate correct permissions for CR0.WP=0/CR4.SMEP=1/EFER.NX=0.
|
|
+ * The iTLB multi-hit workaround can be toggled at any time, so assume
|
|
+ * NX can be used by any non-nested shadow MMU to avoid having to reset
|
|
+ * MMU contexts. Note, KVM forces EFER.NX=1 when TDP is disabled.
|
|
+ */
|
|
+ bool uses_nx = context->nx || !tdp_enabled ||
|
|
context->mmu_role.base.smep_andnot_wp;
|
|
struct rsvd_bits_validate *shadow_zero_check;
|
|
int i;
|
|
diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
|
|
index 00a0bfaed6e86..d6cd702e85b68 100644
|
|
--- a/arch/x86/kvm/mmu/paging_tmpl.h
|
|
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
|
|
@@ -471,8 +471,7 @@ retry_walk:
|
|
|
|
error:
|
|
errcode |= write_fault | user_fault;
|
|
- if (fetch_fault && (mmu->nx ||
|
|
- kvm_read_cr4_bits(vcpu, X86_CR4_SMEP)))
|
|
+ if (fetch_fault && (mmu->nx || mmu->mmu_role.ext.cr4_smep))
|
|
errcode |= PFERR_FETCH_MASK;
|
|
|
|
walker->fault.vector = PF_VECTOR;
|
|
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
|
|
index 61c00f8631f1a..f2ddf663e72e9 100644
|
|
--- a/arch/x86/kvm/mmu/tdp_mmu.c
|
|
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
|
|
@@ -527,7 +527,7 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu, int write,
|
|
kvm_pfn_t pfn, bool prefault)
|
|
{
|
|
u64 new_spte;
|
|
- int ret = 0;
|
|
+ int ret = RET_PF_FIXED;
|
|
int make_spte_ret = 0;
|
|
|
|
if (unlikely(is_noslot_pfn(pfn))) {
|
|
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
|
|
index 32e6f33c2c45b..67554bc7adb26 100644
|
|
--- a/arch/x86/kvm/vmx/nested.c
|
|
+++ b/arch/x86/kvm/vmx/nested.c
|
|
@@ -1142,12 +1142,19 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool ne
|
|
|
|
/*
|
|
* Unconditionally skip the TLB flush on fast CR3 switch, all TLB
|
|
- * flushes are handled by nested_vmx_transition_tlb_flush(). See
|
|
- * nested_vmx_transition_mmu_sync for details on skipping the MMU sync.
|
|
+ * flushes are handled by nested_vmx_transition_tlb_flush().
|
|
*/
|
|
- if (!nested_ept)
|
|
- kvm_mmu_new_pgd(vcpu, cr3, true,
|
|
- !nested_vmx_transition_mmu_sync(vcpu));
|
|
+ if (!nested_ept) {
|
|
+ kvm_mmu_new_pgd(vcpu, cr3, true, true);
|
|
+
|
|
+ /*
|
|
+ * A TLB flush on VM-Enter/VM-Exit flushes all linear mappings
|
|
+ * across all PCIDs, i.e. all PGDs need to be synchronized.
|
|
+ * See nested_vmx_transition_mmu_sync() for more details.
|
|
+ */
|
|
+ if (nested_vmx_transition_mmu_sync(vcpu))
|
|
+ kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
|
|
+ }
|
|
|
|
vcpu->arch.cr3 = cr3;
|
|
kvm_register_mark_available(vcpu, VCPU_EXREG_CR3);
|
|
@@ -5477,8 +5484,6 @@ static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu,
|
|
{
|
|
u32 index = kvm_rcx_read(vcpu);
|
|
u64 new_eptp;
|
|
- bool accessed_dirty;
|
|
- struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
|
|
|
|
if (!nested_cpu_has_eptp_switching(vmcs12) ||
|
|
!nested_cpu_has_ept(vmcs12))
|
|
@@ -5487,13 +5492,10 @@ static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu,
|
|
if (index >= VMFUNC_EPTP_ENTRIES)
|
|
return 1;
|
|
|
|
-
|
|
if (kvm_vcpu_read_guest_page(vcpu, vmcs12->eptp_list_address >> PAGE_SHIFT,
|
|
&new_eptp, index * 8, 8))
|
|
return 1;
|
|
|
|
- accessed_dirty = !!(new_eptp & VMX_EPTP_AD_ENABLE_BIT);
|
|
-
|
|
/*
|
|
* If the (L2) guest does a vmfunc to the currently
|
|
* active ept pointer, we don't have to do anything else
|
|
@@ -5502,8 +5504,6 @@ static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu,
|
|
if (!nested_vmx_check_eptp(vcpu, new_eptp))
|
|
return 1;
|
|
|
|
- mmu->ept_ad = accessed_dirty;
|
|
- mmu->mmu_role.base.ad_disabled = !accessed_dirty;
|
|
vmcs12->ept_pointer = new_eptp;
|
|
|
|
kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu);
|
|
@@ -5529,7 +5529,7 @@ static int handle_vmfunc(struct kvm_vcpu *vcpu)
|
|
}
|
|
|
|
vmcs12 = get_vmcs12(vcpu);
|
|
- if ((vmcs12->vm_function_control & (1 << function)) == 0)
|
|
+ if (!(vmcs12->vm_function_control & BIT_ULL(function)))
|
|
goto fail;
|
|
|
|
switch (function) {
|
|
@@ -5787,6 +5787,9 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu,
|
|
else if (is_breakpoint(intr_info) &&
|
|
vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
|
|
return true;
|
|
+ else if (is_alignment_check(intr_info) &&
|
|
+ !vmx_guest_inject_ac(vcpu))
|
|
+ return true;
|
|
return false;
|
|
case EXIT_REASON_EXTERNAL_INTERRUPT:
|
|
return true;
|
|
diff --git a/arch/x86/kvm/vmx/vmcs.h b/arch/x86/kvm/vmx/vmcs.h
|
|
index 1472c6c376f74..571d9ad80a59e 100644
|
|
--- a/arch/x86/kvm/vmx/vmcs.h
|
|
+++ b/arch/x86/kvm/vmx/vmcs.h
|
|
@@ -117,6 +117,11 @@ static inline bool is_gp_fault(u32 intr_info)
|
|
return is_exception_n(intr_info, GP_VECTOR);
|
|
}
|
|
|
|
+static inline bool is_alignment_check(u32 intr_info)
|
|
+{
|
|
+ return is_exception_n(intr_info, AC_VECTOR);
|
|
+}
|
|
+
|
|
static inline bool is_machine_check(u32 intr_info)
|
|
{
|
|
return is_exception_n(intr_info, MC_VECTOR);
|
|
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
|
|
index 45877364e6829..de24d3826788a 100644
|
|
--- a/arch/x86/kvm/vmx/vmx.c
|
|
+++ b/arch/x86/kvm/vmx/vmx.c
|
|
@@ -4755,7 +4755,7 @@ static int handle_machine_check(struct kvm_vcpu *vcpu)
|
|
* - Guest has #AC detection enabled in CR0
|
|
* - Guest EFLAGS has AC bit set
|
|
*/
|
|
-static inline bool guest_inject_ac(struct kvm_vcpu *vcpu)
|
|
+bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu)
|
|
{
|
|
if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT))
|
|
return true;
|
|
@@ -4864,7 +4864,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
|
|
kvm_run->debug.arch.exception = ex_no;
|
|
break;
|
|
case AC_VECTOR:
|
|
- if (guest_inject_ac(vcpu)) {
|
|
+ if (vmx_guest_inject_ac(vcpu)) {
|
|
kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
|
|
return 1;
|
|
}
|
|
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
|
|
index ae3a89ac0600d..73d87d44b6578 100644
|
|
--- a/arch/x86/kvm/vmx/vmx.h
|
|
+++ b/arch/x86/kvm/vmx/vmx.h
|
|
@@ -352,6 +352,7 @@ void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
|
|
u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa,
|
|
int root_level);
|
|
|
|
+bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu);
|
|
void update_exception_bitmap(struct kvm_vcpu *vcpu);
|
|
void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu);
|
|
bool vmx_nmi_blocked(struct kvm_vcpu *vcpu);
|
|
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
|
|
index d3372cb973079..7bf88e6cbd0e9 100644
|
|
--- a/arch/x86/kvm/x86.c
|
|
+++ b/arch/x86/kvm/x86.c
|
|
@@ -8852,7 +8852,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
|
}
|
|
if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu))
|
|
kvm_vcpu_flush_tlb_current(vcpu);
|
|
- if (kvm_check_request(KVM_REQ_HV_TLB_FLUSH, vcpu))
|
|
+ if (kvm_check_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu))
|
|
kvm_vcpu_flush_tlb_guest(vcpu);
|
|
|
|
if (kvm_check_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu)) {
|
|
diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c
|
|
index cd85a7a2722ba..1254da07ead1f 100644
|
|
--- a/arch/xtensa/kernel/smp.c
|
|
+++ b/arch/xtensa/kernel/smp.c
|
|
@@ -145,7 +145,6 @@ void secondary_start_kernel(void)
|
|
cpumask_set_cpu(cpu, mm_cpumask(mm));
|
|
enter_lazy_tlb(mm, current);
|
|
|
|
- preempt_disable();
|
|
trace_hardirqs_off();
|
|
|
|
calibrate_delay();
|
|
diff --git a/block/blk-flush.c b/block/blk-flush.c
|
|
index fd5cee9f1a3be..7ee7e5e8905d5 100644
|
|
--- a/block/blk-flush.c
|
|
+++ b/block/blk-flush.c
|
|
@@ -220,8 +220,6 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
|
|
unsigned long flags = 0;
|
|
struct blk_flush_queue *fq = blk_get_flush_queue(q, flush_rq->mq_ctx);
|
|
|
|
- blk_account_io_flush(flush_rq);
|
|
-
|
|
/* release the tag's ownership to the req cloned from */
|
|
spin_lock_irqsave(&fq->mq_flush_lock, flags);
|
|
|
|
@@ -231,6 +229,7 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
|
|
return;
|
|
}
|
|
|
|
+ blk_account_io_flush(flush_rq);
|
|
/*
|
|
* Flush request has to be marked as IDLE when it is really ended
|
|
* because its .end_io() is called from timeout code path too for
|
|
diff --git a/block/blk-merge.c b/block/blk-merge.c
|
|
index 7cdd566966473..349cd7d3af815 100644
|
|
--- a/block/blk-merge.c
|
|
+++ b/block/blk-merge.c
|
|
@@ -552,10 +552,14 @@ static inline unsigned int blk_rq_get_max_segments(struct request *rq)
|
|
static inline int ll_new_hw_segment(struct request *req, struct bio *bio,
|
|
unsigned int nr_phys_segs)
|
|
{
|
|
- if (req->nr_phys_segments + nr_phys_segs > blk_rq_get_max_segments(req))
|
|
+ if (blk_integrity_merge_bio(req->q, req, bio) == false)
|
|
goto no_merge;
|
|
|
|
- if (blk_integrity_merge_bio(req->q, req, bio) == false)
|
|
+ /* discard request merge won't add new segment */
|
|
+ if (req_op(req) == REQ_OP_DISCARD)
|
|
+ return 1;
|
|
+
|
|
+ if (req->nr_phys_segments + nr_phys_segs > blk_rq_get_max_segments(req))
|
|
goto no_merge;
|
|
|
|
/*
|
|
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
|
|
index 9c92053e704dc..c4f2f6c123aed 100644
|
|
--- a/block/blk-mq-tag.c
|
|
+++ b/block/blk-mq-tag.c
|
|
@@ -199,6 +199,20 @@ struct bt_iter_data {
|
|
bool reserved;
|
|
};
|
|
|
|
+static struct request *blk_mq_find_and_get_req(struct blk_mq_tags *tags,
|
|
+ unsigned int bitnr)
|
|
+{
|
|
+ struct request *rq;
|
|
+ unsigned long flags;
|
|
+
|
|
+ spin_lock_irqsave(&tags->lock, flags);
|
|
+ rq = tags->rqs[bitnr];
|
|
+ if (!rq || !refcount_inc_not_zero(&rq->ref))
|
|
+ rq = NULL;
|
|
+ spin_unlock_irqrestore(&tags->lock, flags);
|
|
+ return rq;
|
|
+}
|
|
+
|
|
static bool bt_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data)
|
|
{
|
|
struct bt_iter_data *iter_data = data;
|
|
@@ -206,18 +220,22 @@ static bool bt_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data)
|
|
struct blk_mq_tags *tags = hctx->tags;
|
|
bool reserved = iter_data->reserved;
|
|
struct request *rq;
|
|
+ bool ret = true;
|
|
|
|
if (!reserved)
|
|
bitnr += tags->nr_reserved_tags;
|
|
- rq = tags->rqs[bitnr];
|
|
-
|
|
/*
|
|
* We can hit rq == NULL here, because the tagging functions
|
|
* test and set the bit before assigning ->rqs[].
|
|
*/
|
|
- if (rq && rq->q == hctx->queue && rq->mq_hctx == hctx)
|
|
- return iter_data->fn(hctx, rq, iter_data->data, reserved);
|
|
- return true;
|
|
+ rq = blk_mq_find_and_get_req(tags, bitnr);
|
|
+ if (!rq)
|
|
+ return true;
|
|
+
|
|
+ if (rq->q == hctx->queue && rq->mq_hctx == hctx)
|
|
+ ret = iter_data->fn(hctx, rq, iter_data->data, reserved);
|
|
+ blk_mq_put_rq_ref(rq);
|
|
+ return ret;
|
|
}
|
|
|
|
/**
|
|
@@ -264,6 +282,8 @@ static bool bt_tags_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data)
|
|
struct blk_mq_tags *tags = iter_data->tags;
|
|
bool reserved = iter_data->flags & BT_TAG_ITER_RESERVED;
|
|
struct request *rq;
|
|
+ bool ret = true;
|
|
+ bool iter_static_rqs = !!(iter_data->flags & BT_TAG_ITER_STATIC_RQS);
|
|
|
|
if (!reserved)
|
|
bitnr += tags->nr_reserved_tags;
|
|
@@ -272,16 +292,19 @@ static bool bt_tags_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data)
|
|
* We can hit rq == NULL here, because the tagging functions
|
|
* test and set the bit before assigning ->rqs[].
|
|
*/
|
|
- if (iter_data->flags & BT_TAG_ITER_STATIC_RQS)
|
|
+ if (iter_static_rqs)
|
|
rq = tags->static_rqs[bitnr];
|
|
else
|
|
- rq = tags->rqs[bitnr];
|
|
+ rq = blk_mq_find_and_get_req(tags, bitnr);
|
|
if (!rq)
|
|
return true;
|
|
- if ((iter_data->flags & BT_TAG_ITER_STARTED) &&
|
|
- !blk_mq_request_started(rq))
|
|
- return true;
|
|
- return iter_data->fn(rq, iter_data->data, reserved);
|
|
+
|
|
+ if (!(iter_data->flags & BT_TAG_ITER_STARTED) ||
|
|
+ blk_mq_request_started(rq))
|
|
+ ret = iter_data->fn(rq, iter_data->data, reserved);
|
|
+ if (!iter_static_rqs)
|
|
+ blk_mq_put_rq_ref(rq);
|
|
+ return ret;
|
|
}
|
|
|
|
/**
|
|
@@ -348,6 +371,9 @@ void blk_mq_all_tag_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
|
|
* indicates whether or not @rq is a reserved request. Return
|
|
* true to continue iterating tags, false to stop.
|
|
* @priv: Will be passed as second argument to @fn.
|
|
+ *
|
|
+ * We grab one request reference before calling @fn and release it after
|
|
+ * @fn returns.
|
|
*/
|
|
void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset,
|
|
busy_tag_iter_fn *fn, void *priv)
|
|
@@ -516,6 +542,7 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags,
|
|
|
|
tags->nr_tags = total_tags;
|
|
tags->nr_reserved_tags = reserved_tags;
|
|
+ spin_lock_init(&tags->lock);
|
|
|
|
if (flags & BLK_MQ_F_TAG_HCTX_SHARED)
|
|
return tags;
|
|
diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h
|
|
index 7d3e6b333a4a9..f887988e5ef60 100644
|
|
--- a/block/blk-mq-tag.h
|
|
+++ b/block/blk-mq-tag.h
|
|
@@ -20,6 +20,12 @@ struct blk_mq_tags {
|
|
struct request **rqs;
|
|
struct request **static_rqs;
|
|
struct list_head page_list;
|
|
+
|
|
+ /*
|
|
+ * used to clear request reference in rqs[] before freeing one
|
|
+ * request pool
|
|
+ */
|
|
+ spinlock_t lock;
|
|
};
|
|
|
|
extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags,
|
|
diff --git a/block/blk-mq.c b/block/blk-mq.c
|
|
index 4bf9449b45868..a368eb6dc6470 100644
|
|
--- a/block/blk-mq.c
|
|
+++ b/block/blk-mq.c
|
|
@@ -927,6 +927,14 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next)
|
|
return false;
|
|
}
|
|
|
|
+void blk_mq_put_rq_ref(struct request *rq)
|
|
+{
|
|
+ if (is_flush_rq(rq, rq->mq_hctx))
|
|
+ rq->end_io(rq, 0);
|
|
+ else if (refcount_dec_and_test(&rq->ref))
|
|
+ __blk_mq_free_request(rq);
|
|
+}
|
|
+
|
|
static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
|
|
struct request *rq, void *priv, bool reserved)
|
|
{
|
|
@@ -960,11 +968,7 @@ static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
|
|
if (blk_mq_req_expired(rq, next))
|
|
blk_mq_rq_timed_out(rq, reserved);
|
|
|
|
- if (is_flush_rq(rq, hctx))
|
|
- rq->end_io(rq, 0);
|
|
- else if (refcount_dec_and_test(&rq->ref))
|
|
- __blk_mq_free_request(rq);
|
|
-
|
|
+ blk_mq_put_rq_ref(rq);
|
|
return true;
|
|
}
|
|
|
|
@@ -1238,9 +1242,6 @@ static void blk_mq_update_dispatch_busy(struct blk_mq_hw_ctx *hctx, bool busy)
|
|
{
|
|
unsigned int ewma;
|
|
|
|
- if (hctx->queue->elevator)
|
|
- return;
|
|
-
|
|
ewma = hctx->dispatch_busy;
|
|
|
|
if (!ewma && !busy)
|
|
@@ -2272,6 +2273,45 @@ queue_exit:
|
|
return BLK_QC_T_NONE;
|
|
}
|
|
|
|
+static size_t order_to_size(unsigned int order)
|
|
+{
|
|
+ return (size_t)PAGE_SIZE << order;
|
|
+}
|
|
+
|
|
+/* called before freeing request pool in @tags */
|
|
+static void blk_mq_clear_rq_mapping(struct blk_mq_tag_set *set,
|
|
+ struct blk_mq_tags *tags, unsigned int hctx_idx)
|
|
+{
|
|
+ struct blk_mq_tags *drv_tags = set->tags[hctx_idx];
|
|
+ struct page *page;
|
|
+ unsigned long flags;
|
|
+
|
|
+ list_for_each_entry(page, &tags->page_list, lru) {
|
|
+ unsigned long start = (unsigned long)page_address(page);
|
|
+ unsigned long end = start + order_to_size(page->private);
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < set->queue_depth; i++) {
|
|
+ struct request *rq = drv_tags->rqs[i];
|
|
+ unsigned long rq_addr = (unsigned long)rq;
|
|
+
|
|
+ if (rq_addr >= start && rq_addr < end) {
|
|
+ WARN_ON_ONCE(refcount_read(&rq->ref) != 0);
|
|
+ cmpxchg(&drv_tags->rqs[i], rq, NULL);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Wait until all pending iteration is done.
|
|
+ *
|
|
+ * Request reference is cleared and it is guaranteed to be observed
|
|
+ * after the ->lock is released.
|
|
+ */
|
|
+ spin_lock_irqsave(&drv_tags->lock, flags);
|
|
+ spin_unlock_irqrestore(&drv_tags->lock, flags);
|
|
+}
|
|
+
|
|
void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
|
|
unsigned int hctx_idx)
|
|
{
|
|
@@ -2290,6 +2330,8 @@ void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
|
|
}
|
|
}
|
|
|
|
+ blk_mq_clear_rq_mapping(set, tags, hctx_idx);
|
|
+
|
|
while (!list_empty(&tags->page_list)) {
|
|
page = list_first_entry(&tags->page_list, struct page, lru);
|
|
list_del_init(&page->lru);
|
|
@@ -2349,11 +2391,6 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set,
|
|
return tags;
|
|
}
|
|
|
|
-static size_t order_to_size(unsigned int order)
|
|
-{
|
|
- return (size_t)PAGE_SIZE << order;
|
|
-}
|
|
-
|
|
static int blk_mq_init_request(struct blk_mq_tag_set *set, struct request *rq,
|
|
unsigned int hctx_idx, int node)
|
|
{
|
|
diff --git a/block/blk-mq.h b/block/blk-mq.h
|
|
index d2359f7cfd5f2..f792a0920ebb1 100644
|
|
--- a/block/blk-mq.h
|
|
+++ b/block/blk-mq.h
|
|
@@ -47,6 +47,7 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head,
|
|
void blk_mq_flush_busy_ctxs(struct blk_mq_hw_ctx *hctx, struct list_head *list);
|
|
struct request *blk_mq_dequeue_from_ctx(struct blk_mq_hw_ctx *hctx,
|
|
struct blk_mq_ctx *start);
|
|
+void blk_mq_put_rq_ref(struct request *rq);
|
|
|
|
/*
|
|
* Internal helpers for allocating/freeing the request map
|
|
diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h
|
|
index 2bc43e94f4c40..2bcb3495e376b 100644
|
|
--- a/block/blk-rq-qos.h
|
|
+++ b/block/blk-rq-qos.h
|
|
@@ -7,6 +7,7 @@
|
|
#include <linux/blk_types.h>
|
|
#include <linux/atomic.h>
|
|
#include <linux/wait.h>
|
|
+#include <linux/blk-mq.h>
|
|
|
|
#include "blk-mq-debugfs.h"
|
|
|
|
@@ -99,8 +100,21 @@ static inline void rq_wait_init(struct rq_wait *rq_wait)
|
|
|
|
static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
|
|
{
|
|
+ /*
|
|
+ * No IO can be in-flight when adding rqos, so freeze queue, which
|
|
+ * is fine since we only support rq_qos for blk-mq queue.
|
|
+ *
|
|
+ * Reuse ->queue_lock for protecting against other concurrent
|
|
+ * rq_qos adding/deleting
|
|
+ */
|
|
+ blk_mq_freeze_queue(q);
|
|
+
|
|
+ spin_lock_irq(&q->queue_lock);
|
|
rqos->next = q->rq_qos;
|
|
q->rq_qos = rqos;
|
|
+ spin_unlock_irq(&q->queue_lock);
|
|
+
|
|
+ blk_mq_unfreeze_queue(q);
|
|
|
|
if (rqos->ops->debugfs_attrs)
|
|
blk_mq_debugfs_register_rqos(rqos);
|
|
@@ -110,12 +124,22 @@ static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos)
|
|
{
|
|
struct rq_qos **cur;
|
|
|
|
+ /*
|
|
+ * See comment in rq_qos_add() about freezing queue & using
|
|
+ * ->queue_lock.
|
|
+ */
|
|
+ blk_mq_freeze_queue(q);
|
|
+
|
|
+ spin_lock_irq(&q->queue_lock);
|
|
for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) {
|
|
if (*cur == rqos) {
|
|
*cur = rqos->next;
|
|
break;
|
|
}
|
|
}
|
|
+ spin_unlock_irq(&q->queue_lock);
|
|
+
|
|
+ blk_mq_unfreeze_queue(q);
|
|
|
|
blk_mq_debugfs_unregister_rqos(rqos);
|
|
}
|
|
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
|
|
index fd410086fe1de..35d81b5deae1c 100644
|
|
--- a/block/blk-wbt.c
|
|
+++ b/block/blk-wbt.c
|
|
@@ -77,7 +77,8 @@ enum {
|
|
|
|
static inline bool rwb_enabled(struct rq_wb *rwb)
|
|
{
|
|
- return rwb && rwb->wb_normal != 0;
|
|
+ return rwb && rwb->enable_state != WBT_STATE_OFF_DEFAULT &&
|
|
+ rwb->wb_normal != 0;
|
|
}
|
|
|
|
static void wb_timestamp(struct rq_wb *rwb, unsigned long *var)
|
|
@@ -636,9 +637,13 @@ void wbt_set_write_cache(struct request_queue *q, bool write_cache_on)
|
|
void wbt_enable_default(struct request_queue *q)
|
|
{
|
|
struct rq_qos *rqos = wbt_rq_qos(q);
|
|
+
|
|
/* Throttling already enabled? */
|
|
- if (rqos)
|
|
+ if (rqos) {
|
|
+ if (RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
|
|
+ RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT;
|
|
return;
|
|
+ }
|
|
|
|
/* Queue not registered? Maybe shutting down... */
|
|
if (!blk_queue_registered(q))
|
|
@@ -702,7 +707,7 @@ void wbt_disable_default(struct request_queue *q)
|
|
rwb = RQWB(rqos);
|
|
if (rwb->enable_state == WBT_STATE_ON_DEFAULT) {
|
|
blk_stat_deactivate(rwb->cb);
|
|
- rwb->wb_normal = 0;
|
|
+ rwb->enable_state = WBT_STATE_OFF_DEFAULT;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(wbt_disable_default);
|
|
diff --git a/block/blk-wbt.h b/block/blk-wbt.h
|
|
index 16bdc85b8df92..2eb01becde8c4 100644
|
|
--- a/block/blk-wbt.h
|
|
+++ b/block/blk-wbt.h
|
|
@@ -34,6 +34,7 @@ enum {
|
|
enum {
|
|
WBT_STATE_ON_DEFAULT = 1,
|
|
WBT_STATE_ON_MANUAL = 2,
|
|
+ WBT_STATE_OFF_DEFAULT
|
|
};
|
|
|
|
struct rq_wb {
|
|
diff --git a/crypto/shash.c b/crypto/shash.c
|
|
index 2e3433ad97629..0a0a50cb694f0 100644
|
|
--- a/crypto/shash.c
|
|
+++ b/crypto/shash.c
|
|
@@ -20,12 +20,24 @@
|
|
|
|
static const struct crypto_type crypto_shash_type;
|
|
|
|
-int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
|
|
- unsigned int keylen)
|
|
+static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
|
|
+ unsigned int keylen)
|
|
{
|
|
return -ENOSYS;
|
|
}
|
|
-EXPORT_SYMBOL_GPL(shash_no_setkey);
|
|
+
|
|
+/*
|
|
+ * Check whether an shash algorithm has a setkey function.
|
|
+ *
|
|
+ * For CFI compatibility, this must not be an inline function. This is because
|
|
+ * when CFI is enabled, modules won't get the same address for shash_no_setkey
|
|
+ * (if it were exported, which inlining would require) as the core kernel will.
|
|
+ */
|
|
+bool crypto_shash_alg_has_setkey(struct shash_alg *alg)
|
|
+{
|
|
+ return alg->setkey != shash_no_setkey;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(crypto_shash_alg_has_setkey);
|
|
|
|
static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
|
|
unsigned int keylen)
|
|
diff --git a/crypto/sm2.c b/crypto/sm2.c
|
|
index 767e160333f6e..db8a4a265669d 100644
|
|
--- a/crypto/sm2.c
|
|
+++ b/crypto/sm2.c
|
|
@@ -79,10 +79,17 @@ static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec)
|
|
goto free;
|
|
|
|
rc = -ENOMEM;
|
|
+
|
|
+ ec->Q = mpi_point_new(0);
|
|
+ if (!ec->Q)
|
|
+ goto free;
|
|
+
|
|
/* mpi_ec_setup_elliptic_curve */
|
|
ec->G = mpi_point_new(0);
|
|
- if (!ec->G)
|
|
+ if (!ec->G) {
|
|
+ mpi_point_release(ec->Q);
|
|
goto free;
|
|
+ }
|
|
|
|
mpi_set(ec->G->x, x);
|
|
mpi_set(ec->G->y, y);
|
|
@@ -91,6 +98,7 @@ static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec)
|
|
rc = -EINVAL;
|
|
ec->n = mpi_scanval(ecp->n);
|
|
if (!ec->n) {
|
|
+ mpi_point_release(ec->Q);
|
|
mpi_point_release(ec->G);
|
|
goto free;
|
|
}
|
|
@@ -119,12 +127,6 @@ static void sm2_ec_ctx_deinit(struct mpi_ec_ctx *ec)
|
|
memset(ec, 0, sizeof(*ec));
|
|
}
|
|
|
|
-static int sm2_ec_ctx_reset(struct mpi_ec_ctx *ec)
|
|
-{
|
|
- sm2_ec_ctx_deinit(ec);
|
|
- return sm2_ec_ctx_init(ec);
|
|
-}
|
|
-
|
|
/* RESULT must have been initialized and is set on success to the
|
|
* point given by VALUE.
|
|
*/
|
|
@@ -132,55 +134,48 @@ static int sm2_ecc_os2ec(MPI_POINT result, MPI value)
|
|
{
|
|
int rc;
|
|
size_t n;
|
|
- const unsigned char *buf;
|
|
- unsigned char *buf_memory;
|
|
+ unsigned char *buf;
|
|
MPI x, y;
|
|
|
|
- n = (mpi_get_nbits(value)+7)/8;
|
|
- buf_memory = kmalloc(n, GFP_KERNEL);
|
|
- rc = mpi_print(GCRYMPI_FMT_USG, buf_memory, n, &n, value);
|
|
- if (rc) {
|
|
- kfree(buf_memory);
|
|
- return rc;
|
|
- }
|
|
- buf = buf_memory;
|
|
+ n = MPI_NBYTES(value);
|
|
+ buf = kmalloc(n, GFP_KERNEL);
|
|
+ if (!buf)
|
|
+ return -ENOMEM;
|
|
|
|
- if (n < 1) {
|
|
- kfree(buf_memory);
|
|
- return -EINVAL;
|
|
- }
|
|
- if (*buf != 4) {
|
|
- kfree(buf_memory);
|
|
- return -EINVAL; /* No support for point compression. */
|
|
- }
|
|
- if (((n-1)%2)) {
|
|
- kfree(buf_memory);
|
|
- return -EINVAL;
|
|
- }
|
|
- n = (n-1)/2;
|
|
+ rc = mpi_print(GCRYMPI_FMT_USG, buf, n, &n, value);
|
|
+ if (rc)
|
|
+ goto err_freebuf;
|
|
+
|
|
+ rc = -EINVAL;
|
|
+ if (n < 1 || ((n - 1) % 2))
|
|
+ goto err_freebuf;
|
|
+ /* No support for point compression */
|
|
+ if (*buf != 0x4)
|
|
+ goto err_freebuf;
|
|
+
|
|
+ rc = -ENOMEM;
|
|
+ n = (n - 1) / 2;
|
|
x = mpi_read_raw_data(buf + 1, n);
|
|
- if (!x) {
|
|
- kfree(buf_memory);
|
|
- return -ENOMEM;
|
|
- }
|
|
+ if (!x)
|
|
+ goto err_freebuf;
|
|
y = mpi_read_raw_data(buf + 1 + n, n);
|
|
- kfree(buf_memory);
|
|
- if (!y) {
|
|
- mpi_free(x);
|
|
- return -ENOMEM;
|
|
- }
|
|
+ if (!y)
|
|
+ goto err_freex;
|
|
|
|
mpi_normalize(x);
|
|
mpi_normalize(y);
|
|
-
|
|
mpi_set(result->x, x);
|
|
mpi_set(result->y, y);
|
|
mpi_set_ui(result->z, 1);
|
|
|
|
- mpi_free(x);
|
|
- mpi_free(y);
|
|
+ rc = 0;
|
|
|
|
- return 0;
|
|
+ mpi_free(y);
|
|
+err_freex:
|
|
+ mpi_free(x);
|
|
+err_freebuf:
|
|
+ kfree(buf);
|
|
+ return rc;
|
|
}
|
|
|
|
struct sm2_signature_ctx {
|
|
@@ -399,31 +394,15 @@ static int sm2_set_pub_key(struct crypto_akcipher *tfm,
|
|
MPI a;
|
|
int rc;
|
|
|
|
- rc = sm2_ec_ctx_reset(ec);
|
|
- if (rc)
|
|
- return rc;
|
|
-
|
|
- ec->Q = mpi_point_new(0);
|
|
- if (!ec->Q)
|
|
- return -ENOMEM;
|
|
-
|
|
/* include the uncompressed flag '0x04' */
|
|
- rc = -ENOMEM;
|
|
a = mpi_read_raw_data(key, keylen);
|
|
if (!a)
|
|
- goto error;
|
|
+ return -ENOMEM;
|
|
|
|
mpi_normalize(a);
|
|
rc = sm2_ecc_os2ec(ec->Q, a);
|
|
mpi_free(a);
|
|
- if (rc)
|
|
- goto error;
|
|
|
|
- return 0;
|
|
-
|
|
-error:
|
|
- mpi_point_release(ec->Q);
|
|
- ec->Q = NULL;
|
|
return rc;
|
|
}
|
|
|
|
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
|
|
index 44e4125063178..4466156474eef 100644
|
|
--- a/drivers/acpi/Makefile
|
|
+++ b/drivers/acpi/Makefile
|
|
@@ -8,6 +8,11 @@ ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
|
|
#
|
|
# ACPI Boot-Time Table Parsing
|
|
#
|
|
+ifeq ($(CONFIG_ACPI_CUSTOM_DSDT),y)
|
|
+tables.o: $(src)/../../include/$(subst $\",,$(CONFIG_ACPI_CUSTOM_DSDT_FILE)) ;
|
|
+
|
|
+endif
|
|
+
|
|
obj-$(CONFIG_ACPI) += tables.o
|
|
obj-$(CONFIG_X86) += blacklist.o
|
|
|
|
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
|
|
index b8745ce48a47b..b84ab722feb44 100644
|
|
--- a/drivers/acpi/acpi_pad.c
|
|
+++ b/drivers/acpi/acpi_pad.c
|
|
@@ -261,7 +261,7 @@ static uint32_t acpi_pad_idle_cpus_num(void)
|
|
return ps_tsk_num;
|
|
}
|
|
|
|
-static ssize_t acpi_pad_rrtime_store(struct device *dev,
|
|
+static ssize_t rrtime_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
unsigned long num;
|
|
@@ -275,16 +275,14 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev,
|
|
return count;
|
|
}
|
|
|
|
-static ssize_t acpi_pad_rrtime_show(struct device *dev,
|
|
+static ssize_t rrtime_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time);
|
|
}
|
|
-static DEVICE_ATTR(rrtime, S_IRUGO|S_IWUSR,
|
|
- acpi_pad_rrtime_show,
|
|
- acpi_pad_rrtime_store);
|
|
+static DEVICE_ATTR_RW(rrtime);
|
|
|
|
-static ssize_t acpi_pad_idlepct_store(struct device *dev,
|
|
+static ssize_t idlepct_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
unsigned long num;
|
|
@@ -298,16 +296,14 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev,
|
|
return count;
|
|
}
|
|
|
|
-static ssize_t acpi_pad_idlepct_show(struct device *dev,
|
|
+static ssize_t idlepct_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct);
|
|
}
|
|
-static DEVICE_ATTR(idlepct, S_IRUGO|S_IWUSR,
|
|
- acpi_pad_idlepct_show,
|
|
- acpi_pad_idlepct_store);
|
|
+static DEVICE_ATTR_RW(idlepct);
|
|
|
|
-static ssize_t acpi_pad_idlecpus_store(struct device *dev,
|
|
+static ssize_t idlecpus_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
unsigned long num;
|
|
@@ -319,16 +315,14 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev,
|
|
return count;
|
|
}
|
|
|
|
-static ssize_t acpi_pad_idlecpus_show(struct device *dev,
|
|
+static ssize_t idlecpus_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return cpumap_print_to_pagebuf(false, buf,
|
|
to_cpumask(pad_busy_cpus_bits));
|
|
}
|
|
|
|
-static DEVICE_ATTR(idlecpus, S_IRUGO|S_IWUSR,
|
|
- acpi_pad_idlecpus_show,
|
|
- acpi_pad_idlecpus_store);
|
|
+static DEVICE_ATTR_RW(idlecpus);
|
|
|
|
static int acpi_pad_add_sysfs(struct acpi_device *device)
|
|
{
|
|
diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c
|
|
index 7d45cce0c3c18..e9b8e8305e23e 100644
|
|
--- a/drivers/acpi/acpi_tad.c
|
|
+++ b/drivers/acpi/acpi_tad.c
|
|
@@ -237,7 +237,7 @@ static ssize_t time_show(struct device *dev, struct device_attribute *attr,
|
|
rt.tz, rt.daylight);
|
|
}
|
|
|
|
-static DEVICE_ATTR(time, S_IRUSR | S_IWUSR, time_show, time_store);
|
|
+static DEVICE_ATTR_RW(time);
|
|
|
|
static struct attribute *acpi_tad_time_attrs[] = {
|
|
&dev_attr_time.attr,
|
|
@@ -446,7 +446,7 @@ static ssize_t ac_alarm_show(struct device *dev, struct device_attribute *attr,
|
|
return acpi_tad_alarm_read(dev, buf, ACPI_TAD_AC_TIMER);
|
|
}
|
|
|
|
-static DEVICE_ATTR(ac_alarm, S_IRUSR | S_IWUSR, ac_alarm_show, ac_alarm_store);
|
|
+static DEVICE_ATTR_RW(ac_alarm);
|
|
|
|
static ssize_t ac_policy_store(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
@@ -462,7 +462,7 @@ static ssize_t ac_policy_show(struct device *dev, struct device_attribute *attr,
|
|
return acpi_tad_policy_read(dev, buf, ACPI_TAD_AC_TIMER);
|
|
}
|
|
|
|
-static DEVICE_ATTR(ac_policy, S_IRUSR | S_IWUSR, ac_policy_show, ac_policy_store);
|
|
+static DEVICE_ATTR_RW(ac_policy);
|
|
|
|
static ssize_t ac_status_store(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
@@ -478,7 +478,7 @@ static ssize_t ac_status_show(struct device *dev, struct device_attribute *attr,
|
|
return acpi_tad_status_read(dev, buf, ACPI_TAD_AC_TIMER);
|
|
}
|
|
|
|
-static DEVICE_ATTR(ac_status, S_IRUSR | S_IWUSR, ac_status_show, ac_status_store);
|
|
+static DEVICE_ATTR_RW(ac_status);
|
|
|
|
static struct attribute *acpi_tad_attrs[] = {
|
|
&dev_attr_caps.attr,
|
|
@@ -505,7 +505,7 @@ static ssize_t dc_alarm_show(struct device *dev, struct device_attribute *attr,
|
|
return acpi_tad_alarm_read(dev, buf, ACPI_TAD_DC_TIMER);
|
|
}
|
|
|
|
-static DEVICE_ATTR(dc_alarm, S_IRUSR | S_IWUSR, dc_alarm_show, dc_alarm_store);
|
|
+static DEVICE_ATTR_RW(dc_alarm);
|
|
|
|
static ssize_t dc_policy_store(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
@@ -521,7 +521,7 @@ static ssize_t dc_policy_show(struct device *dev, struct device_attribute *attr,
|
|
return acpi_tad_policy_read(dev, buf, ACPI_TAD_DC_TIMER);
|
|
}
|
|
|
|
-static DEVICE_ATTR(dc_policy, S_IRUSR | S_IWUSR, dc_policy_show, dc_policy_store);
|
|
+static DEVICE_ATTR_RW(dc_policy);
|
|
|
|
static ssize_t dc_status_store(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
@@ -537,7 +537,7 @@ static ssize_t dc_status_show(struct device *dev, struct device_attribute *attr,
|
|
return acpi_tad_status_read(dev, buf, ACPI_TAD_DC_TIMER);
|
|
}
|
|
|
|
-static DEVICE_ATTR(dc_status, S_IRUSR | S_IWUSR, dc_status_show, dc_status_store);
|
|
+static DEVICE_ATTR_RW(dc_status);
|
|
|
|
static struct attribute *acpi_tad_dc_attrs[] = {
|
|
&dev_attr_dc_alarm.attr,
|
|
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
|
|
index 125143c41bb81..8768594c79e58 100644
|
|
--- a/drivers/acpi/acpica/nsrepair2.c
|
|
+++ b/drivers/acpi/acpica/nsrepair2.c
|
|
@@ -375,6 +375,13 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
|
|
|
|
(*element_ptr)->common.reference_count =
|
|
original_ref_count;
|
|
+
|
|
+ /*
|
|
+ * The original_element holds a reference from the package object
|
|
+ * that represents _HID. Since a new element was created by _HID,
|
|
+ * remove the reference from the _CID package.
|
|
+ */
|
|
+ acpi_ut_remove_reference(original_element);
|
|
}
|
|
|
|
element_ptr++;
|
|
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
|
|
index fce7ade2aba92..0c8330ed1ffd5 100644
|
|
--- a/drivers/acpi/apei/ghes.c
|
|
+++ b/drivers/acpi/apei/ghes.c
|
|
@@ -441,28 +441,35 @@ static void ghes_kick_task_work(struct callback_head *head)
|
|
gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, node_len);
|
|
}
|
|
|
|
-static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata,
|
|
- int sev)
|
|
+static bool ghes_do_memory_failure(u64 physical_addr, int flags)
|
|
{
|
|
unsigned long pfn;
|
|
- int flags = -1;
|
|
- int sec_sev = ghes_severity(gdata->error_severity);
|
|
- struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata);
|
|
|
|
if (!IS_ENABLED(CONFIG_ACPI_APEI_MEMORY_FAILURE))
|
|
return false;
|
|
|
|
- if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
|
|
- return false;
|
|
-
|
|
- pfn = mem_err->physical_addr >> PAGE_SHIFT;
|
|
+ pfn = PHYS_PFN(physical_addr);
|
|
if (!pfn_valid(pfn)) {
|
|
pr_warn_ratelimited(FW_WARN GHES_PFX
|
|
"Invalid address in generic error data: %#llx\n",
|
|
- mem_err->physical_addr);
|
|
+ physical_addr);
|
|
return false;
|
|
}
|
|
|
|
+ memory_failure_queue(pfn, flags);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata,
|
|
+ int sev)
|
|
+{
|
|
+ int flags = -1;
|
|
+ int sec_sev = ghes_severity(gdata->error_severity);
|
|
+ struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata);
|
|
+
|
|
+ if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
|
|
+ return false;
|
|
+
|
|
/* iff following two events can be handled properly by now */
|
|
if (sec_sev == GHES_SEV_CORRECTED &&
|
|
(gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED))
|
|
@@ -470,14 +477,56 @@ static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata,
|
|
if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE)
|
|
flags = 0;
|
|
|
|
- if (flags != -1) {
|
|
- memory_failure_queue(pfn, flags);
|
|
- return true;
|
|
- }
|
|
+ if (flags != -1)
|
|
+ return ghes_do_memory_failure(mem_err->physical_addr, flags);
|
|
|
|
return false;
|
|
}
|
|
|
|
+static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, int sev)
|
|
+{
|
|
+ struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
|
|
+ bool queued = false;
|
|
+ int sec_sev, i;
|
|
+ char *p;
|
|
+
|
|
+ log_arm_hw_error(err);
|
|
+
|
|
+ sec_sev = ghes_severity(gdata->error_severity);
|
|
+ if (sev != GHES_SEV_RECOVERABLE || sec_sev != GHES_SEV_RECOVERABLE)
|
|
+ return false;
|
|
+
|
|
+ p = (char *)(err + 1);
|
|
+ for (i = 0; i < err->err_info_num; i++) {
|
|
+ struct cper_arm_err_info *err_info = (struct cper_arm_err_info *)p;
|
|
+ bool is_cache = (err_info->type == CPER_ARM_CACHE_ERROR);
|
|
+ bool has_pa = (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR);
|
|
+ const char *error_type = "unknown error";
|
|
+
|
|
+ /*
|
|
+ * The field (err_info->error_info & BIT(26)) is fixed to set to
|
|
+ * 1 in some old firmware of HiSilicon Kunpeng920. We assume that
|
|
+ * firmware won't mix corrected errors in an uncorrected section,
|
|
+ * and don't filter out 'corrected' error here.
|
|
+ */
|
|
+ if (is_cache && has_pa) {
|
|
+ queued = ghes_do_memory_failure(err_info->physical_fault_addr, 0);
|
|
+ p += err_info->length;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (err_info->type < ARRAY_SIZE(cper_proc_error_type_strs))
|
|
+ error_type = cper_proc_error_type_strs[err_info->type];
|
|
+
|
|
+ pr_warn_ratelimited(FW_WARN GHES_PFX
|
|
+ "Unhandled processor error type: %s\n",
|
|
+ error_type);
|
|
+ p += err_info->length;
|
|
+ }
|
|
+
|
|
+ return queued;
|
|
+}
|
|
+
|
|
/*
|
|
* PCIe AER errors need to be sent to the AER driver for reporting and
|
|
* recovery. The GHES severities map to the following AER severities and
|
|
@@ -605,9 +654,7 @@ static bool ghes_do_proc(struct ghes *ghes,
|
|
ghes_handle_aer(gdata);
|
|
}
|
|
else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
|
|
- struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
|
|
-
|
|
- log_arm_hw_error(err);
|
|
+ queued = ghes_handle_arm_hw_error(gdata, sev);
|
|
} else {
|
|
void *err = acpi_hest_get_payload(gdata);
|
|
|
|
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c
|
|
index 251f961c28cc4..e0d14017706ea 100644
|
|
--- a/drivers/acpi/bgrt.c
|
|
+++ b/drivers/acpi/bgrt.c
|
|
@@ -15,40 +15,19 @@
|
|
static void *bgrt_image;
|
|
static struct kobject *bgrt_kobj;
|
|
|
|
-static ssize_t show_version(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.version);
|
|
-}
|
|
-static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
|
|
-
|
|
-static ssize_t show_status(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.status);
|
|
-}
|
|
-static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
|
|
-
|
|
-static ssize_t show_type(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_type);
|
|
-}
|
|
-static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
|
|
-
|
|
-static ssize_t show_xoffset(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_x);
|
|
-}
|
|
-static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL);
|
|
-
|
|
-static ssize_t show_yoffset(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
-{
|
|
- return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_y);
|
|
-}
|
|
-static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
|
|
+#define BGRT_SHOW(_name, _member) \
|
|
+ static ssize_t _name##_show(struct kobject *kobj, \
|
|
+ struct kobj_attribute *attr, char *buf) \
|
|
+ { \
|
|
+ return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab._member); \
|
|
+ } \
|
|
+ struct kobj_attribute bgrt_attr_##_name = __ATTR_RO(_name)
|
|
+
|
|
+BGRT_SHOW(version, version);
|
|
+BGRT_SHOW(status, status);
|
|
+BGRT_SHOW(type, image_type);
|
|
+BGRT_SHOW(xoffset, image_offset_x);
|
|
+BGRT_SHOW(yoffset, image_offset_y);
|
|
|
|
static ssize_t image_read(struct file *file, struct kobject *kobj,
|
|
struct bin_attribute *attr, char *buf, loff_t off, size_t count)
|
|
@@ -60,11 +39,11 @@ static ssize_t image_read(struct file *file, struct kobject *kobj,
|
|
static BIN_ATTR_RO(image, 0); /* size gets filled in later */
|
|
|
|
static struct attribute *bgrt_attributes[] = {
|
|
- &dev_attr_version.attr,
|
|
- &dev_attr_status.attr,
|
|
- &dev_attr_type.attr,
|
|
- &dev_attr_xoffset.attr,
|
|
- &dev_attr_yoffset.attr,
|
|
+ &bgrt_attr_version.attr,
|
|
+ &bgrt_attr_status.attr,
|
|
+ &bgrt_attr_type.attr,
|
|
+ &bgrt_attr_xoffset.attr,
|
|
+ &bgrt_attr_yoffset.attr,
|
|
NULL,
|
|
};
|
|
|
|
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
|
|
index 1682f8b454a2e..e317214aabec5 100644
|
|
--- a/drivers/acpi/bus.c
|
|
+++ b/drivers/acpi/bus.c
|
|
@@ -1245,6 +1245,7 @@ static int __init acpi_init(void)
|
|
|
|
result = acpi_bus_init();
|
|
if (result) {
|
|
+ kobject_put(acpi_kobj);
|
|
disable_acpi();
|
|
return result;
|
|
}
|
|
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
|
|
index 48ff6821a83d4..ecd2ddc2215f5 100644
|
|
--- a/drivers/acpi/device_pm.c
|
|
+++ b/drivers/acpi/device_pm.c
|
|
@@ -18,6 +18,7 @@
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/suspend.h>
|
|
|
|
+#include "fan.h"
|
|
#include "internal.h"
|
|
|
|
#define _COMPONENT ACPI_POWER_COMPONENT
|
|
@@ -1298,10 +1299,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
|
|
* with the generic ACPI PM domain.
|
|
*/
|
|
static const struct acpi_device_id special_pm_ids[] = {
|
|
- {"PNP0C0B", }, /* Generic ACPI fan */
|
|
- {"INT3404", }, /* Fan */
|
|
- {"INTC1044", }, /* Fan for Tiger Lake generation */
|
|
- {"INTC1048", }, /* Fan for Alder Lake generation */
|
|
+ ACPI_FAN_DEVICE_IDS,
|
|
{}
|
|
};
|
|
struct acpi_device *adev = ACPI_COMPANION(dev);
|
|
diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c
|
|
index bfca116482b8b..fe8c7e79f4726 100644
|
|
--- a/drivers/acpi/device_sysfs.c
|
|
+++ b/drivers/acpi/device_sysfs.c
|
|
@@ -325,11 +325,11 @@ int acpi_device_modalias(struct device *dev, char *buf, int size)
|
|
EXPORT_SYMBOL_GPL(acpi_device_modalias);
|
|
|
|
static ssize_t
|
|
-acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
+modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
|
|
}
|
|
-static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
|
|
+static DEVICE_ATTR_RO(modalias);
|
|
|
|
static ssize_t real_power_state_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
@@ -358,8 +358,8 @@ static ssize_t power_state_show(struct device *dev,
|
|
static DEVICE_ATTR_RO(power_state);
|
|
|
|
static ssize_t
|
|
-acpi_eject_store(struct device *d, struct device_attribute *attr,
|
|
- const char *buf, size_t count)
|
|
+eject_store(struct device *d, struct device_attribute *attr,
|
|
+ const char *buf, size_t count)
|
|
{
|
|
struct acpi_device *acpi_device = to_acpi_device(d);
|
|
acpi_object_type not_used;
|
|
@@ -387,28 +387,28 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
|
|
return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
|
|
}
|
|
|
|
-static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
|
|
+static DEVICE_ATTR_WO(eject);
|
|
|
|
static ssize_t
|
|
-acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
+hid_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
|
|
|
return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
|
|
}
|
|
-static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
|
|
+static DEVICE_ATTR_RO(hid);
|
|
|
|
-static ssize_t acpi_device_uid_show(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
+static ssize_t uid_show(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
{
|
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
|
|
|
return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
|
|
}
|
|
-static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
|
|
+static DEVICE_ATTR_RO(uid);
|
|
|
|
-static ssize_t acpi_device_adr_show(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
+static ssize_t adr_show(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
{
|
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
|
|
|
@@ -417,16 +417,16 @@ static ssize_t acpi_device_adr_show(struct device *dev,
|
|
else
|
|
return sprintf(buf, "0x%08llx\n", acpi_dev->pnp.bus_address);
|
|
}
|
|
-static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
|
|
+static DEVICE_ATTR_RO(adr);
|
|
|
|
-static ssize_t acpi_device_path_show(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
+static ssize_t path_show(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
{
|
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
|
|
|
return acpi_object_path(acpi_dev->handle, buf);
|
|
}
|
|
-static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
|
|
+static DEVICE_ATTR_RO(path);
|
|
|
|
/* sysfs file that shows description text from the ACPI _STR method */
|
|
static ssize_t description_show(struct device *dev,
|
|
@@ -446,7 +446,7 @@ static ssize_t description_show(struct device *dev,
|
|
(wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
|
|
acpi_dev->pnp.str_obj->buffer.length,
|
|
UTF16_LITTLE_ENDIAN, buf,
|
|
- PAGE_SIZE);
|
|
+ PAGE_SIZE - 1);
|
|
|
|
buf[result++] = '\n';
|
|
|
|
@@ -455,8 +455,8 @@ static ssize_t description_show(struct device *dev,
|
|
static DEVICE_ATTR_RO(description);
|
|
|
|
static ssize_t
|
|
-acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
|
|
- char *buf) {
|
|
+sun_show(struct device *dev, struct device_attribute *attr,
|
|
+ char *buf) {
|
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
|
acpi_status status;
|
|
unsigned long long sun;
|
|
@@ -467,11 +467,11 @@ acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
return sprintf(buf, "%llu\n", sun);
|
|
}
|
|
-static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
|
|
+static DEVICE_ATTR_RO(sun);
|
|
|
|
static ssize_t
|
|
-acpi_device_hrv_show(struct device *dev, struct device_attribute *attr,
|
|
- char *buf) {
|
|
+hrv_show(struct device *dev, struct device_attribute *attr,
|
|
+ char *buf) {
|
|
struct acpi_device *acpi_dev = to_acpi_device(dev);
|
|
acpi_status status;
|
|
unsigned long long hrv;
|
|
@@ -482,7 +482,7 @@ acpi_device_hrv_show(struct device *dev, struct device_attribute *attr,
|
|
|
|
return sprintf(buf, "%llu\n", hrv);
|
|
}
|
|
-static DEVICE_ATTR(hrv, 0444, acpi_device_hrv_show, NULL);
|
|
+static DEVICE_ATTR_RO(hrv);
|
|
|
|
static ssize_t status_show(struct device *dev, struct device_attribute *attr,
|
|
char *buf) {
|
|
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
|
|
index 24e076f44d238..0937ceab052e8 100644
|
|
--- a/drivers/acpi/dock.c
|
|
+++ b/drivers/acpi/dock.c
|
|
@@ -484,7 +484,7 @@ int dock_notify(struct acpi_device *adev, u32 event)
|
|
/*
|
|
* show_docked - read method for "docked" file in sysfs
|
|
*/
|
|
-static ssize_t show_docked(struct device *dev,
|
|
+static ssize_t docked_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct dock_station *dock_station = dev->platform_data;
|
|
@@ -493,25 +493,25 @@ static ssize_t show_docked(struct device *dev,
|
|
acpi_bus_get_device(dock_station->handle, &adev);
|
|
return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev));
|
|
}
|
|
-static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
|
|
+static DEVICE_ATTR_RO(docked);
|
|
|
|
/*
|
|
* show_flags - read method for flags file in sysfs
|
|
*/
|
|
-static ssize_t show_flags(struct device *dev,
|
|
+static ssize_t flags_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct dock_station *dock_station = dev->platform_data;
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
|
|
|
|
}
|
|
-static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
|
|
+static DEVICE_ATTR_RO(flags);
|
|
|
|
/*
|
|
* write_undock - write method for "undock" file in sysfs
|
|
*/
|
|
-static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
|
|
- const char *buf, size_t count)
|
|
+static ssize_t undock_store(struct device *dev, struct device_attribute *attr,
|
|
+ const char *buf, size_t count)
|
|
{
|
|
int ret;
|
|
struct dock_station *dock_station = dev->platform_data;
|
|
@@ -525,13 +525,13 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
|
|
acpi_scan_lock_release();
|
|
return ret ? ret: count;
|
|
}
|
|
-static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
|
|
+static DEVICE_ATTR_WO(undock);
|
|
|
|
/*
|
|
* show_dock_uid - read method for "uid" file in sysfs
|
|
*/
|
|
-static ssize_t show_dock_uid(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
+static ssize_t uid_show(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
{
|
|
unsigned long long lbuf;
|
|
struct dock_station *dock_station = dev->platform_data;
|
|
@@ -542,10 +542,10 @@ static ssize_t show_dock_uid(struct device *dev,
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf);
|
|
}
|
|
-static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
|
|
+static DEVICE_ATTR_RO(uid);
|
|
|
|
-static ssize_t show_dock_type(struct device *dev,
|
|
- struct device_attribute *attr, char *buf)
|
|
+static ssize_t type_show(struct device *dev,
|
|
+ struct device_attribute *attr, char *buf)
|
|
{
|
|
struct dock_station *dock_station = dev->platform_data;
|
|
char *type;
|
|
@@ -561,7 +561,7 @@ static ssize_t show_dock_type(struct device *dev,
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", type);
|
|
}
|
|
-static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
|
|
+static DEVICE_ATTR_RO(type);
|
|
|
|
static struct attribute *dock_attributes[] = {
|
|
&dev_attr_docked.attr,
|
|
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
|
|
index e0cb1bcfffb29..be3e0921a6c00 100644
|
|
--- a/drivers/acpi/ec.c
|
|
+++ b/drivers/acpi/ec.c
|
|
@@ -183,6 +183,7 @@ static struct workqueue_struct *ec_query_wq;
|
|
|
|
static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
|
|
static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */
|
|
+static int EC_FLAGS_TRUST_DSDT_GPE; /* Needs DSDT GPE as correction setting */
|
|
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
|
|
|
|
/* --------------------------------------------------------------------------
|
|
@@ -1606,7 +1607,8 @@ static int acpi_ec_add(struct acpi_device *device)
|
|
}
|
|
|
|
if (boot_ec && ec->command_addr == boot_ec->command_addr &&
|
|
- ec->data_addr == boot_ec->data_addr) {
|
|
+ ec->data_addr == boot_ec->data_addr &&
|
|
+ !EC_FLAGS_TRUST_DSDT_GPE) {
|
|
/*
|
|
* Trust PNP0C09 namespace location rather than
|
|
* ECDT ID. But trust ECDT GPE rather than _GPE
|
|
@@ -1829,6 +1831,18 @@ static int ec_correct_ecdt(const struct dmi_system_id *id)
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Some ECDTs contain wrong GPE setting, but they share the same port addresses
|
|
+ * with DSDT EC, don't duplicate the DSDT EC with ECDT EC in this case.
|
|
+ * https://bugzilla.kernel.org/show_bug.cgi?id=209989
|
|
+ */
|
|
+static int ec_honor_dsdt_gpe(const struct dmi_system_id *id)
|
|
+{
|
|
+ pr_debug("Detected system needing DSDT GPE setting.\n");
|
|
+ EC_FLAGS_TRUST_DSDT_GPE = 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* Some DSDTs contain wrong GPE setting.
|
|
* Asus FX502VD/VE, GL702VMK, X550VXK, X580VD
|
|
@@ -1859,6 +1873,22 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "GL702VMK"),}, NULL},
|
|
{
|
|
+ ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BA", {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "X505BA"),}, NULL},
|
|
+ {
|
|
+ ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BP", {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "X505BP"),}, NULL},
|
|
+ {
|
|
+ ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BA", {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "X542BA"),}, NULL},
|
|
+ {
|
|
+ ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BP", {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "X542BP"),}, NULL},
|
|
+ {
|
|
ec_honor_ecdt_gpe, "ASUS X550VXK", {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "X550VXK"),}, NULL},
|
|
@@ -1867,6 +1897,11 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL},
|
|
{
|
|
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=209989 */
|
|
+ ec_honor_dsdt_gpe, "HP Pavilion Gaming Laptop 15-cx0xxx", {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-cx0xxx"),}, NULL},
|
|
+ {
|
|
ec_clear_on_resume, "Samsung hardware", {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
|
|
{},
|
|
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
|
|
index 66c3983f0ccca..5cd0ceb50bc8a 100644
|
|
--- a/drivers/acpi/fan.c
|
|
+++ b/drivers/acpi/fan.c
|
|
@@ -16,6 +16,8 @@
|
|
#include <linux/platform_device.h>
|
|
#include <linux/sort.h>
|
|
|
|
+#include "fan.h"
|
|
+
|
|
MODULE_AUTHOR("Paul Diefenbaugh");
|
|
MODULE_DESCRIPTION("ACPI Fan Driver");
|
|
MODULE_LICENSE("GPL");
|
|
@@ -24,10 +26,7 @@ static int acpi_fan_probe(struct platform_device *pdev);
|
|
static int acpi_fan_remove(struct platform_device *pdev);
|
|
|
|
static const struct acpi_device_id fan_device_ids[] = {
|
|
- {"PNP0C0B", 0},
|
|
- {"INT3404", 0},
|
|
- {"INTC1044", 0},
|
|
- {"INTC1048", 0},
|
|
+ ACPI_FAN_DEVICE_IDS,
|
|
{"", 0},
|
|
};
|
|
MODULE_DEVICE_TABLE(acpi, fan_device_ids);
|
|
diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h
|
|
new file mode 100644
|
|
index 0000000000000..dc9a6efa514b0
|
|
--- /dev/null
|
|
+++ b/drivers/acpi/fan.h
|
|
@@ -0,0 +1,13 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0-only */
|
|
+
|
|
+/*
|
|
+ * ACPI fan device IDs are shared between the fan driver and the device power
|
|
+ * management code.
|
|
+ *
|
|
+ * Add new device IDs before the generic ACPI fan one.
|
|
+ */
|
|
+#define ACPI_FAN_DEVICE_IDS \
|
|
+ {"INT3404", }, /* Fan */ \
|
|
+ {"INTC1044", }, /* Fan for Tiger Lake generation */ \
|
|
+ {"INTC1048", }, /* Fan for Alder Lake generation */ \
|
|
+ {"PNP0C0B", } /* Generic ACPI fan */
|
|
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
|
|
index 8048da85b7e07..61115ed8b93fb 100644
|
|
--- a/drivers/acpi/power.c
|
|
+++ b/drivers/acpi/power.c
|
|
@@ -886,15 +886,16 @@ static void acpi_release_power_resource(struct device *dev)
|
|
kfree(resource);
|
|
}
|
|
|
|
-static ssize_t acpi_power_in_use_show(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- char *buf) {
|
|
+static ssize_t resource_in_use_show(struct device *dev,
|
|
+ struct device_attribute *attr,
|
|
+ char *buf)
|
|
+{
|
|
struct acpi_power_resource *resource;
|
|
|
|
resource = to_power_resource(to_acpi_device(dev));
|
|
return sprintf(buf, "%u\n", !!resource->ref_count);
|
|
}
|
|
-static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL);
|
|
+static DEVICE_ATTR_RO(resource_in_use);
|
|
|
|
static void acpi_power_sysfs_remove(struct acpi_device *device)
|
|
{
|
|
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
|
|
index fb161a21d0aec..8377c3ed10ffa 100644
|
|
--- a/drivers/acpi/processor_idle.c
|
|
+++ b/drivers/acpi/processor_idle.c
|
|
@@ -16,6 +16,7 @@
|
|
#include <linux/acpi.h>
|
|
#include <linux/dmi.h>
|
|
#include <linux/sched.h> /* need_resched() */
|
|
+#include <linux/sort.h>
|
|
#include <linux/tick.h>
|
|
#include <linux/cpuidle.h>
|
|
#include <linux/cpu.h>
|
|
@@ -389,10 +390,37 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
|
return;
|
|
}
|
|
|
|
+static int acpi_cst_latency_cmp(const void *a, const void *b)
|
|
+{
|
|
+ const struct acpi_processor_cx *x = a, *y = b;
|
|
+
|
|
+ if (!(x->valid && y->valid))
|
|
+ return 0;
|
|
+ if (x->latency > y->latency)
|
|
+ return 1;
|
|
+ if (x->latency < y->latency)
|
|
+ return -1;
|
|
+ return 0;
|
|
+}
|
|
+static void acpi_cst_latency_swap(void *a, void *b, int n)
|
|
+{
|
|
+ struct acpi_processor_cx *x = a, *y = b;
|
|
+ u32 tmp;
|
|
+
|
|
+ if (!(x->valid && y->valid))
|
|
+ return;
|
|
+ tmp = x->latency;
|
|
+ x->latency = y->latency;
|
|
+ y->latency = tmp;
|
|
+}
|
|
+
|
|
static int acpi_processor_power_verify(struct acpi_processor *pr)
|
|
{
|
|
unsigned int i;
|
|
unsigned int working = 0;
|
|
+ unsigned int last_latency = 0;
|
|
+ unsigned int last_type = 0;
|
|
+ bool buggy_latency = false;
|
|
|
|
pr->power.timer_broadcast_on_state = INT_MAX;
|
|
|
|
@@ -416,12 +444,24 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
|
|
}
|
|
if (!cx->valid)
|
|
continue;
|
|
+ if (cx->type >= last_type && cx->latency < last_latency)
|
|
+ buggy_latency = true;
|
|
+ last_latency = cx->latency;
|
|
+ last_type = cx->type;
|
|
|
|
lapic_timer_check_state(i, pr, cx);
|
|
tsc_check_state(cx->type);
|
|
working++;
|
|
}
|
|
|
|
+ if (buggy_latency) {
|
|
+ pr_notice("FW issue: working around C-state latencies out of order\n");
|
|
+ sort(&pr->power.states[1], max_cstate,
|
|
+ sizeof(struct acpi_processor_cx),
|
|
+ acpi_cst_latency_cmp,
|
|
+ acpi_cst_latency_swap);
|
|
+ }
|
|
+
|
|
lapic_timer_propagate_broadcast(pr);
|
|
|
|
return (working);
|
|
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
|
|
index f2f5f1dc7c61d..9d82440a1d75b 100644
|
|
--- a/drivers/acpi/resource.c
|
|
+++ b/drivers/acpi/resource.c
|
|
@@ -430,6 +430,13 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
|
|
}
|
|
}
|
|
|
|
+static bool irq_is_legacy(struct acpi_resource_irq *irq)
|
|
+{
|
|
+ return irq->triggering == ACPI_EDGE_SENSITIVE &&
|
|
+ irq->polarity == ACPI_ACTIVE_HIGH &&
|
|
+ irq->shareable == ACPI_EXCLUSIVE;
|
|
+}
|
|
+
|
|
/**
|
|
* acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
|
|
* @ares: Input ACPI resource object.
|
|
@@ -468,7 +475,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
|
|
}
|
|
acpi_dev_get_irqresource(res, irq->interrupts[index],
|
|
irq->triggering, irq->polarity,
|
|
- irq->shareable, true);
|
|
+ irq->shareable, irq_is_legacy(irq));
|
|
break;
|
|
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
|
|
ext_irq = &ares->data.extended_irq;
|
|
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
|
|
index 83cd4c95faf0d..33474fd969913 100644
|
|
--- a/drivers/acpi/video_detect.c
|
|
+++ b/drivers/acpi/video_detect.c
|
|
@@ -385,6 +385,30 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
|
DMI_MATCH(DMI_BOARD_NAME, "BA51_MV"),
|
|
},
|
|
},
|
|
+ {
|
|
+ .callback = video_detect_force_native,
|
|
+ .ident = "ASUSTeK COMPUTER INC. GA401",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "GA401"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ .callback = video_detect_force_native,
|
|
+ .ident = "ASUSTeK COMPUTER INC. GA502",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "GA502"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ .callback = video_detect_force_native,
|
|
+ .ident = "ASUSTeK COMPUTER INC. GA503",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
|
|
+ },
|
|
+ },
|
|
|
|
/*
|
|
* Desktops which falsely report a backlight and which our heuristics
|
|
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
|
|
index badab67088935..46208ececbb6a 100644
|
|
--- a/drivers/ata/pata_ep93xx.c
|
|
+++ b/drivers/ata/pata_ep93xx.c
|
|
@@ -928,7 +928,7 @@ static int ep93xx_pata_probe(struct platform_device *pdev)
|
|
/* INT[3] (IRQ_EP93XX_EXT3) line connected as pull down */
|
|
irq = platform_get_irq(pdev, 0);
|
|
if (irq < 0) {
|
|
- err = -ENXIO;
|
|
+ err = irq;
|
|
goto err_rel_gpio;
|
|
}
|
|
|
|
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
|
|
index bd87476ab4813..b5a3f710d76de 100644
|
|
--- a/drivers/ata/pata_octeon_cf.c
|
|
+++ b/drivers/ata/pata_octeon_cf.c
|
|
@@ -898,10 +898,11 @@ static int octeon_cf_probe(struct platform_device *pdev)
|
|
return -EINVAL;
|
|
}
|
|
|
|
- irq_handler = octeon_cf_interrupt;
|
|
i = platform_get_irq(dma_dev, 0);
|
|
- if (i > 0)
|
|
+ if (i > 0) {
|
|
irq = i;
|
|
+ irq_handler = octeon_cf_interrupt;
|
|
+ }
|
|
}
|
|
of_node_put(dma_node);
|
|
}
|
|
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
|
|
index 479c4b29b8562..303f8c375b3af 100644
|
|
--- a/drivers/ata/pata_rb532_cf.c
|
|
+++ b/drivers/ata/pata_rb532_cf.c
|
|
@@ -115,10 +115,12 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
|
|
}
|
|
|
|
irq = platform_get_irq(pdev, 0);
|
|
- if (irq <= 0) {
|
|
+ if (irq < 0) {
|
|
dev_err(&pdev->dev, "no IRQ resource found\n");
|
|
- return -ENOENT;
|
|
+ return irq;
|
|
}
|
|
+ if (!irq)
|
|
+ return -EINVAL;
|
|
|
|
gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN);
|
|
if (IS_ERR(gpiod)) {
|
|
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
|
|
index 64b2ef15ec191..8440203e835ed 100644
|
|
--- a/drivers/ata/sata_highbank.c
|
|
+++ b/drivers/ata/sata_highbank.c
|
|
@@ -469,10 +469,12 @@ static int ahci_highbank_probe(struct platform_device *pdev)
|
|
}
|
|
|
|
irq = platform_get_irq(pdev, 0);
|
|
- if (irq <= 0) {
|
|
+ if (irq < 0) {
|
|
dev_err(dev, "no irq\n");
|
|
- return -EINVAL;
|
|
+ return irq;
|
|
}
|
|
+ if (!irq)
|
|
+ return -EINVAL;
|
|
|
|
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
|
|
if (!hpriv) {
|
|
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
|
|
index a58084c2ed7ce..06d44ae9701f1 100644
|
|
--- a/drivers/block/loop.c
|
|
+++ b/drivers/block/loop.c
|
|
@@ -1161,6 +1161,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
|
|
blk_queue_physical_block_size(lo->lo_queue, bsize);
|
|
blk_queue_io_min(lo->lo_queue, bsize);
|
|
|
|
+ loop_config_discard(lo);
|
|
loop_update_rotational(lo);
|
|
loop_update_dio(lo);
|
|
loop_sysfs_init(lo);
|
|
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
|
|
index ce9dcffdc5bfd..7551cac3fd7a9 100644
|
|
--- a/drivers/bluetooth/btqca.c
|
|
+++ b/drivers/bluetooth/btqca.c
|
|
@@ -143,7 +143,7 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
|
|
EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
|
|
|
|
static void qca_tlv_check_data(struct qca_fw_config *config,
|
|
- const struct firmware *fw, enum qca_btsoc_type soc_type)
|
|
+ u8 *fw_data, enum qca_btsoc_type soc_type)
|
|
{
|
|
const u8 *data;
|
|
u32 type_len;
|
|
@@ -154,7 +154,7 @@ static void qca_tlv_check_data(struct qca_fw_config *config,
|
|
struct tlv_type_nvm *tlv_nvm;
|
|
uint8_t nvm_baud_rate = config->user_baud_rate;
|
|
|
|
- tlv = (struct tlv_type_hdr *)fw->data;
|
|
+ tlv = (struct tlv_type_hdr *)fw_data;
|
|
|
|
type_len = le32_to_cpu(tlv->type_len);
|
|
length = (type_len >> 8) & 0x00ffffff;
|
|
@@ -350,8 +350,9 @@ static int qca_download_firmware(struct hci_dev *hdev,
|
|
enum qca_btsoc_type soc_type)
|
|
{
|
|
const struct firmware *fw;
|
|
+ u8 *data;
|
|
const u8 *segment;
|
|
- int ret, remain, i = 0;
|
|
+ int ret, size, remain, i = 0;
|
|
|
|
bt_dev_info(hdev, "QCA Downloading %s", config->fwname);
|
|
|
|
@@ -362,10 +363,22 @@ static int qca_download_firmware(struct hci_dev *hdev,
|
|
return ret;
|
|
}
|
|
|
|
- qca_tlv_check_data(config, fw, soc_type);
|
|
+ size = fw->size;
|
|
+ data = vmalloc(fw->size);
|
|
+ if (!data) {
|
|
+ bt_dev_err(hdev, "QCA Failed to allocate memory for file: %s",
|
|
+ config->fwname);
|
|
+ release_firmware(fw);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ memcpy(data, fw->data, size);
|
|
+ release_firmware(fw);
|
|
+
|
|
+ qca_tlv_check_data(config, data, soc_type);
|
|
|
|
- segment = fw->data;
|
|
- remain = fw->size;
|
|
+ segment = data;
|
|
+ remain = size;
|
|
while (remain > 0) {
|
|
int segsize = min(MAX_SIZE_PER_TLV_SEGMENT, remain);
|
|
|
|
@@ -395,7 +408,7 @@ static int qca_download_firmware(struct hci_dev *hdev,
|
|
ret = qca_inject_cmd_complete_event(hdev);
|
|
|
|
out:
|
|
- release_firmware(fw);
|
|
+ vfree(data);
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
|
|
index ad47ff0d55c2e..4184faef9f169 100644
|
|
--- a/drivers/bluetooth/hci_qca.c
|
|
+++ b/drivers/bluetooth/hci_qca.c
|
|
@@ -1809,8 +1809,6 @@ static void qca_power_shutdown(struct hci_uart *hu)
|
|
unsigned long flags;
|
|
enum qca_btsoc_type soc_type = qca_soc_type(hu);
|
|
|
|
- qcadev = serdev_device_get_drvdata(hu->serdev);
|
|
-
|
|
/* From this point we go into power off state. But serial port is
|
|
* still open, stop queueing the IBS data and flush all the buffered
|
|
* data in skb's.
|
|
@@ -1826,6 +1824,8 @@ static void qca_power_shutdown(struct hci_uart *hu)
|
|
if (!hu->serdev)
|
|
return;
|
|
|
|
+ qcadev = serdev_device_get_drvdata(hu->serdev);
|
|
+
|
|
if (qca_is_wcn399x(soc_type)) {
|
|
host_set_baudrate(hu, 2400);
|
|
qca_send_power_pulse(hu, false);
|
|
diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
|
|
index aeb895c084607..044dcdd723a70 100644
|
|
--- a/drivers/bus/mhi/core/pm.c
|
|
+++ b/drivers/bus/mhi/core/pm.c
|
|
@@ -809,6 +809,7 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl)
|
|
|
|
ret = wait_event_timeout(mhi_cntrl->state_event,
|
|
mhi_cntrl->dev_state == MHI_STATE_M0 ||
|
|
+ mhi_cntrl->dev_state == MHI_STATE_M2 ||
|
|
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
|
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
|
|
|
diff --git a/drivers/char/hw_random/exynos-trng.c b/drivers/char/hw_random/exynos-trng.c
|
|
index 8e1fe3f8dd2df..c8db62bc5ff72 100644
|
|
--- a/drivers/char/hw_random/exynos-trng.c
|
|
+++ b/drivers/char/hw_random/exynos-trng.c
|
|
@@ -132,7 +132,7 @@ static int exynos_trng_probe(struct platform_device *pdev)
|
|
return PTR_ERR(trng->mem);
|
|
|
|
pm_runtime_enable(&pdev->dev);
|
|
- ret = pm_runtime_get_sync(&pdev->dev);
|
|
+ ret = pm_runtime_resume_and_get(&pdev->dev);
|
|
if (ret < 0) {
|
|
dev_err(&pdev->dev, "Could not get runtime PM.\n");
|
|
goto err_pm_get;
|
|
@@ -165,7 +165,7 @@ err_register:
|
|
clk_disable_unprepare(trng->clk);
|
|
|
|
err_clock:
|
|
- pm_runtime_put_sync(&pdev->dev);
|
|
+ pm_runtime_put_noidle(&pdev->dev);
|
|
|
|
err_pm_get:
|
|
pm_runtime_disable(&pdev->dev);
|
|
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
|
|
index 89681f07bc787..9468e9520cee0 100644
|
|
--- a/drivers/char/pcmcia/cm4000_cs.c
|
|
+++ b/drivers/char/pcmcia/cm4000_cs.c
|
|
@@ -544,6 +544,10 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
|
|
io_read_num_rec_bytes(iobase, &num_bytes_read);
|
|
if (num_bytes_read >= 4) {
|
|
DEBUGP(2, dev, "NumRecBytes = %i\n", num_bytes_read);
|
|
+ if (num_bytes_read > 4) {
|
|
+ rc = -EIO;
|
|
+ goto exit_setprotocol;
|
|
+ }
|
|
break;
|
|
}
|
|
usleep_range(10000, 11000);
|
|
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
|
|
index 55b9d3965ae1b..69579efb247b3 100644
|
|
--- a/drivers/char/tpm/tpm_tis_core.c
|
|
+++ b/drivers/char/tpm/tpm_tis_core.c
|
|
@@ -196,13 +196,24 @@ static u8 tpm_tis_status(struct tpm_chip *chip)
|
|
return 0;
|
|
|
|
if (unlikely((status & TPM_STS_READ_ZERO) != 0)) {
|
|
- /*
|
|
- * If this trips, the chances are the read is
|
|
- * returning 0xff because the locality hasn't been
|
|
- * acquired. Usually because tpm_try_get_ops() hasn't
|
|
- * been called before doing a TPM operation.
|
|
- */
|
|
- WARN_ONCE(1, "TPM returned invalid status\n");
|
|
+ if (!test_and_set_bit(TPM_TIS_INVALID_STATUS, &priv->flags)) {
|
|
+ /*
|
|
+ * If this trips, the chances are the read is
|
|
+ * returning 0xff because the locality hasn't been
|
|
+ * acquired. Usually because tpm_try_get_ops() hasn't
|
|
+ * been called before doing a TPM operation.
|
|
+ */
|
|
+ dev_err(&chip->dev, "invalid TPM_STS.x 0x%02x, dumping stack for forensics\n",
|
|
+ status);
|
|
+
|
|
+ /*
|
|
+ * Dump stack for forensics, as invalid TPM_STS.x could be
|
|
+ * potentially triggered by impaired tpm_try_get_ops() or
|
|
+ * tpm_find_get_ops().
|
|
+ */
|
|
+ dump_stack();
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
|
|
index 9b2d32a59f670..b2a3c6c72882d 100644
|
|
--- a/drivers/char/tpm/tpm_tis_core.h
|
|
+++ b/drivers/char/tpm/tpm_tis_core.h
|
|
@@ -83,6 +83,7 @@ enum tis_defaults {
|
|
|
|
enum tpm_tis_flags {
|
|
TPM_TIS_ITPM_WORKAROUND = BIT(0),
|
|
+ TPM_TIS_INVALID_STATUS = BIT(1),
|
|
};
|
|
|
|
struct tpm_tis_data {
|
|
@@ -90,7 +91,7 @@ struct tpm_tis_data {
|
|
int locality;
|
|
int irq;
|
|
bool irq_tested;
|
|
- unsigned int flags;
|
|
+ unsigned long flags;
|
|
void __iomem *ilb_base_addr;
|
|
u16 clkrun_enabled;
|
|
wait_queue_head_t int_queue;
|
|
diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c
|
|
index 3856f6ebcb34f..de4209003a448 100644
|
|
--- a/drivers/char/tpm/tpm_tis_spi_main.c
|
|
+++ b/drivers/char/tpm/tpm_tis_spi_main.c
|
|
@@ -260,6 +260,8 @@ static int tpm_tis_spi_remove(struct spi_device *dev)
|
|
}
|
|
|
|
static const struct spi_device_id tpm_tis_spi_id[] = {
|
|
+ { "st33htpm-spi", (unsigned long)tpm_tis_spi_probe },
|
|
+ { "slb9670", (unsigned long)tpm_tis_spi_probe },
|
|
{ "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe },
|
|
{ "cr50", (unsigned long)cr50_spi_probe },
|
|
{}
|
|
diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c
|
|
index 61bb224f63309..cbeb51c804eb5 100644
|
|
--- a/drivers/clk/actions/owl-s500.c
|
|
+++ b/drivers/clk/actions/owl-s500.c
|
|
@@ -127,8 +127,7 @@ static struct clk_factor_table sd_factor_table[] = {
|
|
{ 12, 1, 13 }, { 13, 1, 14 }, { 14, 1, 15 }, { 15, 1, 16 },
|
|
{ 16, 1, 17 }, { 17, 1, 18 }, { 18, 1, 19 }, { 19, 1, 20 },
|
|
{ 20, 1, 21 }, { 21, 1, 22 }, { 22, 1, 23 }, { 23, 1, 24 },
|
|
- { 24, 1, 25 }, { 25, 1, 26 }, { 26, 1, 27 }, { 27, 1, 28 },
|
|
- { 28, 1, 29 }, { 29, 1, 30 }, { 30, 1, 31 }, { 31, 1, 32 },
|
|
+ { 24, 1, 25 },
|
|
|
|
/* bit8: /128 */
|
|
{ 256, 1, 1 * 128 }, { 257, 1, 2 * 128 }, { 258, 1, 3 * 128 }, { 259, 1, 4 * 128 },
|
|
@@ -137,19 +136,20 @@ static struct clk_factor_table sd_factor_table[] = {
|
|
{ 268, 1, 13 * 128 }, { 269, 1, 14 * 128 }, { 270, 1, 15 * 128 }, { 271, 1, 16 * 128 },
|
|
{ 272, 1, 17 * 128 }, { 273, 1, 18 * 128 }, { 274, 1, 19 * 128 }, { 275, 1, 20 * 128 },
|
|
{ 276, 1, 21 * 128 }, { 277, 1, 22 * 128 }, { 278, 1, 23 * 128 }, { 279, 1, 24 * 128 },
|
|
- { 280, 1, 25 * 128 }, { 281, 1, 26 * 128 }, { 282, 1, 27 * 128 }, { 283, 1, 28 * 128 },
|
|
- { 284, 1, 29 * 128 }, { 285, 1, 30 * 128 }, { 286, 1, 31 * 128 }, { 287, 1, 32 * 128 },
|
|
+ { 280, 1, 25 * 128 },
|
|
{ 0, 0, 0 },
|
|
};
|
|
|
|
-static struct clk_factor_table bisp_factor_table[] = {
|
|
- { 0, 1, 1 }, { 1, 1, 2 }, { 2, 1, 3 }, { 3, 1, 4 },
|
|
- { 4, 1, 5 }, { 5, 1, 6 }, { 6, 1, 7 }, { 7, 1, 8 },
|
|
+static struct clk_factor_table de_factor_table[] = {
|
|
+ { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 },
|
|
+ { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 },
|
|
+ { 8, 1, 12 },
|
|
{ 0, 0, 0 },
|
|
};
|
|
|
|
-static struct clk_factor_table ahb_factor_table[] = {
|
|
- { 1, 1, 2 }, { 2, 1, 3 },
|
|
+static struct clk_factor_table hde_factor_table[] = {
|
|
+ { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 },
|
|
+ { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 },
|
|
{ 0, 0, 0 },
|
|
};
|
|
|
|
@@ -158,6 +158,13 @@ static struct clk_div_table rmii_ref_div_table[] = {
|
|
{ 0, 0 },
|
|
};
|
|
|
|
+static struct clk_div_table std12rate_div_table[] = {
|
|
+ { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
|
|
+ { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },
|
|
+ { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },
|
|
+ { 0, 0 },
|
|
+};
|
|
+
|
|
static struct clk_div_table i2s_div_table[] = {
|
|
{ 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
|
|
{ 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 },
|
|
@@ -174,7 +181,6 @@ static struct clk_div_table nand_div_table[] = {
|
|
|
|
/* mux clock */
|
|
static OWL_MUX(dev_clk, "dev_clk", dev_clk_mux_p, CMU_DEVPLL, 12, 1, CLK_SET_RATE_PARENT);
|
|
-static OWL_MUX(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, CMU_BUSCLK1, 8, 3, CLK_SET_RATE_PARENT);
|
|
|
|
/* gate clocks */
|
|
static OWL_GATE(gpio_clk, "gpio_clk", "apb_clk", CMU_DEVCLKEN0, 18, 0, 0);
|
|
@@ -187,45 +193,54 @@ static OWL_GATE(timer_clk, "timer_clk", "hosc", CMU_DEVCLKEN1, 27, 0, 0);
|
|
static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0);
|
|
|
|
/* divider clocks */
|
|
-static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0);
|
|
+static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 2, 2, NULL, 0, 0);
|
|
static OWL_DIVIDER(apb_clk, "apb_clk", "ahb_clk", CMU_BUSCLK1, 14, 2, NULL, 0, 0);
|
|
static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0);
|
|
|
|
/* factor clocks */
|
|
-static OWL_FACTOR(ahb_clk, "ahb_clk", "h_clk", CMU_BUSCLK1, 2, 2, ahb_factor_table, 0, 0);
|
|
-static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 3, bisp_factor_table, 0, 0);
|
|
-static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 3, bisp_factor_table, 0, 0);
|
|
+static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 4, de_factor_table, 0, 0);
|
|
+static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 4, de_factor_table, 0, 0);
|
|
|
|
/* composite clocks */
|
|
+static OWL_COMP_DIV(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p,
|
|
+ OWL_MUX_HW(CMU_BUSCLK1, 8, 3),
|
|
+ { 0 },
|
|
+ OWL_DIVIDER_HW(CMU_BUSCLK1, 12, 2, 0, NULL),
|
|
+ CLK_SET_RATE_PARENT);
|
|
+
|
|
+static OWL_COMP_FIXED_FACTOR(ahb_clk, "ahb_clk", "h_clk",
|
|
+ { 0 },
|
|
+ 1, 1, 0);
|
|
+
|
|
static OWL_COMP_FACTOR(vce_clk, "vce_clk", hde_clk_mux_p,
|
|
OWL_MUX_HW(CMU_VCECLK, 4, 2),
|
|
OWL_GATE_HW(CMU_DEVCLKEN0, 26, 0),
|
|
- OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, bisp_factor_table),
|
|
+ OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, hde_factor_table),
|
|
0);
|
|
|
|
static OWL_COMP_FACTOR(vde_clk, "vde_clk", hde_clk_mux_p,
|
|
OWL_MUX_HW(CMU_VDECLK, 4, 2),
|
|
OWL_GATE_HW(CMU_DEVCLKEN0, 25, 0),
|
|
- OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, bisp_factor_table),
|
|
+ OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, hde_factor_table),
|
|
0);
|
|
|
|
-static OWL_COMP_FACTOR(bisp_clk, "bisp_clk", bisp_clk_mux_p,
|
|
+static OWL_COMP_DIV(bisp_clk, "bisp_clk", bisp_clk_mux_p,
|
|
OWL_MUX_HW(CMU_BISPCLK, 4, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
|
|
- OWL_FACTOR_HW(CMU_BISPCLK, 0, 3, 0, bisp_factor_table),
|
|
+ OWL_DIVIDER_HW(CMU_BISPCLK, 0, 4, 0, std12rate_div_table),
|
|
0);
|
|
|
|
-static OWL_COMP_FACTOR(sensor0_clk, "sensor0_clk", sensor_clk_mux_p,
|
|
+static OWL_COMP_DIV(sensor0_clk, "sensor0_clk", sensor_clk_mux_p,
|
|
OWL_MUX_HW(CMU_SENSORCLK, 4, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
|
|
- OWL_FACTOR_HW(CMU_SENSORCLK, 0, 3, 0, bisp_factor_table),
|
|
- CLK_IGNORE_UNUSED);
|
|
+ OWL_DIVIDER_HW(CMU_SENSORCLK, 0, 4, 0, std12rate_div_table),
|
|
+ 0);
|
|
|
|
-static OWL_COMP_FACTOR(sensor1_clk, "sensor1_clk", sensor_clk_mux_p,
|
|
+static OWL_COMP_DIV(sensor1_clk, "sensor1_clk", sensor_clk_mux_p,
|
|
OWL_MUX_HW(CMU_SENSORCLK, 4, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
|
|
- OWL_FACTOR_HW(CMU_SENSORCLK, 8, 3, 0, bisp_factor_table),
|
|
- CLK_IGNORE_UNUSED);
|
|
+ OWL_DIVIDER_HW(CMU_SENSORCLK, 8, 4, 0, std12rate_div_table),
|
|
+ 0);
|
|
|
|
static OWL_COMP_FACTOR(sd0_clk, "sd0_clk", sd_clk_mux_p,
|
|
OWL_MUX_HW(CMU_SD0CLK, 9, 1),
|
|
@@ -305,7 +320,7 @@ static OWL_COMP_FIXED_FACTOR(i2c3_clk, "i2c3_clk", "ethernet_pll_clk",
|
|
static OWL_COMP_DIV(uart0_clk, "uart0_clk", uart_clk_mux_p,
|
|
OWL_MUX_HW(CMU_UART0CLK, 16, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN1, 6, 0),
|
|
- OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
+ OWL_DIVIDER_HW(CMU_UART0CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
CLK_IGNORE_UNUSED);
|
|
|
|
static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p,
|
|
@@ -317,31 +332,31 @@ static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p,
|
|
static OWL_COMP_DIV(uart2_clk, "uart2_clk", uart_clk_mux_p,
|
|
OWL_MUX_HW(CMU_UART2CLK, 16, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN1, 8, 0),
|
|
- OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
+ OWL_DIVIDER_HW(CMU_UART2CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
CLK_IGNORE_UNUSED);
|
|
|
|
static OWL_COMP_DIV(uart3_clk, "uart3_clk", uart_clk_mux_p,
|
|
OWL_MUX_HW(CMU_UART3CLK, 16, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN1, 19, 0),
|
|
- OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
+ OWL_DIVIDER_HW(CMU_UART3CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
CLK_IGNORE_UNUSED);
|
|
|
|
static OWL_COMP_DIV(uart4_clk, "uart4_clk", uart_clk_mux_p,
|
|
OWL_MUX_HW(CMU_UART4CLK, 16, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN1, 20, 0),
|
|
- OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
+ OWL_DIVIDER_HW(CMU_UART4CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
CLK_IGNORE_UNUSED);
|
|
|
|
static OWL_COMP_DIV(uart5_clk, "uart5_clk", uart_clk_mux_p,
|
|
OWL_MUX_HW(CMU_UART5CLK, 16, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN1, 21, 0),
|
|
- OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
+ OWL_DIVIDER_HW(CMU_UART5CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
CLK_IGNORE_UNUSED);
|
|
|
|
static OWL_COMP_DIV(uart6_clk, "uart6_clk", uart_clk_mux_p,
|
|
OWL_MUX_HW(CMU_UART6CLK, 16, 1),
|
|
OWL_GATE_HW(CMU_DEVCLKEN1, 18, 0),
|
|
- OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
+ OWL_DIVIDER_HW(CMU_UART6CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
|
|
CLK_IGNORE_UNUSED);
|
|
|
|
static OWL_COMP_DIV(i2srx_clk, "i2srx_clk", i2s_clk_mux_p,
|
|
diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c
|
|
index e0446e66fa645..eb22f4fdbc6b4 100644
|
|
--- a/drivers/clk/clk-si5341.c
|
|
+++ b/drivers/clk/clk-si5341.c
|
|
@@ -92,12 +92,22 @@ struct clk_si5341_output_config {
|
|
#define SI5341_PN_BASE 0x0002
|
|
#define SI5341_DEVICE_REV 0x0005
|
|
#define SI5341_STATUS 0x000C
|
|
+#define SI5341_LOS 0x000D
|
|
+#define SI5341_STATUS_STICKY 0x0011
|
|
+#define SI5341_LOS_STICKY 0x0012
|
|
#define SI5341_SOFT_RST 0x001C
|
|
#define SI5341_IN_SEL 0x0021
|
|
+#define SI5341_DEVICE_READY 0x00FE
|
|
#define SI5341_XAXB_CFG 0x090E
|
|
#define SI5341_IN_EN 0x0949
|
|
#define SI5341_INX_TO_PFD_EN 0x094A
|
|
|
|
+/* Status bits */
|
|
+#define SI5341_STATUS_SYSINCAL BIT(0)
|
|
+#define SI5341_STATUS_LOSXAXB BIT(1)
|
|
+#define SI5341_STATUS_LOSREF BIT(2)
|
|
+#define SI5341_STATUS_LOL BIT(3)
|
|
+
|
|
/* Input selection */
|
|
#define SI5341_IN_SEL_MASK 0x06
|
|
#define SI5341_IN_SEL_SHIFT 1
|
|
@@ -340,6 +350,8 @@ static const struct si5341_reg_default si5341_reg_defaults[] = {
|
|
{ 0x094A, 0x00 }, /* INx_TO_PFD_EN (disabled) */
|
|
{ 0x0A02, 0x00 }, /* Not in datasheet */
|
|
{ 0x0B44, 0x0F }, /* PDIV_ENB (datasheet does not mention what it is) */
|
|
+ { 0x0B57, 0x10 }, /* VCO_RESET_CALCODE (not described in datasheet) */
|
|
+ { 0x0B58, 0x05 }, /* VCO_RESET_CALCODE (not described in datasheet) */
|
|
};
|
|
|
|
/* Read and interpret a 44-bit followed by a 32-bit value in the regmap */
|
|
@@ -623,6 +635,9 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw,
|
|
SI5341_SYNTH_N_NUM(synth->index), &n_num, &n_den);
|
|
if (err < 0)
|
|
return err;
|
|
+ /* Check for bogus/uninitialized settings */
|
|
+ if (!n_num || !n_den)
|
|
+ return 0;
|
|
|
|
/*
|
|
* n_num and n_den are shifted left as much as possible, so to prevent
|
|
@@ -806,6 +821,9 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
|
{
|
|
unsigned long r;
|
|
|
|
+ if (!rate)
|
|
+ return 0;
|
|
+
|
|
r = *parent_rate >> 1;
|
|
|
|
/* If rate is an even divisor, no changes to parent required */
|
|
@@ -834,11 +852,16 @@ static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
|
unsigned long parent_rate)
|
|
{
|
|
struct clk_si5341_output *output = to_clk_si5341_output(hw);
|
|
- /* Frequency divider is (r_div + 1) * 2 */
|
|
- u32 r_div = (parent_rate / rate) >> 1;
|
|
+ u32 r_div;
|
|
int err;
|
|
u8 r[3];
|
|
|
|
+ if (!rate)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /* Frequency divider is (r_div + 1) * 2 */
|
|
+ r_div = (parent_rate / rate) >> 1;
|
|
+
|
|
if (r_div <= 1)
|
|
r_div = 0;
|
|
else if (r_div >= BIT(24))
|
|
@@ -1083,7 +1106,7 @@ static const struct si5341_reg_default si5341_preamble[] = {
|
|
{ 0x0B25, 0x00 },
|
|
{ 0x0502, 0x01 },
|
|
{ 0x0505, 0x03 },
|
|
- { 0x0957, 0x1F },
|
|
+ { 0x0957, 0x17 },
|
|
{ 0x0B4E, 0x1A },
|
|
};
|
|
|
|
@@ -1189,6 +1212,32 @@ static const struct regmap_range_cfg si5341_regmap_ranges[] = {
|
|
},
|
|
};
|
|
|
|
+static int si5341_wait_device_ready(struct i2c_client *client)
|
|
+{
|
|
+ int count;
|
|
+
|
|
+ /* Datasheet warns: Any attempt to read or write any register other
|
|
+ * than DEVICE_READY before DEVICE_READY reads as 0x0F may corrupt the
|
|
+ * NVM programming and may corrupt the register contents, as they are
|
|
+ * read from NVM. Note that this includes accesses to the PAGE register.
|
|
+ * Also: DEVICE_READY is available on every register page, so no page
|
|
+ * change is needed to read it.
|
|
+ * Do this outside regmap to avoid automatic PAGE register access.
|
|
+ * May take up to 300ms to complete.
|
|
+ */
|
|
+ for (count = 0; count < 15; ++count) {
|
|
+ s32 result = i2c_smbus_read_byte_data(client,
|
|
+ SI5341_DEVICE_READY);
|
|
+ if (result < 0)
|
|
+ return result;
|
|
+ if (result == 0x0F)
|
|
+ return 0;
|
|
+ msleep(20);
|
|
+ }
|
|
+ dev_err(&client->dev, "timeout waiting for DEVICE_READY\n");
|
|
+ return -EIO;
|
|
+}
|
|
+
|
|
static const struct regmap_config si5341_regmap_config = {
|
|
.reg_bits = 8,
|
|
.val_bits = 8,
|
|
@@ -1378,6 +1427,7 @@ static int si5341_probe(struct i2c_client *client,
|
|
unsigned int i;
|
|
struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS];
|
|
bool initialization_required;
|
|
+ u32 status;
|
|
|
|
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
|
if (!data)
|
|
@@ -1385,6 +1435,11 @@ static int si5341_probe(struct i2c_client *client,
|
|
|
|
data->i2c_client = client;
|
|
|
|
+ /* Must be done before otherwise touching hardware */
|
|
+ err = si5341_wait_device_ready(client);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
for (i = 0; i < SI5341_NUM_INPUTS; ++i) {
|
|
input = devm_clk_get(&client->dev, si5341_input_clock_names[i]);
|
|
if (IS_ERR(input)) {
|
|
@@ -1540,6 +1595,22 @@ static int si5341_probe(struct i2c_client *client,
|
|
return err;
|
|
}
|
|
|
|
+ /* wait for device to report input clock present and PLL lock */
|
|
+ err = regmap_read_poll_timeout(data->regmap, SI5341_STATUS, status,
|
|
+ !(status & (SI5341_STATUS_LOSREF | SI5341_STATUS_LOL)),
|
|
+ 10000, 250000);
|
|
+ if (err) {
|
|
+ dev_err(&client->dev, "Error waiting for input clock or PLL lock\n");
|
|
+ return err;
|
|
+ }
|
|
+
|
|
+ /* clear sticky alarm bits from initialization */
|
|
+ err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0);
|
|
+ if (err) {
|
|
+ dev_err(&client->dev, "unable to clear sticky status\n");
|
|
+ return err;
|
|
+ }
|
|
+
|
|
/* Free the names, clk framework makes copies */
|
|
for (i = 0; i < data->num_synth; ++i)
|
|
devm_kfree(&client->dev, (void *)synth_clock_names[i]);
|
|
diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c
|
|
index 43db67337bc06..4e741f94baf02 100644
|
|
--- a/drivers/clk/clk-versaclock5.c
|
|
+++ b/drivers/clk/clk-versaclock5.c
|
|
@@ -69,7 +69,10 @@
|
|
#define VC5_FEEDBACK_FRAC_DIV(n) (0x19 + (n))
|
|
#define VC5_RC_CONTROL0 0x1e
|
|
#define VC5_RC_CONTROL1 0x1f
|
|
-/* Register 0x20 is factory reserved */
|
|
+
|
|
+/* These registers are named "Unused Factory Reserved Registers" */
|
|
+#define VC5_RESERVED_X0(idx) (0x20 + ((idx) * 0x10))
|
|
+#define VC5_RESERVED_X0_BYPASS_SYNC BIT(7) /* bypass_sync<idx> bit */
|
|
|
|
/* Output divider control for divider 1,2,3,4 */
|
|
#define VC5_OUT_DIV_CONTROL(idx) (0x21 + ((idx) * 0x10))
|
|
@@ -87,7 +90,6 @@
|
|
#define VC5_OUT_DIV_SKEW_INT(idx, n) (0x2b + ((idx) * 0x10) + (n))
|
|
#define VC5_OUT_DIV_INT(idx, n) (0x2d + ((idx) * 0x10) + (n))
|
|
#define VC5_OUT_DIV_SKEW_FRAC(idx) (0x2f + ((idx) * 0x10))
|
|
-/* Registers 0x30, 0x40, 0x50 are factory reserved */
|
|
|
|
/* Clock control register for clock 1,2 */
|
|
#define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n))
|
|
@@ -140,6 +142,8 @@
|
|
#define VC5_HAS_INTERNAL_XTAL BIT(0)
|
|
/* chip has PFD requency doubler */
|
|
#define VC5_HAS_PFD_FREQ_DBL BIT(1)
|
|
+/* chip has bits to disable FOD sync */
|
|
+#define VC5_HAS_BYPASS_SYNC_BIT BIT(2)
|
|
|
|
/* Supported IDT VC5 models. */
|
|
enum vc5_model {
|
|
@@ -581,6 +585,23 @@ static int vc5_clk_out_prepare(struct clk_hw *hw)
|
|
unsigned int src;
|
|
int ret;
|
|
|
|
+ /*
|
|
+ * When enabling a FOD, all currently enabled FODs are briefly
|
|
+ * stopped in order to synchronize all of them. This causes a clock
|
|
+ * disruption to any unrelated chips that might be already using
|
|
+ * other clock outputs. Bypass the sync feature to avoid the issue,
|
|
+ * which is possible on the VersaClock 6E family via reserved
|
|
+ * registers.
|
|
+ */
|
|
+ if (vc5->chip_info->flags & VC5_HAS_BYPASS_SYNC_BIT) {
|
|
+ ret = regmap_update_bits(vc5->regmap,
|
|
+ VC5_RESERVED_X0(hwdata->num),
|
|
+ VC5_RESERVED_X0_BYPASS_SYNC,
|
|
+ VC5_RESERVED_X0_BYPASS_SYNC);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
/*
|
|
* If the input mux is disabled, enable it first and
|
|
* select source from matching FOD.
|
|
@@ -1102,7 +1123,7 @@ static const struct vc5_chip_info idt_5p49v6965_info = {
|
|
.model = IDT_VC6_5P49V6965,
|
|
.clk_fod_cnt = 4,
|
|
.clk_out_cnt = 5,
|
|
- .flags = 0,
|
|
+ .flags = VC5_HAS_BYPASS_SYNC_BIT,
|
|
};
|
|
|
|
static const struct i2c_device_id vc5_id[] = {
|
|
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
|
|
index 4e6c81a702214..aac6bcc65c20c 100644
|
|
--- a/drivers/clk/imx/clk-imx8mq.c
|
|
+++ b/drivers/clk/imx/clk-imx8mq.c
|
|
@@ -350,46 +350,26 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
|
|
hws[IMX8MQ_VIDEO2_PLL_OUT] = imx_clk_hw_sscg_pll("video2_pll_out", video2_pll_out_sels, ARRAY_SIZE(video2_pll_out_sels), 0, 0, 0, base + 0x54, 0);
|
|
|
|
/* SYS PLL1 fixed output */
|
|
- hws[IMX8MQ_SYS1_PLL_40M_CG] = imx_clk_hw_gate("sys1_pll_40m_cg", "sys1_pll_out", base + 0x30, 9);
|
|
- hws[IMX8MQ_SYS1_PLL_80M_CG] = imx_clk_hw_gate("sys1_pll_80m_cg", "sys1_pll_out", base + 0x30, 11);
|
|
- hws[IMX8MQ_SYS1_PLL_100M_CG] = imx_clk_hw_gate("sys1_pll_100m_cg", "sys1_pll_out", base + 0x30, 13);
|
|
- hws[IMX8MQ_SYS1_PLL_133M_CG] = imx_clk_hw_gate("sys1_pll_133m_cg", "sys1_pll_out", base + 0x30, 15);
|
|
- hws[IMX8MQ_SYS1_PLL_160M_CG] = imx_clk_hw_gate("sys1_pll_160m_cg", "sys1_pll_out", base + 0x30, 17);
|
|
- hws[IMX8MQ_SYS1_PLL_200M_CG] = imx_clk_hw_gate("sys1_pll_200m_cg", "sys1_pll_out", base + 0x30, 19);
|
|
- hws[IMX8MQ_SYS1_PLL_266M_CG] = imx_clk_hw_gate("sys1_pll_266m_cg", "sys1_pll_out", base + 0x30, 21);
|
|
- hws[IMX8MQ_SYS1_PLL_400M_CG] = imx_clk_hw_gate("sys1_pll_400m_cg", "sys1_pll_out", base + 0x30, 23);
|
|
- hws[IMX8MQ_SYS1_PLL_800M_CG] = imx_clk_hw_gate("sys1_pll_800m_cg", "sys1_pll_out", base + 0x30, 25);
|
|
-
|
|
- hws[IMX8MQ_SYS1_PLL_40M] = imx_clk_hw_fixed_factor("sys1_pll_40m", "sys1_pll_40m_cg", 1, 20);
|
|
- hws[IMX8MQ_SYS1_PLL_80M] = imx_clk_hw_fixed_factor("sys1_pll_80m", "sys1_pll_80m_cg", 1, 10);
|
|
- hws[IMX8MQ_SYS1_PLL_100M] = imx_clk_hw_fixed_factor("sys1_pll_100m", "sys1_pll_100m_cg", 1, 8);
|
|
- hws[IMX8MQ_SYS1_PLL_133M] = imx_clk_hw_fixed_factor("sys1_pll_133m", "sys1_pll_133m_cg", 1, 6);
|
|
- hws[IMX8MQ_SYS1_PLL_160M] = imx_clk_hw_fixed_factor("sys1_pll_160m", "sys1_pll_160m_cg", 1, 5);
|
|
- hws[IMX8MQ_SYS1_PLL_200M] = imx_clk_hw_fixed_factor("sys1_pll_200m", "sys1_pll_200m_cg", 1, 4);
|
|
- hws[IMX8MQ_SYS1_PLL_266M] = imx_clk_hw_fixed_factor("sys1_pll_266m", "sys1_pll_266m_cg", 1, 3);
|
|
- hws[IMX8MQ_SYS1_PLL_400M] = imx_clk_hw_fixed_factor("sys1_pll_400m", "sys1_pll_400m_cg", 1, 2);
|
|
- hws[IMX8MQ_SYS1_PLL_800M] = imx_clk_hw_fixed_factor("sys1_pll_800m", "sys1_pll_800m_cg", 1, 1);
|
|
+ hws[IMX8MQ_SYS1_PLL_40M] = imx_clk_hw_fixed_factor("sys1_pll_40m", "sys1_pll_out", 1, 20);
|
|
+ hws[IMX8MQ_SYS1_PLL_80M] = imx_clk_hw_fixed_factor("sys1_pll_80m", "sys1_pll_out", 1, 10);
|
|
+ hws[IMX8MQ_SYS1_PLL_100M] = imx_clk_hw_fixed_factor("sys1_pll_100m", "sys1_pll_out", 1, 8);
|
|
+ hws[IMX8MQ_SYS1_PLL_133M] = imx_clk_hw_fixed_factor("sys1_pll_133m", "sys1_pll_out", 1, 6);
|
|
+ hws[IMX8MQ_SYS1_PLL_160M] = imx_clk_hw_fixed_factor("sys1_pll_160m", "sys1_pll_out", 1, 5);
|
|
+ hws[IMX8MQ_SYS1_PLL_200M] = imx_clk_hw_fixed_factor("sys1_pll_200m", "sys1_pll_out", 1, 4);
|
|
+ hws[IMX8MQ_SYS1_PLL_266M] = imx_clk_hw_fixed_factor("sys1_pll_266m", "sys1_pll_out", 1, 3);
|
|
+ hws[IMX8MQ_SYS1_PLL_400M] = imx_clk_hw_fixed_factor("sys1_pll_400m", "sys1_pll_out", 1, 2);
|
|
+ hws[IMX8MQ_SYS1_PLL_800M] = imx_clk_hw_fixed_factor("sys1_pll_800m", "sys1_pll_out", 1, 1);
|
|
|
|
/* SYS PLL2 fixed output */
|
|
- hws[IMX8MQ_SYS2_PLL_50M_CG] = imx_clk_hw_gate("sys2_pll_50m_cg", "sys2_pll_out", base + 0x3c, 9);
|
|
- hws[IMX8MQ_SYS2_PLL_100M_CG] = imx_clk_hw_gate("sys2_pll_100m_cg", "sys2_pll_out", base + 0x3c, 11);
|
|
- hws[IMX8MQ_SYS2_PLL_125M_CG] = imx_clk_hw_gate("sys2_pll_125m_cg", "sys2_pll_out", base + 0x3c, 13);
|
|
- hws[IMX8MQ_SYS2_PLL_166M_CG] = imx_clk_hw_gate("sys2_pll_166m_cg", "sys2_pll_out", base + 0x3c, 15);
|
|
- hws[IMX8MQ_SYS2_PLL_200M_CG] = imx_clk_hw_gate("sys2_pll_200m_cg", "sys2_pll_out", base + 0x3c, 17);
|
|
- hws[IMX8MQ_SYS2_PLL_250M_CG] = imx_clk_hw_gate("sys2_pll_250m_cg", "sys2_pll_out", base + 0x3c, 19);
|
|
- hws[IMX8MQ_SYS2_PLL_333M_CG] = imx_clk_hw_gate("sys2_pll_333m_cg", "sys2_pll_out", base + 0x3c, 21);
|
|
- hws[IMX8MQ_SYS2_PLL_500M_CG] = imx_clk_hw_gate("sys2_pll_500m_cg", "sys2_pll_out", base + 0x3c, 23);
|
|
- hws[IMX8MQ_SYS2_PLL_1000M_CG] = imx_clk_hw_gate("sys2_pll_1000m_cg", "sys2_pll_out", base + 0x3c, 25);
|
|
-
|
|
- hws[IMX8MQ_SYS2_PLL_50M] = imx_clk_hw_fixed_factor("sys2_pll_50m", "sys2_pll_50m_cg", 1, 20);
|
|
- hws[IMX8MQ_SYS2_PLL_100M] = imx_clk_hw_fixed_factor("sys2_pll_100m", "sys2_pll_100m_cg", 1, 10);
|
|
- hws[IMX8MQ_SYS2_PLL_125M] = imx_clk_hw_fixed_factor("sys2_pll_125m", "sys2_pll_125m_cg", 1, 8);
|
|
- hws[IMX8MQ_SYS2_PLL_166M] = imx_clk_hw_fixed_factor("sys2_pll_166m", "sys2_pll_166m_cg", 1, 6);
|
|
- hws[IMX8MQ_SYS2_PLL_200M] = imx_clk_hw_fixed_factor("sys2_pll_200m", "sys2_pll_200m_cg", 1, 5);
|
|
- hws[IMX8MQ_SYS2_PLL_250M] = imx_clk_hw_fixed_factor("sys2_pll_250m", "sys2_pll_250m_cg", 1, 4);
|
|
- hws[IMX8MQ_SYS2_PLL_333M] = imx_clk_hw_fixed_factor("sys2_pll_333m", "sys2_pll_333m_cg", 1, 3);
|
|
- hws[IMX8MQ_SYS2_PLL_500M] = imx_clk_hw_fixed_factor("sys2_pll_500m", "sys2_pll_500m_cg", 1, 2);
|
|
- hws[IMX8MQ_SYS2_PLL_1000M] = imx_clk_hw_fixed_factor("sys2_pll_1000m", "sys2_pll_1000m_cg", 1, 1);
|
|
+ hws[IMX8MQ_SYS2_PLL_50M] = imx_clk_hw_fixed_factor("sys2_pll_50m", "sys2_pll_out", 1, 20);
|
|
+ hws[IMX8MQ_SYS2_PLL_100M] = imx_clk_hw_fixed_factor("sys2_pll_100m", "sys2_pll_out", 1, 10);
|
|
+ hws[IMX8MQ_SYS2_PLL_125M] = imx_clk_hw_fixed_factor("sys2_pll_125m", "sys2_pll_out", 1, 8);
|
|
+ hws[IMX8MQ_SYS2_PLL_166M] = imx_clk_hw_fixed_factor("sys2_pll_166m", "sys2_pll_out", 1, 6);
|
|
+ hws[IMX8MQ_SYS2_PLL_200M] = imx_clk_hw_fixed_factor("sys2_pll_200m", "sys2_pll_out", 1, 5);
|
|
+ hws[IMX8MQ_SYS2_PLL_250M] = imx_clk_hw_fixed_factor("sys2_pll_250m", "sys2_pll_out", 1, 4);
|
|
+ hws[IMX8MQ_SYS2_PLL_333M] = imx_clk_hw_fixed_factor("sys2_pll_333m", "sys2_pll_out", 1, 3);
|
|
+ hws[IMX8MQ_SYS2_PLL_500M] = imx_clk_hw_fixed_factor("sys2_pll_500m", "sys2_pll_out", 1, 2);
|
|
+ hws[IMX8MQ_SYS2_PLL_1000M] = imx_clk_hw_fixed_factor("sys2_pll_1000m", "sys2_pll_out", 1, 1);
|
|
|
|
np = dev->of_node;
|
|
base = devm_platform_ioremap_resource(pdev, 0);
|
|
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
|
|
index b814d44917a5d..2876bb83d9d0e 100644
|
|
--- a/drivers/clk/meson/g12a.c
|
|
+++ b/drivers/clk/meson/g12a.c
|
|
@@ -1602,7 +1602,7 @@ static struct clk_regmap g12b_cpub_clk_trace = {
|
|
};
|
|
|
|
static const struct pll_mult_range g12a_gp0_pll_mult_range = {
|
|
- .min = 55,
|
|
+ .min = 125,
|
|
.max = 255,
|
|
};
|
|
|
|
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
|
|
index 564431130a760..1a571c04a76cb 100644
|
|
--- a/drivers/clk/qcom/clk-alpha-pll.c
|
|
+++ b/drivers/clk/qcom/clk-alpha-pll.c
|
|
@@ -1214,7 +1214,7 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw)
|
|
return -EINVAL;
|
|
|
|
/* Setup PLL for calibration frequency */
|
|
- regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l);
|
|
+ regmap_write(pll->clkr.regmap, PLL_CAL_L_VAL(pll), cal_l);
|
|
|
|
/* Bringup the PLL at calibration frequency */
|
|
ret = clk_alpha_pll_enable(hw);
|
|
diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c
|
|
index bb3e80928ebe8..438075a50b9f2 100644
|
|
--- a/drivers/clk/socfpga/clk-agilex.c
|
|
+++ b/drivers/clk/socfpga/clk-agilex.c
|
|
@@ -186,6 +186,41 @@ static const struct clk_parent_data noc_mux[] = {
|
|
.name = "boot_clk", },
|
|
};
|
|
|
|
+static const struct clk_parent_data sdmmc_mux[] = {
|
|
+ { .fw_name = "sdmmc_free_clk",
|
|
+ .name = "sdmmc_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
+static const struct clk_parent_data s2f_user1_mux[] = {
|
|
+ { .fw_name = "s2f_user1_free_clk",
|
|
+ .name = "s2f_user1_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
+static const struct clk_parent_data psi_mux[] = {
|
|
+ { .fw_name = "psi_ref_free_clk",
|
|
+ .name = "psi_ref_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
+static const struct clk_parent_data gpio_db_mux[] = {
|
|
+ { .fw_name = "gpio_db_free_clk",
|
|
+ .name = "gpio_db_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
+static const struct clk_parent_data emac_ptp_mux[] = {
|
|
+ { .fw_name = "emac_ptp_free_clk",
|
|
+ .name = "emac_ptp_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
/* clocks in AO (always on) controller */
|
|
static const struct stratix10_pll_clock agilex_pll_clks[] = {
|
|
{ AGILEX_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
|
|
@@ -211,11 +246,9 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = {
|
|
{ AGILEX_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux),
|
|
0, 0x3C, 0, 0, 0},
|
|
{ AGILEX_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
|
|
- 0, 0x40, 0, 0, 1},
|
|
- { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
|
|
- 0, 4, 0, 0},
|
|
- { AGILEX_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
|
|
- 0, 0, 0, 0x30, 1},
|
|
+ 0, 0x40, 0, 0, 0},
|
|
+ { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0,
|
|
+ 0, 4, 0x30, 1},
|
|
{ AGILEX_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
|
|
0, 0xD4, 0, 0x88, 0},
|
|
{ AGILEX_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
|
|
@@ -225,7 +258,7 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = {
|
|
{ AGILEX_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
|
|
ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3},
|
|
{ AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
|
|
- ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0x88, 4},
|
|
+ ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0, 0},
|
|
{ AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux,
|
|
ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0, 0},
|
|
{ AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux,
|
|
@@ -241,24 +274,24 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = {
|
|
0, 0, 0, 0, 0, 0, 4},
|
|
{ AGILEX_MPU_CCU_CLK, "mpu_ccu_clk", "mpu_clk", NULL, 1, 0, 0x24,
|
|
0, 0, 0, 0, 0, 0, 2},
|
|
- { AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24,
|
|
- 1, 0x44, 0, 2, 0, 0, 0},
|
|
- { AGILEX_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x24,
|
|
- 2, 0x44, 8, 2, 0, 0, 0},
|
|
+ { AGILEX_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
|
|
+ 1, 0x44, 0, 2, 0x30, 1, 0},
|
|
+ { AGILEX_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
|
|
+ 2, 0x44, 8, 2, 0x30, 1, 0},
|
|
/*
|
|
* The l4_sp_clk feeds a 100 MHz clock to various peripherals, one of them
|
|
* being the SP timers, thus cannot get gated.
|
|
*/
|
|
- { AGILEX_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x24,
|
|
- 3, 0x44, 16, 2, 0, 0, 0},
|
|
- { AGILEX_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x24,
|
|
- 4, 0x44, 24, 2, 0, 0, 0},
|
|
- { AGILEX_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x24,
|
|
- 4, 0x44, 26, 2, 0, 0, 0},
|
|
+ { AGILEX_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x24,
|
|
+ 3, 0x44, 16, 2, 0x30, 1, 0},
|
|
+ { AGILEX_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
|
|
+ 4, 0x44, 24, 2, 0x30, 1, 0},
|
|
+ { AGILEX_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
|
|
+ 4, 0x44, 26, 2, 0x30, 1, 0},
|
|
{ AGILEX_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24,
|
|
4, 0x44, 28, 1, 0, 0, 0},
|
|
- { AGILEX_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x24,
|
|
- 5, 0, 0, 0, 0, 0, 0},
|
|
+ { AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24,
|
|
+ 5, 0, 0, 0, 0x30, 1, 0},
|
|
{ AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x24,
|
|
6, 0, 0, 0, 0, 0, 0},
|
|
{ AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
|
|
@@ -267,16 +300,16 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = {
|
|
1, 0, 0, 0, 0x94, 27, 0},
|
|
{ AGILEX_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C,
|
|
2, 0, 0, 0, 0x94, 28, 0},
|
|
- { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0x7C,
|
|
- 3, 0, 0, 0, 0, 0, 0},
|
|
- { AGILEX_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0x7C,
|
|
- 4, 0x98, 0, 16, 0, 0, 0},
|
|
- { AGILEX_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0x7C,
|
|
- 5, 0, 0, 0, 0, 0, 4},
|
|
- { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0x7C,
|
|
- 6, 0, 0, 0, 0, 0, 0},
|
|
- { AGILEX_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0x7C,
|
|
- 7, 0, 0, 0, 0, 0, 0},
|
|
+ { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0x7C,
|
|
+ 3, 0, 0, 0, 0x88, 2, 0},
|
|
+ { AGILEX_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0x7C,
|
|
+ 4, 0x98, 0, 16, 0x88, 3, 0},
|
|
+ { AGILEX_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0x7C,
|
|
+ 5, 0, 0, 0, 0x88, 4, 4},
|
|
+ { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0x7C,
|
|
+ 6, 0, 0, 0, 0x88, 5, 0},
|
|
+ { AGILEX_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0x7C,
|
|
+ 7, 0, 0, 0, 0x88, 6, 0},
|
|
{ AGILEX_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
|
|
8, 0, 0, 0, 0, 0, 0},
|
|
{ AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C,
|
|
diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c
|
|
index 397b77b89b166..bae595f17061f 100644
|
|
--- a/drivers/clk/socfpga/clk-periph-s10.c
|
|
+++ b/drivers/clk/socfpga/clk-periph-s10.c
|
|
@@ -49,16 +49,21 @@ static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
|
|
{
|
|
struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk);
|
|
u32 clk_src, mask;
|
|
- u8 parent;
|
|
+ u8 parent = 0;
|
|
|
|
+ /* handle the bypass first */
|
|
if (socfpgaclk->bypass_reg) {
|
|
mask = (0x1 << socfpgaclk->bypass_shift);
|
|
parent = ((readl(socfpgaclk->bypass_reg) & mask) >>
|
|
socfpgaclk->bypass_shift);
|
|
- } else {
|
|
+ if (parent)
|
|
+ return parent;
|
|
+ }
|
|
+
|
|
+ if (socfpgaclk->hw.reg) {
|
|
clk_src = readl(socfpgaclk->hw.reg);
|
|
parent = (clk_src >> CLK_MGR_FREE_SHIFT) &
|
|
- CLK_MGR_FREE_MASK;
|
|
+ CLK_MGR_FREE_MASK;
|
|
}
|
|
return parent;
|
|
}
|
|
diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c
|
|
index 661a8e9bfb9bd..aaf69058b1dca 100644
|
|
--- a/drivers/clk/socfpga/clk-s10.c
|
|
+++ b/drivers/clk/socfpga/clk-s10.c
|
|
@@ -144,6 +144,41 @@ static const struct clk_parent_data mpu_free_mux[] = {
|
|
.name = "f2s-free-clk", },
|
|
};
|
|
|
|
+static const struct clk_parent_data sdmmc_mux[] = {
|
|
+ { .fw_name = "sdmmc_free_clk",
|
|
+ .name = "sdmmc_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
+static const struct clk_parent_data s2f_user1_mux[] = {
|
|
+ { .fw_name = "s2f_user1_free_clk",
|
|
+ .name = "s2f_user1_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
+static const struct clk_parent_data psi_mux[] = {
|
|
+ { .fw_name = "psi_ref_free_clk",
|
|
+ .name = "psi_ref_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
+static const struct clk_parent_data gpio_db_mux[] = {
|
|
+ { .fw_name = "gpio_db_free_clk",
|
|
+ .name = "gpio_db_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
+static const struct clk_parent_data emac_ptp_mux[] = {
|
|
+ { .fw_name = "emac_ptp_free_clk",
|
|
+ .name = "emac_ptp_free_clk", },
|
|
+ { .fw_name = "boot_clk",
|
|
+ .name = "boot_clk", },
|
|
+};
|
|
+
|
|
/* clocks in AO (always on) controller */
|
|
static const struct stratix10_pll_clock s10_pll_clks[] = {
|
|
{ STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0,
|
|
@@ -167,7 +202,7 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
|
|
{ STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux),
|
|
0, 0x48, 0, 0, 0},
|
|
{ STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux),
|
|
- 0, 0x4C, 0, 0, 0},
|
|
+ 0, 0x4C, 0, 0x3C, 1},
|
|
{ STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0,
|
|
0x50, 0, 0, 0},
|
|
{ STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0,
|
|
@@ -200,10 +235,8 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = {
|
|
0, 0xD4, 0, 0, 0},
|
|
{ STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0,
|
|
0xD8, 0, 0, 0},
|
|
- { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0,
|
|
- 0, 4, 0, 0},
|
|
- { STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux),
|
|
- 0, 0, 0, 0x3C, 1},
|
|
+ { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0,
|
|
+ 0, 4, 0x3C, 1},
|
|
{ STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux),
|
|
0, 0, 2, 0xB0, 0},
|
|
{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
|
|
@@ -227,20 +260,20 @@ static const struct stratix10_gate_clock s10_gate_clks[] = {
|
|
0, 0, 0, 0, 0, 0, 4},
|
|
{ STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30,
|
|
0, 0, 0, 0, 0, 0, 2},
|
|
- { STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30,
|
|
- 1, 0x70, 0, 2, 0, 0, 0},
|
|
- { STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30,
|
|
- 2, 0x70, 8, 2, 0, 0, 0},
|
|
- { STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30,
|
|
- 3, 0x70, 16, 2, 0, 0, 0},
|
|
- { STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30,
|
|
- 4, 0x70, 24, 2, 0, 0, 0},
|
|
- { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30,
|
|
- 4, 0x70, 26, 2, 0, 0, 0},
|
|
+ { STRATIX10_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
|
|
+ 1, 0x70, 0, 2, 0x3C, 1, 0},
|
|
+ { STRATIX10_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
|
|
+ 2, 0x70, 8, 2, 0x3C, 1, 0},
|
|
+ { STRATIX10_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x30,
|
|
+ 3, 0x70, 16, 2, 0x3C, 1, 0},
|
|
+ { STRATIX10_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
|
|
+ 4, 0x70, 24, 2, 0x3C, 1, 0},
|
|
+ { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
|
|
+ 4, 0x70, 26, 2, 0x3C, 1, 0},
|
|
{ STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30,
|
|
4, 0x70, 28, 1, 0, 0, 0},
|
|
- { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30,
|
|
- 5, 0, 0, 0, 0, 0, 0},
|
|
+ { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30,
|
|
+ 5, 0, 0, 0, 0x3C, 1, 0},
|
|
{ STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30,
|
|
6, 0, 0, 0, 0, 0, 0},
|
|
{ STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
|
|
@@ -249,16 +282,16 @@ static const struct stratix10_gate_clock s10_gate_clks[] = {
|
|
1, 0, 0, 0, 0xDC, 27, 0},
|
|
{ STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4,
|
|
2, 0, 0, 0, 0xDC, 28, 0},
|
|
- { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4,
|
|
- 3, 0, 0, 0, 0, 0, 0},
|
|
- { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4,
|
|
- 4, 0xE0, 0, 16, 0, 0, 0},
|
|
- { STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4,
|
|
- 5, 0, 0, 0, 0, 0, 4},
|
|
- { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4,
|
|
- 6, 0, 0, 0, 0, 0, 0},
|
|
- { STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4,
|
|
- 7, 0, 0, 0, 0, 0, 0},
|
|
+ { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0xA4,
|
|
+ 3, 0, 0, 0, 0xB0, 2, 0},
|
|
+ { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0xA4,
|
|
+ 4, 0xE0, 0, 16, 0xB0, 3, 0},
|
|
+ { STRATIX10_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0xA4,
|
|
+ 5, 0, 0, 0, 0xB0, 4, 4},
|
|
+ { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0xA4,
|
|
+ 6, 0, 0, 0, 0xB0, 5, 0},
|
|
+ { STRATIX10_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0xA4,
|
|
+ 7, 0, 0, 0, 0xB0, 6, 0},
|
|
{ STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
|
|
8, 0, 0, 0, 0, 0, 0},
|
|
{ STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4,
|
|
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
|
|
index 9cf249c344d9e..31e752318a104 100644
|
|
--- a/drivers/clk/tegra/clk-tegra30.c
|
|
+++ b/drivers/clk/tegra/clk-tegra30.c
|
|
@@ -1248,7 +1248,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
|
|
{ TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 },
|
|
{ TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 },
|
|
{ TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 },
|
|
- { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 600000000, 0 },
|
|
+ { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 300000000, 0 },
|
|
{ TEGRA30_CLK_SPDIF_IN_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
|
|
{ TEGRA30_CLK_I2S0_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
|
|
{ TEGRA30_CLK_I2S1_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
|
|
diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
|
|
index 33eeabf9c3d12..e5c631f1b5cbe 100644
|
|
--- a/drivers/clocksource/timer-ti-dm.c
|
|
+++ b/drivers/clocksource/timer-ti-dm.c
|
|
@@ -78,6 +78,9 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
|
|
|
|
static void omap_timer_restore_context(struct omap_dm_timer *timer)
|
|
{
|
|
+ __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET,
|
|
+ timer->context.ocp_cfg, 0);
|
|
+
|
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG,
|
|
timer->context.twer);
|
|
omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG,
|
|
@@ -95,6 +98,9 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer)
|
|
|
|
static void omap_timer_save_context(struct omap_dm_timer *timer)
|
|
{
|
|
+ timer->context.ocp_cfg =
|
|
+ __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0);
|
|
+
|
|
timer->context.tclr =
|
|
omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
|
|
timer->context.twer =
|
|
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
|
|
index 1e7e3f2ff09f0..ebee0ad559fad 100644
|
|
--- a/drivers/cpufreq/cpufreq.c
|
|
+++ b/drivers/cpufreq/cpufreq.c
|
|
@@ -1368,9 +1368,14 @@ static int cpufreq_online(unsigned int cpu)
|
|
goto out_free_policy;
|
|
}
|
|
|
|
+ /*
|
|
+ * The initialization has succeeded and the policy is online.
|
|
+ * If there is a problem with its frequency table, take it
|
|
+ * offline and drop it.
|
|
+ */
|
|
ret = cpufreq_table_validate_and_sort(policy);
|
|
if (ret)
|
|
- goto out_exit_policy;
|
|
+ goto out_offline_policy;
|
|
|
|
/* related_cpus should at least include policy->cpus. */
|
|
cpumask_copy(policy->related_cpus, policy->cpus);
|
|
@@ -1513,6 +1518,10 @@ out_destroy_policy:
|
|
|
|
up_write(&policy->rwsem);
|
|
|
|
+out_offline_policy:
|
|
+ if (cpufreq_driver->offline)
|
|
+ cpufreq_driver->offline(policy);
|
|
+
|
|
out_exit_policy:
|
|
if (cpufreq_driver->exit)
|
|
cpufreq_driver->exit(policy);
|
|
diff --git a/drivers/crypto/cavium/nitrox/nitrox_isr.c b/drivers/crypto/cavium/nitrox/nitrox_isr.c
|
|
index 3dec570a190ad..10e3408bf704c 100644
|
|
--- a/drivers/crypto/cavium/nitrox/nitrox_isr.c
|
|
+++ b/drivers/crypto/cavium/nitrox/nitrox_isr.c
|
|
@@ -306,6 +306,10 @@ int nitrox_register_interrupts(struct nitrox_device *ndev)
|
|
* Entry 192: NPS_CORE_INT_ACTIVE
|
|
*/
|
|
nr_vecs = pci_msix_vec_count(pdev);
|
|
+ if (nr_vecs < 0) {
|
|
+ dev_err(DEV(ndev), "Error in getting vec count %d\n", nr_vecs);
|
|
+ return nr_vecs;
|
|
+ }
|
|
|
|
/* Enable MSI-X */
|
|
ret = pci_alloc_irq_vectors(pdev, nr_vecs, nr_vecs, PCI_IRQ_MSIX);
|
|
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
|
|
index 21caed429cc52..d0018794e92e8 100644
|
|
--- a/drivers/crypto/ccp/sev-dev.c
|
|
+++ b/drivers/crypto/ccp/sev-dev.c
|
|
@@ -42,6 +42,10 @@ static int psp_probe_timeout = 5;
|
|
module_param(psp_probe_timeout, int, 0644);
|
|
MODULE_PARM_DESC(psp_probe_timeout, " default timeout value, in seconds, during PSP device probe");
|
|
|
|
+MODULE_FIRMWARE("amd/amd_sev_fam17h_model0xh.sbin"); /* 1st gen EPYC */
|
|
+MODULE_FIRMWARE("amd/amd_sev_fam17h_model3xh.sbin"); /* 2nd gen EPYC */
|
|
+MODULE_FIRMWARE("amd/amd_sev_fam19h_model0xh.sbin"); /* 3rd gen EPYC */
|
|
+
|
|
static bool psp_dead;
|
|
static int psp_timeout;
|
|
|
|
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
|
|
index f471dbaef1fbc..7d346d842a39e 100644
|
|
--- a/drivers/crypto/ccp/sp-pci.c
|
|
+++ b/drivers/crypto/ccp/sp-pci.c
|
|
@@ -222,7 +222,7 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
if (ret) {
|
|
dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
|
|
ret);
|
|
- goto e_err;
|
|
+ goto free_irqs;
|
|
}
|
|
}
|
|
|
|
@@ -230,10 +230,12 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
|
|
ret = sp_init(sp);
|
|
if (ret)
|
|
- goto e_err;
|
|
+ goto free_irqs;
|
|
|
|
return 0;
|
|
|
|
+free_irqs:
|
|
+ sp_free_irqs(sp);
|
|
e_err:
|
|
dev_notice(dev, "initialization failed\n");
|
|
return ret;
|
|
diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c
|
|
index 41f1fcacb2809..630dcb59ad569 100644
|
|
--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c
|
|
+++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c
|
|
@@ -1515,11 +1515,11 @@ static struct skcipher_alg sec_skciphers[] = {
|
|
AES_BLOCK_SIZE, AES_BLOCK_SIZE)
|
|
|
|
SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
|
|
- SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
|
|
+ SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE,
|
|
DES3_EDE_BLOCK_SIZE, 0)
|
|
|
|
SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
|
|
- SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
|
|
+ SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE,
|
|
DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
|
|
|
|
SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
|
|
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
|
|
index 276012e7c482f..5e474a7a1912c 100644
|
|
--- a/drivers/crypto/ixp4xx_crypto.c
|
|
+++ b/drivers/crypto/ixp4xx_crypto.c
|
|
@@ -149,6 +149,8 @@ struct crypt_ctl {
|
|
struct ablk_ctx {
|
|
struct buffer_desc *src;
|
|
struct buffer_desc *dst;
|
|
+ u8 iv[MAX_IVLEN];
|
|
+ bool encrypt;
|
|
};
|
|
|
|
struct aead_ctx {
|
|
@@ -330,7 +332,7 @@ static void free_buf_chain(struct device *dev, struct buffer_desc *buf,
|
|
|
|
buf1 = buf->next;
|
|
phys1 = buf->phys_next;
|
|
- dma_unmap_single(dev, buf->phys_next, buf->buf_len, buf->dir);
|
|
+ dma_unmap_single(dev, buf->phys_addr, buf->buf_len, buf->dir);
|
|
dma_pool_free(buffer_pool, buf, phys);
|
|
buf = buf1;
|
|
phys = phys1;
|
|
@@ -381,6 +383,20 @@ static void one_packet(dma_addr_t phys)
|
|
case CTL_FLAG_PERFORM_ABLK: {
|
|
struct skcipher_request *req = crypt->data.ablk_req;
|
|
struct ablk_ctx *req_ctx = skcipher_request_ctx(req);
|
|
+ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
|
+ unsigned int ivsize = crypto_skcipher_ivsize(tfm);
|
|
+ unsigned int offset;
|
|
+
|
|
+ if (ivsize > 0) {
|
|
+ offset = req->cryptlen - ivsize;
|
|
+ if (req_ctx->encrypt) {
|
|
+ scatterwalk_map_and_copy(req->iv, req->dst,
|
|
+ offset, ivsize, 0);
|
|
+ } else {
|
|
+ memcpy(req->iv, req_ctx->iv, ivsize);
|
|
+ memzero_explicit(req_ctx->iv, ivsize);
|
|
+ }
|
|
+ }
|
|
|
|
if (req_ctx->dst) {
|
|
free_buf_chain(dev, req_ctx->dst, crypt->dst_buf);
|
|
@@ -876,6 +892,7 @@ static int ablk_perform(struct skcipher_request *req, int encrypt)
|
|
struct ablk_ctx *req_ctx = skcipher_request_ctx(req);
|
|
struct buffer_desc src_hook;
|
|
struct device *dev = &pdev->dev;
|
|
+ unsigned int offset;
|
|
gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
|
|
GFP_KERNEL : GFP_ATOMIC;
|
|
|
|
@@ -885,6 +902,7 @@ static int ablk_perform(struct skcipher_request *req, int encrypt)
|
|
return -EAGAIN;
|
|
|
|
dir = encrypt ? &ctx->encrypt : &ctx->decrypt;
|
|
+ req_ctx->encrypt = encrypt;
|
|
|
|
crypt = get_crypt_desc();
|
|
if (!crypt)
|
|
@@ -900,6 +918,10 @@ static int ablk_perform(struct skcipher_request *req, int encrypt)
|
|
|
|
BUG_ON(ivsize && !req->iv);
|
|
memcpy(crypt->iv, req->iv, ivsize);
|
|
+ if (ivsize > 0 && !encrypt) {
|
|
+ offset = req->cryptlen - ivsize;
|
|
+ scatterwalk_map_and_copy(req_ctx->iv, req->src, offset, ivsize, 0);
|
|
+ }
|
|
if (req->src != req->dst) {
|
|
struct buffer_desc dst_hook;
|
|
crypt->mode |= NPE_OP_NOT_IN_PLACE;
|
|
diff --git a/drivers/crypto/nx/nx-842-pseries.c b/drivers/crypto/nx/nx-842-pseries.c
|
|
index 2de5e3672e423..c5ec50a28f30d 100644
|
|
--- a/drivers/crypto/nx/nx-842-pseries.c
|
|
+++ b/drivers/crypto/nx/nx-842-pseries.c
|
|
@@ -538,13 +538,15 @@ static int nx842_OF_set_defaults(struct nx842_devdata *devdata)
|
|
* The status field indicates if the device is enabled when the status
|
|
* is 'okay'. Otherwise the device driver will be disabled.
|
|
*
|
|
- * @prop - struct property point containing the maxsyncop for the update
|
|
+ * @devdata: struct nx842_devdata to use for dev_info
|
|
+ * @prop: struct property point containing the maxsyncop for the update
|
|
*
|
|
* Returns:
|
|
* 0 - Device is available
|
|
* -ENODEV - Device is not available
|
|
*/
|
|
-static int nx842_OF_upd_status(struct property *prop)
|
|
+static int nx842_OF_upd_status(struct nx842_devdata *devdata,
|
|
+ struct property *prop)
|
|
{
|
|
const char *status = (const char *)prop->value;
|
|
|
|
@@ -758,7 +760,7 @@ static int nx842_OF_upd(struct property *new_prop)
|
|
goto out;
|
|
|
|
/* Perform property updates */
|
|
- ret = nx842_OF_upd_status(status);
|
|
+ ret = nx842_OF_upd_status(new_devdata, status);
|
|
if (ret)
|
|
goto error_out;
|
|
|
|
@@ -1071,6 +1073,7 @@ static const struct vio_device_id nx842_vio_driver_ids[] = {
|
|
{"ibm,compression-v1", "ibm,compression"},
|
|
{"", ""},
|
|
};
|
|
+MODULE_DEVICE_TABLE(vio, nx842_vio_driver_ids);
|
|
|
|
static struct vio_driver nx842_vio_driver = {
|
|
.name = KBUILD_MODNAME,
|
|
diff --git a/drivers/crypto/nx/nx-aes-ctr.c b/drivers/crypto/nx/nx-aes-ctr.c
|
|
index 6d5ce1a66f1ee..02ad26012c665 100644
|
|
--- a/drivers/crypto/nx/nx-aes-ctr.c
|
|
+++ b/drivers/crypto/nx/nx-aes-ctr.c
|
|
@@ -118,7 +118,7 @@ static int ctr3686_aes_nx_crypt(struct skcipher_request *req)
|
|
struct nx_crypto_ctx *nx_ctx = crypto_skcipher_ctx(tfm);
|
|
u8 iv[16];
|
|
|
|
- memcpy(iv, nx_ctx->priv.ctr.nonce, CTR_RFC3686_IV_SIZE);
|
|
+ memcpy(iv, nx_ctx->priv.ctr.nonce, CTR_RFC3686_NONCE_SIZE);
|
|
memcpy(iv + CTR_RFC3686_NONCE_SIZE, req->iv, CTR_RFC3686_IV_SIZE);
|
|
iv[12] = iv[13] = iv[14] = 0;
|
|
iv[15] = 1;
|
|
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
|
|
index a3b38d2c92e70..39d17ed1db2f2 100644
|
|
--- a/drivers/crypto/omap-sham.c
|
|
+++ b/drivers/crypto/omap-sham.c
|
|
@@ -371,7 +371,7 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
|
|
{
|
|
int err;
|
|
|
|
- err = pm_runtime_get_sync(dd->dev);
|
|
+ err = pm_runtime_resume_and_get(dd->dev);
|
|
if (err < 0) {
|
|
dev_err(dd->dev, "failed to get sync: %d\n", err);
|
|
return err;
|
|
@@ -2243,7 +2243,7 @@ static int omap_sham_suspend(struct device *dev)
|
|
|
|
static int omap_sham_resume(struct device *dev)
|
|
{
|
|
- int err = pm_runtime_get_sync(dev);
|
|
+ int err = pm_runtime_resume_and_get(dev);
|
|
if (err < 0) {
|
|
dev_err(dev, "failed to get sync: %d\n", err);
|
|
return err;
|
|
diff --git a/drivers/crypto/qat/qat_common/qat_hal.c b/drivers/crypto/qat/qat_common/qat_hal.c
|
|
index 52ef80efeddc6..b40e81e0088f0 100644
|
|
--- a/drivers/crypto/qat/qat_common/qat_hal.c
|
|
+++ b/drivers/crypto/qat/qat_common/qat_hal.c
|
|
@@ -1213,7 +1213,11 @@ static int qat_hal_put_rel_wr_xfer(struct icp_qat_fw_loader_handle *handle,
|
|
pr_err("QAT: bad xfrAddr=0x%x\n", xfr_addr);
|
|
return -EINVAL;
|
|
}
|
|
- qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval);
|
|
+ status = qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval);
|
|
+ if (status) {
|
|
+ pr_err("QAT: failed to read register");
|
|
+ return status;
|
|
+ }
|
|
gpr_addr = qat_hal_get_reg_addr(ICP_GPB_REL, gprnum);
|
|
data16low = 0xffff & data;
|
|
data16hi = 0xffff & (data >> 0x10);
|
|
diff --git a/drivers/crypto/qat/qat_common/qat_uclo.c b/drivers/crypto/qat/qat_common/qat_uclo.c
|
|
index 5d1f28cd66809..6adc91fedb083 100644
|
|
--- a/drivers/crypto/qat/qat_common/qat_uclo.c
|
|
+++ b/drivers/crypto/qat/qat_common/qat_uclo.c
|
|
@@ -342,7 +342,6 @@ static int qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle,
|
|
return 0;
|
|
}
|
|
|
|
-#define ICP_DH895XCC_PESRAM_BAR_SIZE 0x80000
|
|
static int qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle,
|
|
struct icp_qat_uof_initmem *init_mem)
|
|
{
|
|
diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c
|
|
index a2d3da0ad95f3..d8053789c8828 100644
|
|
--- a/drivers/crypto/qce/skcipher.c
|
|
+++ b/drivers/crypto/qce/skcipher.c
|
|
@@ -71,7 +71,7 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req)
|
|
struct scatterlist *sg;
|
|
bool diff_dst;
|
|
gfp_t gfp;
|
|
- int ret;
|
|
+ int dst_nents, src_nents, ret;
|
|
|
|
rctx->iv = req->iv;
|
|
rctx->ivsize = crypto_skcipher_ivsize(skcipher);
|
|
@@ -122,21 +122,26 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req)
|
|
sg_mark_end(sg);
|
|
rctx->dst_sg = rctx->dst_tbl.sgl;
|
|
|
|
- ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
|
- if (ret < 0)
|
|
+ dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
|
+ if (dst_nents < 0) {
|
|
+ ret = dst_nents;
|
|
goto error_free;
|
|
+ }
|
|
|
|
if (diff_dst) {
|
|
- ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
|
- if (ret < 0)
|
|
+ src_nents = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
|
|
+ if (src_nents < 0) {
|
|
+ ret = src_nents;
|
|
goto error_unmap_dst;
|
|
+ }
|
|
rctx->src_sg = req->src;
|
|
} else {
|
|
rctx->src_sg = rctx->dst_sg;
|
|
+ src_nents = dst_nents - 1;
|
|
}
|
|
|
|
- ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents,
|
|
- rctx->dst_sg, rctx->dst_nents,
|
|
+ ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents,
|
|
+ rctx->dst_sg, dst_nents,
|
|
qce_skcipher_done, async_req);
|
|
if (ret)
|
|
goto error_unmap_src;
|
|
diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c
|
|
index 4640fe0c1f221..f15fc1fb37079 100644
|
|
--- a/drivers/crypto/sa2ul.c
|
|
+++ b/drivers/crypto/sa2ul.c
|
|
@@ -2270,9 +2270,9 @@ static int sa_dma_init(struct sa_crypto_data *dd)
|
|
|
|
dd->dma_rx2 = dma_request_chan(dd->dev, "rx2");
|
|
if (IS_ERR(dd->dma_rx2)) {
|
|
- dma_release_channel(dd->dma_rx1);
|
|
- return dev_err_probe(dd->dev, PTR_ERR(dd->dma_rx2),
|
|
- "Unable to request rx2 DMA channel\n");
|
|
+ ret = dev_err_probe(dd->dev, PTR_ERR(dd->dma_rx2),
|
|
+ "Unable to request rx2 DMA channel\n");
|
|
+ goto err_dma_rx2;
|
|
}
|
|
|
|
dd->dma_tx = dma_request_chan(dd->dev, "tx");
|
|
@@ -2293,28 +2293,31 @@ static int sa_dma_init(struct sa_crypto_data *dd)
|
|
if (ret) {
|
|
dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n",
|
|
ret);
|
|
- return ret;
|
|
+ goto err_dma_config;
|
|
}
|
|
|
|
ret = dmaengine_slave_config(dd->dma_rx2, &cfg);
|
|
if (ret) {
|
|
dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n",
|
|
ret);
|
|
- return ret;
|
|
+ goto err_dma_config;
|
|
}
|
|
|
|
ret = dmaengine_slave_config(dd->dma_tx, &cfg);
|
|
if (ret) {
|
|
dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n",
|
|
ret);
|
|
- return ret;
|
|
+ goto err_dma_config;
|
|
}
|
|
|
|
return 0;
|
|
|
|
+err_dma_config:
|
|
+ dma_release_channel(dd->dma_tx);
|
|
err_dma_tx:
|
|
- dma_release_channel(dd->dma_rx1);
|
|
dma_release_channel(dd->dma_rx2);
|
|
+err_dma_rx2:
|
|
+ dma_release_channel(dd->dma_rx1);
|
|
|
|
return ret;
|
|
}
|
|
@@ -2353,13 +2356,14 @@ static int sa_ul_probe(struct platform_device *pdev)
|
|
if (ret < 0) {
|
|
dev_err(&pdev->dev, "%s: failed to get sync: %d\n", __func__,
|
|
ret);
|
|
+ pm_runtime_disable(dev);
|
|
return ret;
|
|
}
|
|
|
|
sa_init_mem(dev_data);
|
|
ret = sa_dma_init(dev_data);
|
|
if (ret)
|
|
- goto disable_pm_runtime;
|
|
+ goto destroy_dma_pool;
|
|
|
|
spin_lock_init(&dev_data->scid_lock);
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
@@ -2389,9 +2393,9 @@ release_dma:
|
|
dma_release_channel(dev_data->dma_rx1);
|
|
dma_release_channel(dev_data->dma_tx);
|
|
|
|
+destroy_dma_pool:
|
|
dma_pool_destroy(dev_data->sc_pool);
|
|
|
|
-disable_pm_runtime:
|
|
pm_runtime_put_sync(&pdev->dev);
|
|
pm_runtime_disable(&pdev->dev);
|
|
|
|
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
|
|
index 3d407eebb2bab..1e2daf4030327 100644
|
|
--- a/drivers/crypto/ux500/hash/hash_core.c
|
|
+++ b/drivers/crypto/ux500/hash/hash_core.c
|
|
@@ -1009,6 +1009,7 @@ static int hash_hw_final(struct ahash_request *req)
|
|
goto out;
|
|
}
|
|
} else if (req->nbytes == 0 && ctx->keylen > 0) {
|
|
+ ret = -EPERM;
|
|
dev_err(device_data->dev, "%s: Empty message with keylength > 0, NOT supported\n",
|
|
__func__);
|
|
goto out;
|
|
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
|
|
index 98f03a02d1122..829128c0cc68c 100644
|
|
--- a/drivers/devfreq/devfreq.c
|
|
+++ b/drivers/devfreq/devfreq.c
|
|
@@ -789,6 +789,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
|
|
if (devfreq->profile->timer < 0
|
|
|| devfreq->profile->timer >= DEVFREQ_TIMER_NUM) {
|
|
mutex_unlock(&devfreq->lock);
|
|
+ err = -EINVAL;
|
|
goto err_dev;
|
|
}
|
|
|
|
diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
|
|
index 7b52691c45d26..4912a7b883801 100644
|
|
--- a/drivers/edac/i10nm_base.c
|
|
+++ b/drivers/edac/i10nm_base.c
|
|
@@ -263,6 +263,9 @@ static int __init i10nm_init(void)
|
|
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
|
|
return -EBUSY;
|
|
|
|
+ if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
|
|
+ return -ENODEV;
|
|
+
|
|
id = x86_match_cpu(i10nm_cpuids);
|
|
if (!id)
|
|
return -ENODEV;
|
|
diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c
|
|
index 928f63a374c78..c94ca1f790c43 100644
|
|
--- a/drivers/edac/pnd2_edac.c
|
|
+++ b/drivers/edac/pnd2_edac.c
|
|
@@ -1554,6 +1554,9 @@ static int __init pnd2_init(void)
|
|
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
|
|
return -EBUSY;
|
|
|
|
+ if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
|
|
+ return -ENODEV;
|
|
+
|
|
id = x86_match_cpu(pnd2_cpuids);
|
|
if (!id)
|
|
return -ENODEV;
|
|
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
|
|
index 93daa4297f2e0..4c626fcd4dcbb 100644
|
|
--- a/drivers/edac/sb_edac.c
|
|
+++ b/drivers/edac/sb_edac.c
|
|
@@ -3510,6 +3510,9 @@ static int __init sbridge_init(void)
|
|
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
|
|
return -EBUSY;
|
|
|
|
+ if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
|
|
+ return -ENODEV;
|
|
+
|
|
id = x86_match_cpu(sbridge_cpuids);
|
|
if (!id)
|
|
return -ENODEV;
|
|
diff --git a/drivers/edac/skx_base.c b/drivers/edac/skx_base.c
|
|
index 2c7db95df3263..f887e31666510 100644
|
|
--- a/drivers/edac/skx_base.c
|
|
+++ b/drivers/edac/skx_base.c
|
|
@@ -656,6 +656,9 @@ static int __init skx_init(void)
|
|
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
|
|
return -EBUSY;
|
|
|
|
+ if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
|
|
+ return -ENODEV;
|
|
+
|
|
id = x86_match_cpu(skx_cpuids);
|
|
if (!id)
|
|
return -ENODEV;
|
|
diff --git a/drivers/edac/ti_edac.c b/drivers/edac/ti_edac.c
|
|
index e7eae20f83d1d..169f96e51c293 100644
|
|
--- a/drivers/edac/ti_edac.c
|
|
+++ b/drivers/edac/ti_edac.c
|
|
@@ -197,6 +197,7 @@ static const struct of_device_id ti_edac_of_match[] = {
|
|
{ .compatible = "ti,emif-dra7xx", .data = (void *)EMIF_TYPE_DRA7 },
|
|
{},
|
|
};
|
|
+MODULE_DEVICE_TABLE(of, ti_edac_of_match);
|
|
|
|
static int _emif_get_id(struct device_node *node)
|
|
{
|
|
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
|
|
index 337b0eea4e629..64008808675ef 100644
|
|
--- a/drivers/extcon/extcon-max8997.c
|
|
+++ b/drivers/extcon/extcon-max8997.c
|
|
@@ -729,7 +729,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
|
|
2, info->status);
|
|
if (ret) {
|
|
dev_err(info->dev, "failed to read MUIC register\n");
|
|
- return ret;
|
|
+ goto err_irq;
|
|
}
|
|
cable_type = max8997_muic_get_cable_type(info,
|
|
MAX8997_CABLE_GROUP_ADC, &attached);
|
|
@@ -784,3 +784,4 @@ module_platform_driver(max8997_muic_driver);
|
|
MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver");
|
|
MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
|
|
MODULE_LICENSE("GPL");
|
|
+MODULE_ALIAS("platform:max8997-muic");
|
|
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c
|
|
index 106d4da647bd9..5e0718dee03bc 100644
|
|
--- a/drivers/extcon/extcon-sm5502.c
|
|
+++ b/drivers/extcon/extcon-sm5502.c
|
|
@@ -88,7 +88,6 @@ static struct reg_data sm5502_reg_data[] = {
|
|
| SM5502_REG_INTM2_MHL_MASK,
|
|
.invert = true,
|
|
},
|
|
- { }
|
|
};
|
|
|
|
/* List of detectable cables */
|
|
diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
|
|
index 3aa489dba30a7..2a7687911c097 100644
|
|
--- a/drivers/firmware/stratix10-svc.c
|
|
+++ b/drivers/firmware/stratix10-svc.c
|
|
@@ -1034,24 +1034,32 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
|
|
|
|
/* add svc client device(s) */
|
|
svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL);
|
|
- if (!svc)
|
|
- return -ENOMEM;
|
|
+ if (!svc) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_free_kfifo;
|
|
+ }
|
|
|
|
svc->stratix10_svc_rsu = platform_device_alloc(STRATIX10_RSU, 0);
|
|
if (!svc->stratix10_svc_rsu) {
|
|
dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU);
|
|
- return -ENOMEM;
|
|
+ ret = -ENOMEM;
|
|
+ goto err_free_kfifo;
|
|
}
|
|
|
|
ret = platform_device_add(svc->stratix10_svc_rsu);
|
|
- if (ret) {
|
|
- platform_device_put(svc->stratix10_svc_rsu);
|
|
- return ret;
|
|
- }
|
|
+ if (ret)
|
|
+ goto err_put_device;
|
|
+
|
|
dev_set_drvdata(dev, svc);
|
|
|
|
pr_info("Intel Service Layer Driver Initialized\n");
|
|
|
|
+ return 0;
|
|
+
|
|
+err_put_device:
|
|
+ platform_device_put(svc->stratix10_svc_rsu);
|
|
+err_free_kfifo:
|
|
+ kfifo_free(&controller->svc_fifo);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
|
|
index 4e60e84cd17a5..59ddc9fd5bca4 100644
|
|
--- a/drivers/fsi/fsi-core.c
|
|
+++ b/drivers/fsi/fsi-core.c
|
|
@@ -724,7 +724,7 @@ static ssize_t cfam_read(struct file *filep, char __user *buf, size_t count,
|
|
rc = count;
|
|
fail:
|
|
*offset = off;
|
|
- return count;
|
|
+ return rc;
|
|
}
|
|
|
|
static ssize_t cfam_write(struct file *filep, const char __user *buf,
|
|
@@ -761,7 +761,7 @@ static ssize_t cfam_write(struct file *filep, const char __user *buf,
|
|
rc = count;
|
|
fail:
|
|
*offset = off;
|
|
- return count;
|
|
+ return rc;
|
|
}
|
|
|
|
static loff_t cfam_llseek(struct file *file, loff_t offset, int whence)
|
|
diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c
|
|
index 9eeb856c8905e..a691f9732a13b 100644
|
|
--- a/drivers/fsi/fsi-occ.c
|
|
+++ b/drivers/fsi/fsi-occ.c
|
|
@@ -445,6 +445,7 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
|
|
goto done;
|
|
|
|
if (resp->return_status == OCC_RESP_CMD_IN_PRG ||
|
|
+ resp->return_status == OCC_RESP_CRIT_INIT ||
|
|
resp->seq_no != seq_no) {
|
|
rc = -ETIMEDOUT;
|
|
|
|
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
|
|
index bfd5e5da80209..84cb965bfed5c 100644
|
|
--- a/drivers/fsi/fsi-sbefifo.c
|
|
+++ b/drivers/fsi/fsi-sbefifo.c
|
|
@@ -325,7 +325,8 @@ static int sbefifo_up_write(struct sbefifo *sbefifo, __be32 word)
|
|
static int sbefifo_request_reset(struct sbefifo *sbefifo)
|
|
{
|
|
struct device *dev = &sbefifo->fsi_dev->dev;
|
|
- u32 status, timeout;
|
|
+ unsigned long end_time;
|
|
+ u32 status;
|
|
int rc;
|
|
|
|
dev_dbg(dev, "Requesting FIFO reset\n");
|
|
@@ -341,7 +342,8 @@ static int sbefifo_request_reset(struct sbefifo *sbefifo)
|
|
}
|
|
|
|
/* Wait for it to complete */
|
|
- for (timeout = 0; timeout < SBEFIFO_RESET_TIMEOUT; timeout++) {
|
|
+ end_time = jiffies + msecs_to_jiffies(SBEFIFO_RESET_TIMEOUT);
|
|
+ while (!time_after(jiffies, end_time)) {
|
|
rc = sbefifo_regr(sbefifo, SBEFIFO_UP | SBEFIFO_STS, &status);
|
|
if (rc) {
|
|
dev_err(dev, "Failed to read UP fifo status during reset"
|
|
@@ -355,7 +357,7 @@ static int sbefifo_request_reset(struct sbefifo *sbefifo)
|
|
return 0;
|
|
}
|
|
|
|
- msleep(1);
|
|
+ cond_resched();
|
|
}
|
|
dev_err(dev, "FIFO reset timed out\n");
|
|
|
|
@@ -400,7 +402,7 @@ static int sbefifo_cleanup_hw(struct sbefifo *sbefifo)
|
|
/* The FIFO already contains a reset request from the SBE ? */
|
|
if (down_status & SBEFIFO_STS_RESET_REQ) {
|
|
dev_info(dev, "Cleanup: FIFO reset request set, resetting\n");
|
|
- rc = sbefifo_regw(sbefifo, SBEFIFO_UP, SBEFIFO_PERFORM_RESET);
|
|
+ rc = sbefifo_regw(sbefifo, SBEFIFO_DOWN, SBEFIFO_PERFORM_RESET);
|
|
if (rc) {
|
|
sbefifo->broken = true;
|
|
dev_err(dev, "Cleanup: Reset reg write failed, rc=%d\n", rc);
|
|
diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
|
|
index b45bfab7b7f55..75d1389e2626d 100644
|
|
--- a/drivers/fsi/fsi-scom.c
|
|
+++ b/drivers/fsi/fsi-scom.c
|
|
@@ -38,9 +38,10 @@
|
|
#define SCOM_STATUS_PIB_RESP_MASK 0x00007000
|
|
#define SCOM_STATUS_PIB_RESP_SHIFT 12
|
|
|
|
-#define SCOM_STATUS_ANY_ERR (SCOM_STATUS_PROTECTION | \
|
|
- SCOM_STATUS_PARITY | \
|
|
- SCOM_STATUS_PIB_ABORT | \
|
|
+#define SCOM_STATUS_FSI2PIB_ERROR (SCOM_STATUS_PROTECTION | \
|
|
+ SCOM_STATUS_PARITY | \
|
|
+ SCOM_STATUS_PIB_ABORT)
|
|
+#define SCOM_STATUS_ANY_ERR (SCOM_STATUS_FSI2PIB_ERROR | \
|
|
SCOM_STATUS_PIB_RESP_MASK)
|
|
/* SCOM address encodings */
|
|
#define XSCOM_ADDR_IND_FLAG BIT_ULL(63)
|
|
@@ -240,13 +241,14 @@ static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
|
|
{
|
|
uint32_t dummy = -1;
|
|
|
|
- if (status & SCOM_STATUS_PROTECTION)
|
|
- return -EPERM;
|
|
- if (status & SCOM_STATUS_PARITY) {
|
|
+ if (status & SCOM_STATUS_FSI2PIB_ERROR)
|
|
fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
|
|
sizeof(uint32_t));
|
|
+
|
|
+ if (status & SCOM_STATUS_PROTECTION)
|
|
+ return -EPERM;
|
|
+ if (status & SCOM_STATUS_PARITY)
|
|
return -EIO;
|
|
- }
|
|
/* Return -EBUSY on PIB abort to force a retry */
|
|
if (status & SCOM_STATUS_PIB_ABORT)
|
|
return -EBUSY;
|
|
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
index 1e448f1b39a18..955a055bd9800 100644
|
|
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
|
|
@@ -268,6 +268,9 @@ dm_dp_mst_detect(struct drm_connector *connector,
|
|
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
|
|
struct amdgpu_dm_connector *master = aconnector->mst_port;
|
|
|
|
+ if (drm_connector_is_unregistered(connector))
|
|
+ return connector_status_disconnected;
|
|
+
|
|
return drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr,
|
|
aconnector->port);
|
|
}
|
|
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
|
|
index 77066bca87939..ee82b2ddf9325 100644
|
|
--- a/drivers/gpu/drm/ast/ast_main.c
|
|
+++ b/drivers/gpu/drm/ast/ast_main.c
|
|
@@ -409,7 +409,7 @@ struct ast_private *ast_device_create(struct drm_driver *drv,
|
|
dev->pdev = pdev;
|
|
pci_set_drvdata(pdev, dev);
|
|
|
|
- ast->regs = pci_iomap(dev->pdev, 1, 0);
|
|
+ ast->regs = pcim_iomap(pdev, 1, 0);
|
|
if (!ast->regs)
|
|
return ERR_PTR(-EIO);
|
|
|
|
@@ -425,7 +425,7 @@ struct ast_private *ast_device_create(struct drm_driver *drv,
|
|
|
|
/* "map" IO regs if the above hasn't done so already */
|
|
if (!ast->ioregs) {
|
|
- ast->ioregs = pci_iomap(dev->pdev, 2, 0);
|
|
+ ast->ioregs = pcim_iomap(pdev, 2, 0);
|
|
if (!ast->ioregs)
|
|
return ERR_PTR(-EIO);
|
|
}
|
|
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
|
|
index e145cbb35baca..4e82647a621ef 100644
|
|
--- a/drivers/gpu/drm/bridge/Kconfig
|
|
+++ b/drivers/gpu/drm/bridge/Kconfig
|
|
@@ -130,7 +130,7 @@ config DRM_SIL_SII8620
|
|
tristate "Silicon Image SII8620 HDMI/MHL bridge"
|
|
depends on OF
|
|
select DRM_KMS_HELPER
|
|
- imply EXTCON
|
|
+ select EXTCON
|
|
depends on RC_CORE || !RC_CORE
|
|
help
|
|
Silicon Image SII8620 HDMI/MHL bridge chip driver.
|
|
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
|
|
index 64f0effb52ac1..044acd07c1538 100644
|
|
--- a/drivers/gpu/drm/drm_bridge.c
|
|
+++ b/drivers/gpu/drm/drm_bridge.c
|
|
@@ -522,6 +522,9 @@ void drm_bridge_chain_pre_enable(struct drm_bridge *bridge)
|
|
list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
|
|
if (iter->funcs->pre_enable)
|
|
iter->funcs->pre_enable(iter);
|
|
+
|
|
+ if (iter == bridge)
|
|
+ break;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(drm_bridge_chain_pre_enable);
|
|
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
|
|
index 3416e9617ee9a..96f3908e4c5b9 100644
|
|
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
|
|
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
|
|
@@ -222,7 +222,7 @@ int dpu_mdss_init(struct drm_device *dev)
|
|
struct msm_drm_private *priv = dev->dev_private;
|
|
struct dpu_mdss *dpu_mdss;
|
|
struct dss_module_power *mp;
|
|
- int ret = 0;
|
|
+ int ret;
|
|
int irq;
|
|
|
|
dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL);
|
|
@@ -250,8 +250,10 @@ int dpu_mdss_init(struct drm_device *dev)
|
|
goto irq_domain_error;
|
|
|
|
irq = platform_get_irq(pdev, 0);
|
|
- if (irq < 0)
|
|
+ if (irq < 0) {
|
|
+ ret = irq;
|
|
goto irq_error;
|
|
+ }
|
|
|
|
irq_set_chained_handler_and_data(irq, dpu_mdss_irq,
|
|
dpu_mdss);
|
|
@@ -260,7 +262,7 @@ int dpu_mdss_init(struct drm_device *dev)
|
|
|
|
pm_runtime_enable(dev->dev);
|
|
|
|
- return ret;
|
|
+ return 0;
|
|
|
|
irq_error:
|
|
_dpu_mdss_irq_domain_fini(dpu_mdss);
|
|
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
|
|
index 0aacc43faefa3..edee4c2a76ce4 100644
|
|
--- a/drivers/gpu/drm/msm/msm_drv.c
|
|
+++ b/drivers/gpu/drm/msm/msm_drv.c
|
|
@@ -505,6 +505,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
|
|
priv->event_thread[i].worker = kthread_create_worker(0,
|
|
"crtc_event:%d", priv->event_thread[i].crtc_id);
|
|
if (IS_ERR(priv->event_thread[i].worker)) {
|
|
+ ret = PTR_ERR(priv->event_thread[i].worker);
|
|
DRM_DEV_ERROR(dev, "failed to create crtc_event kthread\n");
|
|
goto err_msm_uninit;
|
|
}
|
|
diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig
|
|
index 80f6748055e36..3aae387a96af2 100644
|
|
--- a/drivers/gpu/drm/pl111/Kconfig
|
|
+++ b/drivers/gpu/drm/pl111/Kconfig
|
|
@@ -3,6 +3,7 @@ config DRM_PL111
|
|
tristate "DRM Support for PL111 CLCD Controller"
|
|
depends on DRM
|
|
depends on ARM || ARM64 || COMPILE_TEST
|
|
+ depends on VEXPRESS_CONFIG || VEXPRESS_CONFIG=n
|
|
depends on COMMON_CLK
|
|
select DRM_KMS_HELPER
|
|
select DRM_KMS_CMA_HELPER
|
|
diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c
|
|
index c04cd5a2553ce..e377bdbff90dd 100644
|
|
--- a/drivers/gpu/drm/qxl/qxl_dumb.c
|
|
+++ b/drivers/gpu/drm/qxl/qxl_dumb.c
|
|
@@ -58,6 +58,8 @@ int qxl_mode_dumb_create(struct drm_file *file_priv,
|
|
surf.height = args->height;
|
|
surf.stride = pitch;
|
|
surf.format = format;
|
|
+ surf.data = 0;
|
|
+
|
|
r = qxl_gem_object_create_with_handle(qdev, file_priv,
|
|
QXL_GEM_DOMAIN_SURFACE,
|
|
args->size, &surf, &qobj,
|
|
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
|
|
index a4a45daf93f2b..6802d9b65f828 100644
|
|
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
|
|
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
|
|
@@ -73,6 +73,7 @@ static int cdn_dp_grf_write(struct cdn_dp_device *dp,
|
|
ret = regmap_write(dp->grf, reg, val);
|
|
if (ret) {
|
|
DRM_DEV_ERROR(dp->dev, "Could not write to GRF: %d\n", ret);
|
|
+ clk_disable_unprepare(dp->grf_clk);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-reg.c b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
|
|
index 9d2163ef4d6e2..33fb4d05c5065 100644
|
|
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
|
|
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
|
|
@@ -658,7 +658,7 @@ int cdn_dp_config_video(struct cdn_dp_device *dp)
|
|
*/
|
|
do {
|
|
tu_size_reg += 2;
|
|
- symbol = tu_size_reg * mode->clock * bit_per_pix;
|
|
+ symbol = (u64)tu_size_reg * mode->clock * bit_per_pix;
|
|
do_div(symbol, dp->max_lanes * link_rate * 8);
|
|
rem = do_div(symbol, 1000);
|
|
if (tu_size_reg > 64) {
|
|
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
|
|
index 542dcf7eddd66..75a76408cb29e 100644
|
|
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
|
|
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
|
|
@@ -692,13 +692,8 @@ static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_rockchip_phy_ops = {
|
|
.get_timing = dw_mipi_dsi_phy_get_timing,
|
|
};
|
|
|
|
-static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi,
|
|
- int mux)
|
|
+static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi)
|
|
{
|
|
- if (dsi->cdata->lcdsel_grf_reg)
|
|
- regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg,
|
|
- mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big);
|
|
-
|
|
if (dsi->cdata->lanecfg1_grf_reg)
|
|
regmap_write(dsi->grf_regmap, dsi->cdata->lanecfg1_grf_reg,
|
|
dsi->cdata->lanecfg1);
|
|
@@ -712,6 +707,13 @@ static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi,
|
|
dsi->cdata->enable);
|
|
}
|
|
|
|
+static void dw_mipi_dsi_rockchip_set_lcdsel(struct dw_mipi_dsi_rockchip *dsi,
|
|
+ int mux)
|
|
+{
|
|
+ regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg,
|
|
+ mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big);
|
|
+}
|
|
+
|
|
static int
|
|
dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,
|
|
struct drm_crtc_state *crtc_state,
|
|
@@ -767,9 +769,9 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
|
|
return;
|
|
}
|
|
|
|
- dw_mipi_dsi_rockchip_config(dsi, mux);
|
|
+ dw_mipi_dsi_rockchip_set_lcdsel(dsi, mux);
|
|
if (dsi->slave)
|
|
- dw_mipi_dsi_rockchip_config(dsi->slave, mux);
|
|
+ dw_mipi_dsi_rockchip_set_lcdsel(dsi->slave, mux);
|
|
|
|
clk_disable_unprepare(dsi->grf_clk);
|
|
}
|
|
@@ -923,6 +925,24 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev,
|
|
return ret;
|
|
}
|
|
|
|
+ /*
|
|
+ * With the GRF clock running, write lane and dual-mode configurations
|
|
+ * that won't change immediately. If we waited until enable() to do
|
|
+ * this, things like panel preparation would not be able to send
|
|
+ * commands over DSI.
|
|
+ */
|
|
+ ret = clk_prepare_enable(dsi->grf_clk);
|
|
+ if (ret) {
|
|
+ DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ dw_mipi_dsi_rockchip_config(dsi);
|
|
+ if (dsi->slave)
|
|
+ dw_mipi_dsi_rockchip_config(dsi->slave);
|
|
+
|
|
+ clk_disable_unprepare(dsi->grf_clk);
|
|
+
|
|
ret = rockchip_dsi_drm_create_encoder(dsi, drm_dev);
|
|
if (ret) {
|
|
DRM_DEV_ERROR(dev, "Failed to create drm encoder\n");
|
|
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
index c80f7d9fd13f8..0f23144491e40 100644
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
@@ -1013,6 +1013,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
|
|
VOP_WIN_SET(vop, win, alpha_en, 1);
|
|
} else {
|
|
VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0));
|
|
+ VOP_WIN_SET(vop, win, alpha_en, 0);
|
|
}
|
|
|
|
VOP_WIN_SET(vop, win, enable, 1);
|
|
diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
|
|
index 41edd0a421b25..7c20b4a24a7e2 100644
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
|
|
@@ -499,11 +499,11 @@ static int px30_lvds_probe(struct platform_device *pdev,
|
|
if (IS_ERR(lvds->dphy))
|
|
return PTR_ERR(lvds->dphy);
|
|
|
|
- phy_init(lvds->dphy);
|
|
+ ret = phy_init(lvds->dphy);
|
|
if (ret)
|
|
return ret;
|
|
|
|
- phy_set_mode(lvds->dphy, PHY_MODE_LVDS);
|
|
+ ret = phy_set_mode(lvds->dphy, PHY_MODE_LVDS);
|
|
if (ret)
|
|
return ret;
|
|
|
|
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
index 88a8cb840cd54..25a09aaf58838 100644
|
|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
@@ -1795,7 +1795,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
|
|
&hpd_gpio_flags);
|
|
if (vc4_hdmi->hpd_gpio < 0) {
|
|
ret = vc4_hdmi->hpd_gpio;
|
|
- goto err_unprepare_hsm;
|
|
+ goto err_put_ddc;
|
|
}
|
|
|
|
vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
|
|
@@ -1836,8 +1836,8 @@ err_destroy_conn:
|
|
vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
|
|
err_destroy_encoder:
|
|
drm_encoder_cleanup(encoder);
|
|
-err_unprepare_hsm:
|
|
pm_runtime_disable(dev);
|
|
+err_put_ddc:
|
|
put_device(&vc4_hdmi->ddc->dev);
|
|
|
|
return ret;
|
|
diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h
|
|
index 4db25bd9fa22d..127eaf0a0a580 100644
|
|
--- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h
|
|
+++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h
|
|
@@ -1467,6 +1467,7 @@ struct svga3dsurface_cache {
|
|
|
|
/**
|
|
* struct svga3dsurface_loc - Surface location
|
|
+ * @sheet: The multisample sheet.
|
|
* @sub_resource: Surface subresource. Defined as layer * num_mip_levels +
|
|
* mip_level.
|
|
* @x: X coordinate.
|
|
@@ -1474,6 +1475,7 @@ struct svga3dsurface_cache {
|
|
* @z: Z coordinate.
|
|
*/
|
|
struct svga3dsurface_loc {
|
|
+ u32 sheet;
|
|
u32 sub_resource;
|
|
u32 x, y, z;
|
|
};
|
|
@@ -1566,8 +1568,8 @@ svga3dsurface_get_loc(const struct svga3dsurface_cache *cache,
|
|
u32 layer;
|
|
int i;
|
|
|
|
- if (offset >= cache->sheet_bytes)
|
|
- offset %= cache->sheet_bytes;
|
|
+ loc->sheet = offset / cache->sheet_bytes;
|
|
+ offset -= loc->sheet * cache->sheet_bytes;
|
|
|
|
layer = offset / cache->mip_chain_bytes;
|
|
offset -= layer * cache->mip_chain_bytes;
|
|
@@ -1631,6 +1633,7 @@ svga3dsurface_min_loc(const struct svga3dsurface_cache *cache,
|
|
u32 sub_resource,
|
|
struct svga3dsurface_loc *loc)
|
|
{
|
|
+ loc->sheet = 0;
|
|
loc->sub_resource = sub_resource;
|
|
loc->x = loc->y = loc->z = 0;
|
|
}
|
|
@@ -1652,6 +1655,7 @@ svga3dsurface_max_loc(const struct svga3dsurface_cache *cache,
|
|
const struct drm_vmw_size *size;
|
|
u32 mip;
|
|
|
|
+ loc->sheet = 0;
|
|
loc->sub_resource = sub_resource + 1;
|
|
mip = sub_resource % cache->num_mip_levels;
|
|
size = &cache->mip[mip].size;
|
|
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
|
|
index e67e2e8f6e6fa..83e1b54eb8647 100644
|
|
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
|
|
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
|
|
@@ -2759,12 +2759,24 @@ static int vmw_cmd_dx_genmips(struct vmw_private *dev_priv,
|
|
{
|
|
VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXGenMips) =
|
|
container_of(header, typeof(*cmd), header);
|
|
- struct vmw_resource *ret;
|
|
+ struct vmw_resource *view;
|
|
+ struct vmw_res_cache_entry *rcache;
|
|
|
|
- ret = vmw_view_id_val_add(sw_context, vmw_view_sr,
|
|
- cmd->body.shaderResourceViewId);
|
|
+ view = vmw_view_id_val_add(sw_context, vmw_view_sr,
|
|
+ cmd->body.shaderResourceViewId);
|
|
+ if (IS_ERR(view))
|
|
+ return PTR_ERR(view);
|
|
|
|
- return PTR_ERR_OR_ZERO(ret);
|
|
+ /*
|
|
+ * Normally the shader-resource view is not gpu-dirtying, but for
|
|
+ * this particular command it is...
|
|
+ * So mark the last looked-up surface, which is the surface
|
|
+ * the view points to, gpu-dirty.
|
|
+ */
|
|
+ rcache = &sw_context->res_cache[vmw_res_surface];
|
|
+ vmw_validation_res_set_dirty(sw_context->ctx, rcache->private,
|
|
+ VMW_RES_DIRTY_SET);
|
|
+ return 0;
|
|
}
|
|
|
|
/**
|
|
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
|
index 3914bfee0533b..f493b20c7a38c 100644
|
|
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
|
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
|
@@ -1802,6 +1802,19 @@ static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res,
|
|
svga3dsurface_get_loc(cache, &loc2, end - 1);
|
|
svga3dsurface_inc_loc(cache, &loc2);
|
|
|
|
+ if (loc1.sheet != loc2.sheet) {
|
|
+ u32 sub_res;
|
|
+
|
|
+ /*
|
|
+ * Multiple multisample sheets. To do this in an optimized
|
|
+ * fashion, compute the dirty region for each sheet and the
|
|
+ * resulting union. Since this is not a common case, just dirty
|
|
+ * the whole surface.
|
|
+ */
|
|
+ for (sub_res = 0; sub_res < dirty->num_subres; ++sub_res)
|
|
+ vmw_subres_dirty_full(dirty, sub_res);
|
|
+ return;
|
|
+ }
|
|
if (loc1.sub_resource + 1 == loc2.sub_resource) {
|
|
/* Dirty range covers a single sub-resource */
|
|
vmw_subres_dirty_add(dirty, &loc1, &loc2);
|
|
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
|
|
index 0f69f35f2957e..5550c943f9855 100644
|
|
--- a/drivers/hid/hid-core.c
|
|
+++ b/drivers/hid/hid-core.c
|
|
@@ -2306,12 +2306,8 @@ static int hid_device_remove(struct device *dev)
|
|
{
|
|
struct hid_device *hdev = to_hid_device(dev);
|
|
struct hid_driver *hdrv;
|
|
- int ret = 0;
|
|
|
|
- if (down_interruptible(&hdev->driver_input_lock)) {
|
|
- ret = -EINTR;
|
|
- goto end;
|
|
- }
|
|
+ down(&hdev->driver_input_lock);
|
|
hdev->io_started = false;
|
|
|
|
hdrv = hdev->driver;
|
|
@@ -2326,8 +2322,8 @@ static int hid_device_remove(struct device *dev)
|
|
|
|
if (!hdev->io_started)
|
|
up(&hdev->driver_input_lock);
|
|
-end:
|
|
- return ret;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
|
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
|
|
index 195910dd2154e..e3835407e8d23 100644
|
|
--- a/drivers/hid/wacom_wac.h
|
|
+++ b/drivers/hid/wacom_wac.h
|
|
@@ -122,7 +122,7 @@
|
|
#define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0454)
|
|
#define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
|
|
#define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
|
|
-#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)
|
|
+#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0940)
|
|
#define WACOM_HID_WD_MODE_CHANGE (WACOM_HID_UP_WACOMDIGITIZER | 0x0980)
|
|
#define WACOM_HID_WD_MUTE_DEVICE (WACOM_HID_UP_WACOMDIGITIZER | 0x0981)
|
|
#define WACOM_HID_WD_CONTROLPANEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0982)
|
|
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
|
|
index 11170d9a2e1a5..bfd7f00a59ecf 100644
|
|
--- a/drivers/hv/connection.c
|
|
+++ b/drivers/hv/connection.c
|
|
@@ -229,8 +229,10 @@ int vmbus_connect(void)
|
|
*/
|
|
|
|
for (i = 0; ; i++) {
|
|
- if (i == ARRAY_SIZE(vmbus_versions))
|
|
+ if (i == ARRAY_SIZE(vmbus_versions)) {
|
|
+ ret = -EDOM;
|
|
goto cleanup;
|
|
+ }
|
|
|
|
version = vmbus_versions[i];
|
|
if (version > max_version)
|
|
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
|
|
index 05566ecdbe4b4..1b914e418e41e 100644
|
|
--- a/drivers/hv/hv_util.c
|
|
+++ b/drivers/hv/hv_util.c
|
|
@@ -696,8 +696,8 @@ static int hv_timesync_init(struct hv_util_service *srv)
|
|
*/
|
|
hv_ptp_clock = ptp_clock_register(&ptp_hyperv_info, NULL);
|
|
if (IS_ERR_OR_NULL(hv_ptp_clock)) {
|
|
- pr_err("cannot register PTP clock: %ld\n",
|
|
- PTR_ERR(hv_ptp_clock));
|
|
+ pr_err("cannot register PTP clock: %d\n",
|
|
+ PTR_ERR_OR_ZERO(hv_ptp_clock));
|
|
hv_ptp_clock = NULL;
|
|
}
|
|
|
|
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
|
|
index ae2b84263a445..6b884ea009877 100644
|
|
--- a/drivers/hwmon/lm70.c
|
|
+++ b/drivers/hwmon/lm70.c
|
|
@@ -22,10 +22,10 @@
|
|
#include <linux/hwmon.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/mod_devicetable.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/property.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/slab.h>
|
|
-#include <linux/of_device.h>
|
|
-#include <linux/acpi.h>
|
|
|
|
#define DRVNAME "lm70"
|
|
|
|
@@ -148,50 +148,17 @@ static const struct of_device_id lm70_of_ids[] = {
|
|
MODULE_DEVICE_TABLE(of, lm70_of_ids);
|
|
#endif
|
|
|
|
-#ifdef CONFIG_ACPI
|
|
-static const struct acpi_device_id lm70_acpi_ids[] = {
|
|
- {
|
|
- .id = "LM000070",
|
|
- .driver_data = LM70_CHIP_LM70,
|
|
- },
|
|
- {
|
|
- .id = "TMP00121",
|
|
- .driver_data = LM70_CHIP_TMP121,
|
|
- },
|
|
- {
|
|
- .id = "LM000071",
|
|
- .driver_data = LM70_CHIP_LM71,
|
|
- },
|
|
- {
|
|
- .id = "LM000074",
|
|
- .driver_data = LM70_CHIP_LM74,
|
|
- },
|
|
- {},
|
|
-};
|
|
-MODULE_DEVICE_TABLE(acpi, lm70_acpi_ids);
|
|
-#endif
|
|
-
|
|
static int lm70_probe(struct spi_device *spi)
|
|
{
|
|
- const struct of_device_id *of_match;
|
|
struct device *hwmon_dev;
|
|
struct lm70 *p_lm70;
|
|
int chip;
|
|
|
|
- of_match = of_match_device(lm70_of_ids, &spi->dev);
|
|
- if (of_match)
|
|
- chip = (int)(uintptr_t)of_match->data;
|
|
- else {
|
|
-#ifdef CONFIG_ACPI
|
|
- const struct acpi_device_id *acpi_match;
|
|
-
|
|
- acpi_match = acpi_match_device(lm70_acpi_ids, &spi->dev);
|
|
- if (acpi_match)
|
|
- chip = (int)(uintptr_t)acpi_match->driver_data;
|
|
- else
|
|
-#endif
|
|
- chip = spi_get_device_id(spi)->driver_data;
|
|
- }
|
|
+ if (dev_fwnode(&spi->dev))
|
|
+ chip = (int)(uintptr_t)device_get_match_data(&spi->dev);
|
|
+ else
|
|
+ chip = spi_get_device_id(spi)->driver_data;
|
|
+
|
|
|
|
/* signaling is SPI_MODE_0 */
|
|
if (spi->mode & (SPI_CPOL | SPI_CPHA))
|
|
@@ -227,7 +194,6 @@ static struct spi_driver lm70_driver = {
|
|
.driver = {
|
|
.name = "lm70",
|
|
.of_match_table = of_match_ptr(lm70_of_ids),
|
|
- .acpi_match_table = ACPI_PTR(lm70_acpi_ids),
|
|
},
|
|
.id_table = lm70_ids,
|
|
.probe = lm70_probe,
|
|
diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c
|
|
index 062eceb7be0db..613338cbcb170 100644
|
|
--- a/drivers/hwmon/max31722.c
|
|
+++ b/drivers/hwmon/max31722.c
|
|
@@ -6,7 +6,6 @@
|
|
* Copyright (c) 2016, Intel Corporation.
|
|
*/
|
|
|
|
-#include <linux/acpi.h>
|
|
#include <linux/hwmon.h>
|
|
#include <linux/hwmon-sysfs.h>
|
|
#include <linux/kernel.h>
|
|
@@ -133,20 +132,12 @@ static const struct spi_device_id max31722_spi_id[] = {
|
|
{"max31723", 0},
|
|
{}
|
|
};
|
|
-
|
|
-static const struct acpi_device_id __maybe_unused max31722_acpi_id[] = {
|
|
- {"MAX31722", 0},
|
|
- {"MAX31723", 0},
|
|
- {}
|
|
-};
|
|
-
|
|
MODULE_DEVICE_TABLE(spi, max31722_spi_id);
|
|
|
|
static struct spi_driver max31722_driver = {
|
|
.driver = {
|
|
.name = "max31722",
|
|
.pm = &max31722_pm_ops,
|
|
- .acpi_match_table = ACPI_PTR(max31722_acpi_id),
|
|
},
|
|
.probe = max31722_probe,
|
|
.remove = max31722_remove,
|
|
diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c
|
|
index 86e6c71db685c..67677c4377687 100644
|
|
--- a/drivers/hwmon/max31790.c
|
|
+++ b/drivers/hwmon/max31790.c
|
|
@@ -27,6 +27,7 @@
|
|
|
|
/* Fan Config register bits */
|
|
#define MAX31790_FAN_CFG_RPM_MODE 0x80
|
|
+#define MAX31790_FAN_CFG_CTRL_MON 0x10
|
|
#define MAX31790_FAN_CFG_TACH_INPUT_EN 0x08
|
|
#define MAX31790_FAN_CFG_TACH_INPUT 0x01
|
|
|
|
@@ -104,7 +105,7 @@ static struct max31790_data *max31790_update_device(struct device *dev)
|
|
data->tach[NR_CHANNEL + i] = rv;
|
|
} else {
|
|
rv = i2c_smbus_read_word_swapped(client,
|
|
- MAX31790_REG_PWMOUT(i));
|
|
+ MAX31790_REG_PWM_DUTY_CYCLE(i));
|
|
if (rv < 0)
|
|
goto abort;
|
|
data->pwm[i] = rv;
|
|
@@ -170,7 +171,7 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel,
|
|
|
|
switch (attr) {
|
|
case hwmon_fan_input:
|
|
- sr = get_tach_period(data->fan_dynamics[channel]);
|
|
+ sr = get_tach_period(data->fan_dynamics[channel % NR_CHANNEL]);
|
|
rpm = RPM_FROM_REG(data->tach[channel], sr);
|
|
*val = rpm;
|
|
return 0;
|
|
@@ -271,12 +272,12 @@ static int max31790_read_pwm(struct device *dev, u32 attr, int channel,
|
|
*val = data->pwm[channel] >> 8;
|
|
return 0;
|
|
case hwmon_pwm_enable:
|
|
- if (fan_config & MAX31790_FAN_CFG_RPM_MODE)
|
|
+ if (fan_config & MAX31790_FAN_CFG_CTRL_MON)
|
|
+ *val = 0;
|
|
+ else if (fan_config & MAX31790_FAN_CFG_RPM_MODE)
|
|
*val = 2;
|
|
- else if (fan_config & MAX31790_FAN_CFG_TACH_INPUT_EN)
|
|
- *val = 1;
|
|
else
|
|
- *val = 0;
|
|
+ *val = 1;
|
|
return 0;
|
|
default:
|
|
return -EOPNOTSUPP;
|
|
@@ -299,31 +300,41 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel,
|
|
err = -EINVAL;
|
|
break;
|
|
}
|
|
- data->pwm[channel] = val << 8;
|
|
+ data->valid = false;
|
|
err = i2c_smbus_write_word_swapped(client,
|
|
MAX31790_REG_PWMOUT(channel),
|
|
- data->pwm[channel]);
|
|
+ val << 8);
|
|
break;
|
|
case hwmon_pwm_enable:
|
|
fan_config = data->fan_config[channel];
|
|
if (val == 0) {
|
|
- fan_config &= ~(MAX31790_FAN_CFG_TACH_INPUT_EN |
|
|
- MAX31790_FAN_CFG_RPM_MODE);
|
|
+ fan_config |= MAX31790_FAN_CFG_CTRL_MON;
|
|
+ /*
|
|
+ * Disable RPM mode; otherwise disabling fan speed
|
|
+ * monitoring is not possible.
|
|
+ */
|
|
+ fan_config &= ~MAX31790_FAN_CFG_RPM_MODE;
|
|
} else if (val == 1) {
|
|
- fan_config = (fan_config |
|
|
- MAX31790_FAN_CFG_TACH_INPUT_EN) &
|
|
- ~MAX31790_FAN_CFG_RPM_MODE;
|
|
+ fan_config &= ~(MAX31790_FAN_CFG_CTRL_MON | MAX31790_FAN_CFG_RPM_MODE);
|
|
} else if (val == 2) {
|
|
- fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN |
|
|
- MAX31790_FAN_CFG_RPM_MODE;
|
|
+ fan_config &= ~MAX31790_FAN_CFG_CTRL_MON;
|
|
+ /*
|
|
+ * The chip sets MAX31790_FAN_CFG_TACH_INPUT_EN on its
|
|
+ * own if MAX31790_FAN_CFG_RPM_MODE is set.
|
|
+ * Do it here as well to reflect the actual register
|
|
+ * value in the cache.
|
|
+ */
|
|
+ fan_config |= (MAX31790_FAN_CFG_RPM_MODE | MAX31790_FAN_CFG_TACH_INPUT_EN);
|
|
} else {
|
|
err = -EINVAL;
|
|
break;
|
|
}
|
|
- data->fan_config[channel] = fan_config;
|
|
- err = i2c_smbus_write_byte_data(client,
|
|
- MAX31790_REG_FAN_CONFIG(channel),
|
|
- fan_config);
|
|
+ if (fan_config != data->fan_config[channel]) {
|
|
+ err = i2c_smbus_write_byte_data(client, MAX31790_REG_FAN_CONFIG(channel),
|
|
+ fan_config);
|
|
+ if (!err)
|
|
+ data->fan_config[channel] = fan_config;
|
|
+ }
|
|
break;
|
|
default:
|
|
err = -EOPNOTSUPP;
|
|
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
|
|
index cc9e8025c533c..b2088d2d386a4 100644
|
|
--- a/drivers/hwtracing/coresight/coresight-core.c
|
|
+++ b/drivers/hwtracing/coresight/coresight-core.c
|
|
@@ -581,7 +581,7 @@ static struct coresight_device *
|
|
coresight_find_enabled_sink(struct coresight_device *csdev)
|
|
{
|
|
int i;
|
|
- struct coresight_device *sink;
|
|
+ struct coresight_device *sink = NULL;
|
|
|
|
if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
|
|
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
|
|
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
|
|
index 6b74c2b04c157..da56488182d07 100644
|
|
--- a/drivers/iio/accel/bma180.c
|
|
+++ b/drivers/iio/accel/bma180.c
|
|
@@ -55,7 +55,7 @@ struct bma180_part_info {
|
|
|
|
u8 int_reset_reg, int_reset_mask;
|
|
u8 sleep_reg, sleep_mask;
|
|
- u8 bw_reg, bw_mask;
|
|
+ u8 bw_reg, bw_mask, bw_offset;
|
|
u8 scale_reg, scale_mask;
|
|
u8 power_reg, power_mask, lowpower_val;
|
|
u8 int_enable_reg, int_enable_mask;
|
|
@@ -127,6 +127,7 @@ struct bma180_part_info {
|
|
|
|
#define BMA250_RANGE_MASK GENMASK(3, 0) /* Range of accel values */
|
|
#define BMA250_BW_MASK GENMASK(4, 0) /* Accel bandwidth */
|
|
+#define BMA250_BW_OFFSET 8
|
|
#define BMA250_SUSPEND_MASK BIT(7) /* chip will sleep */
|
|
#define BMA250_LOWPOWER_MASK BIT(6)
|
|
#define BMA250_DATA_INTEN_MASK BIT(4)
|
|
@@ -143,6 +144,7 @@ struct bma180_part_info {
|
|
|
|
#define BMA254_RANGE_MASK GENMASK(3, 0) /* Range of accel values */
|
|
#define BMA254_BW_MASK GENMASK(4, 0) /* Accel bandwidth */
|
|
+#define BMA254_BW_OFFSET 8
|
|
#define BMA254_SUSPEND_MASK BIT(7) /* chip will sleep */
|
|
#define BMA254_LOWPOWER_MASK BIT(6)
|
|
#define BMA254_DATA_INTEN_MASK BIT(4)
|
|
@@ -162,7 +164,11 @@ struct bma180_data {
|
|
int scale;
|
|
int bw;
|
|
bool pmode;
|
|
- u8 buff[16]; /* 3x 16-bit + 8-bit + padding + timestamp */
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ s16 chan[4];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
enum bma180_chan {
|
|
@@ -283,7 +289,8 @@ static int bma180_set_bw(struct bma180_data *data, int val)
|
|
for (i = 0; i < data->part_info->num_bw; ++i) {
|
|
if (data->part_info->bw_table[i] == val) {
|
|
ret = bma180_set_bits(data, data->part_info->bw_reg,
|
|
- data->part_info->bw_mask, i);
|
|
+ data->part_info->bw_mask,
|
|
+ i + data->part_info->bw_offset);
|
|
if (ret) {
|
|
dev_err(&data->client->dev,
|
|
"failed to set bandwidth\n");
|
|
@@ -876,6 +883,7 @@ static const struct bma180_part_info bma180_part_info[] = {
|
|
.sleep_mask = BMA250_SUSPEND_MASK,
|
|
.bw_reg = BMA250_BW_REG,
|
|
.bw_mask = BMA250_BW_MASK,
|
|
+ .bw_offset = BMA250_BW_OFFSET,
|
|
.scale_reg = BMA250_RANGE_REG,
|
|
.scale_mask = BMA250_RANGE_MASK,
|
|
.power_reg = BMA250_POWER_REG,
|
|
@@ -905,6 +913,7 @@ static const struct bma180_part_info bma180_part_info[] = {
|
|
.sleep_mask = BMA254_SUSPEND_MASK,
|
|
.bw_reg = BMA254_BW_REG,
|
|
.bw_mask = BMA254_BW_MASK,
|
|
+ .bw_offset = BMA254_BW_OFFSET,
|
|
.scale_reg = BMA254_RANGE_REG,
|
|
.scale_mask = BMA254_RANGE_MASK,
|
|
.power_reg = BMA254_POWER_REG,
|
|
@@ -938,12 +947,12 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p)
|
|
mutex_unlock(&data->mutex);
|
|
goto err;
|
|
}
|
|
- ((s16 *)data->buff)[i++] = ret;
|
|
+ data->scan.chan[i++] = ret;
|
|
}
|
|
|
|
mutex_unlock(&data->mutex);
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns);
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns);
|
|
err:
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
|
|
diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c
|
|
index 3c9b0c6954e60..e8a9db1a82ad8 100644
|
|
--- a/drivers/iio/accel/bma220_spi.c
|
|
+++ b/drivers/iio/accel/bma220_spi.c
|
|
@@ -63,7 +63,11 @@ static const int bma220_scale_table[][2] = {
|
|
struct bma220_data {
|
|
struct spi_device *spi_device;
|
|
struct mutex lock;
|
|
- s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */
|
|
+ struct {
|
|
+ s8 chans[3];
|
|
+ /* Ensure timestamp is naturally aligned. */
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
u8 tx_buf[2] ____cacheline_aligned;
|
|
};
|
|
|
|
@@ -94,12 +98,12 @@ static irqreturn_t bma220_trigger_handler(int irq, void *p)
|
|
|
|
mutex_lock(&data->lock);
|
|
data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK;
|
|
- ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer,
|
|
+ ret = spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans,
|
|
ARRAY_SIZE(bma220_channels) - 1);
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
pf->timestamp);
|
|
err:
|
|
mutex_unlock(&data->lock);
|
|
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
|
|
index 4c5e594024f8c..f05840d17fb71 100644
|
|
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
|
|
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
|
|
@@ -27,8 +27,11 @@ struct accel_3d_state {
|
|
struct hid_sensor_hub_callbacks callbacks;
|
|
struct hid_sensor_common common_attributes;
|
|
struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX];
|
|
- /* Reserve for 3 channels + padding + timestamp */
|
|
- u32 accel_val[ACCEL_3D_CHANNEL_MAX + 3];
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ u32 accel_val[3];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
int scale_pre_decml;
|
|
int scale_post_decml;
|
|
int scale_precision;
|
|
@@ -239,8 +242,8 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev,
|
|
accel_state->timestamp = iio_get_time_ns(indio_dev);
|
|
|
|
hid_sensor_push_data(indio_dev,
|
|
- accel_state->accel_val,
|
|
- sizeof(accel_state->accel_val),
|
|
+ &accel_state->scan,
|
|
+ sizeof(accel_state->scan),
|
|
accel_state->timestamp);
|
|
|
|
accel_state->timestamp = 0;
|
|
@@ -265,7 +268,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
|
|
case HID_USAGE_SENSOR_ACCEL_Y_AXIS:
|
|
case HID_USAGE_SENSOR_ACCEL_Z_AXIS:
|
|
offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS;
|
|
- accel_state->accel_val[CHANNEL_SCAN_INDEX_X + offset] =
|
|
+ accel_state->scan.accel_val[CHANNEL_SCAN_INDEX_X + offset] =
|
|
*(u32 *)raw_data;
|
|
ret = 0;
|
|
break;
|
|
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
|
|
index 560a3373ff20d..c99e90469a245 100644
|
|
--- a/drivers/iio/accel/kxcjk-1013.c
|
|
+++ b/drivers/iio/accel/kxcjk-1013.c
|
|
@@ -132,13 +132,24 @@ enum kx_acpi_type {
|
|
ACPI_KIOX010A,
|
|
};
|
|
|
|
+enum kxcjk1013_axis {
|
|
+ AXIS_X,
|
|
+ AXIS_Y,
|
|
+ AXIS_Z,
|
|
+ AXIS_MAX
|
|
+};
|
|
+
|
|
struct kxcjk1013_data {
|
|
struct i2c_client *client;
|
|
struct iio_trigger *dready_trig;
|
|
struct iio_trigger *motion_trig;
|
|
struct iio_mount_matrix orientation;
|
|
struct mutex mutex;
|
|
- s16 buffer[8];
|
|
+ /* Ensure timestamp naturally aligned */
|
|
+ struct {
|
|
+ s16 chans[AXIS_MAX];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
u8 odr_bits;
|
|
u8 range;
|
|
int wake_thres;
|
|
@@ -152,13 +163,6 @@ struct kxcjk1013_data {
|
|
enum kx_acpi_type acpi_type;
|
|
};
|
|
|
|
-enum kxcjk1013_axis {
|
|
- AXIS_X,
|
|
- AXIS_Y,
|
|
- AXIS_Z,
|
|
- AXIS_MAX,
|
|
-};
|
|
-
|
|
enum kxcjk1013_mode {
|
|
STANDBY,
|
|
OPERATION,
|
|
@@ -1092,12 +1096,12 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
|
|
ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client,
|
|
KXCJK1013_REG_XOUT_L,
|
|
AXIS_MAX * 2,
|
|
- (u8 *)data->buffer);
|
|
+ (u8 *)data->scan.chans);
|
|
mutex_unlock(&data->mutex);
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
data->timestamp);
|
|
err:
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
|
|
index f877263dc6efb..5a2b0ffbb145d 100644
|
|
--- a/drivers/iio/accel/mxc4005.c
|
|
+++ b/drivers/iio/accel/mxc4005.c
|
|
@@ -56,7 +56,11 @@ struct mxc4005_data {
|
|
struct mutex mutex;
|
|
struct regmap *regmap;
|
|
struct iio_trigger *dready_trig;
|
|
- __be16 buffer[8];
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ __be16 chans[3];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
bool trigger_enabled;
|
|
};
|
|
|
|
@@ -135,7 +139,7 @@ static int mxc4005_read_xyz(struct mxc4005_data *data)
|
|
int ret;
|
|
|
|
ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER,
|
|
- data->buffer, sizeof(data->buffer));
|
|
+ data->scan.chans, sizeof(data->scan.chans));
|
|
if (ret < 0) {
|
|
dev_err(data->dev, "failed to read axes\n");
|
|
return ret;
|
|
@@ -301,7 +305,7 @@ static irqreturn_t mxc4005_trigger_handler(int irq, void *private)
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
pf->timestamp);
|
|
|
|
err:
|
|
diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c
|
|
index 3b59887a8581b..7d24801e8aa7c 100644
|
|
--- a/drivers/iio/accel/stk8312.c
|
|
+++ b/drivers/iio/accel/stk8312.c
|
|
@@ -103,7 +103,11 @@ struct stk8312_data {
|
|
u8 mode;
|
|
struct iio_trigger *dready_trig;
|
|
bool dready_trigger_on;
|
|
- s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 64-bit timestamp */
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ s8 chans[3];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL);
|
|
@@ -438,7 +442,7 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p)
|
|
ret = i2c_smbus_read_i2c_block_data(data->client,
|
|
STK8312_REG_XOUT,
|
|
STK8312_ALL_CHANNEL_SIZE,
|
|
- data->buffer);
|
|
+ data->scan.chans);
|
|
if (ret < STK8312_ALL_CHANNEL_SIZE) {
|
|
dev_err(&data->client->dev, "register read failed\n");
|
|
mutex_unlock(&data->lock);
|
|
@@ -452,12 +456,12 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p)
|
|
mutex_unlock(&data->lock);
|
|
goto err;
|
|
}
|
|
- data->buffer[i++] = ret;
|
|
+ data->scan.chans[i++] = ret;
|
|
}
|
|
}
|
|
mutex_unlock(&data->lock);
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
pf->timestamp);
|
|
err:
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c
|
|
index 3ead378b02c9b..e8087d7ee49f9 100644
|
|
--- a/drivers/iio/accel/stk8ba50.c
|
|
+++ b/drivers/iio/accel/stk8ba50.c
|
|
@@ -91,12 +91,11 @@ struct stk8ba50_data {
|
|
u8 sample_rate_idx;
|
|
struct iio_trigger *dready_trig;
|
|
bool dready_trigger_on;
|
|
- /*
|
|
- * 3 x 16-bit channels (10-bit data, 6-bit padding) +
|
|
- * 1 x 16 padding +
|
|
- * 4 x 16 64-bit timestamp
|
|
- */
|
|
- s16 buffer[8];
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ s16 chans[3];
|
|
+ s64 timetamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
#define STK8BA50_ACCEL_CHANNEL(index, reg, axis) { \
|
|
@@ -324,7 +323,7 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p)
|
|
ret = i2c_smbus_read_i2c_block_data(data->client,
|
|
STK8BA50_REG_XOUT,
|
|
STK8BA50_ALL_CHANNEL_SIZE,
|
|
- (u8 *)data->buffer);
|
|
+ (u8 *)data->scan.chans);
|
|
if (ret < STK8BA50_ALL_CHANNEL_SIZE) {
|
|
dev_err(&data->client->dev, "register read failed\n");
|
|
goto err;
|
|
@@ -337,10 +336,10 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p)
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
- data->buffer[i++] = ret;
|
|
+ data->scan.chans[i++] = ret;
|
|
}
|
|
}
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
pf->timestamp);
|
|
err:
|
|
mutex_unlock(&data->lock);
|
|
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
|
|
index b917a4714a9c9..b8139c435a4b0 100644
|
|
--- a/drivers/iio/adc/at91-sama5d2_adc.c
|
|
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
|
|
@@ -403,7 +403,8 @@ struct at91_adc_state {
|
|
struct at91_adc_dma dma_st;
|
|
struct at91_adc_touch touch_st;
|
|
struct iio_dev *indio_dev;
|
|
- u16 buffer[AT91_BUFFER_MAX_HWORDS];
|
|
+ /* Ensure naturally aligned timestamp */
|
|
+ u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8);
|
|
/*
|
|
* lock to prevent concurrent 'single conversion' requests through
|
|
* sysfs.
|
|
diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c
|
|
index 6a173531d355b..f7ee856a6b8b6 100644
|
|
--- a/drivers/iio/adc/hx711.c
|
|
+++ b/drivers/iio/adc/hx711.c
|
|
@@ -86,9 +86,9 @@ struct hx711_data {
|
|
struct mutex lock;
|
|
/*
|
|
* triggered buffer
|
|
- * 2x32-bit channel + 64-bit timestamp
|
|
+ * 2x32-bit channel + 64-bit naturally aligned timestamp
|
|
*/
|
|
- u32 buffer[4];
|
|
+ u32 buffer[4] __aligned(8);
|
|
/*
|
|
* delay after a rising edge on SCK until the data is ready DOUT
|
|
* this is dependent on the hx711 where the datasheet tells a
|
|
diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
|
|
index 30e29f44ebd2e..c480cb489c1a3 100644
|
|
--- a/drivers/iio/adc/mxs-lradc-adc.c
|
|
+++ b/drivers/iio/adc/mxs-lradc-adc.c
|
|
@@ -115,7 +115,8 @@ struct mxs_lradc_adc {
|
|
struct device *dev;
|
|
|
|
void __iomem *base;
|
|
- u32 buffer[10];
|
|
+ /* Maximum of 8 channels + 8 byte ts */
|
|
+ u32 buffer[10] __aligned(8);
|
|
struct iio_trigger *trig;
|
|
struct completion completion;
|
|
spinlock_t lock;
|
|
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
|
|
index 9fef39bcf997b..5b828428be77c 100644
|
|
--- a/drivers/iio/adc/ti-ads1015.c
|
|
+++ b/drivers/iio/adc/ti-ads1015.c
|
|
@@ -395,10 +395,14 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p)
|
|
struct iio_poll_func *pf = p;
|
|
struct iio_dev *indio_dev = pf->indio_dev;
|
|
struct ads1015_data *data = iio_priv(indio_dev);
|
|
- s16 buf[8]; /* 1x s16 ADC val + 3x s16 padding + 4x s16 timestamp */
|
|
+ /* Ensure natural alignment of timestamp */
|
|
+ struct {
|
|
+ s16 chan;
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
int chan, ret, res;
|
|
|
|
- memset(buf, 0, sizeof(buf));
|
|
+ memset(&scan, 0, sizeof(scan));
|
|
|
|
mutex_lock(&data->lock);
|
|
chan = find_first_bit(indio_dev->active_scan_mask,
|
|
@@ -409,10 +413,10 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p)
|
|
goto err;
|
|
}
|
|
|
|
- buf[0] = res;
|
|
+ scan.chan = res;
|
|
mutex_unlock(&data->lock);
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, buf,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
|
|
iio_get_time_ns(indio_dev));
|
|
|
|
err:
|
|
diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c
|
|
index 16bcb37eebb72..79c803537dc42 100644
|
|
--- a/drivers/iio/adc/ti-ads8688.c
|
|
+++ b/drivers/iio/adc/ti-ads8688.c
|
|
@@ -383,7 +383,8 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p)
|
|
{
|
|
struct iio_poll_func *pf = p;
|
|
struct iio_dev *indio_dev = pf->indio_dev;
|
|
- u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)];
|
|
+ /* Ensure naturally aligned timestamp */
|
|
+ u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)] __aligned(8);
|
|
int i, j = 0;
|
|
|
|
for (i = 0; i < indio_dev->masklength; i++) {
|
|
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
|
|
index 1d794cf3e3f13..fd57fc43e8e5c 100644
|
|
--- a/drivers/iio/adc/vf610_adc.c
|
|
+++ b/drivers/iio/adc/vf610_adc.c
|
|
@@ -167,7 +167,11 @@ struct vf610_adc {
|
|
u32 sample_freq_avail[5];
|
|
|
|
struct completion completion;
|
|
- u16 buffer[8];
|
|
+ /* Ensure the timestamp is naturally aligned */
|
|
+ struct {
|
|
+ u16 chan;
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
|
|
@@ -579,9 +583,9 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
|
|
if (coco & VF610_ADC_HS_COCO0) {
|
|
info->value = vf610_adc_read_data(info);
|
|
if (iio_buffer_enabled(indio_dev)) {
|
|
- info->buffer[0] = info->value;
|
|
+ info->scan.chan = info->value;
|
|
iio_push_to_buffers_with_timestamp(indio_dev,
|
|
- info->buffer,
|
|
+ &info->scan,
|
|
iio_get_time_ns(indio_dev));
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
} else
|
|
diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c
|
|
index cdab9d04dedd0..0c8a50de89408 100644
|
|
--- a/drivers/iio/chemical/atlas-sensor.c
|
|
+++ b/drivers/iio/chemical/atlas-sensor.c
|
|
@@ -91,8 +91,8 @@ struct atlas_data {
|
|
struct regmap *regmap;
|
|
struct irq_work work;
|
|
unsigned int interrupt_enabled;
|
|
-
|
|
- __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */
|
|
+ /* 96-bit data + 32-bit pad + 64-bit timestamp */
|
|
+ __be32 buffer[6] __aligned(8);
|
|
};
|
|
|
|
static const struct regmap_config atlas_regmap_config = {
|
|
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
|
|
index 82c050a3899d9..8f885b0af38e5 100644
|
|
--- a/drivers/iio/frequency/adf4350.c
|
|
+++ b/drivers/iio/frequency/adf4350.c
|
|
@@ -563,8 +563,10 @@ static int adf4350_probe(struct spi_device *spi)
|
|
|
|
st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL,
|
|
GPIOD_IN);
|
|
- if (IS_ERR(st->lock_detect_gpiod))
|
|
- return PTR_ERR(st->lock_detect_gpiod);
|
|
+ if (IS_ERR(st->lock_detect_gpiod)) {
|
|
+ ret = PTR_ERR(st->lock_detect_gpiod);
|
|
+ goto error_disable_reg;
|
|
+ }
|
|
|
|
if (pdata->power_up_frequency) {
|
|
ret = adf4350_set_freq(st, pdata->power_up_frequency);
|
|
diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c
|
|
index 8ddda96455fcb..39fe0b1785920 100644
|
|
--- a/drivers/iio/gyro/bmg160_core.c
|
|
+++ b/drivers/iio/gyro/bmg160_core.c
|
|
@@ -96,7 +96,11 @@ struct bmg160_data {
|
|
struct iio_trigger *motion_trig;
|
|
struct iio_mount_matrix orientation;
|
|
struct mutex mutex;
|
|
- s16 buffer[8];
|
|
+ /* Ensure naturally aligned timestamp */
|
|
+ struct {
|
|
+ s16 chans[3];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
u32 dps_range;
|
|
int ev_enable_state;
|
|
int slope_thres;
|
|
@@ -880,12 +884,12 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p)
|
|
|
|
mutex_lock(&data->mutex);
|
|
ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L,
|
|
- data->buffer, AXIS_MAX * 2);
|
|
+ data->scan.chans, AXIS_MAX * 2);
|
|
mutex_unlock(&data->mutex);
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
pf->timestamp);
|
|
err:
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c
|
|
index 02ad1767c845e..3398fa413ec5c 100644
|
|
--- a/drivers/iio/humidity/am2315.c
|
|
+++ b/drivers/iio/humidity/am2315.c
|
|
@@ -33,7 +33,11 @@
|
|
struct am2315_data {
|
|
struct i2c_client *client;
|
|
struct mutex lock;
|
|
- s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ s16 chans[2];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
struct am2315_sensor_data {
|
|
@@ -167,20 +171,20 @@ static irqreturn_t am2315_trigger_handler(int irq, void *p)
|
|
|
|
mutex_lock(&data->lock);
|
|
if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) {
|
|
- data->buffer[0] = sensor_data.hum_data;
|
|
- data->buffer[1] = sensor_data.temp_data;
|
|
+ data->scan.chans[0] = sensor_data.hum_data;
|
|
+ data->scan.chans[1] = sensor_data.temp_data;
|
|
} else {
|
|
i = 0;
|
|
for_each_set_bit(bit, indio_dev->active_scan_mask,
|
|
indio_dev->masklength) {
|
|
- data->buffer[i] = (bit ? sensor_data.temp_data :
|
|
- sensor_data.hum_data);
|
|
+ data->scan.chans[i] = (bit ? sensor_data.temp_data :
|
|
+ sensor_data.hum_data);
|
|
i++;
|
|
}
|
|
}
|
|
mutex_unlock(&data->lock);
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
pf->timestamp);
|
|
err:
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
|
|
index 785a4ce606d89..4aff16466da02 100644
|
|
--- a/drivers/iio/imu/adis16400.c
|
|
+++ b/drivers/iio/imu/adis16400.c
|
|
@@ -647,9 +647,6 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p)
|
|
void *buffer;
|
|
int ret;
|
|
|
|
- if (!adis->buffer)
|
|
- return -ENOMEM;
|
|
-
|
|
if (!(st->variant->flags & ADIS16400_NO_BURST) &&
|
|
st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) {
|
|
st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST;
|
|
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
|
|
index 197d482409911..3c4e4deb87608 100644
|
|
--- a/drivers/iio/imu/adis16475.c
|
|
+++ b/drivers/iio/imu/adis16475.c
|
|
@@ -990,7 +990,7 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p)
|
|
|
|
ret = spi_sync(adis->spi, &adis->msg);
|
|
if (ret)
|
|
- return ret;
|
|
+ goto check_burst32;
|
|
|
|
adis->spi->max_speed_hz = cached_spi_speed_hz;
|
|
buffer = adis->buffer;
|
|
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
|
|
index ac354321f63a3..175af154e4437 100644
|
|
--- a/drivers/iio/imu/adis_buffer.c
|
|
+++ b/drivers/iio/imu/adis_buffer.c
|
|
@@ -129,9 +129,6 @@ static irqreturn_t adis_trigger_handler(int irq, void *p)
|
|
struct adis *adis = iio_device_get_drvdata(indio_dev);
|
|
int ret;
|
|
|
|
- if (!adis->buffer)
|
|
- return -ENOMEM;
|
|
-
|
|
if (adis->data->has_paging) {
|
|
mutex_lock(&adis->state_lock);
|
|
if (adis->current_page != 0) {
|
|
diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c
|
|
index b93b85dbc3a6a..ba53b50d711a1 100644
|
|
--- a/drivers/iio/light/isl29125.c
|
|
+++ b/drivers/iio/light/isl29125.c
|
|
@@ -51,7 +51,11 @@
|
|
struct isl29125_data {
|
|
struct i2c_client *client;
|
|
u8 conf1;
|
|
- u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ u16 chans[3];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
#define ISL29125_CHANNEL(_color, _si) { \
|
|
@@ -184,10 +188,10 @@ static irqreturn_t isl29125_trigger_handler(int irq, void *p)
|
|
if (ret < 0)
|
|
goto done;
|
|
|
|
- data->buffer[j++] = ret;
|
|
+ data->scan.chans[j++] = ret;
|
|
}
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
iio_get_time_ns(indio_dev));
|
|
|
|
done:
|
|
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
|
|
index b4323d2db0b19..74ed2d88a3ed3 100644
|
|
--- a/drivers/iio/light/ltr501.c
|
|
+++ b/drivers/iio/light/ltr501.c
|
|
@@ -32,9 +32,12 @@
|
|
#define LTR501_PART_ID 0x86
|
|
#define LTR501_MANUFAC_ID 0x87
|
|
#define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */
|
|
+#define LTR501_ALS_DATA1_UPPER 0x89 /* upper 8 bits of LTR501_ALS_DATA1 */
|
|
#define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */
|
|
+#define LTR501_ALS_DATA0_UPPER 0x8b /* upper 8 bits of LTR501_ALS_DATA0 */
|
|
#define LTR501_ALS_PS_STATUS 0x8c
|
|
#define LTR501_PS_DATA 0x8d /* 16-bit, little endian */
|
|
+#define LTR501_PS_DATA_UPPER 0x8e /* upper 8 bits of LTR501_PS_DATA */
|
|
#define LTR501_INTR 0x8f /* output mode, polarity, mode */
|
|
#define LTR501_PS_THRESH_UP 0x90 /* 11 bit, ps upper threshold */
|
|
#define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */
|
|
@@ -406,18 +409,19 @@ static int ltr501_read_als(const struct ltr501_data *data, __le16 buf[2])
|
|
|
|
static int ltr501_read_ps(const struct ltr501_data *data)
|
|
{
|
|
- int ret, status;
|
|
+ __le16 status;
|
|
+ int ret;
|
|
|
|
ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA,
|
|
- &status, 2);
|
|
+ &status, sizeof(status));
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- return status;
|
|
+ return le16_to_cpu(status);
|
|
}
|
|
|
|
static int ltr501_read_intr_prst(const struct ltr501_data *data,
|
|
@@ -1205,7 +1209,7 @@ static struct ltr501_chip_info ltr501_chip_info_tbl[] = {
|
|
.als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
|
|
.ps_gain = ltr559_ps_gain_tbl,
|
|
.ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl),
|
|
- .als_mode_active = BIT(1),
|
|
+ .als_mode_active = BIT(0),
|
|
.als_gain_mask = BIT(2) | BIT(3) | BIT(4),
|
|
.als_gain_shift = 2,
|
|
.info = <r501_info,
|
|
@@ -1354,9 +1358,12 @@ static bool ltr501_is_volatile_reg(struct device *dev, unsigned int reg)
|
|
{
|
|
switch (reg) {
|
|
case LTR501_ALS_DATA1:
|
|
+ case LTR501_ALS_DATA1_UPPER:
|
|
case LTR501_ALS_DATA0:
|
|
+ case LTR501_ALS_DATA0_UPPER:
|
|
case LTR501_ALS_PS_STATUS:
|
|
case LTR501_PS_DATA:
|
|
+ case LTR501_PS_DATA_UPPER:
|
|
return true;
|
|
default:
|
|
return false;
|
|
diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c
|
|
index 6fe5d46f80d40..0593abd600ec2 100644
|
|
--- a/drivers/iio/light/tcs3414.c
|
|
+++ b/drivers/iio/light/tcs3414.c
|
|
@@ -53,7 +53,11 @@ struct tcs3414_data {
|
|
u8 control;
|
|
u8 gain;
|
|
u8 timing;
|
|
- u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ u16 chans[4];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
#define TCS3414_CHANNEL(_color, _si, _addr) { \
|
|
@@ -209,10 +213,10 @@ static irqreturn_t tcs3414_trigger_handler(int irq, void *p)
|
|
if (ret < 0)
|
|
goto done;
|
|
|
|
- data->buffer[j++] = ret;
|
|
+ data->scan.chans[j++] = ret;
|
|
}
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
iio_get_time_ns(indio_dev));
|
|
|
|
done:
|
|
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
|
|
index a0dc447aeb68b..371c6a39a1654 100644
|
|
--- a/drivers/iio/light/tcs3472.c
|
|
+++ b/drivers/iio/light/tcs3472.c
|
|
@@ -64,7 +64,11 @@ struct tcs3472_data {
|
|
u8 control;
|
|
u8 atime;
|
|
u8 apers;
|
|
- u16 buffer[8]; /* 4 16-bit channels + 64-bit timestamp */
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ u16 chans[4];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
static const struct iio_event_spec tcs3472_events[] = {
|
|
@@ -386,10 +390,10 @@ static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
|
|
if (ret < 0)
|
|
goto done;
|
|
|
|
- data->buffer[j++] = ret;
|
|
+ data->scan.chans[j++] = ret;
|
|
}
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
iio_get_time_ns(indio_dev));
|
|
|
|
done:
|
|
@@ -531,7 +535,8 @@ static int tcs3472_probe(struct i2c_client *client,
|
|
return 0;
|
|
|
|
free_irq:
|
|
- free_irq(client->irq, indio_dev);
|
|
+ if (client->irq)
|
|
+ free_irq(client->irq, indio_dev);
|
|
buffer_cleanup:
|
|
iio_triggered_buffer_cleanup(indio_dev);
|
|
return ret;
|
|
@@ -559,7 +564,8 @@ static int tcs3472_remove(struct i2c_client *client)
|
|
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
|
|
|
iio_device_unregister(indio_dev);
|
|
- free_irq(client->irq, indio_dev);
|
|
+ if (client->irq)
|
|
+ free_irq(client->irq, indio_dev);
|
|
iio_triggered_buffer_cleanup(indio_dev);
|
|
tcs3472_powerdown(iio_priv(indio_dev));
|
|
|
|
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
|
|
index fff4b36b8b58d..f4feb44903b3f 100644
|
|
--- a/drivers/iio/light/vcnl4000.c
|
|
+++ b/drivers/iio/light/vcnl4000.c
|
|
@@ -910,7 +910,7 @@ static irqreturn_t vcnl4010_trigger_handler(int irq, void *p)
|
|
struct iio_dev *indio_dev = pf->indio_dev;
|
|
struct vcnl4000_data *data = iio_priv(indio_dev);
|
|
const unsigned long *active_scan_mask = indio_dev->active_scan_mask;
|
|
- u16 buffer[8] = {0}; /* 1x16-bit + ts */
|
|
+ u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */
|
|
bool data_read = false;
|
|
unsigned long isr;
|
|
int val = 0;
|
|
diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c
|
|
index 765c44adac574..1bd85e21fd114 100644
|
|
--- a/drivers/iio/light/vcnl4035.c
|
|
+++ b/drivers/iio/light/vcnl4035.c
|
|
@@ -102,7 +102,8 @@ static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p)
|
|
struct iio_poll_func *pf = p;
|
|
struct iio_dev *indio_dev = pf->indio_dev;
|
|
struct vcnl4035_data *data = iio_priv(indio_dev);
|
|
- u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)];
|
|
+ /* Ensure naturally aligned timestamp */
|
|
+ u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)] __aligned(8);
|
|
int ret;
|
|
|
|
ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer);
|
|
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
|
|
index fc6840f9c1fa6..8042175275d09 100644
|
|
--- a/drivers/iio/magnetometer/bmc150_magn.c
|
|
+++ b/drivers/iio/magnetometer/bmc150_magn.c
|
|
@@ -136,8 +136,11 @@ struct bmc150_magn_data {
|
|
struct mutex mutex;
|
|
struct regmap *regmap;
|
|
struct iio_mount_matrix orientation;
|
|
- /* 4 x 32 bits for x, y z, 4 bytes align, 64 bits timestamp */
|
|
- s32 buffer[6];
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ s32 chans[3];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
struct iio_trigger *dready_trig;
|
|
bool dready_trigger_on;
|
|
int max_odr;
|
|
@@ -673,11 +676,11 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
|
|
int ret;
|
|
|
|
mutex_lock(&data->mutex);
|
|
- ret = bmc150_magn_read_xyz(data, data->buffer);
|
|
+ ret = bmc150_magn_read_xyz(data, data->scan.chans);
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
pf->timestamp);
|
|
|
|
err:
|
|
diff --git a/drivers/iio/magnetometer/hmc5843.h b/drivers/iio/magnetometer/hmc5843.h
|
|
index 3f6c0b6629415..242f742f2643a 100644
|
|
--- a/drivers/iio/magnetometer/hmc5843.h
|
|
+++ b/drivers/iio/magnetometer/hmc5843.h
|
|
@@ -33,7 +33,8 @@ enum hmc5843_ids {
|
|
* @lock: update and read regmap data
|
|
* @regmap: hardware access register maps
|
|
* @variant: describe chip variants
|
|
- * @buffer: 3x 16-bit channels + padding + 64-bit timestamp
|
|
+ * @scan: buffer to pack data for passing to
|
|
+ * iio_push_to_buffers_with_timestamp()
|
|
*/
|
|
struct hmc5843_data {
|
|
struct device *dev;
|
|
@@ -41,7 +42,10 @@ struct hmc5843_data {
|
|
struct regmap *regmap;
|
|
const struct hmc5843_chip_info *variant;
|
|
struct iio_mount_matrix orientation;
|
|
- __be16 buffer[8];
|
|
+ struct {
|
|
+ __be16 chans[3];
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
|
|
diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c
|
|
index 780faea61d82e..221563e0c18fd 100644
|
|
--- a/drivers/iio/magnetometer/hmc5843_core.c
|
|
+++ b/drivers/iio/magnetometer/hmc5843_core.c
|
|
@@ -446,13 +446,13 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
|
|
}
|
|
|
|
ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
|
|
- data->buffer, 3 * sizeof(__be16));
|
|
+ data->scan.chans, sizeof(data->scan.chans));
|
|
|
|
mutex_unlock(&data->lock);
|
|
if (ret < 0)
|
|
goto done;
|
|
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
iio_get_time_ns(indio_dev));
|
|
|
|
done:
|
|
diff --git a/drivers/iio/magnetometer/rm3100-core.c b/drivers/iio/magnetometer/rm3100-core.c
|
|
index 7242897a05e95..720234a91db11 100644
|
|
--- a/drivers/iio/magnetometer/rm3100-core.c
|
|
+++ b/drivers/iio/magnetometer/rm3100-core.c
|
|
@@ -78,7 +78,8 @@ struct rm3100_data {
|
|
bool use_interrupt;
|
|
int conversion_time;
|
|
int scale;
|
|
- u8 buffer[RM3100_SCAN_BYTES];
|
|
+ /* Ensure naturally aligned timestamp */
|
|
+ u8 buffer[RM3100_SCAN_BYTES] __aligned(8);
|
|
struct iio_trigger *drdy_trig;
|
|
|
|
/*
|
|
diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c
|
|
index f34ca769dc20d..d7ff74a798ba3 100644
|
|
--- a/drivers/iio/potentiostat/lmp91000.c
|
|
+++ b/drivers/iio/potentiostat/lmp91000.c
|
|
@@ -71,8 +71,8 @@ struct lmp91000_data {
|
|
|
|
struct completion completion;
|
|
u8 chan_select;
|
|
-
|
|
- u32 buffer[4]; /* 64-bit data + 64-bit timestamp */
|
|
+ /* 64-bit data + 64-bit naturally aligned timestamp */
|
|
+ u32 buffer[4] __aligned(8);
|
|
};
|
|
|
|
static const struct iio_chan_spec lmp91000_channels[] = {
|
|
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
|
|
index b79ada839e012..98330e26ac3bd 100644
|
|
--- a/drivers/iio/proximity/as3935.c
|
|
+++ b/drivers/iio/proximity/as3935.c
|
|
@@ -59,7 +59,11 @@ struct as3935_state {
|
|
unsigned long noise_tripped;
|
|
u32 tune_cap;
|
|
u32 nflwdth_reg;
|
|
- u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ u8 chan;
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
u8 buf[2] ____cacheline_aligned;
|
|
};
|
|
|
|
@@ -225,8 +229,8 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private)
|
|
if (ret)
|
|
goto err_read;
|
|
|
|
- st->buffer[0] = val & AS3935_DATA_MASK;
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
|
|
+ st->scan.chan = val & AS3935_DATA_MASK;
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->scan,
|
|
iio_get_time_ns(indio_dev));
|
|
err_read:
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c
|
|
index 90e76451c972a..5b6ea783795d9 100644
|
|
--- a/drivers/iio/proximity/isl29501.c
|
|
+++ b/drivers/iio/proximity/isl29501.c
|
|
@@ -938,7 +938,7 @@ static irqreturn_t isl29501_trigger_handler(int irq, void *p)
|
|
struct iio_dev *indio_dev = pf->indio_dev;
|
|
struct isl29501_private *isl29501 = iio_priv(indio_dev);
|
|
const unsigned long *active_mask = indio_dev->active_scan_mask;
|
|
- u32 buffer[4] = {}; /* 1x16-bit + ts */
|
|
+ u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */
|
|
|
|
if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask))
|
|
isl29501_register_read(isl29501, REG_DISTANCE, buffer);
|
|
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
|
|
index cc206bfa09c78..d854b8d5fbbaf 100644
|
|
--- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
|
|
+++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
|
|
@@ -44,7 +44,11 @@ struct lidar_data {
|
|
int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len);
|
|
int i2c_enabled;
|
|
|
|
- u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ u16 chan;
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
};
|
|
|
|
static const struct iio_chan_spec lidar_channels[] = {
|
|
@@ -230,9 +234,9 @@ static irqreturn_t lidar_trigger_handler(int irq, void *private)
|
|
struct lidar_data *data = iio_priv(indio_dev);
|
|
int ret;
|
|
|
|
- ret = lidar_get_measurement(data, data->buffer);
|
|
+ ret = lidar_get_measurement(data, &data->scan.chan);
|
|
if (!ret) {
|
|
- iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
|
|
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
|
|
iio_get_time_ns(indio_dev));
|
|
} else if (ret != -EINVAL) {
|
|
dev_err(&data->client->dev, "cannot read LIDAR measurement");
|
|
diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c
|
|
index 70beac5c9c1df..9b0886760f76d 100644
|
|
--- a/drivers/iio/proximity/srf08.c
|
|
+++ b/drivers/iio/proximity/srf08.c
|
|
@@ -63,11 +63,11 @@ struct srf08_data {
|
|
int range_mm;
|
|
struct mutex lock;
|
|
|
|
- /*
|
|
- * triggered buffer
|
|
- * 1x16-bit channel + 3x16 padding + 4x16 timestamp
|
|
- */
|
|
- s16 buffer[8];
|
|
+ /* Ensure timestamp is naturally aligned */
|
|
+ struct {
|
|
+ s16 chan;
|
|
+ s64 timestamp __aligned(8);
|
|
+ } scan;
|
|
|
|
/* Sensor-Type */
|
|
enum srf08_sensor_type sensor_type;
|
|
@@ -190,9 +190,9 @@ static irqreturn_t srf08_trigger_handler(int irq, void *p)
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
- data->buffer[0] = sensor_data;
|
|
+ data->scan.chan = sensor_data;
|
|
iio_push_to_buffers_with_timestamp(indio_dev,
|
|
- data->buffer, pf->timestamp);
|
|
+ &data->scan, pf->timestamp);
|
|
|
|
mutex_unlock(&data->lock);
|
|
err:
|
|
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
|
|
index d1e94147fb165..0c879e40bd18d 100644
|
|
--- a/drivers/infiniband/core/cma.c
|
|
+++ b/drivers/infiniband/core/cma.c
|
|
@@ -1856,6 +1856,7 @@ static void _destroy_id(struct rdma_id_private *id_priv,
|
|
{
|
|
cma_cancel_operation(id_priv, state);
|
|
|
|
+ rdma_restrack_del(&id_priv->res);
|
|
if (id_priv->cma_dev) {
|
|
if (rdma_cap_ib_cm(id_priv->id.device, 1)) {
|
|
if (id_priv->cm_id.ib)
|
|
@@ -1865,7 +1866,6 @@ static void _destroy_id(struct rdma_id_private *id_priv,
|
|
iw_destroy_cm_id(id_priv->cm_id.iw);
|
|
}
|
|
cma_leave_mc_groups(id_priv);
|
|
- rdma_restrack_del(&id_priv->res);
|
|
cma_release_dev(id_priv);
|
|
}
|
|
|
|
@@ -2476,8 +2476,10 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog)
|
|
if (IS_ERR(id))
|
|
return PTR_ERR(id);
|
|
|
|
+ mutex_lock(&id_priv->qp_mutex);
|
|
id->tos = id_priv->tos;
|
|
id->tos_set = id_priv->tos_set;
|
|
+ mutex_unlock(&id_priv->qp_mutex);
|
|
id_priv->cm_id.iw = id;
|
|
|
|
memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv),
|
|
@@ -2537,8 +2539,10 @@ static int cma_listen_on_dev(struct rdma_id_private *id_priv,
|
|
cma_id_get(id_priv);
|
|
dev_id_priv->internal_id = 1;
|
|
dev_id_priv->afonly = id_priv->afonly;
|
|
+ mutex_lock(&id_priv->qp_mutex);
|
|
dev_id_priv->tos_set = id_priv->tos_set;
|
|
dev_id_priv->tos = id_priv->tos;
|
|
+ mutex_unlock(&id_priv->qp_mutex);
|
|
|
|
ret = rdma_listen(&dev_id_priv->id, id_priv->backlog);
|
|
if (ret)
|
|
@@ -2585,8 +2589,10 @@ void rdma_set_service_type(struct rdma_cm_id *id, int tos)
|
|
struct rdma_id_private *id_priv;
|
|
|
|
id_priv = container_of(id, struct rdma_id_private, id);
|
|
+ mutex_lock(&id_priv->qp_mutex);
|
|
id_priv->tos = (u8) tos;
|
|
id_priv->tos_set = true;
|
|
+ mutex_unlock(&id_priv->qp_mutex);
|
|
}
|
|
EXPORT_SYMBOL(rdma_set_service_type);
|
|
|
|
@@ -2613,8 +2619,10 @@ int rdma_set_ack_timeout(struct rdma_cm_id *id, u8 timeout)
|
|
return -EINVAL;
|
|
|
|
id_priv = container_of(id, struct rdma_id_private, id);
|
|
+ mutex_lock(&id_priv->qp_mutex);
|
|
id_priv->timeout = timeout;
|
|
id_priv->timeout_set = true;
|
|
+ mutex_unlock(&id_priv->qp_mutex);
|
|
|
|
return 0;
|
|
}
|
|
@@ -3000,8 +3008,11 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
|
|
|
|
u8 default_roce_tos = id_priv->cma_dev->default_roce_tos[id_priv->id.port_num -
|
|
rdma_start_port(id_priv->cma_dev->device)];
|
|
- u8 tos = id_priv->tos_set ? id_priv->tos : default_roce_tos;
|
|
+ u8 tos;
|
|
|
|
+ mutex_lock(&id_priv->qp_mutex);
|
|
+ tos = id_priv->tos_set ? id_priv->tos : default_roce_tos;
|
|
+ mutex_unlock(&id_priv->qp_mutex);
|
|
|
|
work = kzalloc(sizeof *work, GFP_KERNEL);
|
|
if (!work)
|
|
@@ -3048,8 +3059,12 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
|
|
* PacketLifeTime = local ACK timeout/2
|
|
* as a reasonable approximation for RoCE networks.
|
|
*/
|
|
- route->path_rec->packet_life_time = id_priv->timeout_set ?
|
|
- id_priv->timeout - 1 : CMA_IBOE_PACKET_LIFETIME;
|
|
+ mutex_lock(&id_priv->qp_mutex);
|
|
+ if (id_priv->timeout_set && id_priv->timeout)
|
|
+ route->path_rec->packet_life_time = id_priv->timeout - 1;
|
|
+ else
|
|
+ route->path_rec->packet_life_time = CMA_IBOE_PACKET_LIFETIME;
|
|
+ mutex_unlock(&id_priv->qp_mutex);
|
|
|
|
if (!route->path_rec->mtu) {
|
|
ret = -EINVAL;
|
|
@@ -4073,8 +4088,11 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
|
|
if (IS_ERR(cm_id))
|
|
return PTR_ERR(cm_id);
|
|
|
|
+ mutex_lock(&id_priv->qp_mutex);
|
|
cm_id->tos = id_priv->tos;
|
|
cm_id->tos_set = id_priv->tos_set;
|
|
+ mutex_unlock(&id_priv->qp_mutex);
|
|
+
|
|
id_priv->cm_id.iw = cm_id;
|
|
|
|
memcpy(&cm_id->local_addr, cma_src_addr(id_priv),
|
|
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
|
|
index 418d133a8fb08..466026825dd75 100644
|
|
--- a/drivers/infiniband/core/uverbs_cmd.c
|
|
+++ b/drivers/infiniband/core/uverbs_cmd.c
|
|
@@ -3000,12 +3000,29 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs)
|
|
if (!wq)
|
|
return -EINVAL;
|
|
|
|
- wq_attr.curr_wq_state = cmd.curr_wq_state;
|
|
- wq_attr.wq_state = cmd.wq_state;
|
|
if (cmd.attr_mask & IB_WQ_FLAGS) {
|
|
wq_attr.flags = cmd.flags;
|
|
wq_attr.flags_mask = cmd.flags_mask;
|
|
}
|
|
+
|
|
+ if (cmd.attr_mask & IB_WQ_CUR_STATE) {
|
|
+ if (cmd.curr_wq_state > IB_WQS_ERR)
|
|
+ return -EINVAL;
|
|
+
|
|
+ wq_attr.curr_wq_state = cmd.curr_wq_state;
|
|
+ } else {
|
|
+ wq_attr.curr_wq_state = wq->state;
|
|
+ }
|
|
+
|
|
+ if (cmd.attr_mask & IB_WQ_STATE) {
|
|
+ if (cmd.wq_state > IB_WQS_ERR)
|
|
+ return -EINVAL;
|
|
+
|
|
+ wq_attr.wq_state = cmd.wq_state;
|
|
+ } else {
|
|
+ wq_attr.wq_state = wq_attr.curr_wq_state;
|
|
+ }
|
|
+
|
|
ret = wq->device->ops.modify_wq(wq, &wq_attr, cmd.attr_mask,
|
|
&attrs->driver_udata);
|
|
rdma_lookup_put_uobject(&wq->uobject->uevent.uobject,
|
|
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
|
|
index 5cb8e602294ca..6bc0818f4b2c6 100644
|
|
--- a/drivers/infiniband/hw/mlx4/qp.c
|
|
+++ b/drivers/infiniband/hw/mlx4/qp.c
|
|
@@ -4244,13 +4244,8 @@ int mlx4_ib_modify_wq(struct ib_wq *ibwq, struct ib_wq_attr *wq_attr,
|
|
if (wq_attr_mask & IB_WQ_FLAGS)
|
|
return -EOPNOTSUPP;
|
|
|
|
- cur_state = wq_attr_mask & IB_WQ_CUR_STATE ? wq_attr->curr_wq_state :
|
|
- ibwq->state;
|
|
- new_state = wq_attr_mask & IB_WQ_STATE ? wq_attr->wq_state : cur_state;
|
|
-
|
|
- if (cur_state < IB_WQS_RESET || cur_state > IB_WQS_ERR ||
|
|
- new_state < IB_WQS_RESET || new_state > IB_WQS_ERR)
|
|
- return -EINVAL;
|
|
+ cur_state = wq_attr->curr_wq_state;
|
|
+ new_state = wq_attr->wq_state;
|
|
|
|
if ((new_state == IB_WQS_RDY) && (cur_state == IB_WQS_ERR))
|
|
return -EINVAL;
|
|
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
|
|
index b19506707e45c..eb69bec77e5d4 100644
|
|
--- a/drivers/infiniband/hw/mlx5/main.c
|
|
+++ b/drivers/infiniband/hw/mlx5/main.c
|
|
@@ -3440,8 +3440,6 @@ static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev,
|
|
|
|
port->mp.mpi = NULL;
|
|
|
|
- list_add_tail(&mpi->list, &mlx5_ib_unaffiliated_port_list);
|
|
-
|
|
spin_unlock(&port->mp.mpi_lock);
|
|
|
|
err = mlx5_nic_vport_unaffiliate_multiport(mpi->mdev);
|
|
@@ -3594,6 +3592,8 @@ static void mlx5_ib_cleanup_multiport_master(struct mlx5_ib_dev *dev)
|
|
dev->port[i].mp.mpi = NULL;
|
|
} else {
|
|
mlx5_ib_dbg(dev, "unbinding port_num: %d\n", i + 1);
|
|
+ list_add_tail(&dev->port[i].mp.mpi->list,
|
|
+ &mlx5_ib_unaffiliated_port_list);
|
|
mlx5_ib_unbind_slave_port(dev, dev->port[i].mp.mpi);
|
|
}
|
|
}
|
|
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
|
|
index 6d2715f65d788..8beba002e5dd7 100644
|
|
--- a/drivers/infiniband/hw/mlx5/qp.c
|
|
+++ b/drivers/infiniband/hw/mlx5/qp.c
|
|
@@ -5236,10 +5236,8 @@ int mlx5_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
|
|
|
|
rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
|
|
|
|
- curr_wq_state = (wq_attr_mask & IB_WQ_CUR_STATE) ?
|
|
- wq_attr->curr_wq_state : wq->state;
|
|
- wq_state = (wq_attr_mask & IB_WQ_STATE) ?
|
|
- wq_attr->wq_state : curr_wq_state;
|
|
+ curr_wq_state = wq_attr->curr_wq_state;
|
|
+ wq_state = wq_attr->wq_state;
|
|
if (curr_wq_state == IB_WQS_ERR)
|
|
curr_wq_state = MLX5_RQC_STATE_ERR;
|
|
if (wq_state == IB_WQS_ERR)
|
|
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
|
|
index bce44502ab0ed..c071d5b1b85a7 100644
|
|
--- a/drivers/infiniband/sw/rxe/rxe_net.c
|
|
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
|
|
@@ -212,10 +212,8 @@ static struct socket *rxe_setup_udp_tunnel(struct net *net, __be16 port,
|
|
|
|
/* Create UDP socket */
|
|
err = udp_sock_create(net, &udp_cfg, &sock);
|
|
- if (err < 0) {
|
|
- pr_err("failed to create udp socket. err = %d\n", err);
|
|
+ if (err < 0)
|
|
return ERR_PTR(err);
|
|
- }
|
|
|
|
tnl_cfg.encap_type = 1;
|
|
tnl_cfg.encap_rcv = rxe_udp_encap_recv;
|
|
@@ -616,6 +614,12 @@ static int rxe_net_ipv6_init(void)
|
|
|
|
recv_sockets.sk6 = rxe_setup_udp_tunnel(&init_net,
|
|
htons(ROCE_V2_UDP_DPORT), true);
|
|
+ if (PTR_ERR(recv_sockets.sk6) == -EAFNOSUPPORT) {
|
|
+ recv_sockets.sk6 = NULL;
|
|
+ pr_warn("IPv6 is not supported, can not create a UDPv6 socket\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
if (IS_ERR(recv_sockets.sk6)) {
|
|
recv_sockets.sk6 = NULL;
|
|
pr_err("Failed to create IPv6 UDP tunnel\n");
|
|
diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c
|
|
index 1e716fe7014cc..a1b79015e6f22 100644
|
|
--- a/drivers/infiniband/sw/rxe/rxe_qp.c
|
|
+++ b/drivers/infiniband/sw/rxe/rxe_qp.c
|
|
@@ -125,7 +125,6 @@ static void free_rd_atomic_resources(struct rxe_qp *qp)
|
|
void free_rd_atomic_resource(struct rxe_qp *qp, struct resp_res *res)
|
|
{
|
|
if (res->type == RXE_ATOMIC_MASK) {
|
|
- rxe_drop_ref(qp);
|
|
kfree_skb(res->atomic.skb);
|
|
} else if (res->type == RXE_READ_MASK) {
|
|
if (res->read.mr)
|
|
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
|
|
index c7e3b6a4af38f..83c03212099a2 100644
|
|
--- a/drivers/infiniband/sw/rxe/rxe_resp.c
|
|
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
|
|
@@ -966,8 +966,6 @@ static int send_atomic_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
|
|
goto out;
|
|
}
|
|
|
|
- rxe_add_ref(qp);
|
|
-
|
|
res = &qp->resp.resources[qp->resp.res_head];
|
|
free_rd_atomic_resource(qp, res);
|
|
rxe_advance_resp_resource(qp);
|
|
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
|
|
index 7db550ba25d7f..46fad202a380e 100644
|
|
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
|
|
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
|
|
@@ -811,6 +811,9 @@ static struct rtrs_clt_sess *get_next_path_min_inflight(struct path_it *it)
|
|
int inflight;
|
|
|
|
list_for_each_entry_rcu(sess, &clt->paths_list, s.entry) {
|
|
+ if (unlikely(READ_ONCE(sess->state) != RTRS_CLT_CONNECTED))
|
|
+ continue;
|
|
+
|
|
if (unlikely(!list_empty(raw_cpu_ptr(sess->mp_skip_entry))))
|
|
continue;
|
|
|
|
@@ -1724,7 +1727,19 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con,
|
|
queue_depth);
|
|
return -ECONNRESET;
|
|
}
|
|
- if (!sess->rbufs || sess->queue_depth < queue_depth) {
|
|
+ if (sess->queue_depth > 0 && queue_depth != sess->queue_depth) {
|
|
+ rtrs_err(clt, "Error: queue depth changed\n");
|
|
+
|
|
+ /*
|
|
+ * Stop any more reconnection attempts
|
|
+ */
|
|
+ sess->reconnect_attempts = -1;
|
|
+ rtrs_err(clt,
|
|
+ "Disabling auto-reconnect. Trigger a manual reconnect after issue is resolved\n");
|
|
+ return -ECONNRESET;
|
|
+ }
|
|
+
|
|
+ if (!sess->rbufs) {
|
|
kfree(sess->rbufs);
|
|
sess->rbufs = kcalloc(queue_depth, sizeof(*sess->rbufs),
|
|
GFP_KERNEL);
|
|
@@ -1738,7 +1753,7 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con,
|
|
sess->chunk_size = sess->max_io_size + sess->max_hdr_size;
|
|
|
|
/*
|
|
- * Global queue depth and IO size is always a minimum.
|
|
+ * Global IO size is always a minimum.
|
|
* If while a reconnection server sends us a value a bit
|
|
* higher - client does not care and uses cached minimum.
|
|
*
|
|
@@ -1746,8 +1761,7 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con,
|
|
* connections in parallel, use lock.
|
|
*/
|
|
mutex_lock(&clt->paths_mutex);
|
|
- clt->queue_depth = min_not_zero(sess->queue_depth,
|
|
- clt->queue_depth);
|
|
+ clt->queue_depth = sess->queue_depth;
|
|
clt->max_io_size = min_not_zero(sess->max_io_size,
|
|
clt->max_io_size);
|
|
mutex_unlock(&clt->paths_mutex);
|
|
@@ -2692,6 +2706,8 @@ struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops,
|
|
if (err) {
|
|
list_del_rcu(&sess->s.entry);
|
|
rtrs_clt_close_conns(sess, true);
|
|
+ free_percpu(sess->stats->pcpu_stats);
|
|
+ kfree(sess->stats);
|
|
free_sess(sess);
|
|
goto close_all_sess;
|
|
}
|
|
@@ -2700,6 +2716,8 @@ struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops,
|
|
if (err) {
|
|
list_del_rcu(&sess->s.entry);
|
|
rtrs_clt_close_conns(sess, true);
|
|
+ free_percpu(sess->stats->pcpu_stats);
|
|
+ kfree(sess->stats);
|
|
free_sess(sess);
|
|
goto close_all_sess;
|
|
}
|
|
@@ -2959,6 +2977,8 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt *clt,
|
|
close_sess:
|
|
rtrs_clt_remove_path_from_arr(sess);
|
|
rtrs_clt_close_conns(sess, true);
|
|
+ free_percpu(sess->stats->pcpu_stats);
|
|
+ kfree(sess->stats);
|
|
free_sess(sess);
|
|
|
|
return err;
|
|
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c
|
|
index 39708ab4f26e5..7c75e14590173 100644
|
|
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c
|
|
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c
|
|
@@ -214,6 +214,7 @@ rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess *sess)
|
|
device_del(&srv->dev);
|
|
put_device(&srv->dev);
|
|
} else {
|
|
+ put_device(&srv->dev);
|
|
mutex_unlock(&srv->paths_mutex);
|
|
}
|
|
}
|
|
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
|
|
index 43806180f85ec..b033bfa9f3839 100644
|
|
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
|
|
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
|
|
@@ -1490,6 +1490,7 @@ static void free_sess(struct rtrs_srv_sess *sess)
|
|
kobject_del(&sess->kobj);
|
|
kobject_put(&sess->kobj);
|
|
} else {
|
|
+ kfree(sess->stats);
|
|
kfree(sess);
|
|
}
|
|
}
|
|
@@ -1613,7 +1614,7 @@ static int create_con(struct rtrs_srv_sess *sess,
|
|
struct rtrs_sess *s = &sess->s;
|
|
struct rtrs_srv_con *con;
|
|
|
|
- u32 cq_size, wr_queue_size;
|
|
+ u32 cq_size, max_send_wr, max_recv_wr, wr_limit;
|
|
int err, cq_vector;
|
|
|
|
con = kzalloc(sizeof(*con), GFP_KERNEL);
|
|
@@ -1634,30 +1635,42 @@ static int create_con(struct rtrs_srv_sess *sess,
|
|
* All receive and all send (each requiring invalidate)
|
|
* + 2 for drain and heartbeat
|
|
*/
|
|
- wr_queue_size = SERVICE_CON_QUEUE_DEPTH * 3 + 2;
|
|
- cq_size = wr_queue_size;
|
|
+ max_send_wr = SERVICE_CON_QUEUE_DEPTH * 2 + 2;
|
|
+ max_recv_wr = SERVICE_CON_QUEUE_DEPTH + 2;
|
|
+ cq_size = max_send_wr + max_recv_wr;
|
|
} else {
|
|
- /*
|
|
- * If we have all receive requests posted and
|
|
- * all write requests posted and each read request
|
|
- * requires an invalidate request + drain
|
|
- * and qp gets into error state.
|
|
- */
|
|
- cq_size = srv->queue_depth * 3 + 1;
|
|
/*
|
|
* In theory we might have queue_depth * 32
|
|
* outstanding requests if an unsafe global key is used
|
|
* and we have queue_depth read requests each consisting
|
|
* of 32 different addresses. div 3 for mlx5.
|
|
*/
|
|
- wr_queue_size = sess->s.dev->ib_dev->attrs.max_qp_wr / 3;
|
|
+ wr_limit = sess->s.dev->ib_dev->attrs.max_qp_wr / 3;
|
|
+ /* when always_invlaidate enalbed, we need linv+rinv+mr+imm */
|
|
+ if (always_invalidate)
|
|
+ max_send_wr =
|
|
+ min_t(int, wr_limit,
|
|
+ srv->queue_depth * (1 + 4) + 1);
|
|
+ else
|
|
+ max_send_wr =
|
|
+ min_t(int, wr_limit,
|
|
+ srv->queue_depth * (1 + 2) + 1);
|
|
+
|
|
+ max_recv_wr = srv->queue_depth + 1;
|
|
+ /*
|
|
+ * If we have all receive requests posted and
|
|
+ * all write requests posted and each read request
|
|
+ * requires an invalidate request + drain
|
|
+ * and qp gets into error state.
|
|
+ */
|
|
+ cq_size = max_send_wr + max_recv_wr;
|
|
}
|
|
- atomic_set(&con->sq_wr_avail, wr_queue_size);
|
|
+ atomic_set(&con->sq_wr_avail, max_send_wr);
|
|
cq_vector = rtrs_srv_get_next_cq_vector(sess);
|
|
|
|
/* TODO: SOFTIRQ can be faster, but be careful with softirq context */
|
|
err = rtrs_cq_qp_create(&sess->s, &con->c, 1, cq_vector, cq_size,
|
|
- wr_queue_size, wr_queue_size,
|
|
+ max_send_wr, max_recv_wr,
|
|
IB_POLL_WORKQUEUE);
|
|
if (err) {
|
|
rtrs_err(s, "rtrs_cq_qp_create(), err: %d\n", err);
|
|
diff --git a/drivers/infiniband/ulp/rtrs/rtrs.c b/drivers/infiniband/ulp/rtrs/rtrs.c
|
|
index d13aff0aa8165..4629bb758126a 100644
|
|
--- a/drivers/infiniband/ulp/rtrs/rtrs.c
|
|
+++ b/drivers/infiniband/ulp/rtrs/rtrs.c
|
|
@@ -373,7 +373,6 @@ void rtrs_stop_hb(struct rtrs_sess *sess)
|
|
{
|
|
cancel_delayed_work_sync(&sess->hb_dwork);
|
|
sess->hb_missed_cnt = 0;
|
|
- sess->hb_missed_max = 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtrs_stop_hb);
|
|
|
|
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
|
|
index a8f85993dab30..86d5c4c92b363 100644
|
|
--- a/drivers/infiniband/ulp/srp/ib_srp.c
|
|
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
|
|
@@ -998,7 +998,6 @@ static int srp_alloc_req_data(struct srp_rdma_ch *ch)
|
|
struct srp_device *srp_dev = target->srp_host->srp_dev;
|
|
struct ib_device *ibdev = srp_dev->dev;
|
|
struct srp_request *req;
|
|
- void *mr_list;
|
|
dma_addr_t dma_addr;
|
|
int i, ret = -ENOMEM;
|
|
|
|
@@ -1009,12 +1008,12 @@ static int srp_alloc_req_data(struct srp_rdma_ch *ch)
|
|
|
|
for (i = 0; i < target->req_ring_size; ++i) {
|
|
req = &ch->req_ring[i];
|
|
- mr_list = kmalloc_array(target->mr_per_cmd, sizeof(void *),
|
|
- GFP_KERNEL);
|
|
- if (!mr_list)
|
|
- goto out;
|
|
- if (srp_dev->use_fast_reg)
|
|
- req->fr_list = mr_list;
|
|
+ if (srp_dev->use_fast_reg) {
|
|
+ req->fr_list = kmalloc_array(target->mr_per_cmd,
|
|
+ sizeof(void *), GFP_KERNEL);
|
|
+ if (!req->fr_list)
|
|
+ goto out;
|
|
+ }
|
|
req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL);
|
|
if (!req->indirect_desc)
|
|
goto out;
|
|
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
|
|
index 430dc69750048..675fcd0952a2d 100644
|
|
--- a/drivers/input/joydev.c
|
|
+++ b/drivers/input/joydev.c
|
|
@@ -500,7 +500,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
|
|
memcpy(joydev->keypam, keypam, len);
|
|
|
|
for (i = 0; i < joydev->nkey; i++)
|
|
- joydev->keymap[keypam[i] - BTN_MISC] = i;
|
|
+ joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
|
|
|
|
out:
|
|
kfree(keypam);
|
|
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
|
|
index 793ecbbda32ca..9f60f1559e499 100644
|
|
--- a/drivers/input/keyboard/Kconfig
|
|
+++ b/drivers/input/keyboard/Kconfig
|
|
@@ -67,9 +67,6 @@ config KEYBOARD_AMIGA
|
|
To compile this driver as a module, choose M here: the
|
|
module will be called amikbd.
|
|
|
|
-config ATARI_KBD_CORE
|
|
- bool
|
|
-
|
|
config KEYBOARD_APPLESPI
|
|
tristate "Apple SPI keyboard and trackpad"
|
|
depends on ACPI && EFI
|
|
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
|
|
index bb29a7c9a1c0c..54afb38601b9f 100644
|
|
--- a/drivers/input/keyboard/hil_kbd.c
|
|
+++ b/drivers/input/keyboard/hil_kbd.c
|
|
@@ -512,6 +512,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
|
|
HIL_IDD_NUM_AXES_PER_SET(*idd)) {
|
|
printk(KERN_INFO PREFIX
|
|
"combo devices are not supported.\n");
|
|
+ error = -EINVAL;
|
|
goto bail1;
|
|
}
|
|
|
|
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
|
|
index 45113767db964..a06385c55af2a 100644
|
|
--- a/drivers/input/touchscreen/goodix.c
|
|
+++ b/drivers/input/touchscreen/goodix.c
|
|
@@ -178,51 +178,6 @@ static const unsigned long goodix_irq_flags[] = {
|
|
IRQ_TYPE_LEVEL_HIGH,
|
|
};
|
|
|
|
-/*
|
|
- * Those tablets have their coordinates origin at the bottom right
|
|
- * of the tablet, as if rotated 180 degrees
|
|
- */
|
|
-static const struct dmi_system_id rotated_screen[] = {
|
|
-#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
|
- {
|
|
- .ident = "Teclast X89",
|
|
- .matches = {
|
|
- /* tPAD is too generic, also match on bios date */
|
|
- DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
|
|
- DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
|
|
- DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"),
|
|
- },
|
|
- },
|
|
- {
|
|
- .ident = "Teclast X98 Pro",
|
|
- .matches = {
|
|
- /*
|
|
- * Only match BIOS date, because the manufacturers
|
|
- * BIOS does not report the board name at all
|
|
- * (sometimes)...
|
|
- */
|
|
- DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
|
|
- DMI_MATCH(DMI_BIOS_DATE, "10/28/2015"),
|
|
- },
|
|
- },
|
|
- {
|
|
- .ident = "WinBook TW100",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "TW100")
|
|
- }
|
|
- },
|
|
- {
|
|
- .ident = "WinBook TW700",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "TW700")
|
|
- },
|
|
- },
|
|
-#endif
|
|
- {}
|
|
-};
|
|
-
|
|
static const struct dmi_system_id nine_bytes_report[] = {
|
|
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
|
{
|
|
@@ -1121,13 +1076,6 @@ static int goodix_configure_dev(struct goodix_ts_data *ts)
|
|
ABS_MT_POSITION_Y, ts->prop.max_y);
|
|
}
|
|
|
|
- if (dmi_check_system(rotated_screen)) {
|
|
- ts->prop.invert_x = true;
|
|
- ts->prop.invert_y = true;
|
|
- dev_dbg(&ts->client->dev,
|
|
- "Applying '180 degrees rotated screen' quirk\n");
|
|
- }
|
|
-
|
|
if (dmi_check_system(nine_bytes_report)) {
|
|
ts->contact_size = 9;
|
|
|
|
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
|
|
index 397cb1d3f481b..544a8f40b81f1 100644
|
|
--- a/drivers/input/touchscreen/usbtouchscreen.c
|
|
+++ b/drivers/input/touchscreen/usbtouchscreen.c
|
|
@@ -251,7 +251,7 @@ static int e2i_init(struct usbtouch_usb *usbtouch)
|
|
int ret;
|
|
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
|
|
|
|
- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
|
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
|
0x01, 0x02, 0x0000, 0x0081,
|
|
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
|
|
|
@@ -531,7 +531,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
|
|
if (ret)
|
|
return ret;
|
|
|
|
- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
|
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
|
MTOUCHUSB_RESET,
|
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
|
@@ -543,7 +543,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
|
|
msleep(150);
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
|
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
|
MTOUCHUSB_ASYNC_REPORT,
|
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
|
@@ -722,7 +722,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
|
|
}
|
|
|
|
/* start sending data */
|
|
- ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
|
|
+ ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
|
TSC10_CMD_DATA1,
|
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
|
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
|
|
index cc9869cc48e41..fa57986c2309c 100644
|
|
--- a/drivers/iommu/amd/init.c
|
|
+++ b/drivers/iommu/amd/init.c
|
|
@@ -1914,8 +1914,8 @@ static void print_iommu_info(void)
|
|
pci_info(pdev, "Found IOMMU cap 0x%hx\n", iommu->cap_ptr);
|
|
|
|
if (iommu->cap & (1 << IOMMU_CAP_EFR)) {
|
|
- pci_info(pdev, "Extended features (%#llx):",
|
|
- iommu->features);
|
|
+ pr_info("Extended features (%#llx):", iommu->features);
|
|
+
|
|
for (i = 0; i < ARRAY_SIZE(feat_str); ++i) {
|
|
if (iommu_feature(iommu, (1ULL << i)))
|
|
pr_cont(" %s", feat_str[i]);
|
|
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
|
|
index 0cbcd3fc3e7e8..d1539b7399a96 100644
|
|
--- a/drivers/iommu/dma-iommu.c
|
|
+++ b/drivers/iommu/dma-iommu.c
|
|
@@ -216,9 +216,11 @@ resv_iova:
|
|
lo = iova_pfn(iovad, start);
|
|
hi = iova_pfn(iovad, end);
|
|
reserve_iova(iovad, lo, hi);
|
|
- } else {
|
|
+ } else if (end < start) {
|
|
/* dma_ranges list should be sorted */
|
|
- dev_err(&dev->dev, "Failed to reserve IOVA\n");
|
|
+ dev_err(&dev->dev,
|
|
+ "Failed to reserve IOVA [%pa-%pa]\n",
|
|
+ &start, &end);
|
|
return -EINVAL;
|
|
}
|
|
|
|
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
|
|
index 849d3c5f908e4..56e8198e13d10 100644
|
|
--- a/drivers/leds/Kconfig
|
|
+++ b/drivers/leds/Kconfig
|
|
@@ -199,6 +199,7 @@ config LEDS_LM3530
|
|
|
|
config LEDS_LM3532
|
|
tristate "LCD Backlight driver for LM3532"
|
|
+ select REGMAP_I2C
|
|
depends on LEDS_CLASS
|
|
depends on I2C
|
|
help
|
|
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
|
|
index 131ca83f5fb38..4365c1cc4505f 100644
|
|
--- a/drivers/leds/led-class.c
|
|
+++ b/drivers/leds/led-class.c
|
|
@@ -286,10 +286,6 @@ struct led_classdev *__must_check devm_of_led_get(struct device *dev,
|
|
if (!dev)
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
- /* Not using device tree? */
|
|
- if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
|
|
- return ERR_PTR(-ENOTSUPP);
|
|
-
|
|
led = of_led_get(dev->of_node, index);
|
|
if (IS_ERR(led))
|
|
return led;
|
|
diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/leds-as3645a.c
|
|
index e8922fa033796..80411d41e802d 100644
|
|
--- a/drivers/leds/leds-as3645a.c
|
|
+++ b/drivers/leds/leds-as3645a.c
|
|
@@ -545,6 +545,7 @@ static int as3645a_parse_node(struct as3645a *flash,
|
|
if (!flash->indicator_node) {
|
|
dev_warn(&flash->client->dev,
|
|
"can't find indicator node\n");
|
|
+ rval = -ENODEV;
|
|
goto out_err;
|
|
}
|
|
|
|
diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c
|
|
index 632f10db4b3ff..f341da1503a49 100644
|
|
--- a/drivers/leds/leds-ktd2692.c
|
|
+++ b/drivers/leds/leds-ktd2692.c
|
|
@@ -256,6 +256,17 @@ static void ktd2692_setup(struct ktd2692_context *led)
|
|
| KTD2692_REG_FLASH_CURRENT_BASE);
|
|
}
|
|
|
|
+static void regulator_disable_action(void *_data)
|
|
+{
|
|
+ struct device *dev = _data;
|
|
+ struct ktd2692_context *led = dev_get_drvdata(dev);
|
|
+ int ret;
|
|
+
|
|
+ ret = regulator_disable(led->regulator);
|
|
+ if (ret)
|
|
+ dev_err(dev, "Failed to disable supply: %d\n", ret);
|
|
+}
|
|
+
|
|
static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev,
|
|
struct ktd2692_led_config_data *cfg)
|
|
{
|
|
@@ -286,8 +297,14 @@ static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev,
|
|
|
|
if (led->regulator) {
|
|
ret = regulator_enable(led->regulator);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
dev_err(dev, "Failed to enable supply: %d\n", ret);
|
|
+ } else {
|
|
+ ret = devm_add_action_or_reset(dev,
|
|
+ regulator_disable_action, dev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
}
|
|
|
|
child_node = of_get_next_available_child(np, NULL);
|
|
@@ -377,17 +394,9 @@ static int ktd2692_probe(struct platform_device *pdev)
|
|
static int ktd2692_remove(struct platform_device *pdev)
|
|
{
|
|
struct ktd2692_context *led = platform_get_drvdata(pdev);
|
|
- int ret;
|
|
|
|
led_classdev_flash_unregister(&led->fled_cdev);
|
|
|
|
- if (led->regulator) {
|
|
- ret = regulator_disable(led->regulator);
|
|
- if (ret)
|
|
- dev_err(&pdev->dev,
|
|
- "Failed to disable supply: %d\n", ret);
|
|
- }
|
|
-
|
|
mutex_destroy(&led->lock);
|
|
|
|
return 0;
|
|
diff --git a/drivers/leds/leds-lm36274.c b/drivers/leds/leds-lm36274.c
|
|
index aadb03468a40a..a23a9424c2f38 100644
|
|
--- a/drivers/leds/leds-lm36274.c
|
|
+++ b/drivers/leds/leds-lm36274.c
|
|
@@ -127,6 +127,7 @@ static int lm36274_probe(struct platform_device *pdev)
|
|
|
|
ret = lm36274_init(chip);
|
|
if (ret) {
|
|
+ fwnode_handle_put(init_data.fwnode);
|
|
dev_err(chip->dev, "Failed to init the device\n");
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c
|
|
index e945de45388ca..55e6443997ec9 100644
|
|
--- a/drivers/leds/leds-lm3692x.c
|
|
+++ b/drivers/leds/leds-lm3692x.c
|
|
@@ -435,6 +435,7 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
|
|
|
|
ret = fwnode_property_read_u32(child, "reg", &led->led_enable);
|
|
if (ret) {
|
|
+ fwnode_handle_put(child);
|
|
dev_err(&led->client->dev, "reg DT property missing\n");
|
|
return ret;
|
|
}
|
|
@@ -449,12 +450,11 @@ static int lm3692x_probe_dt(struct lm3692x_led *led)
|
|
|
|
ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev,
|
|
&init_data);
|
|
- if (ret) {
|
|
+ if (ret)
|
|
dev_err(&led->client->dev, "led register err: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
|
|
- return 0;
|
|
+ fwnode_handle_put(init_data.fwnode);
|
|
+ return ret;
|
|
}
|
|
|
|
static int lm3692x_probe(struct i2c_client *client,
|
|
diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c
|
|
index 7d216cdb91a8a..912e8bb22a995 100644
|
|
--- a/drivers/leds/leds-lm3697.c
|
|
+++ b/drivers/leds/leds-lm3697.c
|
|
@@ -203,11 +203,9 @@ static int lm3697_probe_dt(struct lm3697 *priv)
|
|
|
|
priv->enable_gpio = devm_gpiod_get_optional(dev, "enable",
|
|
GPIOD_OUT_LOW);
|
|
- if (IS_ERR(priv->enable_gpio)) {
|
|
- ret = PTR_ERR(priv->enable_gpio);
|
|
- dev_err(dev, "Failed to get enable gpio: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
+ if (IS_ERR(priv->enable_gpio))
|
|
+ return dev_err_probe(dev, PTR_ERR(priv->enable_gpio),
|
|
+ "Failed to get enable GPIO\n");
|
|
|
|
priv->regulator = devm_regulator_get(dev, "vled");
|
|
if (IS_ERR(priv->regulator))
|
|
diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c
|
|
index f13117eed976d..d4529082935b8 100644
|
|
--- a/drivers/leds/leds-lp50xx.c
|
|
+++ b/drivers/leds/leds-lp50xx.c
|
|
@@ -496,6 +496,7 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
|
|
ret = fwnode_property_read_u32(led_node, "color",
|
|
&color_id);
|
|
if (ret) {
|
|
+ fwnode_handle_put(led_node);
|
|
dev_err(priv->dev, "Cannot read color\n");
|
|
goto child_out;
|
|
}
|
|
@@ -519,7 +520,6 @@ static int lp50xx_probe_dt(struct lp50xx *priv)
|
|
goto child_out;
|
|
}
|
|
i++;
|
|
- fwnode_handle_put(child);
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
|
|
index 077e5c6a9ef7d..3d100a004760f 100644
|
|
--- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
|
|
+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
|
|
@@ -128,7 +128,7 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
|
|
if (apcs_data->clk_name) {
|
|
apcs->clk = platform_device_register_data(&pdev->dev,
|
|
apcs_data->clk_name,
|
|
- PLATFORM_DEVID_NONE,
|
|
+ PLATFORM_DEVID_AUTO,
|
|
NULL, 0);
|
|
if (IS_ERR(apcs->clk))
|
|
dev_err(&pdev->dev, "failed to register APCS clk\n");
|
|
diff --git a/drivers/mailbox/qcom-ipcc.c b/drivers/mailbox/qcom-ipcc.c
|
|
index 2d13c72944c6f..584700cd15855 100644
|
|
--- a/drivers/mailbox/qcom-ipcc.c
|
|
+++ b/drivers/mailbox/qcom-ipcc.c
|
|
@@ -155,6 +155,11 @@ static int qcom_ipcc_mbox_send_data(struct mbox_chan *chan, void *data)
|
|
return 0;
|
|
}
|
|
|
|
+static void qcom_ipcc_mbox_shutdown(struct mbox_chan *chan)
|
|
+{
|
|
+ chan->con_priv = NULL;
|
|
+}
|
|
+
|
|
static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox,
|
|
const struct of_phandle_args *ph)
|
|
{
|
|
@@ -184,6 +189,7 @@ static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox,
|
|
|
|
static const struct mbox_chan_ops ipcc_mbox_chan_ops = {
|
|
.send_data = qcom_ipcc_mbox_send_data,
|
|
+ .shutdown = qcom_ipcc_mbox_shutdown,
|
|
};
|
|
|
|
static int qcom_ipcc_setup_mbox(struct qcom_ipcc *ipcc)
|
|
diff --git a/drivers/media/cec/platform/s5p/s5p_cec.c b/drivers/media/cec/platform/s5p/s5p_cec.c
|
|
index 2a3e7ffefe0a2..028a09a7531ef 100644
|
|
--- a/drivers/media/cec/platform/s5p/s5p_cec.c
|
|
+++ b/drivers/media/cec/platform/s5p/s5p_cec.c
|
|
@@ -35,10 +35,13 @@ MODULE_PARM_DESC(debug, "debug level (0-2)");
|
|
|
|
static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
|
{
|
|
+ int ret;
|
|
struct s5p_cec_dev *cec = cec_get_drvdata(adap);
|
|
|
|
if (enable) {
|
|
- pm_runtime_get_sync(cec->dev);
|
|
+ ret = pm_runtime_resume_and_get(cec->dev);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
s5p_cec_reset(cec);
|
|
|
|
@@ -51,7 +54,7 @@ static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
|
} else {
|
|
s5p_cec_mask_tx_interrupts(cec);
|
|
s5p_cec_mask_rx_interrupts(cec);
|
|
- pm_runtime_disable(cec->dev);
|
|
+ pm_runtime_put(cec->dev);
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c
|
|
index c1511094fdc7b..b735e23701373 100644
|
|
--- a/drivers/media/common/siano/smscoreapi.c
|
|
+++ b/drivers/media/common/siano/smscoreapi.c
|
|
@@ -908,7 +908,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
|
|
void *buffer, size_t size)
|
|
{
|
|
struct sms_firmware *firmware = (struct sms_firmware *) buffer;
|
|
- struct sms_msg_data4 *msg;
|
|
+ struct sms_msg_data5 *msg;
|
|
u32 mem_address, calc_checksum = 0;
|
|
u32 i, *ptr;
|
|
u8 *payload = firmware->payload;
|
|
@@ -989,24 +989,20 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
|
|
goto exit_fw_download;
|
|
|
|
if (coredev->mode == DEVICE_MODE_NONE) {
|
|
- struct sms_msg_data *trigger_msg =
|
|
- (struct sms_msg_data *) msg;
|
|
-
|
|
pr_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ\n");
|
|
SMS_INIT_MSG(&msg->x_msg_header,
|
|
MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
|
|
- sizeof(struct sms_msg_hdr) +
|
|
- sizeof(u32) * 5);
|
|
+ sizeof(*msg));
|
|
|
|
- trigger_msg->msg_data[0] = firmware->start_address;
|
|
+ msg->msg_data[0] = firmware->start_address;
|
|
/* Entry point */
|
|
- trigger_msg->msg_data[1] = 6; /* Priority */
|
|
- trigger_msg->msg_data[2] = 0x200; /* Stack size */
|
|
- trigger_msg->msg_data[3] = 0; /* Parameter */
|
|
- trigger_msg->msg_data[4] = 4; /* Task ID */
|
|
+ msg->msg_data[1] = 6; /* Priority */
|
|
+ msg->msg_data[2] = 0x200; /* Stack size */
|
|
+ msg->msg_data[3] = 0; /* Parameter */
|
|
+ msg->msg_data[4] = 4; /* Task ID */
|
|
|
|
- rc = smscore_sendrequest_and_wait(coredev, trigger_msg,
|
|
- trigger_msg->x_msg_header.msg_length,
|
|
+ rc = smscore_sendrequest_and_wait(coredev, msg,
|
|
+ msg->x_msg_header.msg_length,
|
|
&coredev->trigger_done);
|
|
} else {
|
|
SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_EXEC_REQ,
|
|
diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h
|
|
index b3b793b5caf35..16c45afabc530 100644
|
|
--- a/drivers/media/common/siano/smscoreapi.h
|
|
+++ b/drivers/media/common/siano/smscoreapi.h
|
|
@@ -629,9 +629,9 @@ struct sms_msg_data2 {
|
|
u32 msg_data[2];
|
|
};
|
|
|
|
-struct sms_msg_data4 {
|
|
+struct sms_msg_data5 {
|
|
struct sms_msg_hdr x_msg_header;
|
|
- u32 msg_data[4];
|
|
+ u32 msg_data[5];
|
|
};
|
|
|
|
struct sms_data_download {
|
|
diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c
|
|
index ae17407e477a4..7cc654bc52d37 100644
|
|
--- a/drivers/media/common/siano/smsdvb-main.c
|
|
+++ b/drivers/media/common/siano/smsdvb-main.c
|
|
@@ -1176,6 +1176,10 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
|
|
return 0;
|
|
|
|
media_graph_error:
|
|
+ mutex_lock(&g_smsdvb_clientslock);
|
|
+ list_del(&client->entry);
|
|
+ mutex_unlock(&g_smsdvb_clientslock);
|
|
+
|
|
smsdvb_debugfs_release(client);
|
|
|
|
client_error:
|
|
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
|
|
index 89620da983bab..dddebea644bb8 100644
|
|
--- a/drivers/media/dvb-core/dvb_net.c
|
|
+++ b/drivers/media/dvb-core/dvb_net.c
|
|
@@ -45,6 +45,7 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/netdevice.h>
|
|
+#include <linux/nospec.h>
|
|
#include <linux/etherdevice.h>
|
|
#include <linux/dvb/net.h>
|
|
#include <linux/uio.h>
|
|
@@ -1462,14 +1463,20 @@ static int dvb_net_do_ioctl(struct file *file,
|
|
struct net_device *netdev;
|
|
struct dvb_net_priv *priv_data;
|
|
struct dvb_net_if *dvbnetif = parg;
|
|
+ int if_num = dvbnetif->if_num;
|
|
|
|
- if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
|
|
- !dvbnet->state[dvbnetif->if_num]) {
|
|
+ if (if_num >= DVB_NET_DEVICES_MAX) {
|
|
ret = -EINVAL;
|
|
goto ioctl_error;
|
|
}
|
|
+ if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
|
|
|
|
- netdev = dvbnet->device[dvbnetif->if_num];
|
|
+ if (!dvbnet->state[if_num]) {
|
|
+ ret = -EINVAL;
|
|
+ goto ioctl_error;
|
|
+ }
|
|
+
|
|
+ netdev = dvbnet->device[if_num];
|
|
|
|
priv_data = netdev_priv(netdev);
|
|
dvbnetif->pid=priv_data->pid;
|
|
@@ -1522,14 +1529,20 @@ static int dvb_net_do_ioctl(struct file *file,
|
|
struct net_device *netdev;
|
|
struct dvb_net_priv *priv_data;
|
|
struct __dvb_net_if_old *dvbnetif = parg;
|
|
+ int if_num = dvbnetif->if_num;
|
|
+
|
|
+ if (if_num >= DVB_NET_DEVICES_MAX) {
|
|
+ ret = -EINVAL;
|
|
+ goto ioctl_error;
|
|
+ }
|
|
+ if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
|
|
|
|
- if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
|
|
- !dvbnet->state[dvbnetif->if_num]) {
|
|
+ if (!dvbnet->state[if_num]) {
|
|
ret = -EINVAL;
|
|
goto ioctl_error;
|
|
}
|
|
|
|
- netdev = dvbnet->device[dvbnetif->if_num];
|
|
+ netdev = dvbnet->device[if_num];
|
|
|
|
priv_data = netdev_priv(netdev);
|
|
dvbnetif->pid=priv_data->pid;
|
|
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
|
|
index e8119ad0bc71d..92376592455ee 100644
|
|
--- a/drivers/media/i2c/ir-kbd-i2c.c
|
|
+++ b/drivers/media/i2c/ir-kbd-i2c.c
|
|
@@ -678,8 +678,8 @@ static int zilog_tx(struct rc_dev *rcdev, unsigned int *txbuf,
|
|
goto out_unlock;
|
|
}
|
|
|
|
- i = i2c_master_recv(ir->tx_c, buf, 1);
|
|
- if (i != 1) {
|
|
+ ret = i2c_master_recv(ir->tx_c, buf, 1);
|
|
+ if (ret != 1) {
|
|
dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret);
|
|
ret = -EIO;
|
|
goto out_unlock;
|
|
diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c
|
|
index 42f64175a6dff..fb78a1cedc03b 100644
|
|
--- a/drivers/media/i2c/ov2659.c
|
|
+++ b/drivers/media/i2c/ov2659.c
|
|
@@ -204,6 +204,7 @@ struct ov2659 {
|
|
struct i2c_client *client;
|
|
struct v4l2_ctrl_handler ctrls;
|
|
struct v4l2_ctrl *link_frequency;
|
|
+ struct clk *clk;
|
|
const struct ov2659_framesize *frame_size;
|
|
struct sensor_register *format_ctrl_regs;
|
|
struct ov2659_pll_ctrl pll;
|
|
@@ -1270,6 +1271,8 @@ static int ov2659_power_off(struct device *dev)
|
|
|
|
gpiod_set_value(ov2659->pwdn_gpio, 1);
|
|
|
|
+ clk_disable_unprepare(ov2659->clk);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1278,9 +1281,17 @@ static int ov2659_power_on(struct device *dev)
|
|
struct i2c_client *client = to_i2c_client(dev);
|
|
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
|
struct ov2659 *ov2659 = to_ov2659(sd);
|
|
+ int ret;
|
|
|
|
dev_dbg(&client->dev, "%s:\n", __func__);
|
|
|
|
+ ret = clk_prepare_enable(ov2659->clk);
|
|
+ if (ret) {
|
|
+ dev_err(&client->dev, "%s: failed to enable clock\n",
|
|
+ __func__);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
gpiod_set_value(ov2659->pwdn_gpio, 0);
|
|
|
|
if (ov2659->resetb_gpio) {
|
|
@@ -1425,7 +1436,6 @@ static int ov2659_probe(struct i2c_client *client)
|
|
const struct ov2659_platform_data *pdata = ov2659_get_pdata(client);
|
|
struct v4l2_subdev *sd;
|
|
struct ov2659 *ov2659;
|
|
- struct clk *clk;
|
|
int ret;
|
|
|
|
if (!pdata) {
|
|
@@ -1440,11 +1450,11 @@ static int ov2659_probe(struct i2c_client *client)
|
|
ov2659->pdata = pdata;
|
|
ov2659->client = client;
|
|
|
|
- clk = devm_clk_get(&client->dev, "xvclk");
|
|
- if (IS_ERR(clk))
|
|
- return PTR_ERR(clk);
|
|
+ ov2659->clk = devm_clk_get(&client->dev, "xvclk");
|
|
+ if (IS_ERR(ov2659->clk))
|
|
+ return PTR_ERR(ov2659->clk);
|
|
|
|
- ov2659->xvclk_frequency = clk_get_rate(clk);
|
|
+ ov2659->xvclk_frequency = clk_get_rate(ov2659->clk);
|
|
if (ov2659->xvclk_frequency < 6000000 ||
|
|
ov2659->xvclk_frequency > 27000000)
|
|
return -EINVAL;
|
|
@@ -1506,7 +1516,9 @@ static int ov2659_probe(struct i2c_client *client)
|
|
ov2659->frame_size = &ov2659_framesizes[2];
|
|
ov2659->format_ctrl_regs = ov2659_formats[0].format_ctrl_regs;
|
|
|
|
- ov2659_power_on(&client->dev);
|
|
+ ret = ov2659_power_on(&client->dev);
|
|
+ if (ret < 0)
|
|
+ goto error;
|
|
|
|
ret = ov2659_detect(sd);
|
|
if (ret < 0)
|
|
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
|
|
index 5b4c4a3547c93..71804a70bc6d7 100644
|
|
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
|
|
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
|
|
@@ -1386,7 +1386,7 @@ static int __s5c73m3_power_on(struct s5c73m3 *state)
|
|
s5c73m3_gpio_deassert(state, STBY);
|
|
usleep_range(100, 200);
|
|
|
|
- s5c73m3_gpio_deassert(state, RST);
|
|
+ s5c73m3_gpio_deassert(state, RSET);
|
|
usleep_range(50, 100);
|
|
|
|
return 0;
|
|
@@ -1401,7 +1401,7 @@ static int __s5c73m3_power_off(struct s5c73m3 *state)
|
|
{
|
|
int i, ret;
|
|
|
|
- if (s5c73m3_gpio_assert(state, RST))
|
|
+ if (s5c73m3_gpio_assert(state, RSET))
|
|
usleep_range(10, 50);
|
|
|
|
if (s5c73m3_gpio_assert(state, STBY))
|
|
@@ -1606,7 +1606,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state)
|
|
|
|
state->mclk_frequency = pdata->mclk_frequency;
|
|
state->gpio[STBY] = pdata->gpio_stby;
|
|
- state->gpio[RST] = pdata->gpio_reset;
|
|
+ state->gpio[RSET] = pdata->gpio_reset;
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h
|
|
index ef7e85b34263b..c3fcfdd3ea66d 100644
|
|
--- a/drivers/media/i2c/s5c73m3/s5c73m3.h
|
|
+++ b/drivers/media/i2c/s5c73m3/s5c73m3.h
|
|
@@ -353,7 +353,7 @@ struct s5c73m3_ctrls {
|
|
|
|
enum s5c73m3_gpio_id {
|
|
STBY,
|
|
- RST,
|
|
+ RSET,
|
|
GPIO_NUM,
|
|
};
|
|
|
|
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
|
|
index b2d53417badf6..4e97309a67f41 100644
|
|
--- a/drivers/media/i2c/s5k4ecgx.c
|
|
+++ b/drivers/media/i2c/s5k4ecgx.c
|
|
@@ -173,7 +173,7 @@ static const char * const s5k4ecgx_supply_names[] = {
|
|
|
|
enum s5k4ecgx_gpio_id {
|
|
STBY,
|
|
- RST,
|
|
+ RSET,
|
|
GPIO_NUM,
|
|
};
|
|
|
|
@@ -476,7 +476,7 @@ static int __s5k4ecgx_power_on(struct s5k4ecgx *priv)
|
|
if (s5k4ecgx_gpio_set_value(priv, STBY, priv->gpio[STBY].level))
|
|
usleep_range(30, 50);
|
|
|
|
- if (s5k4ecgx_gpio_set_value(priv, RST, priv->gpio[RST].level))
|
|
+ if (s5k4ecgx_gpio_set_value(priv, RSET, priv->gpio[RSET].level))
|
|
usleep_range(30, 50);
|
|
|
|
return 0;
|
|
@@ -484,7 +484,7 @@ static int __s5k4ecgx_power_on(struct s5k4ecgx *priv)
|
|
|
|
static int __s5k4ecgx_power_off(struct s5k4ecgx *priv)
|
|
{
|
|
- if (s5k4ecgx_gpio_set_value(priv, RST, !priv->gpio[RST].level))
|
|
+ if (s5k4ecgx_gpio_set_value(priv, RSET, !priv->gpio[RSET].level))
|
|
usleep_range(30, 50);
|
|
|
|
if (s5k4ecgx_gpio_set_value(priv, STBY, !priv->gpio[STBY].level))
|
|
@@ -872,7 +872,7 @@ static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv,
|
|
int ret;
|
|
|
|
priv->gpio[STBY].gpio = -EINVAL;
|
|
- priv->gpio[RST].gpio = -EINVAL;
|
|
+ priv->gpio[RSET].gpio = -EINVAL;
|
|
|
|
ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_STBY");
|
|
|
|
@@ -891,7 +891,7 @@ static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv,
|
|
s5k4ecgx_free_gpios(priv);
|
|
return ret;
|
|
}
|
|
- priv->gpio[RST] = *gpio;
|
|
+ priv->gpio[RSET] = *gpio;
|
|
if (gpio_is_valid(gpio->gpio))
|
|
gpio_set_value(gpio->gpio, 0);
|
|
|
|
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
|
|
index ec6f22efe19ad..ec65a8e084c6a 100644
|
|
--- a/drivers/media/i2c/s5k5baf.c
|
|
+++ b/drivers/media/i2c/s5k5baf.c
|
|
@@ -235,7 +235,7 @@ struct s5k5baf_gpio {
|
|
|
|
enum s5k5baf_gpio_id {
|
|
STBY,
|
|
- RST,
|
|
+ RSET,
|
|
NUM_GPIOS,
|
|
};
|
|
|
|
@@ -969,7 +969,7 @@ static int s5k5baf_power_on(struct s5k5baf *state)
|
|
|
|
s5k5baf_gpio_deassert(state, STBY);
|
|
usleep_range(50, 100);
|
|
- s5k5baf_gpio_deassert(state, RST);
|
|
+ s5k5baf_gpio_deassert(state, RSET);
|
|
return 0;
|
|
|
|
err_reg_dis:
|
|
@@ -987,7 +987,7 @@ static int s5k5baf_power_off(struct s5k5baf *state)
|
|
state->apply_cfg = 0;
|
|
state->apply_crop = 0;
|
|
|
|
- s5k5baf_gpio_assert(state, RST);
|
|
+ s5k5baf_gpio_assert(state, RSET);
|
|
s5k5baf_gpio_assert(state, STBY);
|
|
|
|
if (!IS_ERR(state->clock))
|
|
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c
|
|
index 72439fae7968b..6516e205e9a3d 100644
|
|
--- a/drivers/media/i2c/s5k6aa.c
|
|
+++ b/drivers/media/i2c/s5k6aa.c
|
|
@@ -177,7 +177,7 @@ static const char * const s5k6aa_supply_names[] = {
|
|
|
|
enum s5k6aa_gpio_id {
|
|
STBY,
|
|
- RST,
|
|
+ RSET,
|
|
GPIO_NUM,
|
|
};
|
|
|
|
@@ -841,7 +841,7 @@ static int __s5k6aa_power_on(struct s5k6aa *s5k6aa)
|
|
ret = s5k6aa->s_power(1);
|
|
usleep_range(4000, 5000);
|
|
|
|
- if (s5k6aa_gpio_deassert(s5k6aa, RST))
|
|
+ if (s5k6aa_gpio_deassert(s5k6aa, RSET))
|
|
msleep(20);
|
|
|
|
return ret;
|
|
@@ -851,7 +851,7 @@ static int __s5k6aa_power_off(struct s5k6aa *s5k6aa)
|
|
{
|
|
int ret;
|
|
|
|
- if (s5k6aa_gpio_assert(s5k6aa, RST))
|
|
+ if (s5k6aa_gpio_assert(s5k6aa, RSET))
|
|
usleep_range(100, 150);
|
|
|
|
if (s5k6aa->s_power) {
|
|
@@ -1510,7 +1510,7 @@ static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
|
|
int ret;
|
|
|
|
s5k6aa->gpio[STBY].gpio = -EINVAL;
|
|
- s5k6aa->gpio[RST].gpio = -EINVAL;
|
|
+ s5k6aa->gpio[RSET].gpio = -EINVAL;
|
|
|
|
gpio = &pdata->gpio_stby;
|
|
if (gpio_is_valid(gpio->gpio)) {
|
|
@@ -1533,7 +1533,7 @@ static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- s5k6aa->gpio[RST] = *gpio;
|
|
+ s5k6aa->gpio[RSET] = *gpio;
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
|
|
index 1b309bb743c7b..f21da11caf224 100644
|
|
--- a/drivers/media/i2c/tc358743.c
|
|
+++ b/drivers/media/i2c/tc358743.c
|
|
@@ -1974,6 +1974,7 @@ static int tc358743_probe_of(struct tc358743_state *state)
|
|
bps_pr_lane = 2 * endpoint.link_frequencies[0];
|
|
if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) {
|
|
dev_err(dev, "unsupported bps per lane: %u bps\n", bps_pr_lane);
|
|
+ ret = -EINVAL;
|
|
goto disable_clk;
|
|
}
|
|
|
|
diff --git a/drivers/media/mc/Makefile b/drivers/media/mc/Makefile
|
|
index 119037f0e686d..2b7af42ba59c1 100644
|
|
--- a/drivers/media/mc/Makefile
|
|
+++ b/drivers/media/mc/Makefile
|
|
@@ -3,7 +3,7 @@
|
|
mc-objs := mc-device.o mc-devnode.o mc-entity.o \
|
|
mc-request.o
|
|
|
|
-ifeq ($(CONFIG_USB),y)
|
|
+ifneq ($(CONFIG_USB),)
|
|
mc-objs += mc-dev-allocator.o
|
|
endif
|
|
|
|
diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c
|
|
index 79ba15a9385a5..0705913972c66 100644
|
|
--- a/drivers/media/pci/bt8xx/bt878.c
|
|
+++ b/drivers/media/pci/bt8xx/bt878.c
|
|
@@ -300,7 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id)
|
|
}
|
|
if (astat & BT878_ARISCI) {
|
|
bt->finished_block = (stat & BT878_ARISCS) >> 28;
|
|
- tasklet_schedule(&bt->tasklet);
|
|
+ if (bt->tasklet.callback)
|
|
+ tasklet_schedule(&bt->tasklet);
|
|
break;
|
|
}
|
|
count++;
|
|
@@ -477,6 +478,9 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
|
|
btwrite(0, BT878_AINT_MASK);
|
|
bt878_num++;
|
|
|
|
+ if (!bt->tasklet.func)
|
|
+ tasklet_disable(&bt->tasklet);
|
|
+
|
|
return 0;
|
|
|
|
fail2:
|
|
diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c
|
|
index 0695078ef8125..1bd8bbe57a30e 100644
|
|
--- a/drivers/media/pci/cobalt/cobalt-driver.c
|
|
+++ b/drivers/media/pci/cobalt/cobalt-driver.c
|
|
@@ -667,6 +667,7 @@ static int cobalt_probe(struct pci_dev *pci_dev,
|
|
return -ENOMEM;
|
|
cobalt->pci_dev = pci_dev;
|
|
cobalt->instance = i;
|
|
+ mutex_init(&cobalt->pci_lock);
|
|
|
|
retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev);
|
|
if (retval) {
|
|
diff --git a/drivers/media/pci/cobalt/cobalt-driver.h b/drivers/media/pci/cobalt/cobalt-driver.h
|
|
index bca68572b3242..12c33e035904c 100644
|
|
--- a/drivers/media/pci/cobalt/cobalt-driver.h
|
|
+++ b/drivers/media/pci/cobalt/cobalt-driver.h
|
|
@@ -251,6 +251,8 @@ struct cobalt {
|
|
int instance;
|
|
struct pci_dev *pci_dev;
|
|
struct v4l2_device v4l2_dev;
|
|
+ /* serialize PCI access in cobalt_s_bit_sysctrl() */
|
|
+ struct mutex pci_lock;
|
|
|
|
void __iomem *bar0, *bar1;
|
|
|
|
@@ -320,10 +322,13 @@ static inline u32 cobalt_g_sysctrl(struct cobalt *cobalt)
|
|
static inline void cobalt_s_bit_sysctrl(struct cobalt *cobalt,
|
|
int bit, int val)
|
|
{
|
|
- u32 ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
|
|
+ u32 ctrl;
|
|
|
|
+ mutex_lock(&cobalt->pci_lock);
|
|
+ ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
|
|
cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE,
|
|
(ctrl & ~(1UL << bit)) | (val << bit));
|
|
+ mutex_unlock(&cobalt->pci_lock);
|
|
}
|
|
|
|
static inline u32 cobalt_g_sysstat(struct cobalt *cobalt)
|
|
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
|
|
index dcbfe8c9abc72..2fe4a0bd02844 100644
|
|
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
|
|
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
|
|
@@ -1476,7 +1476,8 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
|
|
struct v4l2_fwnode_endpoint vep = {
|
|
.bus_type = V4L2_MBUS_CSI2_DPHY
|
|
};
|
|
- struct sensor_async_subdev *s_asd = NULL;
|
|
+ struct sensor_async_subdev *s_asd;
|
|
+ struct v4l2_async_subdev *asd;
|
|
struct fwnode_handle *ep;
|
|
|
|
ep = fwnode_graph_get_endpoint_by_id(
|
|
@@ -1490,27 +1491,23 @@ static int cio2_parse_firmware(struct cio2_device *cio2)
|
|
if (ret)
|
|
goto err_parse;
|
|
|
|
- s_asd = kzalloc(sizeof(*s_asd), GFP_KERNEL);
|
|
- if (!s_asd) {
|
|
- ret = -ENOMEM;
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
+ &cio2->notifier, ep, sizeof(*s_asd));
|
|
+ if (IS_ERR(asd)) {
|
|
+ ret = PTR_ERR(asd);
|
|
goto err_parse;
|
|
}
|
|
|
|
+ s_asd = container_of(asd, struct sensor_async_subdev, asd);
|
|
s_asd->csi2.port = vep.base.port;
|
|
s_asd->csi2.lanes = vep.bus.mipi_csi2.num_data_lanes;
|
|
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
- &cio2->notifier, ep, &s_asd->asd);
|
|
- if (ret)
|
|
- goto err_parse;
|
|
-
|
|
fwnode_handle_put(ep);
|
|
|
|
continue;
|
|
|
|
err_parse:
|
|
fwnode_handle_put(ep);
|
|
- kfree(s_asd);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
|
|
index 0fb9f9ba1219d..31cee69adbe1f 100644
|
|
--- a/drivers/media/platform/am437x/am437x-vpfe.c
|
|
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
|
|
@@ -1021,7 +1021,9 @@ static int vpfe_initialize_device(struct vpfe_device *vpfe)
|
|
if (ret)
|
|
return ret;
|
|
|
|
- pm_runtime_get_sync(vpfe->pdev);
|
|
+ ret = pm_runtime_resume_and_get(vpfe->pdev);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
vpfe_config_enable(&vpfe->ccdc, 1);
|
|
|
|
@@ -2443,7 +2445,11 @@ static int vpfe_probe(struct platform_device *pdev)
|
|
pm_runtime_enable(&pdev->dev);
|
|
|
|
/* for now just enable it here instead of waiting for the open */
|
|
- pm_runtime_get_sync(&pdev->dev);
|
|
+ ret = pm_runtime_resume_and_get(&pdev->dev);
|
|
+ if (ret < 0) {
|
|
+ vpfe_err(vpfe, "Unable to resume device.\n");
|
|
+ goto probe_out_v4l2_unregister;
|
|
+ }
|
|
|
|
vpfe_ccdc_config_defaults(ccdc);
|
|
|
|
@@ -2530,6 +2536,11 @@ static int vpfe_suspend(struct device *dev)
|
|
|
|
/* only do full suspend if streaming has started */
|
|
if (vb2_start_streaming_called(&vpfe->buffer_queue)) {
|
|
+ /*
|
|
+ * ignore RPM resume errors here, as it is already too late.
|
|
+ * A check like that should happen earlier, either at
|
|
+ * open() or just before start streaming.
|
|
+ */
|
|
pm_runtime_get_sync(dev);
|
|
vpfe_config_enable(ccdc, 1);
|
|
|
|
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
|
|
index 27a3c92c73bce..f1cf847d1cc2d 100644
|
|
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
|
|
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
|
|
@@ -56,10 +56,8 @@ static void __gsc_m2m_job_abort(struct gsc_ctx *ctx)
|
|
static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
|
|
{
|
|
struct gsc_ctx *ctx = q->drv_priv;
|
|
- int ret;
|
|
|
|
- ret = pm_runtime_get_sync(&ctx->gsc_dev->pdev->dev);
|
|
- return ret > 0 ? 0 : ret;
|
|
+ return pm_runtime_resume_and_get(&ctx->gsc_dev->pdev->dev);
|
|
}
|
|
|
|
static void __gsc_m2m_cleanup_queue(struct gsc_ctx *ctx)
|
|
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
|
|
index 6000a4e789adb..808b490c1910f 100644
|
|
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
|
|
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
|
|
@@ -478,11 +478,9 @@ static int fimc_capture_open(struct file *file)
|
|
goto unlock;
|
|
|
|
set_bit(ST_CAPT_BUSY, &fimc->state);
|
|
- ret = pm_runtime_get_sync(&fimc->pdev->dev);
|
|
- if (ret < 0) {
|
|
- pm_runtime_put_sync(&fimc->pdev->dev);
|
|
+ ret = pm_runtime_resume_and_get(&fimc->pdev->dev);
|
|
+ if (ret < 0)
|
|
goto unlock;
|
|
- }
|
|
|
|
ret = v4l2_fh_open(file);
|
|
if (ret) {
|
|
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
|
|
index 32ab01e89196d..d26fa5967d821 100644
|
|
--- a/drivers/media/platform/exynos4-is/fimc-is.c
|
|
+++ b/drivers/media/platform/exynos4-is/fimc-is.c
|
|
@@ -828,9 +828,9 @@ static int fimc_is_probe(struct platform_device *pdev)
|
|
goto err_irq;
|
|
}
|
|
|
|
- ret = pm_runtime_get_sync(dev);
|
|
+ ret = pm_runtime_resume_and_get(dev);
|
|
if (ret < 0)
|
|
- goto err_pm;
|
|
+ goto err_irq;
|
|
|
|
vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
|
|
|
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
|
|
index 612b9872afc87..83688a7982f70 100644
|
|
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
|
|
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
|
|
@@ -275,7 +275,7 @@ static int isp_video_open(struct file *file)
|
|
if (ret < 0)
|
|
goto unlock;
|
|
|
|
- ret = pm_runtime_get_sync(&isp->pdev->dev);
|
|
+ ret = pm_runtime_resume_and_get(&isp->pdev->dev);
|
|
if (ret < 0)
|
|
goto rel_fh;
|
|
|
|
@@ -293,7 +293,6 @@ static int isp_video_open(struct file *file)
|
|
if (!ret)
|
|
goto unlock;
|
|
rel_fh:
|
|
- pm_runtime_put_noidle(&isp->pdev->dev);
|
|
v4l2_fh_release(file);
|
|
unlock:
|
|
mutex_unlock(&isp->video_lock);
|
|
@@ -306,17 +305,20 @@ static int isp_video_release(struct file *file)
|
|
struct fimc_is_video *ivc = &isp->video_capture;
|
|
struct media_entity *entity = &ivc->ve.vdev.entity;
|
|
struct media_device *mdev = entity->graph_obj.mdev;
|
|
+ bool is_singular_file;
|
|
|
|
mutex_lock(&isp->video_lock);
|
|
|
|
- if (v4l2_fh_is_singular_file(file) && ivc->streaming) {
|
|
+ is_singular_file = v4l2_fh_is_singular_file(file);
|
|
+
|
|
+ if (is_singular_file && ivc->streaming) {
|
|
media_pipeline_stop(entity);
|
|
ivc->streaming = 0;
|
|
}
|
|
|
|
_vb2_fop_release(file, NULL);
|
|
|
|
- if (v4l2_fh_is_singular_file(file)) {
|
|
+ if (is_singular_file) {
|
|
fimc_pipeline_call(&ivc->ve, close);
|
|
|
|
mutex_lock(&mdev->graph_mutex);
|
|
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c
|
|
index a77c49b185115..74b49d30901ed 100644
|
|
--- a/drivers/media/platform/exynos4-is/fimc-isp.c
|
|
+++ b/drivers/media/platform/exynos4-is/fimc-isp.c
|
|
@@ -304,11 +304,10 @@ static int fimc_isp_subdev_s_power(struct v4l2_subdev *sd, int on)
|
|
pr_debug("on: %d\n", on);
|
|
|
|
if (on) {
|
|
- ret = pm_runtime_get_sync(&is->pdev->dev);
|
|
- if (ret < 0) {
|
|
- pm_runtime_put(&is->pdev->dev);
|
|
+ ret = pm_runtime_resume_and_get(&is->pdev->dev);
|
|
+ if (ret < 0)
|
|
return ret;
|
|
- }
|
|
+
|
|
set_bit(IS_ST_PWR_ON, &is->state);
|
|
|
|
ret = fimc_is_start_firmware(is);
|
|
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
|
|
index fdd0d369b1925..d279f282d5921 100644
|
|
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
|
|
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
|
|
@@ -469,9 +469,9 @@ static int fimc_lite_open(struct file *file)
|
|
}
|
|
|
|
set_bit(ST_FLITE_IN_USE, &fimc->state);
|
|
- ret = pm_runtime_get_sync(&fimc->pdev->dev);
|
|
+ ret = pm_runtime_resume_and_get(&fimc->pdev->dev);
|
|
if (ret < 0)
|
|
- goto err_pm;
|
|
+ goto err_in_use;
|
|
|
|
ret = v4l2_fh_open(file);
|
|
if (ret < 0)
|
|
@@ -499,6 +499,7 @@ static int fimc_lite_open(struct file *file)
|
|
v4l2_fh_release(file);
|
|
err_pm:
|
|
pm_runtime_put_sync(&fimc->pdev->dev);
|
|
+err_in_use:
|
|
clear_bit(ST_FLITE_IN_USE, &fimc->state);
|
|
unlock:
|
|
mutex_unlock(&fimc->lock);
|
|
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
|
|
index 4acb179556c41..24b1badd20807 100644
|
|
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
|
|
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
|
|
@@ -73,17 +73,14 @@ static void fimc_m2m_shutdown(struct fimc_ctx *ctx)
|
|
static int start_streaming(struct vb2_queue *q, unsigned int count)
|
|
{
|
|
struct fimc_ctx *ctx = q->drv_priv;
|
|
- int ret;
|
|
|
|
- ret = pm_runtime_get_sync(&ctx->fimc_dev->pdev->dev);
|
|
- return ret > 0 ? 0 : ret;
|
|
+ return pm_runtime_resume_and_get(&ctx->fimc_dev->pdev->dev);
|
|
}
|
|
|
|
static void stop_streaming(struct vb2_queue *q)
|
|
{
|
|
struct fimc_ctx *ctx = q->drv_priv;
|
|
|
|
-
|
|
fimc_m2m_shutdown(ctx);
|
|
fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
|
|
pm_runtime_put(&ctx->fimc_dev->pdev->dev);
|
|
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
|
|
index e636c33e847bd..a9a8f0433fb2c 100644
|
|
--- a/drivers/media/platform/exynos4-is/media-dev.c
|
|
+++ b/drivers/media/platform/exynos4-is/media-dev.c
|
|
@@ -508,11 +508,9 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
|
|
if (!fmd->pmf)
|
|
return -ENXIO;
|
|
|
|
- ret = pm_runtime_get_sync(fmd->pmf);
|
|
- if (ret < 0) {
|
|
- pm_runtime_put(fmd->pmf);
|
|
+ ret = pm_runtime_resume_and_get(fmd->pmf);
|
|
+ if (ret < 0)
|
|
return ret;
|
|
- }
|
|
|
|
fmd->num_sensors = 0;
|
|
|
|
@@ -1282,13 +1280,11 @@ static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
|
|
static int cam_clk_prepare(struct clk_hw *hw)
|
|
{
|
|
struct cam_clk *camclk = to_cam_clk(hw);
|
|
- int ret;
|
|
|
|
if (camclk->fmd->pmf == NULL)
|
|
return -ENODEV;
|
|
|
|
- ret = pm_runtime_get_sync(camclk->fmd->pmf);
|
|
- return ret < 0 ? ret : 0;
|
|
+ return pm_runtime_resume_and_get(camclk->fmd->pmf);
|
|
}
|
|
|
|
static void cam_clk_unprepare(struct clk_hw *hw)
|
|
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
|
|
index 1aac167abb175..ebf39c8568943 100644
|
|
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
|
|
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
|
|
@@ -494,7 +494,7 @@ static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
|
|
struct device *dev = &state->pdev->dev;
|
|
|
|
if (on)
|
|
- return pm_runtime_get_sync(dev);
|
|
+ return pm_runtime_resume_and_get(dev);
|
|
|
|
return pm_runtime_put_sync(dev);
|
|
}
|
|
@@ -509,11 +509,9 @@ static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
|
|
|
|
if (enable) {
|
|
s5pcsis_clear_counters(state);
|
|
- ret = pm_runtime_get_sync(&state->pdev->dev);
|
|
- if (ret && ret != 1) {
|
|
- pm_runtime_put_noidle(&state->pdev->dev);
|
|
+ ret = pm_runtime_resume_and_get(&state->pdev->dev);
|
|
+ if (ret < 0)
|
|
return ret;
|
|
- }
|
|
}
|
|
|
|
mutex_lock(&state->lock);
|
|
@@ -535,7 +533,7 @@ unlock:
|
|
if (!enable)
|
|
pm_runtime_put(&state->pdev->dev);
|
|
|
|
- return ret == 1 ? 0 : ret;
|
|
+ return ret;
|
|
}
|
|
|
|
static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd,
|
|
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
|
|
index 34266fba824f2..e56c5e56e824a 100644
|
|
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
|
|
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
|
|
@@ -918,6 +918,7 @@ static int mclk_enable(struct clk_hw *hw)
|
|
struct mcam_camera *cam = container_of(hw, struct mcam_camera, mclk_hw);
|
|
int mclk_src;
|
|
int mclk_div;
|
|
+ int ret;
|
|
|
|
/*
|
|
* Clock the sensor appropriately. Controller clock should
|
|
@@ -931,7 +932,9 @@ static int mclk_enable(struct clk_hw *hw)
|
|
mclk_div = 2;
|
|
}
|
|
|
|
- pm_runtime_get_sync(cam->dev);
|
|
+ ret = pm_runtime_resume_and_get(cam->dev);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
clk_enable(cam->clk[0]);
|
|
mcam_reg_write(cam, REG_CLKCTRL, (mclk_src << 29) | mclk_div);
|
|
mcam_ctlr_power_up(cam);
|
|
@@ -1611,7 +1614,9 @@ static int mcam_v4l_open(struct file *filp)
|
|
ret = sensor_call(cam, core, s_power, 1);
|
|
if (ret)
|
|
goto out;
|
|
- pm_runtime_get_sync(cam->dev);
|
|
+ ret = pm_runtime_resume_and_get(cam->dev);
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
__mcam_cam_reset(cam);
|
|
mcam_set_config_needed(cam, 1);
|
|
}
|
|
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
|
|
index 724c7333b6e5a..45fc741c55411 100644
|
|
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
|
|
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
|
|
@@ -394,12 +394,12 @@ static int mtk_mdp_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
|
|
struct mtk_mdp_ctx *ctx = q->drv_priv;
|
|
int ret;
|
|
|
|
- ret = pm_runtime_get_sync(&ctx->mdp_dev->pdev->dev);
|
|
+ ret = pm_runtime_resume_and_get(&ctx->mdp_dev->pdev->dev);
|
|
if (ret < 0)
|
|
- mtk_mdp_dbg(1, "[%d] pm_runtime_get_sync failed:%d",
|
|
+ mtk_mdp_dbg(1, "[%d] pm_runtime_resume_and_get failed:%d",
|
|
ctx->id, ret);
|
|
|
|
- return 0;
|
|
+ return ret;
|
|
}
|
|
|
|
static void *mtk_mdp_m2m_buf_remove(struct mtk_mdp_ctx *ctx,
|
|
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
|
|
index 145686d2c219c..f59ef8c8c9db4 100644
|
|
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
|
|
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
|
|
@@ -126,7 +126,9 @@ static int fops_vcodec_open(struct file *file)
|
|
mtk_vcodec_dec_set_default_params(ctx);
|
|
|
|
if (v4l2_fh_is_singular(&ctx->fh)) {
|
|
- mtk_vcodec_dec_pw_on(&dev->pm);
|
|
+ ret = mtk_vcodec_dec_pw_on(&dev->pm);
|
|
+ if (ret < 0)
|
|
+ goto err_load_fw;
|
|
/*
|
|
* Does nothing if firmware was already loaded.
|
|
*/
|
|
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
|
|
index ddee7046ce422..6038db96f71c3 100644
|
|
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
|
|
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
|
|
@@ -88,13 +88,15 @@ void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
|
|
put_device(dev->pm.larbvdec);
|
|
}
|
|
|
|
-void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
|
|
+int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
|
|
{
|
|
int ret;
|
|
|
|
- ret = pm_runtime_get_sync(pm->dev);
|
|
+ ret = pm_runtime_resume_and_get(pm->dev);
|
|
if (ret)
|
|
- mtk_v4l2_err("pm_runtime_get_sync fail %d", ret);
|
|
+ mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
|
|
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
|
|
index 872d8bf8cfaf3..280aeaefdb651 100644
|
|
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
|
|
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
|
|
@@ -12,7 +12,7 @@
|
|
int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev);
|
|
void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev);
|
|
|
|
-void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
|
|
+int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
|
|
void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm);
|
|
void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm);
|
|
void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm);
|
|
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
|
|
index b1fc4518e275d..1311b4996eceb 100644
|
|
--- a/drivers/media/platform/omap3isp/isp.c
|
|
+++ b/drivers/media/platform/omap3isp/isp.c
|
|
@@ -2126,21 +2126,6 @@ static void isp_parse_of_csi1_endpoint(struct device *dev,
|
|
buscfg->bus.ccp2.crc = 1;
|
|
}
|
|
|
|
-static int isp_alloc_isd(struct isp_async_subdev **isd,
|
|
- struct isp_bus_cfg **buscfg)
|
|
-{
|
|
- struct isp_async_subdev *__isd;
|
|
-
|
|
- __isd = kzalloc(sizeof(*__isd), GFP_KERNEL);
|
|
- if (!__isd)
|
|
- return -ENOMEM;
|
|
-
|
|
- *isd = __isd;
|
|
- *buscfg = &__isd->bus;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
static struct {
|
|
u32 phy;
|
|
u32 csi2_if;
|
|
@@ -2156,7 +2141,7 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
|
|
{
|
|
struct fwnode_handle *ep;
|
|
struct isp_async_subdev *isd = NULL;
|
|
- struct isp_bus_cfg *buscfg;
|
|
+ struct v4l2_async_subdev *asd;
|
|
unsigned int i;
|
|
|
|
ep = fwnode_graph_get_endpoint_by_id(
|
|
@@ -2174,20 +2159,15 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
|
|
ret = v4l2_fwnode_endpoint_parse(ep, &vep);
|
|
|
|
if (!ret) {
|
|
- ret = isp_alloc_isd(&isd, &buscfg);
|
|
- if (ret)
|
|
- return ret;
|
|
- }
|
|
-
|
|
- if (!ret) {
|
|
- isp_parse_of_parallel_endpoint(isp->dev, &vep, buscfg);
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
- &isp->notifier, ep, &isd->asd);
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
+ &isp->notifier, ep, sizeof(*isd));
|
|
+ if (!IS_ERR(asd)) {
|
|
+ isd = container_of(asd, struct isp_async_subdev, asd);
|
|
+ isp_parse_of_parallel_endpoint(isp->dev, &vep, &isd->bus);
|
|
+ }
|
|
}
|
|
|
|
fwnode_handle_put(ep);
|
|
- if (ret)
|
|
- kfree(isd);
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(isp_bus_interfaces); i++) {
|
|
@@ -2206,15 +2186,8 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
|
|
dev_dbg(isp->dev, "parsing serial interface %u, node %pOF\n", i,
|
|
to_of_node(ep));
|
|
|
|
- ret = isp_alloc_isd(&isd, &buscfg);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
ret = v4l2_fwnode_endpoint_parse(ep, &vep);
|
|
- if (!ret) {
|
|
- buscfg->interface = isp_bus_interfaces[i].csi2_if;
|
|
- isp_parse_of_csi2_endpoint(isp->dev, &vep, buscfg);
|
|
- } else if (ret == -ENXIO) {
|
|
+ if (ret == -ENXIO) {
|
|
vep = (struct v4l2_fwnode_endpoint)
|
|
{ .bus_type = V4L2_MBUS_CSI1 };
|
|
ret = v4l2_fwnode_endpoint_parse(ep, &vep);
|
|
@@ -2224,21 +2197,35 @@ static int isp_parse_of_endpoints(struct isp_device *isp)
|
|
{ .bus_type = V4L2_MBUS_CCP2 };
|
|
ret = v4l2_fwnode_endpoint_parse(ep, &vep);
|
|
}
|
|
- if (!ret) {
|
|
- buscfg->interface =
|
|
- isp_bus_interfaces[i].csi1_if;
|
|
- isp_parse_of_csi1_endpoint(isp->dev, &vep,
|
|
- buscfg);
|
|
- }
|
|
}
|
|
|
|
- if (!ret)
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
- &isp->notifier, ep, &isd->asd);
|
|
+ if (!ret) {
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
+ &isp->notifier, ep, sizeof(*isd));
|
|
+
|
|
+ if (!IS_ERR(asd)) {
|
|
+ isd = container_of(asd, struct isp_async_subdev, asd);
|
|
+
|
|
+ switch (vep.bus_type) {
|
|
+ case V4L2_MBUS_CSI2_DPHY:
|
|
+ isd->bus.interface =
|
|
+ isp_bus_interfaces[i].csi2_if;
|
|
+ isp_parse_of_csi2_endpoint(isp->dev, &vep, &isd->bus);
|
|
+ break;
|
|
+ case V4L2_MBUS_CSI1:
|
|
+ case V4L2_MBUS_CCP2:
|
|
+ isd->bus.interface =
|
|
+ isp_bus_interfaces[i].csi1_if;
|
|
+ isp_parse_of_csi1_endpoint(isp->dev, &vep,
|
|
+ &isd->bus);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
|
|
fwnode_handle_put(ep);
|
|
- if (ret)
|
|
- kfree(isd);
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
|
|
index fd5993b3e6743..58ddebbb84468 100644
|
|
--- a/drivers/media/platform/qcom/venus/core.c
|
|
+++ b/drivers/media/platform/qcom/venus/core.c
|
|
@@ -48,52 +48,86 @@ static const struct hfi_core_ops venus_core_ops = {
|
|
.event_notify = venus_event_notify,
|
|
};
|
|
|
|
+#define RPM_WAIT_FOR_IDLE_MAX_ATTEMPTS 10
|
|
+
|
|
static void venus_sys_error_handler(struct work_struct *work)
|
|
{
|
|
struct venus_core *core =
|
|
container_of(work, struct venus_core, work.work);
|
|
- int ret = 0;
|
|
-
|
|
- pm_runtime_get_sync(core->dev);
|
|
+ int ret, i, max_attempts = RPM_WAIT_FOR_IDLE_MAX_ATTEMPTS;
|
|
+ const char *err_msg = "";
|
|
+ bool failed = false;
|
|
+
|
|
+ ret = pm_runtime_get_sync(core->dev);
|
|
+ if (ret < 0) {
|
|
+ err_msg = "resume runtime PM";
|
|
+ max_attempts = 0;
|
|
+ failed = true;
|
|
+ }
|
|
|
|
hfi_core_deinit(core, true);
|
|
|
|
- dev_warn(core->dev, "system error has occurred, starting recovery!\n");
|
|
-
|
|
mutex_lock(&core->lock);
|
|
|
|
- while (pm_runtime_active(core->dev_dec) || pm_runtime_active(core->dev_enc))
|
|
+ for (i = 0; i < max_attempts; i++) {
|
|
+ if (!pm_runtime_active(core->dev_dec) && !pm_runtime_active(core->dev_enc))
|
|
+ break;
|
|
msleep(10);
|
|
+ }
|
|
|
|
venus_shutdown(core);
|
|
|
|
pm_runtime_put_sync(core->dev);
|
|
|
|
- while (core->pmdomains[0] && pm_runtime_active(core->pmdomains[0]))
|
|
+ for (i = 0; i < max_attempts; i++) {
|
|
+ if (!core->pmdomains[0] || !pm_runtime_active(core->pmdomains[0]))
|
|
+ break;
|
|
usleep_range(1000, 1500);
|
|
+ }
|
|
|
|
hfi_reinit(core);
|
|
|
|
- pm_runtime_get_sync(core->dev);
|
|
+ ret = pm_runtime_get_sync(core->dev);
|
|
+ if (ret < 0) {
|
|
+ err_msg = "resume runtime PM";
|
|
+ failed = true;
|
|
+ }
|
|
+
|
|
+ ret = venus_boot(core);
|
|
+ if (ret && !failed) {
|
|
+ err_msg = "boot Venus";
|
|
+ failed = true;
|
|
+ }
|
|
|
|
- ret |= venus_boot(core);
|
|
- ret |= hfi_core_resume(core, true);
|
|
+ ret = hfi_core_resume(core, true);
|
|
+ if (ret && !failed) {
|
|
+ err_msg = "resume HFI";
|
|
+ failed = true;
|
|
+ }
|
|
|
|
enable_irq(core->irq);
|
|
|
|
mutex_unlock(&core->lock);
|
|
|
|
- ret |= hfi_core_init(core);
|
|
+ ret = hfi_core_init(core);
|
|
+ if (ret && !failed) {
|
|
+ err_msg = "init HFI";
|
|
+ failed = true;
|
|
+ }
|
|
|
|
pm_runtime_put_sync(core->dev);
|
|
|
|
- if (ret) {
|
|
+ if (failed) {
|
|
disable_irq_nosync(core->irq);
|
|
- dev_warn(core->dev, "recovery failed (%d)\n", ret);
|
|
+ dev_warn_ratelimited(core->dev,
|
|
+ "System error has occurred, recovery failed to %s\n",
|
|
+ err_msg);
|
|
schedule_delayed_work(&core->work, msecs_to_jiffies(10));
|
|
return;
|
|
}
|
|
|
|
+ dev_warn(core->dev, "system error has occurred (recovered)\n");
|
|
+
|
|
mutex_lock(&core->lock);
|
|
core->sys_error = false;
|
|
mutex_unlock(&core->lock);
|
|
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
|
|
index 15bcb7f6e113c..1cb5eaabf340b 100644
|
|
--- a/drivers/media/platform/s5p-g2d/g2d.c
|
|
+++ b/drivers/media/platform/s5p-g2d/g2d.c
|
|
@@ -276,6 +276,9 @@ static int g2d_release(struct file *file)
|
|
struct g2d_dev *dev = video_drvdata(file);
|
|
struct g2d_ctx *ctx = fh2ctx(file->private_data);
|
|
|
|
+ mutex_lock(&dev->mutex);
|
|
+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
|
|
+ mutex_unlock(&dev->mutex);
|
|
v4l2_ctrl_handler_free(&ctx->ctrl_handler);
|
|
v4l2_fh_del(&ctx->fh);
|
|
v4l2_fh_exit(&ctx->fh);
|
|
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
|
|
index 9b22dd8e34f44..d515eb08c3ee4 100644
|
|
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
|
|
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
|
|
@@ -2566,11 +2566,8 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
|
|
static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
|
|
{
|
|
struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
|
|
- int ret;
|
|
-
|
|
- ret = pm_runtime_get_sync(ctx->jpeg->dev);
|
|
|
|
- return ret > 0 ? 0 : ret;
|
|
+ return pm_runtime_resume_and_get(ctx->jpeg->dev);
|
|
}
|
|
|
|
static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
|
|
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
|
|
index b22dc1d725276..7d30e0c9447e8 100644
|
|
--- a/drivers/media/platform/sh_vou.c
|
|
+++ b/drivers/media/platform/sh_vou.c
|
|
@@ -1133,7 +1133,11 @@ static int sh_vou_open(struct file *file)
|
|
if (v4l2_fh_is_singular_file(file) &&
|
|
vou_dev->status == SH_VOU_INITIALISING) {
|
|
/* First open */
|
|
- pm_runtime_get_sync(vou_dev->v4l2_dev.dev);
|
|
+ err = pm_runtime_resume_and_get(vou_dev->v4l2_dev.dev);
|
|
+ if (err < 0) {
|
|
+ v4l2_fh_release(file);
|
|
+ goto done_open;
|
|
+ }
|
|
err = sh_vou_hw_init(vou_dev);
|
|
if (err < 0) {
|
|
pm_runtime_put(vou_dev->v4l2_dev.dev);
|
|
diff --git a/drivers/media/platform/sti/bdisp/Makefile b/drivers/media/platform/sti/bdisp/Makefile
|
|
index caf7ccd193eaa..39ade0a347236 100644
|
|
--- a/drivers/media/platform/sti/bdisp/Makefile
|
|
+++ b/drivers/media/platform/sti/bdisp/Makefile
|
|
@@ -1,4 +1,4 @@
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
-obj-$(CONFIG_VIDEO_STI_BDISP) := bdisp.o
|
|
+obj-$(CONFIG_VIDEO_STI_BDISP) += bdisp.o
|
|
|
|
bdisp-objs := bdisp-v4l2.o bdisp-hw.o bdisp-debug.o
|
|
diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
|
|
index 060ca85f64d5d..85288da9d2ae6 100644
|
|
--- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
|
|
+++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
|
|
@@ -499,7 +499,7 @@ static int bdisp_start_streaming(struct vb2_queue *q, unsigned int count)
|
|
{
|
|
struct bdisp_ctx *ctx = q->drv_priv;
|
|
struct vb2_v4l2_buffer *buf;
|
|
- int ret = pm_runtime_get_sync(ctx->bdisp_dev->dev);
|
|
+ int ret = pm_runtime_resume_and_get(ctx->bdisp_dev->dev);
|
|
|
|
if (ret < 0) {
|
|
dev_err(ctx->bdisp_dev->dev, "failed to set runtime PM\n");
|
|
@@ -1364,10 +1364,10 @@ static int bdisp_probe(struct platform_device *pdev)
|
|
|
|
/* Power management */
|
|
pm_runtime_enable(dev);
|
|
- ret = pm_runtime_get_sync(dev);
|
|
+ ret = pm_runtime_resume_and_get(dev);
|
|
if (ret < 0) {
|
|
dev_err(dev, "failed to set PM\n");
|
|
- goto err_pm;
|
|
+ goto err_remove;
|
|
}
|
|
|
|
/* Filters */
|
|
@@ -1395,6 +1395,7 @@ err_filter:
|
|
bdisp_hw_free_filters(bdisp->dev);
|
|
err_pm:
|
|
pm_runtime_put(dev);
|
|
+err_remove:
|
|
bdisp_debugfs_remove(bdisp);
|
|
v4l2_device_unregister(&bdisp->v4l2_dev);
|
|
err_clk:
|
|
diff --git a/drivers/media/platform/sti/delta/Makefile b/drivers/media/platform/sti/delta/Makefile
|
|
index 92b37e216f004..32412fa4c6328 100644
|
|
--- a/drivers/media/platform/sti/delta/Makefile
|
|
+++ b/drivers/media/platform/sti/delta/Makefile
|
|
@@ -1,5 +1,5 @@
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
-obj-$(CONFIG_VIDEO_STI_DELTA_DRIVER) := st-delta.o
|
|
+obj-$(CONFIG_VIDEO_STI_DELTA_DRIVER) += st-delta.o
|
|
st-delta-y := delta-v4l2.o delta-mem.o delta-ipc.o delta-debug.o
|
|
|
|
# MJPEG support
|
|
diff --git a/drivers/media/platform/sti/hva/Makefile b/drivers/media/platform/sti/hva/Makefile
|
|
index 74b41ec52f976..b5a5478bdd016 100644
|
|
--- a/drivers/media/platform/sti/hva/Makefile
|
|
+++ b/drivers/media/platform/sti/hva/Makefile
|
|
@@ -1,4 +1,4 @@
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
-obj-$(CONFIG_VIDEO_STI_HVA) := st-hva.o
|
|
+obj-$(CONFIG_VIDEO_STI_HVA) += st-hva.o
|
|
st-hva-y := hva-v4l2.o hva-hw.o hva-mem.o hva-h264.o
|
|
st-hva-$(CONFIG_VIDEO_STI_HVA_DEBUGFS) += hva-debugfs.o
|
|
diff --git a/drivers/media/platform/sti/hva/hva-hw.c b/drivers/media/platform/sti/hva/hva-hw.c
|
|
index 43f279e2a6a38..cf4c891bf619a 100644
|
|
--- a/drivers/media/platform/sti/hva/hva-hw.c
|
|
+++ b/drivers/media/platform/sti/hva/hva-hw.c
|
|
@@ -130,8 +130,7 @@ static irqreturn_t hva_hw_its_irq_thread(int irq, void *arg)
|
|
ctx_id = (hva->sts_reg & 0xFF00) >> 8;
|
|
if (ctx_id >= HVA_MAX_INSTANCES) {
|
|
dev_err(dev, "%s %s: bad context identifier: %d\n",
|
|
- ctx->name, __func__, ctx_id);
|
|
- ctx->hw_err = true;
|
|
+ HVA_PREFIX, __func__, ctx_id);
|
|
goto out;
|
|
}
|
|
|
|
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
|
|
index eb15c8c725ca0..64f25921463e9 100644
|
|
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
|
|
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
|
|
@@ -118,6 +118,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
|
|
struct v4l2_fwnode_endpoint vep = {
|
|
.bus_type = V4L2_MBUS_PARALLEL,
|
|
};
|
|
+ struct v4l2_async_subdev *asd;
|
|
struct fwnode_handle *ep;
|
|
int ret;
|
|
|
|
@@ -134,10 +135,12 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi)
|
|
|
|
csi->bus = vep.bus.parallel;
|
|
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier,
|
|
- ep, &csi->asd);
|
|
- if (ret)
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier,
|
|
+ ep, sizeof(*asd));
|
|
+ if (IS_ERR(asd)) {
|
|
+ ret = PTR_ERR(asd);
|
|
goto out;
|
|
+ }
|
|
|
|
csi->notifier.ops = &sun4i_csi_notify_ops;
|
|
|
|
diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
|
|
index 0f67ff652c2e1..a5f61ee0ec4df 100644
|
|
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
|
|
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
|
|
@@ -139,7 +139,6 @@ struct sun4i_csi {
|
|
struct v4l2_mbus_framefmt subdev_fmt;
|
|
|
|
/* V4L2 Async variables */
|
|
- struct v4l2_async_subdev asd;
|
|
struct v4l2_async_notifier notifier;
|
|
struct v4l2_subdev *src_subdev;
|
|
int src_pad;
|
|
diff --git a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c
|
|
index 3f81dd17755cb..fbcca59a0517c 100644
|
|
--- a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c
|
|
+++ b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c
|
|
@@ -494,7 +494,7 @@ static int rotate_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|
struct device *dev = ctx->dev->dev;
|
|
int ret;
|
|
|
|
- ret = pm_runtime_get_sync(dev);
|
|
+ ret = pm_runtime_resume_and_get(dev);
|
|
if (ret < 0) {
|
|
dev_err(dev, "Failed to enable module\n");
|
|
|
|
diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c
|
|
index 53570250a25d5..640ce76fe0d92 100644
|
|
--- a/drivers/media/platform/video-mux.c
|
|
+++ b/drivers/media/platform/video-mux.c
|
|
@@ -362,7 +362,7 @@ static int video_mux_async_register(struct video_mux *vmux,
|
|
|
|
for (i = 0; i < num_input_pads; i++) {
|
|
struct v4l2_async_subdev *asd;
|
|
- struct fwnode_handle *ep;
|
|
+ struct fwnode_handle *ep, *remote_ep;
|
|
|
|
ep = fwnode_graph_get_endpoint_by_id(
|
|
dev_fwnode(vmux->subdev.dev), i, 0,
|
|
@@ -370,19 +370,21 @@ static int video_mux_async_register(struct video_mux *vmux,
|
|
if (!ep)
|
|
continue;
|
|
|
|
- asd = kzalloc(sizeof(*asd), GFP_KERNEL);
|
|
- if (!asd) {
|
|
+ /* Skip dangling endpoints for backwards compatibility */
|
|
+ remote_ep = fwnode_graph_get_remote_endpoint(ep);
|
|
+ if (!remote_ep) {
|
|
fwnode_handle_put(ep);
|
|
- return -ENOMEM;
|
|
+ continue;
|
|
}
|
|
+ fwnode_handle_put(remote_ep);
|
|
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
- &vmux->notifier, ep, asd);
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
+ &vmux->notifier, ep, sizeof(*asd));
|
|
|
|
fwnode_handle_put(ep);
|
|
|
|
- if (ret) {
|
|
- kfree(asd);
|
|
+ if (IS_ERR(asd)) {
|
|
+ ret = PTR_ERR(asd);
|
|
/* OK if asd already exists */
|
|
if (ret != -EEXIST)
|
|
return ret;
|
|
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
|
|
index a8a72d5fbd129..caefac07af927 100644
|
|
--- a/drivers/media/usb/au0828/au0828-core.c
|
|
+++ b/drivers/media/usb/au0828/au0828-core.c
|
|
@@ -199,8 +199,8 @@ static int au0828_media_device_init(struct au0828_dev *dev,
|
|
struct media_device *mdev;
|
|
|
|
mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE);
|
|
- if (!mdev)
|
|
- return -ENOMEM;
|
|
+ if (IS_ERR(mdev))
|
|
+ return PTR_ERR(mdev);
|
|
|
|
dev->media_dev = mdev;
|
|
#endif
|
|
diff --git a/drivers/media/usb/cpia2/cpia2.h b/drivers/media/usb/cpia2/cpia2.h
|
|
index 50835f5f7512c..57b7f1ea68da5 100644
|
|
--- a/drivers/media/usb/cpia2/cpia2.h
|
|
+++ b/drivers/media/usb/cpia2/cpia2.h
|
|
@@ -429,6 +429,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd);
|
|
int cpia2_do_command(struct camera_data *cam,
|
|
unsigned int command,
|
|
unsigned char direction, unsigned char param);
|
|
+void cpia2_deinit_camera_struct(struct camera_data *cam, struct usb_interface *intf);
|
|
struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf);
|
|
int cpia2_init_camera(struct camera_data *cam);
|
|
int cpia2_allocate_buffers(struct camera_data *cam);
|
|
diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c
|
|
index e747548ab2869..b5a2d06fb356b 100644
|
|
--- a/drivers/media/usb/cpia2/cpia2_core.c
|
|
+++ b/drivers/media/usb/cpia2/cpia2_core.c
|
|
@@ -2163,6 +2163,18 @@ static void reset_camera_struct(struct camera_data *cam)
|
|
cam->height = cam->params.roi.height;
|
|
}
|
|
|
|
+/******************************************************************************
|
|
+ *
|
|
+ * cpia2_init_camera_struct
|
|
+ *
|
|
+ * Deinitialize camera struct
|
|
+ *****************************************************************************/
|
|
+void cpia2_deinit_camera_struct(struct camera_data *cam, struct usb_interface *intf)
|
|
+{
|
|
+ v4l2_device_unregister(&cam->v4l2_dev);
|
|
+ kfree(cam);
|
|
+}
|
|
+
|
|
/******************************************************************************
|
|
*
|
|
* cpia2_init_camera_struct
|
|
diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c
|
|
index 3ab80a7b44985..76aac06f9fb8e 100644
|
|
--- a/drivers/media/usb/cpia2/cpia2_usb.c
|
|
+++ b/drivers/media/usb/cpia2/cpia2_usb.c
|
|
@@ -844,15 +844,13 @@ static int cpia2_usb_probe(struct usb_interface *intf,
|
|
ret = set_alternate(cam, USBIF_CMDONLY);
|
|
if (ret < 0) {
|
|
ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret);
|
|
- kfree(cam);
|
|
- return ret;
|
|
+ goto alt_err;
|
|
}
|
|
|
|
|
|
if((ret = cpia2_init_camera(cam)) < 0) {
|
|
ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret);
|
|
- kfree(cam);
|
|
- return ret;
|
|
+ goto alt_err;
|
|
}
|
|
LOG(" CPiA Version: %d.%02d (%d.%d)\n",
|
|
cam->params.version.firmware_revision_hi,
|
|
@@ -872,11 +870,14 @@ static int cpia2_usb_probe(struct usb_interface *intf,
|
|
ret = cpia2_register_camera(cam);
|
|
if (ret < 0) {
|
|
ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret);
|
|
- kfree(cam);
|
|
- return ret;
|
|
+ goto alt_err;
|
|
}
|
|
|
|
return 0;
|
|
+
|
|
+alt_err:
|
|
+ cpia2_deinit_camera_struct(cam, intf);
|
|
+ return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
diff --git a/drivers/media/usb/dvb-usb/cinergyT2-core.c b/drivers/media/usb/dvb-usb/cinergyT2-core.c
|
|
index 969a7ec71dff7..4116ba5c45fcb 100644
|
|
--- a/drivers/media/usb/dvb-usb/cinergyT2-core.c
|
|
+++ b/drivers/media/usb/dvb-usb/cinergyT2-core.c
|
|
@@ -78,6 +78,8 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
|
|
|
|
ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
|
|
if (ret < 0) {
|
|
+ if (adap->fe_adap[0].fe)
|
|
+ adap->fe_adap[0].fe->ops.release(adap->fe_adap[0].fe);
|
|
deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep state info\n");
|
|
}
|
|
mutex_unlock(&d->data_mutex);
|
|
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
|
|
index 761992ad05e2a..7707de7bae7ca 100644
|
|
--- a/drivers/media/usb/dvb-usb/cxusb.c
|
|
+++ b/drivers/media/usb/dvb-usb/cxusb.c
|
|
@@ -1947,7 +1947,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
|
|
|
|
.size_of_priv = sizeof(struct cxusb_state),
|
|
|
|
- .num_adapters = 2,
|
|
+ .num_adapters = 1,
|
|
.adapter = {
|
|
{
|
|
.num_frontends = 1,
|
|
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
|
|
index 5aa15a7a49def..59529cbf9cd0b 100644
|
|
--- a/drivers/media/usb/em28xx/em28xx-input.c
|
|
+++ b/drivers/media/usb/em28xx/em28xx-input.c
|
|
@@ -720,7 +720,8 @@ static int em28xx_ir_init(struct em28xx *dev)
|
|
dev->board.has_ir_i2c = 0;
|
|
dev_warn(&dev->intf->dev,
|
|
"No i2c IR remote control device found.\n");
|
|
- return -ENODEV;
|
|
+ err = -ENODEV;
|
|
+ goto ref_put;
|
|
}
|
|
}
|
|
|
|
@@ -735,7 +736,7 @@ static int em28xx_ir_init(struct em28xx *dev)
|
|
|
|
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
|
|
if (!ir)
|
|
- return -ENOMEM;
|
|
+ goto ref_put;
|
|
rc = rc_allocate_device(RC_DRIVER_SCANCODE);
|
|
if (!rc)
|
|
goto error;
|
|
@@ -839,6 +840,9 @@ error:
|
|
dev->ir = NULL;
|
|
rc_free_device(rc);
|
|
kfree(ir);
|
|
+ref_put:
|
|
+ em28xx_shutdown_buttons(dev);
|
|
+ kref_put(&dev->ref, em28xx_free_device);
|
|
return err;
|
|
}
|
|
|
|
diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c
|
|
index 2c05ea2598e76..ce4ee8bc75c85 100644
|
|
--- a/drivers/media/usb/gspca/gl860/gl860.c
|
|
+++ b/drivers/media/usb/gspca/gl860/gl860.c
|
|
@@ -561,8 +561,8 @@ int gl860_RTx(struct gspca_dev *gspca_dev,
|
|
len, 400 + 200 * (len > 1));
|
|
memcpy(pdata, gspca_dev->usb_buf, len);
|
|
} else {
|
|
- r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
|
- req, pref, val, index, NULL, len, 400);
|
|
+ gspca_err(gspca_dev, "zero-length read request\n");
|
|
+ r = -EINVAL;
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
|
|
index f4a727918e352..d38dee1792e41 100644
|
|
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
|
|
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
|
|
@@ -2676,9 +2676,8 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
|
|
pvr2_stream_destroy(hdw->vid_stream);
|
|
hdw->vid_stream = NULL;
|
|
}
|
|
- pvr2_i2c_core_done(hdw);
|
|
v4l2_device_unregister(&hdw->v4l2_dev);
|
|
- pvr2_hdw_remove_usb_stuff(hdw);
|
|
+ pvr2_hdw_disconnect(hdw);
|
|
mutex_lock(&pvr2_unit_mtx);
|
|
do {
|
|
if ((hdw->unit_number >= 0) &&
|
|
@@ -2705,6 +2704,7 @@ void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
|
|
{
|
|
pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);
|
|
LOCK_TAKE(hdw->big_lock);
|
|
+ pvr2_i2c_core_done(hdw);
|
|
LOCK_TAKE(hdw->ctl_lock);
|
|
pvr2_hdw_remove_usb_stuff(hdw);
|
|
LOCK_GIVE(hdw->ctl_lock);
|
|
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
|
|
index e3ab003a6c851..33babe6e8b3a2 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-async.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-async.c
|
|
@@ -673,26 +673,26 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
|
|
}
|
|
EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev);
|
|
|
|
-int
|
|
+struct v4l2_async_subdev *
|
|
v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
|
|
struct fwnode_handle *endpoint,
|
|
- struct v4l2_async_subdev *asd)
|
|
+ unsigned int asd_struct_size)
|
|
{
|
|
+ struct v4l2_async_subdev *asd;
|
|
struct fwnode_handle *remote;
|
|
- int ret;
|
|
|
|
remote = fwnode_graph_get_remote_port_parent(endpoint);
|
|
if (!remote)
|
|
- return -ENOTCONN;
|
|
+ return ERR_PTR(-ENOTCONN);
|
|
|
|
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
|
|
- asd->match.fwnode = remote;
|
|
-
|
|
- ret = v4l2_async_notifier_add_subdev(notif, asd);
|
|
- if (ret)
|
|
- fwnode_handle_put(remote);
|
|
-
|
|
- return ret;
|
|
+ asd = v4l2_async_notifier_add_fwnode_subdev(notif, remote,
|
|
+ asd_struct_size);
|
|
+ /*
|
|
+ * Calling v4l2_async_notifier_add_fwnode_subdev grabs a refcount,
|
|
+ * so drop the one we got in fwnode_graph_get_remote_port_parent.
|
|
+ */
|
|
+ fwnode_handle_put(remote);
|
|
+ return asd;
|
|
}
|
|
EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_remote_subdev);
|
|
|
|
diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c
|
|
index 684574f58e82d..90eec79ee995a 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-fh.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-fh.c
|
|
@@ -96,6 +96,7 @@ int v4l2_fh_release(struct file *filp)
|
|
v4l2_fh_del(fh);
|
|
v4l2_fh_exit(fh);
|
|
kfree(fh);
|
|
+ filp->private_data = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
|
|
index a7d508e74d6b3..fbf0dcb313c82 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-subdev.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
|
|
@@ -428,30 +428,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
|
|
|
|
return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK);
|
|
|
|
- case VIDIOC_DQEVENT_TIME32: {
|
|
- struct v4l2_event_time32 *ev32 = arg;
|
|
- struct v4l2_event ev = { };
|
|
-
|
|
- if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
|
|
- return -ENOIOCTLCMD;
|
|
-
|
|
- rval = v4l2_event_dequeue(vfh, &ev, file->f_flags & O_NONBLOCK);
|
|
-
|
|
- *ev32 = (struct v4l2_event_time32) {
|
|
- .type = ev.type,
|
|
- .pending = ev.pending,
|
|
- .sequence = ev.sequence,
|
|
- .timestamp.tv_sec = ev.timestamp.tv_sec,
|
|
- .timestamp.tv_nsec = ev.timestamp.tv_nsec,
|
|
- .id = ev.id,
|
|
- };
|
|
-
|
|
- memcpy(&ev32->u, &ev.u, sizeof(ev.u));
|
|
- memcpy(&ev32->reserved, &ev.reserved, sizeof(ev.reserved));
|
|
-
|
|
- return rval;
|
|
- }
|
|
-
|
|
case VIDIOC_SUBSCRIBE_EVENT:
|
|
return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg);
|
|
|
|
diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c
|
|
index 102dbb8080da5..29271ad4728a2 100644
|
|
--- a/drivers/memstick/host/rtsx_usb_ms.c
|
|
+++ b/drivers/memstick/host/rtsx_usb_ms.c
|
|
@@ -799,9 +799,9 @@ static int rtsx_usb_ms_drv_probe(struct platform_device *pdev)
|
|
|
|
return 0;
|
|
err_out:
|
|
- memstick_free_host(msh);
|
|
pm_runtime_disable(ms_dev(host));
|
|
pm_runtime_put_noidle(ms_dev(host));
|
|
+ memstick_free_host(msh);
|
|
return err;
|
|
}
|
|
|
|
@@ -828,9 +828,6 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev)
|
|
}
|
|
mutex_unlock(&host->host_mutex);
|
|
|
|
- memstick_remove_host(msh);
|
|
- memstick_free_host(msh);
|
|
-
|
|
/* Balance possible unbalanced usage count
|
|
* e.g. unconditional module removal
|
|
*/
|
|
@@ -838,10 +835,11 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev)
|
|
pm_runtime_put(ms_dev(host));
|
|
|
|
pm_runtime_disable(ms_dev(host));
|
|
- platform_set_drvdata(pdev, NULL);
|
|
-
|
|
+ memstick_remove_host(msh);
|
|
dev_dbg(ms_dev(host),
|
|
": Realtek USB Memstick controller has been removed\n");
|
|
+ memstick_free_host(msh);
|
|
+ platform_set_drvdata(pdev, NULL);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
|
|
index 4789507f325b8..b8847ae04d938 100644
|
|
--- a/drivers/mfd/Kconfig
|
|
+++ b/drivers/mfd/Kconfig
|
|
@@ -465,6 +465,7 @@ config MFD_MP2629
|
|
tristate "Monolithic Power Systems MP2629 ADC and Battery charger"
|
|
depends on I2C
|
|
select REGMAP_I2C
|
|
+ select MFD_CORE
|
|
help
|
|
Select this option to enable support for Monolithic Power Systems
|
|
battery charger. This provides ADC, thermal and battery charger power
|
|
diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c
|
|
index dc452df1f1bfe..652a5e60067f8 100644
|
|
--- a/drivers/mfd/rn5t618.c
|
|
+++ b/drivers/mfd/rn5t618.c
|
|
@@ -104,7 +104,7 @@ static int rn5t618_irq_init(struct rn5t618 *rn5t618)
|
|
|
|
ret = devm_regmap_add_irq_chip(rn5t618->dev, rn5t618->regmap,
|
|
rn5t618->irq,
|
|
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
|
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
|
0, irq_chip, &rn5t618->irq_data);
|
|
if (ret)
|
|
dev_err(rn5t618->dev, "Failed to register IRQ chip\n");
|
|
diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c
|
|
index 81c70e5bc168f..3e4a594c110b3 100644
|
|
--- a/drivers/misc/eeprom/idt_89hpesx.c
|
|
+++ b/drivers/misc/eeprom/idt_89hpesx.c
|
|
@@ -1126,11 +1126,10 @@ static void idt_get_fw_data(struct idt_89hpesx_dev *pdev)
|
|
|
|
device_for_each_child_node(dev, fwnode) {
|
|
ee_id = idt_ee_match_id(fwnode);
|
|
- if (!ee_id) {
|
|
- dev_warn(dev, "Skip unsupported EEPROM device");
|
|
- continue;
|
|
- } else
|
|
+ if (ee_id)
|
|
break;
|
|
+
|
|
+ dev_warn(dev, "Skip unsupported EEPROM device %pfw\n", fwnode);
|
|
}
|
|
|
|
/* If there is no fwnode EEPROM device, then set zero size */
|
|
@@ -1161,6 +1160,7 @@ static void idt_get_fw_data(struct idt_89hpesx_dev *pdev)
|
|
else /* if (!fwnode_property_read_bool(node, "read-only")) */
|
|
pdev->eero = false;
|
|
|
|
+ fwnode_handle_put(fwnode);
|
|
dev_info(dev, "EEPROM of %d bytes found by 0x%x",
|
|
pdev->eesize, pdev->eeaddr);
|
|
}
|
|
diff --git a/drivers/misc/habanalabs/common/habanalabs_drv.c b/drivers/misc/habanalabs/common/habanalabs_drv.c
|
|
index 3bcef64a677ae..ded92b3cbdb27 100644
|
|
--- a/drivers/misc/habanalabs/common/habanalabs_drv.c
|
|
+++ b/drivers/misc/habanalabs/common/habanalabs_drv.c
|
|
@@ -421,6 +421,7 @@ static int hl_pci_probe(struct pci_dev *pdev,
|
|
return 0;
|
|
|
|
disable_device:
|
|
+ pci_disable_pcie_error_reporting(pdev);
|
|
pci_set_drvdata(pdev, NULL);
|
|
destroy_hdev(hdev);
|
|
|
|
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
|
|
index 3246598e4d7e3..87bac99207023 100644
|
|
--- a/drivers/mmc/core/block.c
|
|
+++ b/drivers/mmc/core/block.c
|
|
@@ -1003,6 +1003,12 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
|
|
|
|
switch (mq_rq->drv_op) {
|
|
case MMC_DRV_OP_IOCTL:
|
|
+ if (card->ext_csd.cmdq_en) {
|
|
+ ret = mmc_cmdq_disable(card);
|
|
+ if (ret)
|
|
+ break;
|
|
+ }
|
|
+ fallthrough;
|
|
case MMC_DRV_OP_IOCTL_RPMB:
|
|
idata = mq_rq->drv_op_data;
|
|
for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
|
|
@@ -1013,6 +1019,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
|
|
/* Always switch back to main area after RPMB access */
|
|
if (rpmb_ioctl)
|
|
mmc_blk_part_switch(card, 0);
|
|
+ else if (card->reenable_cmdq && !card->ext_csd.cmdq_en)
|
|
+ mmc_cmdq_enable(card);
|
|
break;
|
|
case MMC_DRV_OP_BOOT_WP:
|
|
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
|
|
diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c
|
|
index 19cbb6171b358..9cd8862e6cbd0 100644
|
|
--- a/drivers/mmc/host/sdhci-sprd.c
|
|
+++ b/drivers/mmc/host/sdhci-sprd.c
|
|
@@ -393,6 +393,7 @@ static void sdhci_sprd_request_done(struct sdhci_host *host,
|
|
static struct sdhci_ops sdhci_sprd_ops = {
|
|
.read_l = sdhci_sprd_readl,
|
|
.write_l = sdhci_sprd_writel,
|
|
+ .write_w = sdhci_sprd_writew,
|
|
.write_b = sdhci_sprd_writeb,
|
|
.set_clock = sdhci_sprd_set_clock,
|
|
.get_max_clock = sdhci_sprd_get_max_clock,
|
|
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c
|
|
index 615f3d008af1e..b9b79b1089a00 100644
|
|
--- a/drivers/mmc/host/usdhi6rol0.c
|
|
+++ b/drivers/mmc/host/usdhi6rol0.c
|
|
@@ -1801,6 +1801,7 @@ static int usdhi6_probe(struct platform_device *pdev)
|
|
|
|
version = usdhi6_read(host, USDHI6_VERSION);
|
|
if ((version & 0xfff) != 0xa0d) {
|
|
+ ret = -EPERM;
|
|
dev_err(dev, "Version not recognized %x\n", version);
|
|
goto e_clk_off;
|
|
}
|
|
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
|
|
index 9b755ea0fa03c..f07c71db3cafe 100644
|
|
--- a/drivers/mmc/host/via-sdmmc.c
|
|
+++ b/drivers/mmc/host/via-sdmmc.c
|
|
@@ -857,6 +857,9 @@ static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask)
|
|
{
|
|
BUG_ON(intmask == 0);
|
|
|
|
+ if (!host->data)
|
|
+ return;
|
|
+
|
|
if (intmask & VIA_CRDR_SDSTS_DT)
|
|
host->data->error = -ETIMEDOUT;
|
|
else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC))
|
|
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
|
|
index 739cf63ef6e2f..4950d10d3a191 100644
|
|
--- a/drivers/mmc/host/vub300.c
|
|
+++ b/drivers/mmc/host/vub300.c
|
|
@@ -2279,7 +2279,7 @@ static int vub300_probe(struct usb_interface *interface,
|
|
if (retval < 0)
|
|
goto error5;
|
|
retval =
|
|
- usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
|
|
+ usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
|
|
SET_ROM_WAIT_STATES,
|
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
firmware_rom_wait_states, 0x0000, NULL, 0, HZ);
|
|
diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
|
|
index fbb4ea751be8e..0ee3192916d97 100644
|
|
--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
|
|
+++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
|
|
@@ -272,6 +272,37 @@ static int anfc_pkt_len_config(unsigned int len, unsigned int *steps,
|
|
return 0;
|
|
}
|
|
|
|
+static int anfc_select_target(struct nand_chip *chip, int target)
|
|
+{
|
|
+ struct anand *anand = to_anand(chip);
|
|
+ struct arasan_nfc *nfc = to_anfc(chip->controller);
|
|
+ int ret;
|
|
+
|
|
+ /* Update the controller timings and the potential ECC configuration */
|
|
+ writel_relaxed(anand->timings, nfc->base + DATA_INTERFACE_REG);
|
|
+
|
|
+ /* Update clock frequency */
|
|
+ if (nfc->cur_clk != anand->clk) {
|
|
+ clk_disable_unprepare(nfc->controller_clk);
|
|
+ ret = clk_set_rate(nfc->controller_clk, anand->clk);
|
|
+ if (ret) {
|
|
+ dev_err(nfc->dev, "Failed to change clock rate\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = clk_prepare_enable(nfc->controller_clk);
|
|
+ if (ret) {
|
|
+ dev_err(nfc->dev,
|
|
+ "Failed to re-enable the controller clock\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ nfc->cur_clk = anand->clk;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* When using the embedded hardware ECC engine, the controller is in charge of
|
|
* feeding the engine with, first, the ECC residue present in the data array.
|
|
@@ -400,6 +431,18 @@ static int anfc_read_page_hw_ecc(struct nand_chip *chip, u8 *buf,
|
|
return 0;
|
|
}
|
|
|
|
+static int anfc_sel_read_page_hw_ecc(struct nand_chip *chip, u8 *buf,
|
|
+ int oob_required, int page)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = anfc_select_target(chip, chip->cur_cs);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return anfc_read_page_hw_ecc(chip, buf, oob_required, page);
|
|
+};
|
|
+
|
|
static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
|
|
int oob_required, int page)
|
|
{
|
|
@@ -460,6 +503,18 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
|
|
return ret;
|
|
}
|
|
|
|
+static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf,
|
|
+ int oob_required, int page)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = anfc_select_target(chip, chip->cur_cs);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return anfc_write_page_hw_ecc(chip, buf, oob_required, page);
|
|
+};
|
|
+
|
|
/* NAND framework ->exec_op() hooks and related helpers */
|
|
static int anfc_parse_instructions(struct nand_chip *chip,
|
|
const struct nand_subop *subop,
|
|
@@ -752,37 +807,6 @@ static const struct nand_op_parser anfc_op_parser = NAND_OP_PARSER(
|
|
NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
|
|
);
|
|
|
|
-static int anfc_select_target(struct nand_chip *chip, int target)
|
|
-{
|
|
- struct anand *anand = to_anand(chip);
|
|
- struct arasan_nfc *nfc = to_anfc(chip->controller);
|
|
- int ret;
|
|
-
|
|
- /* Update the controller timings and the potential ECC configuration */
|
|
- writel_relaxed(anand->timings, nfc->base + DATA_INTERFACE_REG);
|
|
-
|
|
- /* Update clock frequency */
|
|
- if (nfc->cur_clk != anand->clk) {
|
|
- clk_disable_unprepare(nfc->controller_clk);
|
|
- ret = clk_set_rate(nfc->controller_clk, anand->clk);
|
|
- if (ret) {
|
|
- dev_err(nfc->dev, "Failed to change clock rate\n");
|
|
- return ret;
|
|
- }
|
|
-
|
|
- ret = clk_prepare_enable(nfc->controller_clk);
|
|
- if (ret) {
|
|
- dev_err(nfc->dev,
|
|
- "Failed to re-enable the controller clock\n");
|
|
- return ret;
|
|
- }
|
|
-
|
|
- nfc->cur_clk = anand->clk;
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
static int anfc_check_op(struct nand_chip *chip,
|
|
const struct nand_operation *op)
|
|
{
|
|
@@ -1006,8 +1030,8 @@ static int anfc_init_hw_ecc_controller(struct arasan_nfc *nfc,
|
|
if (!anand->bch)
|
|
return -EINVAL;
|
|
|
|
- ecc->read_page = anfc_read_page_hw_ecc;
|
|
- ecc->write_page = anfc_write_page_hw_ecc;
|
|
+ ecc->read_page = anfc_sel_read_page_hw_ecc;
|
|
+ ecc->write_page = anfc_sel_write_page_hw_ecc;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
|
|
index f5ca2002d08e8..d00c916f133bd 100644
|
|
--- a/drivers/mtd/nand/raw/marvell_nand.c
|
|
+++ b/drivers/mtd/nand/raw/marvell_nand.c
|
|
@@ -3036,8 +3036,10 @@ static int __maybe_unused marvell_nfc_resume(struct device *dev)
|
|
return ret;
|
|
|
|
ret = clk_prepare_enable(nfc->reg_clk);
|
|
- if (ret < 0)
|
|
+ if (ret < 0) {
|
|
+ clk_disable_unprepare(nfc->core_clk);
|
|
return ret;
|
|
+ }
|
|
|
|
/*
|
|
* Reset nfc->selected_chip so the next command will cause the timing
|
|
diff --git a/drivers/mtd/parsers/redboot.c b/drivers/mtd/parsers/redboot.c
|
|
index 91146bdc47132..3ccd6363ee8cb 100644
|
|
--- a/drivers/mtd/parsers/redboot.c
|
|
+++ b/drivers/mtd/parsers/redboot.c
|
|
@@ -45,6 +45,7 @@ static inline int redboot_checksum(struct fis_image_desc *img)
|
|
static void parse_redboot_of(struct mtd_info *master)
|
|
{
|
|
struct device_node *np;
|
|
+ struct device_node *npart;
|
|
u32 dirblock;
|
|
int ret;
|
|
|
|
@@ -52,7 +53,11 @@ static void parse_redboot_of(struct mtd_info *master)
|
|
if (!np)
|
|
return;
|
|
|
|
- ret = of_property_read_u32(np, "fis-index-block", &dirblock);
|
|
+ npart = of_get_child_by_name(np, "partitions");
|
|
+ if (!npart)
|
|
+ return;
|
|
+
|
|
+ ret = of_property_read_u32(npart, "fis-index-block", &dirblock);
|
|
if (ret)
|
|
return;
|
|
|
|
diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c
|
|
index 40c33b8a5fda3..ac5801a98680d 100644
|
|
--- a/drivers/net/can/peak_canfd/peak_canfd.c
|
|
+++ b/drivers/net/can/peak_canfd/peak_canfd.c
|
|
@@ -351,8 +351,8 @@ static int pucan_handle_status(struct peak_canfd_priv *priv,
|
|
return err;
|
|
}
|
|
|
|
- /* start network queue (echo_skb array is empty) */
|
|
- netif_start_queue(ndev);
|
|
+ /* wake network queue up (echo_skb array is empty) */
|
|
+ netif_wake_queue(ndev);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
|
|
index 4f52810bebf89..db9f15f17610b 100644
|
|
--- a/drivers/net/can/usb/ems_usb.c
|
|
+++ b/drivers/net/can/usb/ems_usb.c
|
|
@@ -1053,7 +1053,6 @@ static void ems_usb_disconnect(struct usb_interface *intf)
|
|
|
|
if (dev) {
|
|
unregister_netdev(dev->netdev);
|
|
- free_candev(dev->netdev);
|
|
|
|
unlink_all_urbs(dev);
|
|
|
|
@@ -1061,6 +1060,8 @@ static void ems_usb_disconnect(struct usb_interface *intf)
|
|
|
|
kfree(dev->intr_in_buffer);
|
|
kfree(dev->tx_msg_buffer);
|
|
+
|
|
+ free_candev(dev->netdev);
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
|
|
index e273b2bd82ba7..82852c57cc0e4 100644
|
|
--- a/drivers/net/dsa/sja1105/sja1105_main.c
|
|
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
|
|
@@ -1711,6 +1711,12 @@ static int sja1105_reload_cbs(struct sja1105_private *priv)
|
|
{
|
|
int rc = 0, i;
|
|
|
|
+ /* The credit based shapers are only allocated if
|
|
+ * CONFIG_NET_SCH_CBS is enabled.
|
|
+ */
|
|
+ if (!priv->cbs)
|
|
+ return 0;
|
|
+
|
|
for (i = 0; i < priv->info->num_cbs_shapers; i++) {
|
|
struct sja1105_cbs_entry *cbs = &priv->cbs[i];
|
|
|
|
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
|
|
index 9c5891bbfe61a..f4f50b3a472e1 100644
|
|
--- a/drivers/net/ethernet/aeroflex/greth.c
|
|
+++ b/drivers/net/ethernet/aeroflex/greth.c
|
|
@@ -1539,10 +1539,11 @@ static int greth_of_remove(struct platform_device *of_dev)
|
|
mdiobus_unregister(greth->mdio);
|
|
|
|
unregister_netdev(ndev);
|
|
- free_netdev(ndev);
|
|
|
|
of_iounmap(&of_dev->resource[0], greth->regs, resource_size(&of_dev->resource[0]));
|
|
|
|
+ free_netdev(ndev);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h
|
|
index f5fba8b8cdea9..a47e2710487ec 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h
|
|
@@ -91,7 +91,7 @@ struct aq_macsec_txsc {
|
|
u32 hw_sc_idx;
|
|
unsigned long tx_sa_idx_busy;
|
|
const struct macsec_secy *sw_secy;
|
|
- u8 tx_sa_key[MACSEC_NUM_AN][MACSEC_KEYID_LEN];
|
|
+ u8 tx_sa_key[MACSEC_NUM_AN][MACSEC_MAX_KEY_LEN];
|
|
struct aq_macsec_tx_sc_stats stats;
|
|
struct aq_macsec_tx_sa_stats tx_sa_stats[MACSEC_NUM_AN];
|
|
};
|
|
@@ -101,7 +101,7 @@ struct aq_macsec_rxsc {
|
|
unsigned long rx_sa_idx_busy;
|
|
const struct macsec_secy *sw_secy;
|
|
const struct macsec_rx_sc *sw_rxsc;
|
|
- u8 rx_sa_key[MACSEC_NUM_AN][MACSEC_KEYID_LEN];
|
|
+ u8 rx_sa_key[MACSEC_NUM_AN][MACSEC_MAX_KEY_LEN];
|
|
struct aq_macsec_rx_sa_stats rx_sa_stats[MACSEC_NUM_AN];
|
|
};
|
|
|
|
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
|
index fcca023f22e54..41f7f078cd27c 100644
|
|
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
|
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
|
@@ -4296,3 +4296,4 @@ MODULE_AUTHOR("Broadcom Corporation");
|
|
MODULE_DESCRIPTION("Broadcom GENET Ethernet controller driver");
|
|
MODULE_ALIAS("platform:bcmgenet");
|
|
MODULE_LICENSE("GPL");
|
|
+MODULE_SOFTDEP("pre: mdio-bcm-unimac");
|
|
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
|
index 701c12c9e0337..649c5c429bd7c 100644
|
|
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
|
|
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
|
|
@@ -550,7 +550,7 @@ int be_process_mcc(struct be_adapter *adapter)
|
|
int num = 0, status = 0;
|
|
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
|
|
|
|
- spin_lock_bh(&adapter->mcc_cq_lock);
|
|
+ spin_lock(&adapter->mcc_cq_lock);
|
|
|
|
while ((compl = be_mcc_compl_get(adapter))) {
|
|
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
|
|
@@ -566,7 +566,7 @@ int be_process_mcc(struct be_adapter *adapter)
|
|
if (num)
|
|
be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
|
|
|
|
- spin_unlock_bh(&adapter->mcc_cq_lock);
|
|
+ spin_unlock(&adapter->mcc_cq_lock);
|
|
return status;
|
|
}
|
|
|
|
@@ -581,7 +581,9 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
|
|
if (be_check_error(adapter, BE_ERROR_ANY))
|
|
return -EIO;
|
|
|
|
+ local_bh_disable();
|
|
status = be_process_mcc(adapter);
|
|
+ local_bh_enable();
|
|
|
|
if (atomic_read(&mcc_obj->q.used) == 0)
|
|
break;
|
|
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
|
|
index cb1e1ad652d09..89697cb09d1c0 100644
|
|
--- a/drivers/net/ethernet/emulex/benet/be_main.c
|
|
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
|
|
@@ -5509,7 +5509,9 @@ static void be_worker(struct work_struct *work)
|
|
* mcc completions
|
|
*/
|
|
if (!netif_running(adapter->netdev)) {
|
|
+ local_bh_disable();
|
|
be_process_mcc(adapter);
|
|
+ local_bh_enable();
|
|
goto reschedule;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c
|
|
index 815fb62c4b02e..3d74401b4f102 100644
|
|
--- a/drivers/net/ethernet/ezchip/nps_enet.c
|
|
+++ b/drivers/net/ethernet/ezchip/nps_enet.c
|
|
@@ -610,7 +610,7 @@ static s32 nps_enet_probe(struct platform_device *pdev)
|
|
|
|
/* Get IRQ number */
|
|
priv->irq = platform_get_irq(pdev, 0);
|
|
- if (!priv->irq) {
|
|
+ if (priv->irq < 0) {
|
|
dev_err(dev, "failed to retrieve <irq Rx-Tx> value from device tree\n");
|
|
err = -ENODEV;
|
|
goto out_netdev;
|
|
@@ -645,8 +645,8 @@ static s32 nps_enet_remove(struct platform_device *pdev)
|
|
struct nps_enet_priv *priv = netdev_priv(ndev);
|
|
|
|
unregister_netdev(ndev);
|
|
- free_netdev(ndev);
|
|
netif_napi_del(&priv->napi);
|
|
+ free_netdev(ndev);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
|
|
index c9c380c508791..5bc11d1bb9df8 100644
|
|
--- a/drivers/net/ethernet/faraday/ftgmac100.c
|
|
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
|
|
@@ -1831,14 +1831,17 @@ static int ftgmac100_probe(struct platform_device *pdev)
|
|
if (np && of_get_property(np, "use-ncsi", NULL)) {
|
|
if (!IS_ENABLED(CONFIG_NET_NCSI)) {
|
|
dev_err(&pdev->dev, "NCSI stack not enabled\n");
|
|
+ err = -EINVAL;
|
|
goto err_ncsi_dev;
|
|
}
|
|
|
|
dev_info(&pdev->dev, "Using NCSI interface\n");
|
|
priv->use_ncsi = true;
|
|
priv->ndev = ncsi_register_dev(netdev, ftgmac100_ncsi_handler);
|
|
- if (!priv->ndev)
|
|
+ if (!priv->ndev) {
|
|
+ err = -EINVAL;
|
|
goto err_ncsi_dev;
|
|
+ }
|
|
} else if (np && of_get_property(np, "phy-handle", NULL)) {
|
|
struct phy_device *phy;
|
|
|
|
@@ -1846,6 +1849,7 @@ static int ftgmac100_probe(struct platform_device *pdev)
|
|
&ftgmac100_adjust_link);
|
|
if (!phy) {
|
|
dev_err(&pdev->dev, "Failed to connect to phy\n");
|
|
+ err = -EINVAL;
|
|
goto err_setup_mdio;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
|
|
index d6e35421d8f7b..3a74e4645ce65 100644
|
|
--- a/drivers/net/ethernet/google/gve/gve_main.c
|
|
+++ b/drivers/net/ethernet/google/gve/gve_main.c
|
|
@@ -1286,8 +1286,8 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
|
gve_write_version(®_bar->driver_version);
|
|
/* Get max queues to alloc etherdev */
|
|
- max_rx_queues = ioread32be(®_bar->max_tx_queues);
|
|
- max_tx_queues = ioread32be(®_bar->max_rx_queues);
|
|
+ max_tx_queues = ioread32be(®_bar->max_tx_queues);
|
|
+ max_rx_queues = ioread32be(®_bar->max_rx_queues);
|
|
/* Alloc and setup the netdev and priv */
|
|
dev = alloc_etherdev_mqs(sizeof(*priv), max_tx_queues, max_rx_queues);
|
|
if (!dev) {
|
|
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
|
|
index c2e7404757869..f630667364253 100644
|
|
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
|
|
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
|
|
@@ -2617,10 +2617,8 @@ static int ehea_restart_qps(struct net_device *dev)
|
|
u16 dummy16 = 0;
|
|
|
|
cb0 = (void *)get_zeroed_page(GFP_KERNEL);
|
|
- if (!cb0) {
|
|
- ret = -ENOMEM;
|
|
- goto out;
|
|
- }
|
|
+ if (!cb0)
|
|
+ return -ENOMEM;
|
|
|
|
for (i = 0; i < (port->num_def_qps); i++) {
|
|
struct ehea_port_res *pr = &port->port_res[i];
|
|
@@ -2640,6 +2638,7 @@ static int ehea_restart_qps(struct net_device *dev)
|
|
cb0);
|
|
if (hret != H_SUCCESS) {
|
|
netdev_err(dev, "query_ehea_qp failed (1)\n");
|
|
+ ret = -EFAULT;
|
|
goto out;
|
|
}
|
|
|
|
@@ -2652,6 +2651,7 @@ static int ehea_restart_qps(struct net_device *dev)
|
|
&dummy64, &dummy16, &dummy16);
|
|
if (hret != H_SUCCESS) {
|
|
netdev_err(dev, "modify_ehea_qp failed (1)\n");
|
|
+ ret = -EFAULT;
|
|
goto out;
|
|
}
|
|
|
|
@@ -2660,6 +2660,7 @@ static int ehea_restart_qps(struct net_device *dev)
|
|
cb0);
|
|
if (hret != H_SUCCESS) {
|
|
netdev_err(dev, "query_ehea_qp failed (2)\n");
|
|
+ ret = -EFAULT;
|
|
goto out;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
|
|
index 8cc444684491a..3134c1988db36 100644
|
|
--- a/drivers/net/ethernet/ibm/ibmvnic.c
|
|
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
|
|
@@ -212,12 +212,11 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
|
|
mutex_lock(&adapter->fw_lock);
|
|
adapter->fw_done_rc = 0;
|
|
reinit_completion(&adapter->fw_done);
|
|
- rc = send_request_map(adapter, ltb->addr,
|
|
- ltb->size, ltb->map_id);
|
|
+
|
|
+ rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
|
|
if (rc) {
|
|
- dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
|
|
- mutex_unlock(&adapter->fw_lock);
|
|
- return rc;
|
|
+ dev_err(dev, "send_request_map failed, rc = %d\n", rc);
|
|
+ goto out;
|
|
}
|
|
|
|
rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
|
|
@@ -225,20 +224,23 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
|
|
dev_err(dev,
|
|
"Long term map request aborted or timed out,rc = %d\n",
|
|
rc);
|
|
- dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
|
|
- mutex_unlock(&adapter->fw_lock);
|
|
- return rc;
|
|
+ goto out;
|
|
}
|
|
|
|
if (adapter->fw_done_rc) {
|
|
dev_err(dev, "Couldn't map long term buffer,rc = %d\n",
|
|
adapter->fw_done_rc);
|
|
+ rc = -1;
|
|
+ goto out;
|
|
+ }
|
|
+ rc = 0;
|
|
+out:
|
|
+ if (rc) {
|
|
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
|
|
- mutex_unlock(&adapter->fw_lock);
|
|
- return -1;
|
|
+ ltb->buff = NULL;
|
|
}
|
|
mutex_unlock(&adapter->fw_lock);
|
|
- return 0;
|
|
+ return rc;
|
|
}
|
|
|
|
static void free_long_term_buff(struct ibmvnic_adapter *adapter,
|
|
@@ -258,6 +260,8 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
|
|
adapter->reset_reason != VNIC_RESET_TIMEOUT)
|
|
send_request_unmap(adapter, ltb->map_id);
|
|
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
|
|
+ ltb->buff = NULL;
|
|
+ ltb->map_id = 0;
|
|
}
|
|
|
|
static int reset_long_term_buff(struct ibmvnic_adapter *adapter,
|
|
@@ -747,8 +751,11 @@ static int init_tx_pools(struct net_device *netdev)
|
|
|
|
adapter->tso_pool = kcalloc(tx_subcrqs,
|
|
sizeof(struct ibmvnic_tx_pool), GFP_KERNEL);
|
|
- if (!adapter->tso_pool)
|
|
+ if (!adapter->tso_pool) {
|
|
+ kfree(adapter->tx_pool);
|
|
+ adapter->tx_pool = NULL;
|
|
return -1;
|
|
+ }
|
|
|
|
adapter->num_active_tx_pools = tx_subcrqs;
|
|
|
|
@@ -1166,6 +1173,11 @@ static int __ibmvnic_open(struct net_device *netdev)
|
|
|
|
netif_tx_start_all_queues(netdev);
|
|
|
|
+ if (prev_state == VNIC_CLOSED) {
|
|
+ for (i = 0; i < adapter->req_rx_queues; i++)
|
|
+ napi_schedule(&adapter->napi[i]);
|
|
+ }
|
|
+
|
|
adapter->state = VNIC_OPEN;
|
|
return rc;
|
|
}
|
|
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
index a0948002ddf85..b3ad95ac3d859 100644
|
|
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
|
|
@@ -5222,18 +5222,20 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|
pm_runtime_resume(netdev->dev.parent);
|
|
|
|
/* Checking if MAC is in DMoff state*/
|
|
- pcim_state = er32(STATUS);
|
|
- while (pcim_state & E1000_STATUS_PCIM_STATE) {
|
|
- if (tries++ == dmoff_exit_timeout) {
|
|
- e_dbg("Error in exiting dmoff\n");
|
|
- break;
|
|
- }
|
|
- usleep_range(10000, 20000);
|
|
+ if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) {
|
|
pcim_state = er32(STATUS);
|
|
-
|
|
- /* Checking if MAC exited DMoff state */
|
|
- if (!(pcim_state & E1000_STATUS_PCIM_STATE))
|
|
- e1000_phy_hw_reset(&adapter->hw);
|
|
+ while (pcim_state & E1000_STATUS_PCIM_STATE) {
|
|
+ if (tries++ == dmoff_exit_timeout) {
|
|
+ e_dbg("Error in exiting dmoff\n");
|
|
+ break;
|
|
+ }
|
|
+ usleep_range(10000, 20000);
|
|
+ pcim_state = er32(STATUS);
|
|
+
|
|
+ /* Checking if MAC exited DMoff state */
|
|
+ if (!(pcim_state & E1000_STATUS_PCIM_STATE))
|
|
+ e1000_phy_hw_reset(&adapter->hw);
|
|
+ }
|
|
}
|
|
|
|
/* update snapshot of PHY registers on LSC */
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
index 5d48bc0c3f6c4..874073f7f0248 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
@@ -1262,8 +1262,7 @@ static int i40e_set_link_ksettings(struct net_device *netdev,
|
|
if (ethtool_link_ksettings_test_link_mode(&safe_ks,
|
|
supported,
|
|
Autoneg) &&
|
|
- hw->phy.link_info.phy_type !=
|
|
- I40E_PHY_TYPE_10GBASE_T) {
|
|
+ hw->phy.media_type != I40E_MEDIA_TYPE_BASET) {
|
|
netdev_info(netdev, "Autoneg cannot be disabled on this phy\n");
|
|
err = -EINVAL;
|
|
goto done;
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
index f0edea7cdbccc..52e31f712a545 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
|
|
@@ -31,7 +31,7 @@ static void i40e_vsi_reinit_locked(struct i40e_vsi *vsi);
|
|
static void i40e_handle_reset_warning(struct i40e_pf *pf, bool lock_acquired);
|
|
static int i40e_add_vsi(struct i40e_vsi *vsi);
|
|
static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi);
|
|
-static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit);
|
|
+static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit, bool lock_acquired);
|
|
static int i40e_setup_misc_vector(struct i40e_pf *pf);
|
|
static void i40e_determine_queue_usage(struct i40e_pf *pf);
|
|
static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
|
|
@@ -8347,6 +8347,8 @@ int i40e_vsi_open(struct i40e_vsi *vsi)
|
|
dev_driver_string(&pf->pdev->dev),
|
|
dev_name(&pf->pdev->dev));
|
|
err = i40e_vsi_request_irq(vsi, int_name);
|
|
+ if (err)
|
|
+ goto err_setup_rx;
|
|
|
|
} else {
|
|
err = -EINVAL;
|
|
@@ -10112,7 +10114,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
|
|
/* do basic switch setup */
|
|
if (!lock_acquired)
|
|
rtnl_lock();
|
|
- ret = i40e_setup_pf_switch(pf, reinit);
|
|
+ ret = i40e_setup_pf_switch(pf, reinit, true);
|
|
if (ret)
|
|
goto end_unlock;
|
|
|
|
@@ -14167,10 +14169,11 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig)
|
|
* i40e_setup_pf_switch - Setup the HW switch on startup or after reset
|
|
* @pf: board private structure
|
|
* @reinit: if the Main VSI needs to re-initialized.
|
|
+ * @lock_acquired: indicates whether or not the lock has been acquired
|
|
*
|
|
* Returns 0 on success, negative value on failure
|
|
**/
|
|
-static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
|
|
+static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit, bool lock_acquired)
|
|
{
|
|
u16 flags = 0;
|
|
int ret;
|
|
@@ -14272,9 +14275,15 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit)
|
|
|
|
i40e_ptp_init(pf);
|
|
|
|
+ if (!lock_acquired)
|
|
+ rtnl_lock();
|
|
+
|
|
/* repopulate tunnel port filters */
|
|
udp_tunnel_nic_reset_ntf(pf->vsi[pf->lan_vsi]->netdev);
|
|
|
|
+ if (!lock_acquired)
|
|
+ rtnl_unlock();
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -15046,7 +15055,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
|
|
}
|
|
#endif
|
|
- err = i40e_setup_pf_switch(pf, false);
|
|
+ err = i40e_setup_pf_switch(pf, false, false);
|
|
if (err) {
|
|
dev_info(&pdev->dev, "setup_pf_switch failed: %d\n", err);
|
|
goto err_vsis;
|
|
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
|
|
index 6aa13c9f9fc9c..a9f65d6677617 100644
|
|
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
|
|
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
|
|
@@ -7045,6 +7045,8 @@ static int mvpp2_probe(struct platform_device *pdev)
|
|
return 0;
|
|
|
|
err_port_probe:
|
|
+ fwnode_handle_put(port_fwnode);
|
|
+
|
|
i = 0;
|
|
fwnode_for_each_available_child_node(fwnode, port_fwnode) {
|
|
if (priv->port_list[i])
|
|
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
|
|
index ade8c44c01cd1..9a0870dc2f034 100644
|
|
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
|
|
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
|
|
@@ -2536,9 +2536,13 @@ static int pch_gbe_probe(struct pci_dev *pdev,
|
|
adapter->pdev = pdev;
|
|
adapter->hw.back = adapter;
|
|
adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR];
|
|
+
|
|
adapter->pdata = (struct pch_gbe_privdata *)pci_id->driver_data;
|
|
- if (adapter->pdata && adapter->pdata->platform_init)
|
|
- adapter->pdata->platform_init(pdev);
|
|
+ if (adapter->pdata && adapter->pdata->platform_init) {
|
|
+ ret = adapter->pdata->platform_init(pdev);
|
|
+ if (ret)
|
|
+ goto err_free_netdev;
|
|
+ }
|
|
|
|
adapter->ptp_pdev =
|
|
pci_get_domain_bus_and_slot(pci_domain_nr(adapter->pdev->bus),
|
|
@@ -2633,7 +2637,7 @@ err_free_netdev:
|
|
*/
|
|
static int pch_gbe_minnow_platform_init(struct pci_dev *pdev)
|
|
{
|
|
- unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH | GPIOF_EXPORT;
|
|
+ unsigned long flags = GPIOF_OUT_INIT_HIGH;
|
|
unsigned gpio = MINNOW_PHY_RESET_GPIO;
|
|
int ret;
|
|
|
|
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
|
|
index 501d676fd88b9..0805edef56254 100644
|
|
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
|
|
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
|
|
@@ -1433,12 +1433,12 @@ static void am65_cpsw_nuss_free_tx_chns(void *data)
|
|
for (i = 0; i < common->tx_ch_num; i++) {
|
|
struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
|
|
|
|
- if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
|
|
- k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
|
|
-
|
|
if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
|
|
k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
|
|
|
|
+ if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
|
|
+ k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
|
|
+
|
|
memset(tx_chn, 0, sizeof(*tx_chn));
|
|
}
|
|
}
|
|
@@ -1458,12 +1458,12 @@ void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common)
|
|
|
|
netif_napi_del(&tx_chn->napi_tx);
|
|
|
|
- if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
|
|
- k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
|
|
-
|
|
if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
|
|
k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
|
|
|
|
+ if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
|
|
+ k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
|
|
+
|
|
memset(tx_chn, 0, sizeof(*tx_chn));
|
|
}
|
|
}
|
|
@@ -1550,11 +1550,11 @@ static void am65_cpsw_nuss_free_rx_chns(void *data)
|
|
|
|
rx_chn = &common->rx_chns;
|
|
|
|
- if (!IS_ERR_OR_NULL(rx_chn->rx_chn))
|
|
- k3_udma_glue_release_rx_chn(rx_chn->rx_chn);
|
|
-
|
|
if (!IS_ERR_OR_NULL(rx_chn->desc_pool))
|
|
k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
|
|
+
|
|
+ if (!IS_ERR_OR_NULL(rx_chn->rx_chn))
|
|
+ k3_udma_glue_release_rx_chn(rx_chn->rx_chn);
|
|
}
|
|
|
|
static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
|
|
diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
|
|
index c0bf7d78276e4..626e1ce817fcf 100644
|
|
--- a/drivers/net/ieee802154/mac802154_hwsim.c
|
|
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
|
|
@@ -480,7 +480,7 @@ static int hwsim_del_edge_nl(struct sk_buff *msg, struct genl_info *info)
|
|
struct hwsim_edge *e;
|
|
u32 v0, v1;
|
|
|
|
- if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
|
|
+ if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] ||
|
|
!info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
|
|
return -EINVAL;
|
|
|
|
@@ -715,6 +715,8 @@ static int hwsim_subscribe_all_others(struct hwsim_phy *phy)
|
|
|
|
return 0;
|
|
|
|
+sub_fail:
|
|
+ hwsim_edge_unsubscribe_me(phy);
|
|
me_fail:
|
|
rcu_read_lock();
|
|
list_for_each_entry_rcu(e, &phy->edges, list) {
|
|
@@ -722,8 +724,6 @@ me_fail:
|
|
hwsim_free_edge(e);
|
|
}
|
|
rcu_read_unlock();
|
|
-sub_fail:
|
|
- hwsim_edge_unsubscribe_me(phy);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -824,12 +824,17 @@ err_pib:
|
|
static void hwsim_del(struct hwsim_phy *phy)
|
|
{
|
|
struct hwsim_pib *pib;
|
|
+ struct hwsim_edge *e;
|
|
|
|
hwsim_edge_unsubscribe_me(phy);
|
|
|
|
list_del(&phy->list);
|
|
|
|
rcu_read_lock();
|
|
+ list_for_each_entry_rcu(e, &phy->edges, list) {
|
|
+ list_del_rcu(&e->list);
|
|
+ hwsim_free_edge(e);
|
|
+ }
|
|
pib = rcu_dereference(phy->pib);
|
|
rcu_read_unlock();
|
|
|
|
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
|
|
index 11ca5fa902a16..c601d3df27220 100644
|
|
--- a/drivers/net/macsec.c
|
|
+++ b/drivers/net/macsec.c
|
|
@@ -1818,7 +1818,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info)
|
|
ctx.sa.rx_sa = rx_sa;
|
|
ctx.secy = secy;
|
|
memcpy(ctx.sa.key, nla_data(tb_sa[MACSEC_SA_ATTR_KEY]),
|
|
- MACSEC_KEYID_LEN);
|
|
+ secy->key_len);
|
|
|
|
err = macsec_offload(ops->mdo_add_rxsa, &ctx);
|
|
if (err)
|
|
@@ -2060,7 +2060,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info)
|
|
ctx.sa.tx_sa = tx_sa;
|
|
ctx.secy = secy;
|
|
memcpy(ctx.sa.key, nla_data(tb_sa[MACSEC_SA_ATTR_KEY]),
|
|
- MACSEC_KEYID_LEN);
|
|
+ secy->key_len);
|
|
|
|
err = macsec_offload(ops->mdo_add_txsa, &ctx);
|
|
if (err)
|
|
diff --git a/drivers/net/phy/mscc/mscc_macsec.c b/drivers/net/phy/mscc/mscc_macsec.c
|
|
index 10be266e48e8b..b7b2521c73fb6 100644
|
|
--- a/drivers/net/phy/mscc/mscc_macsec.c
|
|
+++ b/drivers/net/phy/mscc/mscc_macsec.c
|
|
@@ -501,7 +501,7 @@ static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow)
|
|
}
|
|
|
|
/* Derive the AES key to get a key for the hash autentication */
|
|
-static int vsc8584_macsec_derive_key(const u8 key[MACSEC_KEYID_LEN],
|
|
+static int vsc8584_macsec_derive_key(const u8 key[MACSEC_MAX_KEY_LEN],
|
|
u16 key_len, u8 hkey[16])
|
|
{
|
|
const u8 input[AES_BLOCK_SIZE] = {0};
|
|
diff --git a/drivers/net/phy/mscc/mscc_macsec.h b/drivers/net/phy/mscc/mscc_macsec.h
|
|
index 9c6d25e36de2a..453304bae7784 100644
|
|
--- a/drivers/net/phy/mscc/mscc_macsec.h
|
|
+++ b/drivers/net/phy/mscc/mscc_macsec.h
|
|
@@ -81,7 +81,7 @@ struct macsec_flow {
|
|
/* Highest takes precedence [0..15] */
|
|
u8 priority;
|
|
|
|
- u8 key[MACSEC_KEYID_LEN];
|
|
+ u8 key[MACSEC_MAX_KEY_LEN];
|
|
|
|
union {
|
|
struct macsec_rx_sa *rx_sa;
|
|
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
|
|
index bc96ac0c5769c..2746f77745e4d 100644
|
|
--- a/drivers/net/vrf.c
|
|
+++ b/drivers/net/vrf.c
|
|
@@ -1312,22 +1312,22 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
|
|
int orig_iif = skb->skb_iif;
|
|
bool need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr);
|
|
bool is_ndisc = ipv6_ndisc_frame(skb);
|
|
- bool is_ll_src;
|
|
|
|
/* loopback, multicast & non-ND link-local traffic; do not push through
|
|
* packet taps again. Reset pkt_type for upper layers to process skb.
|
|
- * for packets with lladdr src, however, skip so that the dst can be
|
|
- * determine at input using original ifindex in the case that daddr
|
|
- * needs strict
|
|
+ * For strict packets with a source LLA, determine the dst using the
|
|
+ * original ifindex.
|
|
*/
|
|
- is_ll_src = ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL;
|
|
- if (skb->pkt_type == PACKET_LOOPBACK ||
|
|
- (need_strict && !is_ndisc && !is_ll_src)) {
|
|
+ if (skb->pkt_type == PACKET_LOOPBACK || (need_strict && !is_ndisc)) {
|
|
skb->dev = vrf_dev;
|
|
skb->skb_iif = vrf_dev->ifindex;
|
|
IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
|
|
+
|
|
if (skb->pkt_type == PACKET_LOOPBACK)
|
|
skb->pkt_type = PACKET_HOST;
|
|
+ else if (ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)
|
|
+ vrf_ip6_input_dst(skb, vrf_dev, orig_iif);
|
|
+
|
|
goto out;
|
|
}
|
|
|
|
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
|
|
index d3b698d9e2e6a..48fbdce6a70e7 100644
|
|
--- a/drivers/net/vxlan.c
|
|
+++ b/drivers/net/vxlan.c
|
|
@@ -2163,6 +2163,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|
struct neighbour *n;
|
|
struct nd_msg *msg;
|
|
|
|
+ rcu_read_lock();
|
|
in6_dev = __in6_dev_get(dev);
|
|
if (!in6_dev)
|
|
goto out;
|
|
@@ -2214,6 +2215,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
|
|
}
|
|
|
|
out:
|
|
+ rcu_read_unlock();
|
|
consume_skb(skb);
|
|
return NETDEV_TX_OK;
|
|
}
|
|
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
|
|
index f5c0f9bac8404..36183fdfb7f03 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
|
@@ -5482,6 +5482,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|
|
|
if (arvif->nohwcrypt &&
|
|
!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
|
+ ret = -EINVAL;
|
|
ath10k_warn(ar, "cryptmode module param needed for sw crypto\n");
|
|
goto err;
|
|
}
|
|
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
|
|
index 36426efdb2ea0..86f52bcb3e4db 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/pci.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/pci.c
|
|
@@ -3684,8 +3684,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
|
ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
|
|
if (bus_params.chip_id != 0xffffffff) {
|
|
if (!ath10k_pci_chip_is_supported(pdev->device,
|
|
- bus_params.chip_id))
|
|
+ bus_params.chip_id)) {
|
|
+ ret = -ENODEV;
|
|
goto err_unsupported;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -3696,11 +3698,15 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
|
}
|
|
|
|
bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
|
|
- if (bus_params.chip_id == 0xffffffff)
|
|
+ if (bus_params.chip_id == 0xffffffff) {
|
|
+ ret = -ENODEV;
|
|
goto err_unsupported;
|
|
+ }
|
|
|
|
- if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id))
|
|
- goto err_free_irq;
|
|
+ if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) {
|
|
+ ret = -ENODEV;
|
|
+ goto err_unsupported;
|
|
+ }
|
|
|
|
ret = ath10k_core_register(ar, &bus_params);
|
|
if (ret) {
|
|
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
|
|
index a68fe3a45a744..28de2c7ae8991 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/core.c
|
|
@@ -329,7 +329,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
|
|
if (len < ALIGN(ie_len, 4)) {
|
|
ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n",
|
|
ie_id, ie_len, len);
|
|
- return -EINVAL;
|
|
+ ret = -EINVAL;
|
|
+ goto err;
|
|
}
|
|
|
|
switch (ie_id) {
|
|
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
|
|
index 0738c784616f1..cc0c30ceaa0d4 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -5123,11 +5123,6 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
|
|
if (WARN_ON(!arvif->is_up))
|
|
continue;
|
|
|
|
- ret = ath11k_mac_setup_bcn_tmpl(arvif);
|
|
- if (ret)
|
|
- ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
|
|
- ret);
|
|
-
|
|
ret = ath11k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def);
|
|
if (ret) {
|
|
ath11k_warn(ab, "failed to restart vdev %d: %d\n",
|
|
@@ -5135,6 +5130,11 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
|
|
continue;
|
|
}
|
|
|
|
+ ret = ath11k_mac_setup_bcn_tmpl(arvif);
|
|
+ if (ret)
|
|
+ ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n",
|
|
+ ret);
|
|
+
|
|
ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
|
|
arvif->bssid);
|
|
if (ret) {
|
|
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
|
|
index 8dbf68b94228c..ac805f56627ab 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/main.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
|
@@ -307,6 +307,11 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
|
|
hchan = ah->curchan;
|
|
}
|
|
|
|
+ if (!hchan) {
|
|
+ fastcc = false;
|
|
+ hchan = ath9k_cmn_get_channel(sc->hw, ah, &sc->cur_chan->chandef);
|
|
+ }
|
|
+
|
|
if (!ath_prepare_reset(sc))
|
|
fastcc = false;
|
|
|
|
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
|
|
index b2d760873992f..ba9bea79381c5 100644
|
|
--- a/drivers/net/wireless/ath/carl9170/Kconfig
|
|
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
|
|
@@ -16,13 +16,11 @@ config CARL9170
|
|
|
|
config CARL9170_LEDS
|
|
bool "SoftLED Support"
|
|
- depends on CARL9170
|
|
- select MAC80211_LEDS
|
|
- select LEDS_CLASS
|
|
- select NEW_LEDS
|
|
default y
|
|
+ depends on CARL9170
|
|
+ depends on MAC80211_LEDS
|
|
help
|
|
- This option is necessary, if you want your device' LEDs to blink
|
|
+ This option is necessary, if you want your device's LEDs to blink.
|
|
|
|
Say Y, unless you need the LEDs for firmware debugging.
|
|
|
|
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
|
|
index 706728fba72d7..9f8e44210e89a 100644
|
|
--- a/drivers/net/wireless/ath/wcn36xx/main.c
|
|
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
|
|
@@ -293,23 +293,16 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
|
|
goto out_free_dxe_pool;
|
|
}
|
|
|
|
- wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
|
|
- if (!wcn->hal_buf) {
|
|
- wcn36xx_err("Failed to allocate smd buf\n");
|
|
- ret = -ENOMEM;
|
|
- goto out_free_dxe_ctl;
|
|
- }
|
|
-
|
|
ret = wcn36xx_smd_load_nv(wcn);
|
|
if (ret) {
|
|
wcn36xx_err("Failed to push NV to chip\n");
|
|
- goto out_free_smd_buf;
|
|
+ goto out_free_dxe_ctl;
|
|
}
|
|
|
|
ret = wcn36xx_smd_start(wcn);
|
|
if (ret) {
|
|
wcn36xx_err("Failed to start chip\n");
|
|
- goto out_free_smd_buf;
|
|
+ goto out_free_dxe_ctl;
|
|
}
|
|
|
|
if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
|
|
@@ -336,8 +329,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
|
|
|
|
out_smd_stop:
|
|
wcn36xx_smd_stop(wcn);
|
|
-out_free_smd_buf:
|
|
- kfree(wcn->hal_buf);
|
|
out_free_dxe_ctl:
|
|
wcn36xx_dxe_free_ctl_blks(wcn);
|
|
out_free_dxe_pool:
|
|
@@ -372,8 +363,6 @@ static void wcn36xx_stop(struct ieee80211_hw *hw)
|
|
|
|
wcn36xx_dxe_free_mem_pools(wcn);
|
|
wcn36xx_dxe_free_ctl_blks(wcn);
|
|
-
|
|
- kfree(wcn->hal_buf);
|
|
}
|
|
|
|
static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable)
|
|
@@ -1398,6 +1387,12 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
|
mutex_init(&wcn->hal_mutex);
|
|
mutex_init(&wcn->scan_lock);
|
|
|
|
+ wcn->hal_buf = devm_kmalloc(wcn->dev, WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
|
|
+ if (!wcn->hal_buf) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out_wq;
|
|
+ }
|
|
+
|
|
ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
|
|
if (ret < 0) {
|
|
wcn36xx_err("failed to set DMA mask: %d\n", ret);
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
index 23e6422c2251b..c2b6e5c966d04 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
@@ -2767,8 +2767,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
|
struct brcmf_sta_info_le sta_info_le;
|
|
u32 sta_flags;
|
|
u32 is_tdls_peer;
|
|
- s32 total_rssi;
|
|
- s32 count_rssi;
|
|
+ s32 total_rssi_avg = 0;
|
|
+ s32 total_rssi = 0;
|
|
+ s32 count_rssi = 0;
|
|
int rssi;
|
|
u32 i;
|
|
|
|
@@ -2834,25 +2835,27 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
|
|
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
|
|
sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
|
|
}
|
|
- total_rssi = 0;
|
|
- count_rssi = 0;
|
|
for (i = 0; i < BRCMF_ANT_MAX; i++) {
|
|
- if (sta_info_le.rssi[i]) {
|
|
- sinfo->chain_signal_avg[count_rssi] =
|
|
- sta_info_le.rssi[i];
|
|
- sinfo->chain_signal[count_rssi] =
|
|
- sta_info_le.rssi[i];
|
|
- total_rssi += sta_info_le.rssi[i];
|
|
- count_rssi++;
|
|
- }
|
|
+ if (sta_info_le.rssi[i] == 0 ||
|
|
+ sta_info_le.rx_lastpkt_rssi[i] == 0)
|
|
+ continue;
|
|
+ sinfo->chains |= BIT(count_rssi);
|
|
+ sinfo->chain_signal[count_rssi] =
|
|
+ sta_info_le.rx_lastpkt_rssi[i];
|
|
+ sinfo->chain_signal_avg[count_rssi] =
|
|
+ sta_info_le.rssi[i];
|
|
+ total_rssi += sta_info_le.rx_lastpkt_rssi[i];
|
|
+ total_rssi_avg += sta_info_le.rssi[i];
|
|
+ count_rssi++;
|
|
}
|
|
if (count_rssi) {
|
|
- sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
|
|
- sinfo->chains = count_rssi;
|
|
-
|
|
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
|
|
- total_rssi /= count_rssi;
|
|
- sinfo->signal = total_rssi;
|
|
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
|
|
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
|
|
+ sinfo->filled |=
|
|
+ BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG);
|
|
+ sinfo->signal = total_rssi / count_rssi;
|
|
+ sinfo->signal_avg = total_rssi_avg / count_rssi;
|
|
} else if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
|
|
&ifp->vif->sme_state)) {
|
|
memset(&scb_val, 0, sizeof(scb_val));
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
|
index 59c2b2b6027da..6d5d5c39c6359 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
|
|
@@ -4157,7 +4157,6 @@ static int brcmf_sdio_bus_reset(struct device *dev)
|
|
if (ret) {
|
|
brcmf_err("Failed to probe after sdio device reset: ret %d\n",
|
|
ret);
|
|
- brcmf_sdiod_remove(sdiodev);
|
|
}
|
|
|
|
return ret;
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
|
|
index 818e523f6025d..fb76b4a69a059 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
|
|
@@ -1221,6 +1221,7 @@ static int brcms_bcma_probe(struct bcma_device *pdev)
|
|
{
|
|
struct brcms_info *wl;
|
|
struct ieee80211_hw *hw;
|
|
+ int ret;
|
|
|
|
dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n",
|
|
pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class,
|
|
@@ -1245,11 +1246,16 @@ static int brcms_bcma_probe(struct bcma_device *pdev)
|
|
wl = brcms_attach(pdev);
|
|
if (!wl) {
|
|
pr_err("%s: brcms_attach failed!\n", __func__);
|
|
- return -ENODEV;
|
|
+ ret = -ENODEV;
|
|
+ goto err_free_ieee80211;
|
|
}
|
|
brcms_led_register(wl);
|
|
|
|
return 0;
|
|
+
|
|
+err_free_ieee80211:
|
|
+ ieee80211_free_hw(hw);
|
|
+ return ret;
|
|
}
|
|
|
|
static int brcms_suspend(struct bcma_device *pdev)
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
|
|
index e4f91bce222d8..61d3d4e0b7d94 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h
|
|
@@ -1,7 +1,7 @@
|
|
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
|
/******************************************************************************
|
|
*
|
|
- * Copyright(c) 2020 Intel Corporation
|
|
+ * Copyright(c) 2020-2021 Intel Corporation
|
|
*
|
|
*****************************************************************************/
|
|
|
|
@@ -10,7 +10,7 @@
|
|
|
|
#include "fw/notif-wait.h"
|
|
|
|
-#define MVM_UCODE_PNVM_TIMEOUT (HZ / 10)
|
|
+#define MVM_UCODE_PNVM_TIMEOUT (HZ / 4)
|
|
|
|
int iwl_pnvm_load(struct iwl_trans *trans,
|
|
struct iwl_notif_wait_data *notif_wait);
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
|
|
index 7626117c01fa3..7186e1dbbd6b5 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
|
|
@@ -1085,6 +1085,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|
if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA))
|
|
return -1;
|
|
|
|
+ if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->he_cap.has_he)
|
|
+ return -1;
|
|
+
|
|
if (unlikely(ieee80211_is_probe_resp(fc)))
|
|
iwl_mvm_probe_resp_set_noa(mvm, skb);
|
|
|
|
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
|
|
index 33cf952cc01d3..b2de8d03c5fac 100644
|
|
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
|
|
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
|
|
@@ -1232,7 +1232,7 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter)
|
|
static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
|
|
{
|
|
struct pcie_service_card *card = adapter->card;
|
|
- u32 tmp;
|
|
+ u32 *cookie;
|
|
|
|
card->sleep_cookie_vbase = dma_alloc_coherent(&card->dev->dev,
|
|
sizeof(u32),
|
|
@@ -1243,13 +1243,11 @@ static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
|
|
"dma_alloc_coherent failed!\n");
|
|
return -ENOMEM;
|
|
}
|
|
+ cookie = (u32 *)card->sleep_cookie_vbase;
|
|
/* Init val of Sleep Cookie */
|
|
- tmp = FW_AWAKE_COOKIE;
|
|
- put_unaligned(tmp, card->sleep_cookie_vbase);
|
|
+ *cookie = FW_AWAKE_COOKIE;
|
|
|
|
- mwifiex_dbg(adapter, INFO,
|
|
- "alloc_scook: sleep cookie=0x%x\n",
|
|
- get_unaligned(card->sleep_cookie_vbase));
|
|
+ mwifiex_dbg(adapter, INFO, "alloc_scook: sleep cookie=0x%x\n", *cookie);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
|
|
index 4cf7c5d343258..490d55651de39 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
|
|
@@ -133,20 +133,21 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|
struct mt76_tx_info *tx_info)
|
|
{
|
|
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
|
|
- struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid);
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
|
|
struct ieee80211_key_conf *key = info->control.hw_key;
|
|
int pid, id;
|
|
u8 *txwi = (u8 *)txwi_ptr;
|
|
struct mt76_txwi_cache *t;
|
|
+ struct mt7615_sta *msta;
|
|
void *txp;
|
|
|
|
+ msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
|
|
if (!wcid)
|
|
wcid = &dev->mt76.global_wcid;
|
|
|
|
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
|
|
|
|
- if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
|
|
+ if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) {
|
|
struct mt7615_phy *phy = &dev->phy;
|
|
|
|
if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2)
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
|
|
index 3b29a6d3dc641..18082b4ce7d3d 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
|
|
@@ -243,14 +243,15 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|
struct ieee80211_sta *sta,
|
|
struct mt76_tx_info *tx_info)
|
|
{
|
|
- struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid);
|
|
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
|
|
struct sk_buff *skb = tx_info->skb;
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
+ struct mt7615_sta *msta;
|
|
int pad;
|
|
|
|
+ msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
|
|
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) &&
|
|
- !msta->rate_probe) {
|
|
+ msta && !msta->rate_probe) {
|
|
/* request to configure sampling rate */
|
|
spin_lock_bh(&dev->mt76.lock);
|
|
mt7615_mac_set_rates(&dev->phy, msta, &info->control.rates[0],
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
|
|
index 44ef4bc7a46e5..073c29eb2ed8f 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/tx.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
|
|
@@ -278,7 +278,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta,
|
|
skb_set_queue_mapping(skb, qid);
|
|
}
|
|
|
|
- if (!(wcid->tx_info & MT_WCID_TX_INFO_SET))
|
|
+ if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET))
|
|
ieee80211_get_tx_rates(info->control.vif, sta, skb,
|
|
info->control.rates, 1);
|
|
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
|
|
index b718f5d810be8..79ad6232dce83 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
|
|
@@ -3510,26 +3510,28 @@ static void rtw8822c_pwrtrack_set(struct rtw_dev *rtwdev, u8 rf_path)
|
|
}
|
|
}
|
|
|
|
-static void rtw8822c_pwr_track_path(struct rtw_dev *rtwdev,
|
|
- struct rtw_swing_table *swing_table,
|
|
- u8 path)
|
|
+static void rtw8822c_pwr_track_stats(struct rtw_dev *rtwdev, u8 path)
|
|
{
|
|
- struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
|
- u8 thermal_value, delta;
|
|
+ u8 thermal_value;
|
|
|
|
if (rtwdev->efuse.thermal_meter[path] == 0xff)
|
|
return;
|
|
|
|
thermal_value = rtw_read_rf(rtwdev, path, RF_T_METER, 0x7e);
|
|
-
|
|
rtw_phy_pwrtrack_avg(rtwdev, thermal_value, path);
|
|
+}
|
|
|
|
- delta = rtw_phy_pwrtrack_get_delta(rtwdev, path);
|
|
+static void rtw8822c_pwr_track_path(struct rtw_dev *rtwdev,
|
|
+ struct rtw_swing_table *swing_table,
|
|
+ u8 path)
|
|
+{
|
|
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
|
+ u8 delta;
|
|
|
|
+ delta = rtw_phy_pwrtrack_get_delta(rtwdev, path);
|
|
dm_info->delta_power_index[path] =
|
|
rtw_phy_pwrtrack_get_pwridx(rtwdev, swing_table, path, path,
|
|
delta);
|
|
-
|
|
rtw8822c_pwrtrack_set(rtwdev, path);
|
|
}
|
|
|
|
@@ -3540,12 +3542,12 @@ static void __rtw8822c_pwr_track(struct rtw_dev *rtwdev)
|
|
|
|
rtw_phy_config_swing_table(rtwdev, &swing_table);
|
|
|
|
+ for (i = 0; i < rtwdev->hal.rf_path_num; i++)
|
|
+ rtw8822c_pwr_track_stats(rtwdev, i);
|
|
if (rtw_phy_pwrtrack_need_lck(rtwdev))
|
|
rtw8822c_do_lck(rtwdev);
|
|
-
|
|
for (i = 0; i < rtwdev->hal.rf_path_num; i++)
|
|
rtw8822c_pwr_track_path(rtwdev, &swing_table, i);
|
|
-
|
|
}
|
|
|
|
static void rtw8822c_pwr_track(struct rtw_dev *rtwdev)
|
|
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
|
|
index ce9892152f4d4..99b21a2c83861 100644
|
|
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
|
|
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
|
|
@@ -203,7 +203,7 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
|
|
wh->frame_control |= cpu_to_le16(RSI_SET_PS_ENABLE);
|
|
|
|
if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&
|
|
- (common->secinfo.security_enable)) {
|
|
+ info->control.hw_key) {
|
|
if (rsi_is_cipher_wep(common))
|
|
ieee80211_size += 4;
|
|
else
|
|
@@ -470,9 +470,9 @@ int rsi_prepare_beacon(struct rsi_common *common, struct sk_buff *skb)
|
|
}
|
|
|
|
if (common->band == NL80211_BAND_2GHZ)
|
|
- bcn_frm->bbp_info |= cpu_to_le16(RSI_RATE_1);
|
|
+ bcn_frm->rate_info |= cpu_to_le16(RSI_RATE_1);
|
|
else
|
|
- bcn_frm->bbp_info |= cpu_to_le16(RSI_RATE_6);
|
|
+ bcn_frm->rate_info |= cpu_to_le16(RSI_RATE_6);
|
|
|
|
if (mac_bcn->data[tim_offset + 2] == 0)
|
|
bcn_frm->frame_info |= cpu_to_le16(RSI_DATA_DESC_DTIM_BEACON);
|
|
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
|
|
index 16025300cddb3..57c9e3559dfd1 100644
|
|
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
|
|
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
|
|
@@ -1028,7 +1028,6 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
|
|
mutex_lock(&common->mutex);
|
|
switch (cmd) {
|
|
case SET_KEY:
|
|
- secinfo->security_enable = true;
|
|
status = rsi_hal_key_config(hw, vif, key, sta);
|
|
if (status) {
|
|
mutex_unlock(&common->mutex);
|
|
@@ -1047,8 +1046,6 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
|
|
break;
|
|
|
|
case DISABLE_KEY:
|
|
- if (vif->type == NL80211_IFTYPE_STATION)
|
|
- secinfo->security_enable = false;
|
|
rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
|
|
memset(key, 0, sizeof(struct ieee80211_key_conf));
|
|
status = rsi_hal_key_config(hw, vif, key, sta);
|
|
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
|
|
index 33c76d39a8e96..b6d050a2fbe7e 100644
|
|
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
|
|
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
|
|
@@ -1803,8 +1803,7 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
|
|
RSI_WIFI_MGMT_Q);
|
|
cmd_frame->desc.desc_dword0.frame_type = WOWLAN_CONFIG_PARAMS;
|
|
cmd_frame->host_sleep_status = sleep_status;
|
|
- if (common->secinfo.security_enable &&
|
|
- common->secinfo.gtk_cipher)
|
|
+ if (common->secinfo.gtk_cipher)
|
|
flags |= RSI_WOW_GTK_REKEY;
|
|
if (sleep_status)
|
|
cmd_frame->wow_flags = flags;
|
|
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
|
|
index 73a19e43106b1..b3e25bc28682c 100644
|
|
--- a/drivers/net/wireless/rsi/rsi_main.h
|
|
+++ b/drivers/net/wireless/rsi/rsi_main.h
|
|
@@ -151,7 +151,6 @@ enum edca_queue {
|
|
};
|
|
|
|
struct security_info {
|
|
- bool security_enable;
|
|
u32 ptk_cipher;
|
|
u32 gtk_cipher;
|
|
};
|
|
diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c
|
|
index 988581cc134b7..1f856fbbc0ea4 100644
|
|
--- a/drivers/net/wireless/st/cw1200/scan.c
|
|
+++ b/drivers/net/wireless/st/cw1200/scan.c
|
|
@@ -75,30 +75,27 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
|
|
if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
|
|
return -EINVAL;
|
|
|
|
- /* will be unlocked in cw1200_scan_work() */
|
|
- down(&priv->scan.lock);
|
|
- mutex_lock(&priv->conf_mutex);
|
|
-
|
|
frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
|
|
req->ie_len);
|
|
- if (!frame.skb) {
|
|
- mutex_unlock(&priv->conf_mutex);
|
|
- up(&priv->scan.lock);
|
|
+ if (!frame.skb)
|
|
return -ENOMEM;
|
|
- }
|
|
|
|
if (req->ie_len)
|
|
skb_put_data(frame.skb, req->ie, req->ie_len);
|
|
|
|
+ /* will be unlocked in cw1200_scan_work() */
|
|
+ down(&priv->scan.lock);
|
|
+ mutex_lock(&priv->conf_mutex);
|
|
+
|
|
ret = wsm_set_template_frame(priv, &frame);
|
|
if (!ret) {
|
|
/* Host want to be the probe responder. */
|
|
ret = wsm_set_probe_responder(priv, true);
|
|
}
|
|
if (ret) {
|
|
- dev_kfree_skb(frame.skb);
|
|
mutex_unlock(&priv->conf_mutex);
|
|
up(&priv->scan.lock);
|
|
+ dev_kfree_skb(frame.skb);
|
|
return ret;
|
|
}
|
|
|
|
@@ -120,8 +117,8 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
|
|
++priv->scan.n_ssids;
|
|
}
|
|
|
|
- dev_kfree_skb(frame.skb);
|
|
mutex_unlock(&priv->conf_mutex);
|
|
+ dev_kfree_skb(frame.skb);
|
|
queue_work(priv->workqueue, &priv->scan.work);
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
|
|
index c1f3446216c5c..3f05df98697d3 100644
|
|
--- a/drivers/nvme/host/pci.c
|
|
+++ b/drivers/nvme/host/pci.c
|
|
@@ -1027,7 +1027,7 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx)
|
|
|
|
static inline void nvme_update_cq_head(struct nvme_queue *nvmeq)
|
|
{
|
|
- u16 tmp = nvmeq->cq_head + 1;
|
|
+ u32 tmp = nvmeq->cq_head + 1;
|
|
|
|
if (tmp == nvmeq->q_depth) {
|
|
nvmeq->cq_head = 0;
|
|
@@ -2836,10 +2836,7 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
|
|
#ifdef CONFIG_ACPI
|
|
static bool nvme_acpi_storage_d3(struct pci_dev *dev)
|
|
{
|
|
- struct acpi_device *adev;
|
|
- struct pci_dev *root;
|
|
- acpi_handle handle;
|
|
- acpi_status status;
|
|
+ struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
|
|
u8 val;
|
|
|
|
/*
|
|
@@ -2847,28 +2844,9 @@ static bool nvme_acpi_storage_d3(struct pci_dev *dev)
|
|
* must use D3 to support deep platform power savings during
|
|
* suspend-to-idle.
|
|
*/
|
|
- root = pcie_find_root_port(dev);
|
|
- if (!root)
|
|
- return false;
|
|
|
|
- adev = ACPI_COMPANION(&root->dev);
|
|
if (!adev)
|
|
return false;
|
|
-
|
|
- /*
|
|
- * The property is defined in the PXSX device for South complex ports
|
|
- * and in the PEGP device for North complex ports.
|
|
- */
|
|
- status = acpi_get_handle(adev->handle, "PXSX", &handle);
|
|
- if (ACPI_FAILURE(status)) {
|
|
- status = acpi_get_handle(adev->handle, "PEGP", &handle);
|
|
- if (ACPI_FAILURE(status))
|
|
- return false;
|
|
- }
|
|
-
|
|
- if (acpi_bus_get_device(handle, &adev))
|
|
- return false;
|
|
-
|
|
if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
|
|
&val))
|
|
return false;
|
|
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
|
|
index cd4e73aa98074..640031cbda7cc 100644
|
|
--- a/drivers/nvme/target/fc.c
|
|
+++ b/drivers/nvme/target/fc.c
|
|
@@ -2499,13 +2499,6 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
|
|
u32 xfrlen = be32_to_cpu(cmdiu->data_len);
|
|
int ret;
|
|
|
|
- /*
|
|
- * if there is no nvmet mapping to the targetport there
|
|
- * shouldn't be requests. just terminate them.
|
|
- */
|
|
- if (!tgtport->pe)
|
|
- goto transport_error;
|
|
-
|
|
/*
|
|
* Fused commands are currently not supported in the linux
|
|
* implementation.
|
|
@@ -2533,7 +2526,8 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport,
|
|
|
|
fod->req.cmd = &fod->cmdiubuf.sqe;
|
|
fod->req.cqe = &fod->rspiubuf.cqe;
|
|
- fod->req.port = tgtport->pe->port;
|
|
+ if (tgtport->pe)
|
|
+ fod->req.port = tgtport->pe->port;
|
|
|
|
/* clear any response payload */
|
|
memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf));
|
|
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
|
|
index f2e697000b96f..57ff31b6b1e47 100644
|
|
--- a/drivers/of/fdt.c
|
|
+++ b/drivers/of/fdt.c
|
|
@@ -501,11 +501,11 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
|
|
|
|
if (size &&
|
|
early_init_dt_reserve_memory_arch(base, size, nomap) == 0)
|
|
- pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n",
|
|
- uname, &base, (unsigned long)size / SZ_1M);
|
|
+ pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n",
|
|
+ uname, &base, (unsigned long)(size / SZ_1M));
|
|
else
|
|
- pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n",
|
|
- uname, &base, (unsigned long)size / SZ_1M);
|
|
+ pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n",
|
|
+ uname, &base, (unsigned long)(size / SZ_1M));
|
|
|
|
len -= t_len;
|
|
if (first) {
|
|
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
|
|
index a7fbc5e37e19e..6c95bbdf9265a 100644
|
|
--- a/drivers/of/of_reserved_mem.c
|
|
+++ b/drivers/of/of_reserved_mem.c
|
|
@@ -134,9 +134,9 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
|
|
ret = early_init_dt_alloc_reserved_memory_arch(size,
|
|
align, start, end, nomap, &base);
|
|
if (ret == 0) {
|
|
- pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n",
|
|
+ pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
|
|
uname, &base,
|
|
- (unsigned long)size / SZ_1M);
|
|
+ (unsigned long)(size / SZ_1M));
|
|
break;
|
|
}
|
|
len -= t_len;
|
|
@@ -146,8 +146,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
|
|
ret = early_init_dt_alloc_reserved_memory_arch(size, align,
|
|
0, 0, nomap, &base);
|
|
if (ret == 0)
|
|
- pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n",
|
|
- uname, &base, (unsigned long)size / SZ_1M);
|
|
+ pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
|
|
+ uname, &base, (unsigned long)(size / SZ_1M));
|
|
}
|
|
|
|
if (base == 0) {
|
|
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
|
|
index 03ed5cb1c4b25..d57c538bbb2db 100644
|
|
--- a/drivers/pci/controller/pci-hyperv.c
|
|
+++ b/drivers/pci/controller/pci-hyperv.c
|
|
@@ -3480,6 +3480,9 @@ static void __exit exit_hv_pci_drv(void)
|
|
|
|
static int __init init_hv_pci_drv(void)
|
|
{
|
|
+ if (!hv_is_hyperv_initialized())
|
|
+ return -ENODEV;
|
|
+
|
|
/* Set the invalid domain number's bit, so it will not be used */
|
|
set_bit(HVPCI_DOM_INVALID, hvpci_dom_map);
|
|
|
|
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
|
|
index 46defb1dcf867..bb019e3839888 100644
|
|
--- a/drivers/perf/arm-cmn.c
|
|
+++ b/drivers/perf/arm-cmn.c
|
|
@@ -1212,7 +1212,7 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn)
|
|
irq = cmn->dtc[i].irq;
|
|
for (j = i; j--; ) {
|
|
if (cmn->dtc[j].irq == irq) {
|
|
- cmn->dtc[j].irq_friend = j - i;
|
|
+ cmn->dtc[j].irq_friend = i - j;
|
|
goto next;
|
|
}
|
|
}
|
|
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
|
|
index 5274f7fe359eb..afa8efbdad8fa 100644
|
|
--- a/drivers/perf/arm_smmuv3_pmu.c
|
|
+++ b/drivers/perf/arm_smmuv3_pmu.c
|
|
@@ -275,7 +275,7 @@ static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
|
|
struct perf_event *event, int idx)
|
|
{
|
|
u32 span, sid;
|
|
- unsigned int num_ctrs = smmu_pmu->num_counters;
|
|
+ unsigned int cur_idx, num_ctrs = smmu_pmu->num_counters;
|
|
bool filter_en = !!get_filter_enable(event);
|
|
|
|
span = filter_en ? get_filter_span(event) :
|
|
@@ -283,17 +283,19 @@ static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
|
|
sid = filter_en ? get_filter_stream_id(event) :
|
|
SMMU_PMCG_DEFAULT_FILTER_SID;
|
|
|
|
- /* Support individual filter settings */
|
|
- if (!smmu_pmu->global_filter) {
|
|
+ cur_idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
|
|
+ /*
|
|
+ * Per-counter filtering, or scheduling the first globally-filtered
|
|
+ * event into an empty PMU so idx == 0 and it works out equivalent.
|
|
+ */
|
|
+ if (!smmu_pmu->global_filter || cur_idx == num_ctrs) {
|
|
smmu_pmu_set_event_filter(event, idx, span, sid);
|
|
return 0;
|
|
}
|
|
|
|
- /* Requested settings same as current global settings*/
|
|
- idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
|
|
- if (idx == num_ctrs ||
|
|
- smmu_pmu_check_global_filter(smmu_pmu->events[idx], event)) {
|
|
- smmu_pmu_set_event_filter(event, 0, span, sid);
|
|
+ /* Otherwise, must match whatever's currently scheduled */
|
|
+ if (smmu_pmu_check_global_filter(smmu_pmu->events[cur_idx], event)) {
|
|
+ smmu_pmu_set_evtyper(smmu_pmu, idx, get_event(event));
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
|
|
index 397540a4b799c..7f7bc0993670f 100644
|
|
--- a/drivers/perf/fsl_imx8_ddr_perf.c
|
|
+++ b/drivers/perf/fsl_imx8_ddr_perf.c
|
|
@@ -623,8 +623,10 @@ static int ddr_perf_probe(struct platform_device *pdev)
|
|
|
|
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d",
|
|
num);
|
|
- if (!name)
|
|
- return -ENOMEM;
|
|
+ if (!name) {
|
|
+ ret = -ENOMEM;
|
|
+ goto cpuhp_state_err;
|
|
+ }
|
|
|
|
pmu->devtype_data = of_device_get_match_data(&pdev->dev);
|
|
|
|
diff --git a/drivers/phy/socionext/phy-uniphier-pcie.c b/drivers/phy/socionext/phy-uniphier-pcie.c
|
|
index e4adab375c737..6bdbd1f214dd4 100644
|
|
--- a/drivers/phy/socionext/phy-uniphier-pcie.c
|
|
+++ b/drivers/phy/socionext/phy-uniphier-pcie.c
|
|
@@ -24,11 +24,13 @@
|
|
#define PORT_SEL_1 FIELD_PREP(PORT_SEL_MASK, 1)
|
|
|
|
#define PCL_PHY_TEST_I 0x2000
|
|
-#define PCL_PHY_TEST_O 0x2004
|
|
#define TESTI_DAT_MASK GENMASK(13, 6)
|
|
#define TESTI_ADR_MASK GENMASK(5, 1)
|
|
#define TESTI_WR_EN BIT(0)
|
|
|
|
+#define PCL_PHY_TEST_O 0x2004
|
|
+#define TESTO_DAT_MASK GENMASK(7, 0)
|
|
+
|
|
#define PCL_PHY_RESET 0x200c
|
|
#define PCL_PHY_RESET_N_MNMODE BIT(8) /* =1:manual */
|
|
#define PCL_PHY_RESET_N BIT(0) /* =1:deasssert */
|
|
@@ -77,11 +79,12 @@ static void uniphier_pciephy_set_param(struct uniphier_pciephy_priv *priv,
|
|
val = FIELD_PREP(TESTI_DAT_MASK, 1);
|
|
val |= FIELD_PREP(TESTI_ADR_MASK, reg);
|
|
uniphier_pciephy_testio_write(priv, val);
|
|
- val = readl(priv->base + PCL_PHY_TEST_O);
|
|
+ val = readl(priv->base + PCL_PHY_TEST_O) & TESTO_DAT_MASK;
|
|
|
|
/* update value */
|
|
- val &= ~FIELD_PREP(TESTI_DAT_MASK, mask);
|
|
- val = FIELD_PREP(TESTI_DAT_MASK, mask & param);
|
|
+ val &= ~mask;
|
|
+ val |= mask & param;
|
|
+ val = FIELD_PREP(TESTI_DAT_MASK, val);
|
|
val |= FIELD_PREP(TESTI_ADR_MASK, reg);
|
|
uniphier_pciephy_testio_write(priv, val);
|
|
uniphier_pciephy_testio_write(priv, val | TESTI_WR_EN);
|
|
diff --git a/drivers/phy/ti/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c
|
|
index 57adc08a89b2d..9fe6ea6fdae55 100644
|
|
--- a/drivers/phy/ti/phy-dm816x-usb.c
|
|
+++ b/drivers/phy/ti/phy-dm816x-usb.c
|
|
@@ -242,19 +242,28 @@ static int dm816x_usb_phy_probe(struct platform_device *pdev)
|
|
|
|
pm_runtime_enable(phy->dev);
|
|
generic_phy = devm_phy_create(phy->dev, NULL, &ops);
|
|
- if (IS_ERR(generic_phy))
|
|
- return PTR_ERR(generic_phy);
|
|
+ if (IS_ERR(generic_phy)) {
|
|
+ error = PTR_ERR(generic_phy);
|
|
+ goto clk_unprepare;
|
|
+ }
|
|
|
|
phy_set_drvdata(generic_phy, phy);
|
|
|
|
phy_provider = devm_of_phy_provider_register(phy->dev,
|
|
of_phy_simple_xlate);
|
|
- if (IS_ERR(phy_provider))
|
|
- return PTR_ERR(phy_provider);
|
|
+ if (IS_ERR(phy_provider)) {
|
|
+ error = PTR_ERR(phy_provider);
|
|
+ goto clk_unprepare;
|
|
+ }
|
|
|
|
usb_add_phy_dev(&phy->phy);
|
|
|
|
return 0;
|
|
+
|
|
+clk_unprepare:
|
|
+ pm_runtime_disable(phy->dev);
|
|
+ clk_unprepare(phy->refclk);
|
|
+ return error;
|
|
}
|
|
|
|
static int dm816x_usb_phy_remove(struct platform_device *pdev)
|
|
diff --git a/drivers/pinctrl/renesas/pfc-r8a7796.c b/drivers/pinctrl/renesas/pfc-r8a7796.c
|
|
index 55f0344a3d3e9..3878d6b0db149 100644
|
|
--- a/drivers/pinctrl/renesas/pfc-r8a7796.c
|
|
+++ b/drivers/pinctrl/renesas/pfc-r8a7796.c
|
|
@@ -68,6 +68,7 @@
|
|
PIN_NOGP_CFG(QSPI1_MOSI_IO0, "QSPI1_MOSI_IO0", fn, CFG_FLAGS), \
|
|
PIN_NOGP_CFG(QSPI1_SPCLK, "QSPI1_SPCLK", fn, CFG_FLAGS), \
|
|
PIN_NOGP_CFG(QSPI1_SSL, "QSPI1_SSL", fn, CFG_FLAGS), \
|
|
+ PIN_NOGP_CFG(PRESET_N, "PRESET#", fn, SH_PFC_PIN_CFG_PULL_DOWN),\
|
|
PIN_NOGP_CFG(RPC_INT_N, "RPC_INT#", fn, CFG_FLAGS), \
|
|
PIN_NOGP_CFG(RPC_RESET_N, "RPC_RESET#", fn, CFG_FLAGS), \
|
|
PIN_NOGP_CFG(RPC_WP_N, "RPC_WP#", fn, CFG_FLAGS), \
|
|
@@ -6109,7 +6110,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
|
|
[ 4] = RCAR_GP_PIN(6, 29), /* USB30_OVC */
|
|
[ 5] = RCAR_GP_PIN(6, 30), /* GP6_30 */
|
|
[ 6] = RCAR_GP_PIN(6, 31), /* GP6_31 */
|
|
- [ 7] = SH_PFC_PIN_NONE,
|
|
+ [ 7] = PIN_PRESET_N, /* PRESET# */
|
|
[ 8] = SH_PFC_PIN_NONE,
|
|
[ 9] = SH_PFC_PIN_NONE,
|
|
[10] = SH_PFC_PIN_NONE,
|
|
diff --git a/drivers/pinctrl/renesas/pfc-r8a77990.c b/drivers/pinctrl/renesas/pfc-r8a77990.c
|
|
index aed04a4c61163..240aadc4611fb 100644
|
|
--- a/drivers/pinctrl/renesas/pfc-r8a77990.c
|
|
+++ b/drivers/pinctrl/renesas/pfc-r8a77990.c
|
|
@@ -54,10 +54,10 @@
|
|
PIN_NOGP_CFG(FSCLKST_N, "FSCLKST_N", fn, CFG_FLAGS), \
|
|
PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, CFG_FLAGS), \
|
|
PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT_N", fn, CFG_FLAGS), \
|
|
- PIN_NOGP_CFG(TCK, "TCK", fn, CFG_FLAGS), \
|
|
- PIN_NOGP_CFG(TDI, "TDI", fn, CFG_FLAGS), \
|
|
- PIN_NOGP_CFG(TMS, "TMS", fn, CFG_FLAGS), \
|
|
- PIN_NOGP_CFG(TRST_N, "TRST_N", fn, CFG_FLAGS)
|
|
+ PIN_NOGP_CFG(TCK, "TCK", fn, SH_PFC_PIN_CFG_PULL_UP), \
|
|
+ PIN_NOGP_CFG(TDI, "TDI", fn, SH_PFC_PIN_CFG_PULL_UP), \
|
|
+ PIN_NOGP_CFG(TMS, "TMS", fn, SH_PFC_PIN_CFG_PULL_UP), \
|
|
+ PIN_NOGP_CFG(TRST_N, "TRST_N", fn, SH_PFC_PIN_CFG_PULL_UP)
|
|
|
|
/*
|
|
* F_() : just information
|
|
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
|
|
index 1d9fbabd02fb7..949ddeb673bc5 100644
|
|
--- a/drivers/platform/x86/asus-nb-wmi.c
|
|
+++ b/drivers/platform/x86/asus-nb-wmi.c
|
|
@@ -110,11 +110,6 @@ static struct quirk_entry quirk_asus_forceals = {
|
|
.wmi_force_als_set = true,
|
|
};
|
|
|
|
-static struct quirk_entry quirk_asus_vendor_backlight = {
|
|
- .wmi_backlight_power = true,
|
|
- .wmi_backlight_set_devstate = true,
|
|
-};
|
|
-
|
|
static struct quirk_entry quirk_asus_use_kbd_dock_devid = {
|
|
.use_kbd_dock_devid = true,
|
|
};
|
|
@@ -420,78 +415,6 @@ static const struct dmi_system_id asus_quirks[] = {
|
|
},
|
|
.driver_data = &quirk_asus_forceals,
|
|
},
|
|
- {
|
|
- .callback = dmi_matched,
|
|
- .ident = "ASUSTeK COMPUTER INC. GA401IH",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "GA401IH"),
|
|
- },
|
|
- .driver_data = &quirk_asus_vendor_backlight,
|
|
- },
|
|
- {
|
|
- .callback = dmi_matched,
|
|
- .ident = "ASUSTeK COMPUTER INC. GA401II",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "GA401II"),
|
|
- },
|
|
- .driver_data = &quirk_asus_vendor_backlight,
|
|
- },
|
|
- {
|
|
- .callback = dmi_matched,
|
|
- .ident = "ASUSTeK COMPUTER INC. GA401IU",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "GA401IU"),
|
|
- },
|
|
- .driver_data = &quirk_asus_vendor_backlight,
|
|
- },
|
|
- {
|
|
- .callback = dmi_matched,
|
|
- .ident = "ASUSTeK COMPUTER INC. GA401IV",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "GA401IV"),
|
|
- },
|
|
- .driver_data = &quirk_asus_vendor_backlight,
|
|
- },
|
|
- {
|
|
- .callback = dmi_matched,
|
|
- .ident = "ASUSTeK COMPUTER INC. GA401IVC",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "GA401IVC"),
|
|
- },
|
|
- .driver_data = &quirk_asus_vendor_backlight,
|
|
- },
|
|
- {
|
|
- .callback = dmi_matched,
|
|
- .ident = "ASUSTeK COMPUTER INC. GA502II",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "GA502II"),
|
|
- },
|
|
- .driver_data = &quirk_asus_vendor_backlight,
|
|
- },
|
|
- {
|
|
- .callback = dmi_matched,
|
|
- .ident = "ASUSTeK COMPUTER INC. GA502IU",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "GA502IU"),
|
|
- },
|
|
- .driver_data = &quirk_asus_vendor_backlight,
|
|
- },
|
|
- {
|
|
- .callback = dmi_matched,
|
|
- .ident = "ASUSTeK COMPUTER INC. GA502IV",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "GA502IV"),
|
|
- },
|
|
- .driver_data = &quirk_asus_vendor_backlight,
|
|
- },
|
|
{
|
|
.callback = dmi_matched,
|
|
.ident = "Asus Transformer T100TA / T100HA / T100CHI",
|
|
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
|
|
index fa7232ad8c395..352508d304675 100644
|
|
--- a/drivers/platform/x86/toshiba_acpi.c
|
|
+++ b/drivers/platform/x86/toshiba_acpi.c
|
|
@@ -2831,6 +2831,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
|
|
|
|
if (!dev->info_supported && !dev->system_event_supported) {
|
|
pr_warn("No hotkey query interface found\n");
|
|
+ error = -EINVAL;
|
|
goto err_remove_filter;
|
|
}
|
|
|
|
diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
|
|
index 3743d895399e7..99260915122c0 100644
|
|
--- a/drivers/platform/x86/touchscreen_dmi.c
|
|
+++ b/drivers/platform/x86/touchscreen_dmi.c
|
|
@@ -299,6 +299,35 @@ static const struct ts_dmi_data estar_beauty_hd_data = {
|
|
.properties = estar_beauty_hd_props,
|
|
};
|
|
|
|
+/* Generic props + data for upside-down mounted GDIX1001 touchscreens */
|
|
+static const struct property_entry gdix1001_upside_down_props[] = {
|
|
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
|
|
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
|
|
+ { }
|
|
+};
|
|
+
|
|
+static const struct ts_dmi_data gdix1001_00_upside_down_data = {
|
|
+ .acpi_name = "GDIX1001:00",
|
|
+ .properties = gdix1001_upside_down_props,
|
|
+};
|
|
+
|
|
+static const struct ts_dmi_data gdix1001_01_upside_down_data = {
|
|
+ .acpi_name = "GDIX1001:01",
|
|
+ .properties = gdix1001_upside_down_props,
|
|
+};
|
|
+
|
|
+static const struct property_entry glavey_tm800a550l_props[] = {
|
|
+ PROPERTY_ENTRY_STRING("firmware-name", "gt912-glavey-tm800a550l.fw"),
|
|
+ PROPERTY_ENTRY_STRING("goodix,config-name", "gt912-glavey-tm800a550l.cfg"),
|
|
+ PROPERTY_ENTRY_U32("goodix,main-clk", 54),
|
|
+ { }
|
|
+};
|
|
+
|
|
+static const struct ts_dmi_data glavey_tm800a550l_data = {
|
|
+ .acpi_name = "GDIX1001:00",
|
|
+ .properties = glavey_tm800a550l_props,
|
|
+};
|
|
+
|
|
static const struct property_entry gp_electronic_t701_props[] = {
|
|
PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
|
|
PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
|
|
@@ -995,6 +1024,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),
|
|
},
|
|
},
|
|
+ { /* Glavey TM800A550L */
|
|
+ .driver_data = (void *)&glavey_tm800a550l_data,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
|
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
|
|
+ /* Above strings are too generic, also match on BIOS version */
|
|
+ DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
|
|
+ },
|
|
+ },
|
|
{
|
|
/* GP-electronic T701 */
|
|
.driver_data = (void *)&gp_electronic_t701_data,
|
|
@@ -1268,6 +1306,24 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
|
DMI_MATCH(DMI_BOARD_NAME, "X3 Plus"),
|
|
},
|
|
},
|
|
+ {
|
|
+ /* Teclast X89 (Android version / BIOS) */
|
|
+ .driver_data = (void *)&gdix1001_00_upside_down_data,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "WISKY"),
|
|
+ DMI_MATCH(DMI_BOARD_NAME, "3G062i"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
+ /* Teclast X89 (Windows version / BIOS) */
|
|
+ .driver_data = (void *)&gdix1001_01_upside_down_data,
|
|
+ .matches = {
|
|
+ /* tPAD is too generic, also match on bios date */
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
|
|
+ DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
|
|
+ DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"),
|
|
+ },
|
|
+ },
|
|
{
|
|
/* Teclast X98 Plus II */
|
|
.driver_data = (void *)&teclast_x98plus2_data,
|
|
@@ -1276,6 +1332,19 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
|
|
},
|
|
},
|
|
+ {
|
|
+ /* Teclast X98 Pro */
|
|
+ .driver_data = (void *)&gdix1001_00_upside_down_data,
|
|
+ .matches = {
|
|
+ /*
|
|
+ * Only match BIOS date, because the manufacturers
|
|
+ * BIOS does not report the board name at all
|
|
+ * (sometimes)...
|
|
+ */
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
|
|
+ DMI_MATCH(DMI_BIOS_DATE, "10/28/2015"),
|
|
+ },
|
|
+ },
|
|
{
|
|
/* Trekstor Primebook C11 */
|
|
.driver_data = (void *)&trekstor_primebook_c11_data,
|
|
@@ -1351,6 +1420,22 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "VINGA Twizzle J116"),
|
|
},
|
|
},
|
|
+ {
|
|
+ /* "WinBook TW100" */
|
|
+ .driver_data = (void *)&gdix1001_00_upside_down_data,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "TW100")
|
|
+ }
|
|
+ },
|
|
+ {
|
|
+ /* WinBook TW700 */
|
|
+ .driver_data = (void *)&gdix1001_00_upside_down_data,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "TW700")
|
|
+ },
|
|
+ },
|
|
{
|
|
/* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */
|
|
.driver_data = (void *)&chuwi_vi8_data,
|
|
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
|
|
index e18d291c7f21c..23fa429ebe760 100644
|
|
--- a/drivers/regulator/da9052-regulator.c
|
|
+++ b/drivers/regulator/da9052-regulator.c
|
|
@@ -250,7 +250,8 @@ static int da9052_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
|
|
case DA9052_ID_BUCK3:
|
|
case DA9052_ID_LDO2:
|
|
case DA9052_ID_LDO3:
|
|
- ret = (new_sel - old_sel) * info->step_uV / 6250;
|
|
+ ret = DIV_ROUND_UP(abs(new_sel - old_sel) * info->step_uV,
|
|
+ 6250);
|
|
break;
|
|
}
|
|
|
|
diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c
|
|
index 1684faf82ed25..94f02f3099dd4 100644
|
|
--- a/drivers/regulator/fan53880.c
|
|
+++ b/drivers/regulator/fan53880.c
|
|
@@ -79,7 +79,7 @@ static const struct regulator_desc fan53880_regulators[] = {
|
|
.n_linear_ranges = 2,
|
|
.n_voltages = 0xf8,
|
|
.vsel_reg = FAN53880_BUCKVOUT,
|
|
- .vsel_mask = 0x7f,
|
|
+ .vsel_mask = 0xff,
|
|
.enable_reg = FAN53880_ENABLE,
|
|
.enable_mask = 0x10,
|
|
.enable_time = 480,
|
|
diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c
|
|
index ac2ee2030211a..b44f492a2b832 100644
|
|
--- a/drivers/regulator/hi655x-regulator.c
|
|
+++ b/drivers/regulator/hi655x-regulator.c
|
|
@@ -72,7 +72,7 @@ enum hi655x_regulator_id {
|
|
static int hi655x_is_enabled(struct regulator_dev *rdev)
|
|
{
|
|
unsigned int value = 0;
|
|
- struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
|
|
+ const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
|
|
|
|
regmap_read(rdev->regmap, regulator->status_reg, &value);
|
|
return (value & rdev->desc->enable_mask);
|
|
@@ -80,7 +80,7 @@ static int hi655x_is_enabled(struct regulator_dev *rdev)
|
|
|
|
static int hi655x_disable(struct regulator_dev *rdev)
|
|
{
|
|
- struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
|
|
+ const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
|
|
|
|
return regmap_write(rdev->regmap, regulator->disable_reg,
|
|
rdev->desc->enable_mask);
|
|
@@ -169,7 +169,6 @@ static const struct hi655x_regulator regulators[] = {
|
|
static int hi655x_regulator_probe(struct platform_device *pdev)
|
|
{
|
|
unsigned int i;
|
|
- struct hi655x_regulator *regulator;
|
|
struct hi655x_pmic *pmic;
|
|
struct regulator_config config = { };
|
|
struct regulator_dev *rdev;
|
|
@@ -180,22 +179,17 @@ static int hi655x_regulator_probe(struct platform_device *pdev)
|
|
return -ENODEV;
|
|
}
|
|
|
|
- regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL);
|
|
- if (!regulator)
|
|
- return -ENOMEM;
|
|
-
|
|
- platform_set_drvdata(pdev, regulator);
|
|
-
|
|
config.dev = pdev->dev.parent;
|
|
config.regmap = pmic->regmap;
|
|
- config.driver_data = regulator;
|
|
for (i = 0; i < ARRAY_SIZE(regulators); i++) {
|
|
+ config.driver_data = (void *) ®ulators[i];
|
|
+
|
|
rdev = devm_regulator_register(&pdev->dev,
|
|
®ulators[i].rdesc,
|
|
&config);
|
|
if (IS_ERR(rdev)) {
|
|
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
|
- regulator->rdesc.name);
|
|
+ regulators[i].rdesc.name);
|
|
return PTR_ERR(rdev);
|
|
}
|
|
}
|
|
diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c
|
|
index 13cb6ac9a8929..1d4eb5dc4fac8 100644
|
|
--- a/drivers/regulator/mt6358-regulator.c
|
|
+++ b/drivers/regulator/mt6358-regulator.c
|
|
@@ -457,7 +457,7 @@ static struct mt6358_regulator_info mt6358_regulators[] = {
|
|
MT6358_REG_FIXED("ldo_vaud28", VAUD28,
|
|
MT6358_LDO_VAUD28_CON0, 0, 2800000),
|
|
MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx,
|
|
- MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0x10, 0),
|
|
+ MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0xf, 0),
|
|
MT6358_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx,
|
|
MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00, 8),
|
|
MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx,
|
|
diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c
|
|
index 2e02e26b516c4..e75b0973e3256 100644
|
|
--- a/drivers/regulator/uniphier-regulator.c
|
|
+++ b/drivers/regulator/uniphier-regulator.c
|
|
@@ -201,6 +201,7 @@ static const struct of_device_id uniphier_regulator_match[] = {
|
|
},
|
|
{ /* Sentinel */ },
|
|
};
|
|
+MODULE_DEVICE_TABLE(of, uniphier_regulator_match);
|
|
|
|
static struct platform_driver uniphier_regulator_driver = {
|
|
.probe = uniphier_regulator_probe,
|
|
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
|
|
index d774aa18f57a5..d096b58cd06c1 100644
|
|
--- a/drivers/rtc/rtc-stm32.c
|
|
+++ b/drivers/rtc/rtc-stm32.c
|
|
@@ -754,7 +754,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
|
|
|
ret = clk_prepare_enable(rtc->rtc_ck);
|
|
if (ret)
|
|
- goto err;
|
|
+ goto err_no_rtc_ck;
|
|
|
|
if (rtc->data->need_dbp)
|
|
regmap_update_bits(rtc->dbp, rtc->dbp_reg,
|
|
@@ -830,10 +830,12 @@ static int stm32_rtc_probe(struct platform_device *pdev)
|
|
}
|
|
|
|
return 0;
|
|
+
|
|
err:
|
|
+ clk_disable_unprepare(rtc->rtc_ck);
|
|
+err_no_rtc_ck:
|
|
if (rtc->data->has_pclk)
|
|
clk_disable_unprepare(rtc->pclk);
|
|
- clk_disable_unprepare(rtc->rtc_ck);
|
|
|
|
if (rtc->data->need_dbp)
|
|
regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
|
|
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
|
|
index dfcbe54591fbd..93e22785a0e09 100644
|
|
--- a/drivers/s390/cio/chp.c
|
|
+++ b/drivers/s390/cio/chp.c
|
|
@@ -255,6 +255,9 @@ static ssize_t chp_status_write(struct device *dev,
|
|
if (!num_args)
|
|
return count;
|
|
|
|
+ /* Wait until previous actions have settled. */
|
|
+ css_wait_for_slow_path();
|
|
+
|
|
if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
|
|
mutex_lock(&cp->lock);
|
|
error = s390_vary_chpid(cp->chpid, 1);
|
|
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
|
|
index fc06a40021688..93aa7eabe8b1f 100644
|
|
--- a/drivers/s390/cio/chsc.c
|
|
+++ b/drivers/s390/cio/chsc.c
|
|
@@ -757,8 +757,6 @@ int chsc_chp_vary(struct chp_id chpid, int on)
|
|
{
|
|
struct channel_path *chp = chpid_to_chp(chpid);
|
|
|
|
- /* Wait until previous actions have settled. */
|
|
- css_wait_for_slow_path();
|
|
/*
|
|
* Redo PathVerification on the devices the chpid connects to
|
|
*/
|
|
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
|
|
index 24ace18240480..ec8a621d232d6 100644
|
|
--- a/drivers/scsi/FlashPoint.c
|
|
+++ b/drivers/scsi/FlashPoint.c
|
|
@@ -40,7 +40,7 @@ struct sccb_mgr_info {
|
|
u16 si_per_targ_ultra_nego;
|
|
u16 si_per_targ_no_disc;
|
|
u16 si_per_targ_wide_nego;
|
|
- u16 si_flags;
|
|
+ u16 si_mflags;
|
|
unsigned char si_card_family;
|
|
unsigned char si_bustype;
|
|
unsigned char si_card_model[3];
|
|
@@ -1073,22 +1073,22 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
|
|
ScamFlg =
|
|
(unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
|
|
|
|
- pCardInfo->si_flags = 0x0000;
|
|
+ pCardInfo->si_mflags = 0x0000;
|
|
|
|
if (i & 0x01)
|
|
- pCardInfo->si_flags |= SCSI_PARITY_ENA;
|
|
+ pCardInfo->si_mflags |= SCSI_PARITY_ENA;
|
|
|
|
if (!(i & 0x02))
|
|
- pCardInfo->si_flags |= SOFT_RESET;
|
|
+ pCardInfo->si_mflags |= SOFT_RESET;
|
|
|
|
if (i & 0x10)
|
|
- pCardInfo->si_flags |= EXTENDED_TRANSLATION;
|
|
+ pCardInfo->si_mflags |= EXTENDED_TRANSLATION;
|
|
|
|
if (ScamFlg & SCAM_ENABLED)
|
|
- pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
|
|
+ pCardInfo->si_mflags |= FLAG_SCAM_ENABLED;
|
|
|
|
if (ScamFlg & SCAM_LEVEL2)
|
|
- pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
|
|
+ pCardInfo->si_mflags |= FLAG_SCAM_LEVEL2;
|
|
|
|
j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
|
|
if (i & 0x04) {
|
|
@@ -1104,7 +1104,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
|
|
|
|
if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
|
|
|
|
- pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
|
|
+ pCardInfo->si_mflags |= SUPPORT_16TAR_32LUN;
|
|
|
|
pCardInfo->si_card_family = HARPOON_FAMILY;
|
|
pCardInfo->si_bustype = BUSTYPE_PCI;
|
|
@@ -1140,15 +1140,15 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
|
|
|
|
if (pCardInfo->si_card_model[1] == '3') {
|
|
if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
|
|
- pCardInfo->si_flags |= LOW_BYTE_TERM;
|
|
+ pCardInfo->si_mflags |= LOW_BYTE_TERM;
|
|
} else if (pCardInfo->si_card_model[2] == '0') {
|
|
temp = RD_HARPOON(ioport + hp_xfer_pad);
|
|
WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
|
|
if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
|
|
- pCardInfo->si_flags |= LOW_BYTE_TERM;
|
|
+ pCardInfo->si_mflags |= LOW_BYTE_TERM;
|
|
WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
|
|
if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
|
|
- pCardInfo->si_flags |= HIGH_BYTE_TERM;
|
|
+ pCardInfo->si_mflags |= HIGH_BYTE_TERM;
|
|
WR_HARPOON(ioport + hp_xfer_pad, temp);
|
|
} else {
|
|
temp = RD_HARPOON(ioport + hp_ee_ctrl);
|
|
@@ -1166,9 +1166,9 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
|
|
WR_HARPOON(ioport + hp_ee_ctrl, temp);
|
|
WR_HARPOON(ioport + hp_xfer_pad, temp2);
|
|
if (!(temp3 & BIT(7)))
|
|
- pCardInfo->si_flags |= LOW_BYTE_TERM;
|
|
+ pCardInfo->si_mflags |= LOW_BYTE_TERM;
|
|
if (!(temp3 & BIT(6)))
|
|
- pCardInfo->si_flags |= HIGH_BYTE_TERM;
|
|
+ pCardInfo->si_mflags |= HIGH_BYTE_TERM;
|
|
}
|
|
|
|
ARAM_ACCESS(ioport);
|
|
@@ -1275,7 +1275,7 @@ static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
|
|
WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
|
|
CurrCard->ourId = pCardInfo->si_id;
|
|
|
|
- i = (unsigned char)pCardInfo->si_flags;
|
|
+ i = (unsigned char)pCardInfo->si_mflags;
|
|
if (i & SCSI_PARITY_ENA)
|
|
WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
|
|
|
|
@@ -1289,14 +1289,14 @@ static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
|
|
j |= SCSI_TERM_ENA_H;
|
|
WR_HARPOON(ioport + hp_ee_ctrl, j);
|
|
|
|
- if (!(pCardInfo->si_flags & SOFT_RESET)) {
|
|
+ if (!(pCardInfo->si_mflags & SOFT_RESET)) {
|
|
|
|
FPT_sresb(ioport, thisCard);
|
|
|
|
FPT_scini(thisCard, pCardInfo->si_id, 0);
|
|
}
|
|
|
|
- if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
|
|
+ if (pCardInfo->si_mflags & POST_ALL_UNDERRRUNS)
|
|
CurrCard->globalFlags |= F_NO_FILTER;
|
|
|
|
if (pCurrNvRam) {
|
|
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
index 5f845d7094fcc..008f734698f71 100644
|
|
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
@@ -6007,8 +6007,10 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
|
|
handle, parent_handle,
|
|
(u64)sas_expander->sas_address, sas_expander->num_phys);
|
|
|
|
- if (!sas_expander->num_phys)
|
|
+ if (!sas_expander->num_phys) {
|
|
+ rc = -1;
|
|
goto out_fail;
|
|
+ }
|
|
sas_expander->phy = kcalloc(sas_expander->num_phys,
|
|
sizeof(struct _sas_phy), GFP_KERNEL);
|
|
if (!sas_expander->phy) {
|
|
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
|
|
index 31d7a6ddc9db7..a045d00509d5c 100644
|
|
--- a/drivers/scsi/scsi_lib.c
|
|
+++ b/drivers/scsi/scsi_lib.c
|
|
@@ -760,6 +760,7 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
|
|
case 0x07: /* operation in progress */
|
|
case 0x08: /* Long write in progress */
|
|
case 0x09: /* self test in progress */
|
|
+ case 0x11: /* notify (enable spinup) required */
|
|
case 0x14: /* space allocation in progress */
|
|
case 0x1a: /* start stop unit in progress */
|
|
case 0x1b: /* sanitize in progress */
|
|
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
|
|
index c53c3f9fa526a..c520239082fc6 100644
|
|
--- a/drivers/scsi/scsi_transport_iscsi.c
|
|
+++ b/drivers/scsi/scsi_transport_iscsi.c
|
|
@@ -1979,6 +1979,8 @@ static void __iscsi_unblock_session(struct work_struct *work)
|
|
*/
|
|
void iscsi_unblock_session(struct iscsi_cls_session *session)
|
|
{
|
|
+ flush_work(&session->block_work);
|
|
+
|
|
queue_work(iscsi_eh_timer_workq, &session->unblock_work);
|
|
/*
|
|
* Blocking the session can be done from any context so we only
|
|
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
|
|
index a418c3c7001c0..304ff2ee7d75a 100644
|
|
--- a/drivers/soundwire/stream.c
|
|
+++ b/drivers/soundwire/stream.c
|
|
@@ -422,7 +422,6 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
|
|
struct completion *port_ready;
|
|
struct sdw_dpn_prop *dpn_prop;
|
|
struct sdw_prepare_ch prep_ch;
|
|
- unsigned int time_left;
|
|
bool intr = false;
|
|
int ret = 0, val;
|
|
u32 addr;
|
|
@@ -479,15 +478,15 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus,
|
|
|
|
/* Wait for completion on port ready */
|
|
port_ready = &s_rt->slave->port_ready[prep_ch.num];
|
|
- time_left = wait_for_completion_timeout(port_ready,
|
|
- msecs_to_jiffies(dpn_prop->ch_prep_timeout));
|
|
+ wait_for_completion_timeout(port_ready,
|
|
+ msecs_to_jiffies(dpn_prop->ch_prep_timeout));
|
|
|
|
val = sdw_read(s_rt->slave, SDW_DPN_PREPARESTATUS(p_rt->num));
|
|
- val &= p_rt->ch_mask;
|
|
- if (!time_left || val) {
|
|
+ if ((val < 0) || (val & p_rt->ch_mask)) {
|
|
+ ret = (val < 0) ? val : -ETIMEDOUT;
|
|
dev_err(&s_rt->slave->dev,
|
|
- "Chn prep failed for port:%d\n", prep_ch.num);
|
|
- return -ETIMEDOUT;
|
|
+ "Chn prep failed for port %d: %d\n", prep_ch.num, ret);
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c
|
|
index df981e55c24c9..89b91cdfb2a54 100644
|
|
--- a/drivers/spi/spi-loopback-test.c
|
|
+++ b/drivers/spi/spi-loopback-test.c
|
|
@@ -874,7 +874,7 @@ static int spi_test_run_iter(struct spi_device *spi,
|
|
test.transfers[i].len = len;
|
|
if (test.transfers[i].tx_buf)
|
|
test.transfers[i].tx_buf += tx_off;
|
|
- if (test.transfers[i].tx_buf)
|
|
+ if (test.transfers[i].rx_buf)
|
|
test.transfers[i].rx_buf += rx_off;
|
|
}
|
|
|
|
diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
|
|
index ecba6b4a5d85d..b2c4621db34d7 100644
|
|
--- a/drivers/spi/spi-meson-spicc.c
|
|
+++ b/drivers/spi/spi-meson-spicc.c
|
|
@@ -725,7 +725,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|
ret = clk_prepare_enable(spicc->pclk);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "pclk clock enable failed\n");
|
|
- goto out_master;
|
|
+ goto out_core_clk;
|
|
}
|
|
|
|
device_reset_optional(&pdev->dev);
|
|
@@ -752,7 +752,7 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|
ret = meson_spicc_clk_init(spicc);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "clock registration failed\n");
|
|
- goto out_master;
|
|
+ goto out_clk;
|
|
}
|
|
|
|
ret = devm_spi_register_master(&pdev->dev, master);
|
|
@@ -764,9 +764,11 @@ static int meson_spicc_probe(struct platform_device *pdev)
|
|
return 0;
|
|
|
|
out_clk:
|
|
- clk_disable_unprepare(spicc->core);
|
|
clk_disable_unprepare(spicc->pclk);
|
|
|
|
+out_core_clk:
|
|
+ clk_disable_unprepare(spicc->core);
|
|
+
|
|
out_master:
|
|
spi_master_put(master);
|
|
|
|
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c
|
|
index ccd817ee4917b..0d0cd061d3563 100644
|
|
--- a/drivers/spi/spi-omap-100k.c
|
|
+++ b/drivers/spi/spi-omap-100k.c
|
|
@@ -241,7 +241,7 @@ static int omap1_spi100k_setup_transfer(struct spi_device *spi,
|
|
else
|
|
word_len = spi->bits_per_word;
|
|
|
|
- if (spi->bits_per_word > 32)
|
|
+ if (word_len > 32)
|
|
return -EINVAL;
|
|
cs->word_len = word_len;
|
|
|
|
diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c
|
|
index 19238e1b76b44..803d92f8d0316 100644
|
|
--- a/drivers/spi/spi-sun6i.c
|
|
+++ b/drivers/spi/spi-sun6i.c
|
|
@@ -290,6 +290,10 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
|
|
}
|
|
|
|
sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg);
|
|
+ /* Finally enable the bus - doing so before might raise SCK to HIGH */
|
|
+ reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG);
|
|
+ reg |= SUN6I_GBL_CTL_BUS_ENABLE;
|
|
+ sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg);
|
|
|
|
/* Setup the transfer now... */
|
|
if (sspi->tx_buf)
|
|
@@ -398,7 +402,7 @@ static int sun6i_spi_runtime_resume(struct device *dev)
|
|
}
|
|
|
|
sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG,
|
|
- SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
|
|
+ SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP);
|
|
|
|
return 0;
|
|
|
|
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
|
|
index b459e369079f8..7fb020a1d66aa 100644
|
|
--- a/drivers/spi/spi-topcliff-pch.c
|
|
+++ b/drivers/spi/spi-topcliff-pch.c
|
|
@@ -580,8 +580,10 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw)
|
|
data->pkt_tx_buff = kzalloc(size, GFP_KERNEL);
|
|
if (data->pkt_tx_buff != NULL) {
|
|
data->pkt_rx_buff = kzalloc(size, GFP_KERNEL);
|
|
- if (!data->pkt_rx_buff)
|
|
+ if (!data->pkt_rx_buff) {
|
|
kfree(data->pkt_tx_buff);
|
|
+ data->pkt_tx_buff = NULL;
|
|
+ }
|
|
}
|
|
|
|
if (!data->pkt_rx_buff) {
|
|
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
|
|
index 0cf67de741e78..8c261eac2cee5 100644
|
|
--- a/drivers/spi/spi.c
|
|
+++ b/drivers/spi/spi.c
|
|
@@ -2050,6 +2050,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
|
|
/* Store a pointer to the node in the device structure */
|
|
of_node_get(nc);
|
|
spi->dev.of_node = nc;
|
|
+ spi->dev.fwnode = of_fwnode_handle(nc);
|
|
|
|
/* Register the new device */
|
|
rc = spi_add_device(spi);
|
|
@@ -2613,9 +2614,10 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr)
|
|
native_cs_mask |= BIT(i);
|
|
}
|
|
|
|
- ctlr->unused_native_cs = ffz(native_cs_mask);
|
|
- if (num_cs_gpios && ctlr->max_native_cs &&
|
|
- ctlr->unused_native_cs >= ctlr->max_native_cs) {
|
|
+ ctlr->unused_native_cs = ffs(~native_cs_mask) - 1;
|
|
+
|
|
+ if ((ctlr->flags & SPI_MASTER_GPIO_SS) && num_cs_gpios &&
|
|
+ ctlr->max_native_cs && ctlr->unused_native_cs >= ctlr->max_native_cs) {
|
|
dev_err(dev, "No unused native chip select available\n");
|
|
return -EINVAL;
|
|
}
|
|
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
|
|
index f49ab1aa2149a..4161e5d1f276e 100644
|
|
--- a/drivers/ssb/scan.c
|
|
+++ b/drivers/ssb/scan.c
|
|
@@ -325,6 +325,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
|
|
if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
|
|
pr_err("More than %d ssb cores found (%d)\n",
|
|
SSB_MAX_NR_CORES, bus->nr_devices);
|
|
+ err = -EINVAL;
|
|
goto err_unmap;
|
|
}
|
|
if (bus->bustype == SSB_BUSTYPE_SSB) {
|
|
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
|
|
index 7fe0afb42234f..66c5c2169704b 100644
|
|
--- a/drivers/ssb/sdio.c
|
|
+++ b/drivers/ssb/sdio.c
|
|
@@ -411,7 +411,6 @@ static void ssb_sdio_block_write(struct ssb_device *dev, const void *buffer,
|
|
sdio_claim_host(bus->host_sdio);
|
|
if (unlikely(ssb_sdio_switch_core(bus, dev))) {
|
|
error = -EIO;
|
|
- memset((void *)buffer, 0xff, count);
|
|
goto err_out;
|
|
}
|
|
offset |= bus->sdio_sbaddr & 0xffff;
|
|
diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c
|
|
index eeeeec97ad278..b545c2ca80a41 100644
|
|
--- a/drivers/staging/fbtft/fb_agm1264k-fl.c
|
|
+++ b/drivers/staging/fbtft/fb_agm1264k-fl.c
|
|
@@ -84,9 +84,9 @@ static void reset(struct fbtft_par *par)
|
|
|
|
dev_dbg(par->info->device, "%s()\n", __func__);
|
|
|
|
- gpiod_set_value(par->gpio.reset, 0);
|
|
- udelay(20);
|
|
gpiod_set_value(par->gpio.reset, 1);
|
|
+ udelay(20);
|
|
+ gpiod_set_value(par->gpio.reset, 0);
|
|
mdelay(120);
|
|
}
|
|
|
|
@@ -194,12 +194,12 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
|
|
/* select chip */
|
|
if (*buf) {
|
|
/* cs1 */
|
|
- gpiod_set_value(par->CS0, 1);
|
|
- gpiod_set_value(par->CS1, 0);
|
|
- } else {
|
|
- /* cs0 */
|
|
gpiod_set_value(par->CS0, 0);
|
|
gpiod_set_value(par->CS1, 1);
|
|
+ } else {
|
|
+ /* cs0 */
|
|
+ gpiod_set_value(par->CS0, 1);
|
|
+ gpiod_set_value(par->CS1, 0);
|
|
}
|
|
|
|
gpiod_set_value(par->RS, 0); /* RS->0 (command mode) */
|
|
@@ -397,8 +397,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
|
|
}
|
|
kfree(convert_buf);
|
|
|
|
- gpiod_set_value(par->CS0, 1);
|
|
- gpiod_set_value(par->CS1, 1);
|
|
+ gpiod_set_value(par->CS0, 0);
|
|
+ gpiod_set_value(par->CS1, 0);
|
|
|
|
return ret;
|
|
}
|
|
@@ -419,10 +419,10 @@ static int write(struct fbtft_par *par, void *buf, size_t len)
|
|
for (i = 0; i < 8; ++i)
|
|
gpiod_set_value(par->gpio.db[i], data & (1 << i));
|
|
/* set E */
|
|
- gpiod_set_value(par->EPIN, 1);
|
|
+ gpiod_set_value(par->EPIN, 0);
|
|
udelay(5);
|
|
/* unset E - write */
|
|
- gpiod_set_value(par->EPIN, 0);
|
|
+ gpiod_set_value(par->EPIN, 1);
|
|
udelay(1);
|
|
}
|
|
|
|
diff --git a/drivers/staging/fbtft/fb_bd663474.c b/drivers/staging/fbtft/fb_bd663474.c
|
|
index e2c7646588f8c..1629c2c440a97 100644
|
|
--- a/drivers/staging/fbtft/fb_bd663474.c
|
|
+++ b/drivers/staging/fbtft/fb_bd663474.c
|
|
@@ -12,7 +12,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include "fbtft.h"
|
|
@@ -24,9 +23,6 @@
|
|
|
|
static int init_display(struct fbtft_par *par)
|
|
{
|
|
- if (par->gpio.cs)
|
|
- gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
|
|
-
|
|
par->fbtftops.reset(par);
|
|
|
|
/* Initialization sequence from Lib_UTFT */
|
|
diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c
|
|
index 05648c3ffe474..6582a2c90aafc 100644
|
|
--- a/drivers/staging/fbtft/fb_ili9163.c
|
|
+++ b/drivers/staging/fbtft/fb_ili9163.c
|
|
@@ -11,7 +11,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/delay.h>
|
|
#include <video/mipi_display.h>
|
|
|
|
@@ -77,9 +76,6 @@ static int init_display(struct fbtft_par *par)
|
|
{
|
|
par->fbtftops.reset(par);
|
|
|
|
- if (par->gpio.cs)
|
|
- gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
|
|
-
|
|
write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */
|
|
mdelay(500);
|
|
write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE); /* exit sleep */
|
|
diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c
|
|
index f2e72d14431db..a8f4c618b754c 100644
|
|
--- a/drivers/staging/fbtft/fb_ili9320.c
|
|
+++ b/drivers/staging/fbtft/fb_ili9320.c
|
|
@@ -8,7 +8,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/delay.h>
|
|
|
|
diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c
|
|
index c9aa4cb431236..16d3b17ca2798 100644
|
|
--- a/drivers/staging/fbtft/fb_ili9325.c
|
|
+++ b/drivers/staging/fbtft/fb_ili9325.c
|
|
@@ -10,7 +10,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include "fbtft.h"
|
|
@@ -85,9 +84,6 @@ static int init_display(struct fbtft_par *par)
|
|
{
|
|
par->fbtftops.reset(par);
|
|
|
|
- if (par->gpio.cs)
|
|
- gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
|
|
-
|
|
bt &= 0x07;
|
|
vc &= 0x07;
|
|
vrh &= 0x0f;
|
|
diff --git a/drivers/staging/fbtft/fb_ili9340.c b/drivers/staging/fbtft/fb_ili9340.c
|
|
index 415183c7054a8..704236bcaf3ff 100644
|
|
--- a/drivers/staging/fbtft/fb_ili9340.c
|
|
+++ b/drivers/staging/fbtft/fb_ili9340.c
|
|
@@ -8,7 +8,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/delay.h>
|
|
#include <video/mipi_display.h>
|
|
|
|
diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c
|
|
index 8c7de32903434..62f27172f8449 100644
|
|
--- a/drivers/staging/fbtft/fb_s6d1121.c
|
|
+++ b/drivers/staging/fbtft/fb_s6d1121.c
|
|
@@ -12,7 +12,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include "fbtft.h"
|
|
@@ -29,9 +28,6 @@ static int init_display(struct fbtft_par *par)
|
|
{
|
|
par->fbtftops.reset(par);
|
|
|
|
- if (par->gpio.cs)
|
|
- gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
|
|
-
|
|
/* Initialization sequence from Lib_UTFT */
|
|
|
|
write_reg(par, 0x0011, 0x2004);
|
|
diff --git a/drivers/staging/fbtft/fb_sh1106.c b/drivers/staging/fbtft/fb_sh1106.c
|
|
index 6f7249493ea3b..7b9ab39e1c1a8 100644
|
|
--- a/drivers/staging/fbtft/fb_sh1106.c
|
|
+++ b/drivers/staging/fbtft/fb_sh1106.c
|
|
@@ -9,7 +9,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include "fbtft.h"
|
|
diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c
|
|
index 7a3fe022cc69d..f27bab38b3ec4 100644
|
|
--- a/drivers/staging/fbtft/fb_ssd1289.c
|
|
+++ b/drivers/staging/fbtft/fb_ssd1289.c
|
|
@@ -10,7 +10,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
|
|
#include "fbtft.h"
|
|
|
|
@@ -28,9 +27,6 @@ static int init_display(struct fbtft_par *par)
|
|
{
|
|
par->fbtftops.reset(par);
|
|
|
|
- if (par->gpio.cs)
|
|
- gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
|
|
-
|
|
write_reg(par, 0x00, 0x0001);
|
|
write_reg(par, 0x03, 0xA8A4);
|
|
write_reg(par, 0x0C, 0x0000);
|
|
diff --git a/drivers/staging/fbtft/fb_ssd1325.c b/drivers/staging/fbtft/fb_ssd1325.c
|
|
index 8a3140d41d8bb..796a2ac3e1948 100644
|
|
--- a/drivers/staging/fbtft/fb_ssd1325.c
|
|
+++ b/drivers/staging/fbtft/fb_ssd1325.c
|
|
@@ -35,8 +35,6 @@ static int init_display(struct fbtft_par *par)
|
|
{
|
|
par->fbtftops.reset(par);
|
|
|
|
- gpiod_set_value(par->gpio.cs, 0);
|
|
-
|
|
write_reg(par, 0xb3);
|
|
write_reg(par, 0xf0);
|
|
write_reg(par, 0xae);
|
|
diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c
|
|
index 37622c9462aa7..ec5eced7f8cbd 100644
|
|
--- a/drivers/staging/fbtft/fb_ssd1331.c
|
|
+++ b/drivers/staging/fbtft/fb_ssd1331.c
|
|
@@ -81,8 +81,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
|
|
va_start(args, len);
|
|
|
|
*buf = (u8)va_arg(args, unsigned int);
|
|
- if (par->gpio.dc)
|
|
- gpiod_set_value(par->gpio.dc, 0);
|
|
+ gpiod_set_value(par->gpio.dc, 0);
|
|
ret = par->fbtftops.write(par, par->buf, sizeof(u8));
|
|
if (ret < 0) {
|
|
va_end(args);
|
|
@@ -104,8 +103,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
|
|
return;
|
|
}
|
|
}
|
|
- if (par->gpio.dc)
|
|
- gpiod_set_value(par->gpio.dc, 1);
|
|
+ gpiod_set_value(par->gpio.dc, 1);
|
|
va_end(args);
|
|
}
|
|
|
|
diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c
|
|
index 900b28d826b28..cf263a58a1489 100644
|
|
--- a/drivers/staging/fbtft/fb_ssd1351.c
|
|
+++ b/drivers/staging/fbtft/fb_ssd1351.c
|
|
@@ -2,7 +2,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/delay.h>
|
|
|
|
diff --git a/drivers/staging/fbtft/fb_upd161704.c b/drivers/staging/fbtft/fb_upd161704.c
|
|
index c77832ae5e5ba..c680160d63807 100644
|
|
--- a/drivers/staging/fbtft/fb_upd161704.c
|
|
+++ b/drivers/staging/fbtft/fb_upd161704.c
|
|
@@ -12,7 +12,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include "fbtft.h"
|
|
@@ -26,9 +25,6 @@ static int init_display(struct fbtft_par *par)
|
|
{
|
|
par->fbtftops.reset(par);
|
|
|
|
- if (par->gpio.cs)
|
|
- gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
|
|
-
|
|
/* Initialization sequence from Lib_UTFT */
|
|
|
|
/* register reset */
|
|
diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c
|
|
index 76b25df376b8f..a57e1f4feef35 100644
|
|
--- a/drivers/staging/fbtft/fb_watterott.c
|
|
+++ b/drivers/staging/fbtft/fb_watterott.c
|
|
@@ -8,7 +8,6 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
-#include <linux/gpio/consumer.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include "fbtft.h"
|
|
diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c
|
|
index 63c65dd67b175..3d422bc116411 100644
|
|
--- a/drivers/staging/fbtft/fbtft-bus.c
|
|
+++ b/drivers/staging/fbtft/fbtft-bus.c
|
|
@@ -135,8 +135,7 @@ int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
|
|
remain = len / 2;
|
|
vmem16 = (u16 *)(par->info->screen_buffer + offset);
|
|
|
|
- if (par->gpio.dc)
|
|
- gpiod_set_value(par->gpio.dc, 1);
|
|
+ gpiod_set_value(par->gpio.dc, 1);
|
|
|
|
/* non buffered write */
|
|
if (!par->txbuf.buf)
|
|
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
|
|
index 4f362dad4436a..3723269890d5f 100644
|
|
--- a/drivers/staging/fbtft/fbtft-core.c
|
|
+++ b/drivers/staging/fbtft/fbtft-core.c
|
|
@@ -38,8 +38,7 @@ int fbtft_write_buf_dc(struct fbtft_par *par, void *buf, size_t len, int dc)
|
|
{
|
|
int ret;
|
|
|
|
- if (par->gpio.dc)
|
|
- gpiod_set_value(par->gpio.dc, dc);
|
|
+ gpiod_set_value(par->gpio.dc, dc);
|
|
|
|
ret = par->fbtftops.write(par, buf, len);
|
|
if (ret < 0)
|
|
@@ -76,20 +75,16 @@ static int fbtft_request_one_gpio(struct fbtft_par *par,
|
|
struct gpio_desc **gpiop)
|
|
{
|
|
struct device *dev = par->info->device;
|
|
- int ret = 0;
|
|
|
|
*gpiop = devm_gpiod_get_index_optional(dev, name, index,
|
|
- GPIOD_OUT_HIGH);
|
|
- if (IS_ERR(*gpiop)) {
|
|
- ret = PTR_ERR(*gpiop);
|
|
- dev_err(dev,
|
|
- "Failed to request %s GPIO: %d\n", name, ret);
|
|
- return ret;
|
|
- }
|
|
+ GPIOD_OUT_LOW);
|
|
+ if (IS_ERR(*gpiop))
|
|
+ return dev_err_probe(dev, PTR_ERR(*gpiop), "Failed to request %s GPIO\n", name);
|
|
+
|
|
fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n",
|
|
__func__, name);
|
|
|
|
- return ret;
|
|
+ return 0;
|
|
}
|
|
|
|
static int fbtft_request_gpios(struct fbtft_par *par)
|
|
@@ -226,11 +221,15 @@ static void fbtft_reset(struct fbtft_par *par)
|
|
{
|
|
if (!par->gpio.reset)
|
|
return;
|
|
+
|
|
fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__);
|
|
+
|
|
gpiod_set_value_cansleep(par->gpio.reset, 1);
|
|
usleep_range(20, 40);
|
|
gpiod_set_value_cansleep(par->gpio.reset, 0);
|
|
msleep(120);
|
|
+
|
|
+ gpiod_set_value_cansleep(par->gpio.cs, 1); /* Activate chip */
|
|
}
|
|
|
|
static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line,
|
|
@@ -922,8 +921,6 @@ static int fbtft_init_display_from_property(struct fbtft_par *par)
|
|
goto out_free;
|
|
|
|
par->fbtftops.reset(par);
|
|
- if (par->gpio.cs)
|
|
- gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
|
|
|
|
index = -1;
|
|
val = values[++index];
|
|
@@ -1018,8 +1015,6 @@ int fbtft_init_display(struct fbtft_par *par)
|
|
}
|
|
|
|
par->fbtftops.reset(par);
|
|
- if (par->gpio.cs)
|
|
- gpiod_set_value(par->gpio.cs, 0); /* Activate chip */
|
|
|
|
i = 0;
|
|
while (i < FBTFT_MAX_INIT_SEQUENCE) {
|
|
diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c
|
|
index 0863d257d7620..de1904a443c27 100644
|
|
--- a/drivers/staging/fbtft/fbtft-io.c
|
|
+++ b/drivers/staging/fbtft/fbtft-io.c
|
|
@@ -142,12 +142,12 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len)
|
|
data = *(u8 *)buf;
|
|
|
|
/* Start writing by pulling down /WR */
|
|
- gpiod_set_value(par->gpio.wr, 0);
|
|
+ gpiod_set_value(par->gpio.wr, 1);
|
|
|
|
/* Set data */
|
|
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
|
|
if (data == prev_data) {
|
|
- gpiod_set_value(par->gpio.wr, 0); /* used as delay */
|
|
+ gpiod_set_value(par->gpio.wr, 1); /* used as delay */
|
|
} else {
|
|
for (i = 0; i < 8; i++) {
|
|
if ((data & 1) != (prev_data & 1))
|
|
@@ -165,7 +165,7 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len)
|
|
#endif
|
|
|
|
/* Pullup /WR */
|
|
- gpiod_set_value(par->gpio.wr, 1);
|
|
+ gpiod_set_value(par->gpio.wr, 0);
|
|
|
|
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
|
|
prev_data = *(u8 *)buf;
|
|
@@ -192,12 +192,12 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len)
|
|
data = *(u16 *)buf;
|
|
|
|
/* Start writing by pulling down /WR */
|
|
- gpiod_set_value(par->gpio.wr, 0);
|
|
+ gpiod_set_value(par->gpio.wr, 1);
|
|
|
|
/* Set data */
|
|
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
|
|
if (data == prev_data) {
|
|
- gpiod_set_value(par->gpio.wr, 0); /* used as delay */
|
|
+ gpiod_set_value(par->gpio.wr, 1); /* used as delay */
|
|
} else {
|
|
for (i = 0; i < 16; i++) {
|
|
if ((data & 1) != (prev_data & 1))
|
|
@@ -215,7 +215,7 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len)
|
|
#endif
|
|
|
|
/* Pullup /WR */
|
|
- gpiod_set_value(par->gpio.wr, 1);
|
|
+ gpiod_set_value(par->gpio.wr, 0);
|
|
|
|
#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO
|
|
prev_data = *(u16 *)buf;
|
|
diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c
|
|
index 571f47d394843..bd5f874334043 100644
|
|
--- a/drivers/staging/gdm724x/gdm_lte.c
|
|
+++ b/drivers/staging/gdm724x/gdm_lte.c
|
|
@@ -611,10 +611,12 @@ static void gdm_lte_netif_rx(struct net_device *dev, char *buf,
|
|
* bytes (99,130,83,99 dec)
|
|
*/
|
|
} __packed;
|
|
- void *addr = buf + sizeof(struct iphdr) +
|
|
- sizeof(struct udphdr) +
|
|
- offsetof(struct dhcp_packet, chaddr);
|
|
- ether_addr_copy(nic->dest_mac_addr, addr);
|
|
+ int offset = sizeof(struct iphdr) +
|
|
+ sizeof(struct udphdr) +
|
|
+ offsetof(struct dhcp_packet, chaddr);
|
|
+ if (offset + ETH_ALEN > len)
|
|
+ return;
|
|
+ ether_addr_copy(nic->dest_mac_addr, buf + offset);
|
|
}
|
|
}
|
|
|
|
@@ -677,6 +679,7 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len)
|
|
struct sdu *sdu = NULL;
|
|
u8 endian = phy_dev->get_endian(phy_dev->priv_dev);
|
|
u8 *data = (u8 *)multi_sdu->data;
|
|
+ int copied;
|
|
u16 i = 0;
|
|
u16 num_packet;
|
|
u16 hci_len;
|
|
@@ -688,6 +691,12 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len)
|
|
num_packet = gdm_dev16_to_cpu(endian, multi_sdu->num_packet);
|
|
|
|
for (i = 0; i < num_packet; i++) {
|
|
+ copied = data - multi_sdu->data;
|
|
+ if (len < copied + sizeof(*sdu)) {
|
|
+ pr_err("rx prevent buffer overflow");
|
|
+ return;
|
|
+ }
|
|
+
|
|
sdu = (struct sdu *)data;
|
|
|
|
cmd_evt = gdm_dev16_to_cpu(endian, sdu->cmd_evt);
|
|
@@ -698,7 +707,8 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len)
|
|
pr_err("rx sdu wrong hci %04x\n", cmd_evt);
|
|
return;
|
|
}
|
|
- if (hci_len < 12) {
|
|
+ if (hci_len < 12 ||
|
|
+ len < copied + sizeof(*sdu) + (hci_len - 12)) {
|
|
pr_err("rx sdu invalid len %d\n", hci_len);
|
|
return;
|
|
}
|
|
diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
|
|
index 3cd00cc0a3641..7749ca9a8ebbf 100644
|
|
--- a/drivers/staging/media/hantro/hantro_drv.c
|
|
+++ b/drivers/staging/media/hantro/hantro_drv.c
|
|
@@ -56,16 +56,12 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts)
|
|
return hantro_get_dec_buf_addr(ctx, buf);
|
|
}
|
|
|
|
-static void hantro_job_finish(struct hantro_dev *vpu,
|
|
- struct hantro_ctx *ctx,
|
|
- enum vb2_buffer_state result)
|
|
+static void hantro_job_finish_no_pm(struct hantro_dev *vpu,
|
|
+ struct hantro_ctx *ctx,
|
|
+ enum vb2_buffer_state result)
|
|
{
|
|
struct vb2_v4l2_buffer *src, *dst;
|
|
|
|
- pm_runtime_mark_last_busy(vpu->dev);
|
|
- pm_runtime_put_autosuspend(vpu->dev);
|
|
- clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks);
|
|
-
|
|
src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
|
|
dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
|
|
|
|
@@ -81,6 +77,18 @@ static void hantro_job_finish(struct hantro_dev *vpu,
|
|
result);
|
|
}
|
|
|
|
+static void hantro_job_finish(struct hantro_dev *vpu,
|
|
+ struct hantro_ctx *ctx,
|
|
+ enum vb2_buffer_state result)
|
|
+{
|
|
+ pm_runtime_mark_last_busy(vpu->dev);
|
|
+ pm_runtime_put_autosuspend(vpu->dev);
|
|
+
|
|
+ clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks);
|
|
+
|
|
+ hantro_job_finish_no_pm(vpu, ctx, result);
|
|
+}
|
|
+
|
|
void hantro_irq_done(struct hantro_dev *vpu,
|
|
enum vb2_buffer_state result)
|
|
{
|
|
@@ -152,12 +160,15 @@ static void device_run(void *priv)
|
|
src = hantro_get_src_buf(ctx);
|
|
dst = hantro_get_dst_buf(ctx);
|
|
|
|
+ ret = pm_runtime_get_sync(ctx->dev->dev);
|
|
+ if (ret < 0) {
|
|
+ pm_runtime_put_noidle(ctx->dev->dev);
|
|
+ goto err_cancel_job;
|
|
+ }
|
|
+
|
|
ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks);
|
|
if (ret)
|
|
goto err_cancel_job;
|
|
- ret = pm_runtime_get_sync(ctx->dev->dev);
|
|
- if (ret < 0)
|
|
- goto err_cancel_job;
|
|
|
|
v4l2_m2m_buf_copy_metadata(src, dst, true);
|
|
|
|
@@ -165,7 +176,7 @@ static void device_run(void *priv)
|
|
return;
|
|
|
|
err_cancel_job:
|
|
- hantro_job_finish(ctx->dev, ctx, VB2_BUF_STATE_ERROR);
|
|
+ hantro_job_finish_no_pm(ctx->dev, ctx, VB2_BUF_STATE_ERROR);
|
|
}
|
|
|
|
static struct v4l2_m2m_ops vpu_m2m_ops = {
|
|
diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c
|
|
index f5fbdbc4ffdb1..5c2ca61add8e8 100644
|
|
--- a/drivers/staging/media/hantro/hantro_v4l2.c
|
|
+++ b/drivers/staging/media/hantro/hantro_v4l2.c
|
|
@@ -639,7 +639,14 @@ static int hantro_buf_prepare(struct vb2_buffer *vb)
|
|
ret = hantro_buf_plane_check(vb, pix_fmt);
|
|
if (ret)
|
|
return ret;
|
|
- vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);
|
|
+ /*
|
|
+ * Buffer's bytesused must be written by driver for CAPTURE buffers.
|
|
+ * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
|
|
+ * it to buffer length).
|
|
+ */
|
|
+ if (V4L2_TYPE_IS_CAPTURE(vq->type))
|
|
+ vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
|
|
index 21ebf77696964..d9a8667b4bedf 100644
|
|
--- a/drivers/staging/media/imx/imx-media-csi.c
|
|
+++ b/drivers/staging/media/imx/imx-media-csi.c
|
|
@@ -753,9 +753,10 @@ static int csi_setup(struct csi_priv *priv)
|
|
|
|
static int csi_start(struct csi_priv *priv)
|
|
{
|
|
- struct v4l2_fract *output_fi;
|
|
+ struct v4l2_fract *input_fi, *output_fi;
|
|
int ret;
|
|
|
|
+ input_fi = &priv->frame_interval[CSI_SINK_PAD];
|
|
output_fi = &priv->frame_interval[priv->active_output_pad];
|
|
|
|
/* start upstream */
|
|
@@ -764,6 +765,17 @@ static int csi_start(struct csi_priv *priv)
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ /* Skip first few frames from a BT.656 source */
|
|
+ if (priv->upstream_ep.bus_type == V4L2_MBUS_BT656) {
|
|
+ u32 delay_usec, bad_frames = 20;
|
|
+
|
|
+ delay_usec = DIV_ROUND_UP_ULL((u64)USEC_PER_SEC *
|
|
+ input_fi->numerator * bad_frames,
|
|
+ input_fi->denominator);
|
|
+
|
|
+ usleep_range(delay_usec, delay_usec + 1000);
|
|
+ }
|
|
+
|
|
if (priv->dest == IPU_CSI_DEST_IDMAC) {
|
|
ret = csi_idmac_start(priv);
|
|
if (ret)
|
|
@@ -1930,19 +1942,13 @@ static int imx_csi_async_register(struct csi_priv *priv)
|
|
port, 0,
|
|
FWNODE_GRAPH_ENDPOINT_NEXT);
|
|
if (ep) {
|
|
- asd = kzalloc(sizeof(*asd), GFP_KERNEL);
|
|
- if (!asd) {
|
|
- fwnode_handle_put(ep);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
- &priv->notifier, ep, asd);
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
+ &priv->notifier, ep, sizeof(*asd));
|
|
|
|
fwnode_handle_put(ep);
|
|
|
|
- if (ret) {
|
|
- kfree(asd);
|
|
+ if (IS_ERR(asd)) {
|
|
+ ret = PTR_ERR(asd);
|
|
/* OK if asd already exists */
|
|
if (ret != -EEXIST)
|
|
return ret;
|
|
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
|
|
index 94d87d27d3896..9457761b7c8ba 100644
|
|
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
|
|
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
|
|
@@ -557,7 +557,7 @@ static int csi2_async_register(struct csi2_dev *csi2)
|
|
struct v4l2_fwnode_endpoint vep = {
|
|
.bus_type = V4L2_MBUS_CSI2_DPHY,
|
|
};
|
|
- struct v4l2_async_subdev *asd = NULL;
|
|
+ struct v4l2_async_subdev *asd;
|
|
struct fwnode_handle *ep;
|
|
int ret;
|
|
|
|
@@ -577,19 +577,13 @@ static int csi2_async_register(struct csi2_dev *csi2)
|
|
dev_dbg(csi2->dev, "data lanes: %d\n", csi2->bus.num_data_lanes);
|
|
dev_dbg(csi2->dev, "flags: 0x%08x\n", csi2->bus.flags);
|
|
|
|
- asd = kzalloc(sizeof(*asd), GFP_KERNEL);
|
|
- if (!asd) {
|
|
- ret = -ENOMEM;
|
|
- goto err_parse;
|
|
- }
|
|
-
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
- &csi2->notifier, ep, asd);
|
|
- if (ret)
|
|
- goto err_parse;
|
|
-
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
+ &csi2->notifier, ep, sizeof(*asd));
|
|
fwnode_handle_put(ep);
|
|
|
|
+ if (IS_ERR(asd))
|
|
+ return PTR_ERR(asd);
|
|
+
|
|
csi2->notifier.ops = &csi2_notify_ops;
|
|
|
|
ret = v4l2_async_subdev_notifier_register(&csi2->sd,
|
|
@@ -601,7 +595,6 @@ static int csi2_async_register(struct csi2_dev *csi2)
|
|
|
|
err_parse:
|
|
fwnode_handle_put(ep);
|
|
- kfree(asd);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c
|
|
index ac52b1daf9914..6c59485291ca3 100644
|
|
--- a/drivers/staging/media/imx/imx7-media-csi.c
|
|
+++ b/drivers/staging/media/imx/imx7-media-csi.c
|
|
@@ -1191,7 +1191,7 @@ static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = {
|
|
|
|
static int imx7_csi_async_register(struct imx7_csi *csi)
|
|
{
|
|
- struct v4l2_async_subdev *asd = NULL;
|
|
+ struct v4l2_async_subdev *asd;
|
|
struct fwnode_handle *ep;
|
|
int ret;
|
|
|
|
@@ -1200,19 +1200,13 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
|
|
ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0,
|
|
FWNODE_GRAPH_ENDPOINT_NEXT);
|
|
if (ep) {
|
|
- asd = kzalloc(sizeof(*asd), GFP_KERNEL);
|
|
- if (!asd) {
|
|
- fwnode_handle_put(ep);
|
|
- return -ENOMEM;
|
|
- }
|
|
-
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
- &csi->notifier, ep, asd);
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
+ &csi->notifier, ep, sizeof(*asd));
|
|
|
|
fwnode_handle_put(ep);
|
|
|
|
- if (ret) {
|
|
- kfree(asd);
|
|
+ if (IS_ERR(asd)) {
|
|
+ ret = PTR_ERR(asd);
|
|
/* OK if asd already exists */
|
|
if (ret != -EEXIST)
|
|
return ret;
|
|
diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c
|
|
index 7612993cc1d68..a392f9012626b 100644
|
|
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
|
|
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
|
|
@@ -597,13 +597,15 @@ static void mipi_csis_clear_counters(struct csi_state *state)
|
|
|
|
static void mipi_csis_log_counters(struct csi_state *state, bool non_errors)
|
|
{
|
|
- int i = non_errors ? MIPI_CSIS_NUM_EVENTS : MIPI_CSIS_NUM_EVENTS - 4;
|
|
+ unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS
|
|
+ : MIPI_CSIS_NUM_EVENTS - 6;
|
|
struct device *dev = &state->pdev->dev;
|
|
unsigned long flags;
|
|
+ unsigned int i;
|
|
|
|
spin_lock_irqsave(&state->slock, flags);
|
|
|
|
- for (i--; i >= 0; i--) {
|
|
+ for (i = 0; i < num_events; ++i) {
|
|
if (state->events[i].counter > 0 || state->debug)
|
|
dev_info(dev, "%s events: %d\n", state->events[i].name,
|
|
state->events[i].counter);
|
|
@@ -1004,7 +1006,7 @@ static int mipi_csis_async_register(struct csi_state *state)
|
|
struct v4l2_fwnode_endpoint vep = {
|
|
.bus_type = V4L2_MBUS_CSI2_DPHY,
|
|
};
|
|
- struct v4l2_async_subdev *asd = NULL;
|
|
+ struct v4l2_async_subdev *asd;
|
|
struct fwnode_handle *ep;
|
|
int ret;
|
|
|
|
@@ -1024,17 +1026,13 @@ static int mipi_csis_async_register(struct csi_state *state)
|
|
dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes);
|
|
dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags);
|
|
|
|
- asd = kzalloc(sizeof(*asd), GFP_KERNEL);
|
|
- if (!asd) {
|
|
- ret = -ENOMEM;
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
+ &state->notifier, ep, sizeof(*asd));
|
|
+ if (IS_ERR(asd)) {
|
|
+ ret = PTR_ERR(asd);
|
|
goto err_parse;
|
|
}
|
|
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(
|
|
- &state->notifier, ep, asd);
|
|
- if (ret)
|
|
- goto err_parse;
|
|
-
|
|
fwnode_handle_put(ep);
|
|
|
|
state->notifier.ops = &mipi_csis_notify_ops;
|
|
@@ -1048,7 +1046,6 @@ static int mipi_csis_async_register(struct csi_state *state)
|
|
|
|
err_parse:
|
|
fwnode_handle_put(ep);
|
|
- kfree(asd);
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/staging/media/rkisp1/rkisp1-dev.c b/drivers/staging/media/rkisp1/rkisp1-dev.c
|
|
index 91584695804bb..06de5540c8af4 100644
|
|
--- a/drivers/staging/media/rkisp1/rkisp1-dev.c
|
|
+++ b/drivers/staging/media/rkisp1/rkisp1-dev.c
|
|
@@ -252,6 +252,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
|
|
.bus_type = V4L2_MBUS_CSI2_DPHY
|
|
};
|
|
struct rkisp1_sensor_async *rk_asd = NULL;
|
|
+ struct v4l2_async_subdev *asd;
|
|
struct fwnode_handle *ep;
|
|
|
|
ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev),
|
|
@@ -263,21 +264,18 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
|
|
if (ret)
|
|
goto err_parse;
|
|
|
|
- rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL);
|
|
- if (!rk_asd) {
|
|
- ret = -ENOMEM;
|
|
+ asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
|
|
+ sizeof(*rk_asd));
|
|
+ if (IS_ERR(asd)) {
|
|
+ ret = PTR_ERR(asd);
|
|
goto err_parse;
|
|
}
|
|
|
|
+ rk_asd = container_of(asd, struct rkisp1_sensor_async, asd);
|
|
rk_asd->mbus_type = vep.bus_type;
|
|
rk_asd->mbus_flags = vep.bus.mipi_csi2.flags;
|
|
rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes;
|
|
|
|
- ret = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep,
|
|
- &rk_asd->asd);
|
|
- if (ret)
|
|
- goto err_parse;
|
|
-
|
|
dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n",
|
|
vep.base.id, rk_asd->lanes);
|
|
|
|
@@ -288,7 +286,6 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1)
|
|
continue;
|
|
err_parse:
|
|
fwnode_handle_put(ep);
|
|
- kfree(rk_asd);
|
|
v4l2_async_notifier_cleanup(ntf);
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index 1263991de76f9..e68303e2b3907 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -471,7 +471,15 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb)
|
|
if (vb2_plane_size(vb, i) < sizeimage)
|
|
return -EINVAL;
|
|
}
|
|
- vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage);
|
|
+
|
|
+ /*
|
|
+ * Buffer's bytesused must be written by driver for CAPTURE buffers.
|
|
+ * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
|
|
+ * it to buffer length).
|
|
+ */
|
|
+ if (V4L2_TYPE_IS_CAPTURE(vq->type))
|
|
+ vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -691,7 +699,7 @@ static void rkvdec_device_run(void *priv)
|
|
if (WARN_ON(!desc))
|
|
return;
|
|
|
|
- ret = pm_runtime_get_sync(rkvdec->dev);
|
|
+ ret = pm_runtime_resume_and_get(rkvdec->dev);
|
|
if (ret < 0) {
|
|
rkvdec_job_finish_no_pm(ctx, VB2_BUF_STATE_ERROR);
|
|
return;
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
index ce497d0197dfc..10744fab7ceaa 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
|
|
@@ -477,8 +477,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
|
slice_params->flags);
|
|
|
|
reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT,
|
|
- V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT,
|
|
- pps->flags);
|
|
+ V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT,
|
|
+ slice_params->flags);
|
|
|
|
/* FIXME: For multi-slice support. */
|
|
reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC;
|
|
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
index 911f607d9b092..16327be904d1a 100644
|
|
--- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c
|
|
@@ -449,7 +449,13 @@ static int cedrus_buf_prepare(struct vb2_buffer *vb)
|
|
if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
|
|
return -EINVAL;
|
|
|
|
- vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
|
|
+ /*
|
|
+ * Buffer's bytesused must be written by driver for CAPTURE buffers.
|
|
+ * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets
|
|
+ * it to buffer length).
|
|
+ */
|
|
+ if (V4L2_TYPE_IS_CAPTURE(vq->type))
|
|
+ vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi
|
|
index 82aa93634eda3..27222f7b246fd 100644
|
|
--- a/drivers/staging/mt7621-dts/mt7621.dtsi
|
|
+++ b/drivers/staging/mt7621-dts/mt7621.dtsi
|
|
@@ -519,7 +519,7 @@
|
|
|
|
bus-range = <0 255>;
|
|
ranges = <
|
|
- 0x02000000 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */
|
|
+ 0x02000000 0 0x60000000 0x60000000 0 0x10000000 /* pci memory */
|
|
0x01000000 0 0x00000000 0x1e160000 0 0x00010000 /* io space */
|
|
>;
|
|
|
|
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
|
|
index 715f1fe8b4726..22974277afa08 100644
|
|
--- a/drivers/staging/rtl8712/hal_init.c
|
|
+++ b/drivers/staging/rtl8712/hal_init.c
|
|
@@ -40,7 +40,10 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
|
|
dev_err(&udev->dev, "r8712u: Firmware request failed\n");
|
|
usb_put_dev(udev);
|
|
usb_set_intfdata(usb_intf, NULL);
|
|
+ r8712_free_drv_sw(adapter);
|
|
+ adapter->dvobj_deinit(adapter);
|
|
complete(&adapter->rtl8712_fw_ready);
|
|
+ free_netdev(adapter->pnetdev);
|
|
return;
|
|
}
|
|
adapter->fw = firmware;
|
|
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
|
|
index 0c3ae8495afb7..2214aca097308 100644
|
|
--- a/drivers/staging/rtl8712/os_intfs.c
|
|
+++ b/drivers/staging/rtl8712/os_intfs.c
|
|
@@ -328,8 +328,6 @@ int r8712_init_drv_sw(struct _adapter *padapter)
|
|
|
|
void r8712_free_drv_sw(struct _adapter *padapter)
|
|
{
|
|
- struct net_device *pnetdev = padapter->pnetdev;
|
|
-
|
|
r8712_free_cmd_priv(&padapter->cmdpriv);
|
|
r8712_free_evt_priv(&padapter->evtpriv);
|
|
r8712_DeInitSwLeds(padapter);
|
|
@@ -339,8 +337,6 @@ void r8712_free_drv_sw(struct _adapter *padapter)
|
|
_r8712_free_sta_priv(&padapter->stapriv);
|
|
_r8712_free_recv_priv(&padapter->recvpriv);
|
|
mp871xdeinit(padapter);
|
|
- if (pnetdev)
|
|
- free_netdev(pnetdev);
|
|
}
|
|
|
|
static void enable_video_mode(struct _adapter *padapter, int cbw40_value)
|
|
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
|
|
index dc21e7743349c..b760bc3559373 100644
|
|
--- a/drivers/staging/rtl8712/usb_intf.c
|
|
+++ b/drivers/staging/rtl8712/usb_intf.c
|
|
@@ -361,7 +361,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
|
|
/* step 1. */
|
|
pnetdev = r8712_init_netdev();
|
|
if (!pnetdev)
|
|
- goto error;
|
|
+ goto put_dev;
|
|
padapter = netdev_priv(pnetdev);
|
|
disable_ht_for_spec_devid(pdid, padapter);
|
|
pdvobjpriv = &padapter->dvobjpriv;
|
|
@@ -381,16 +381,16 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
|
|
* initialize the dvobj_priv
|
|
*/
|
|
if (!padapter->dvobj_init) {
|
|
- goto error;
|
|
+ goto put_dev;
|
|
} else {
|
|
status = padapter->dvobj_init(padapter);
|
|
if (status != _SUCCESS)
|
|
- goto error;
|
|
+ goto free_netdev;
|
|
}
|
|
/* step 4. */
|
|
status = r8712_init_drv_sw(padapter);
|
|
if (status)
|
|
- goto error;
|
|
+ goto dvobj_deinit;
|
|
/* step 5. read efuse/eeprom data and get mac_addr */
|
|
{
|
|
int i, offset;
|
|
@@ -570,17 +570,20 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,
|
|
}
|
|
/* step 6. Load the firmware asynchronously */
|
|
if (rtl871x_load_fw(padapter))
|
|
- goto error;
|
|
+ goto deinit_drv_sw;
|
|
spin_lock_init(&padapter->lock_rx_ff0_filter);
|
|
mutex_init(&padapter->mutex_start);
|
|
return 0;
|
|
-error:
|
|
+
|
|
+deinit_drv_sw:
|
|
+ r8712_free_drv_sw(padapter);
|
|
+dvobj_deinit:
|
|
+ padapter->dvobj_deinit(padapter);
|
|
+free_netdev:
|
|
+ free_netdev(pnetdev);
|
|
+put_dev:
|
|
usb_put_dev(udev);
|
|
usb_set_intfdata(pusb_intf, NULL);
|
|
- if (padapter && padapter->dvobj_deinit)
|
|
- padapter->dvobj_deinit(padapter);
|
|
- if (pnetdev)
|
|
- free_netdev(pnetdev);
|
|
return -ENODEV;
|
|
}
|
|
|
|
@@ -612,6 +615,7 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
|
|
r8712_stop_drv_timers(padapter);
|
|
r871x_dev_unload(padapter);
|
|
r8712_free_drv_sw(padapter);
|
|
+ free_netdev(pnetdev);
|
|
|
|
/* decrease the reference count of the usb device structure
|
|
* when disconnect
|
|
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
|
|
index 9097bcbd67d82..d697ea55a0da1 100644
|
|
--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
|
|
+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
|
|
@@ -1862,7 +1862,7 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
|
|
int status;
|
|
int err = -ENODEV;
|
|
struct vchiq_mmal_instance *instance;
|
|
- static struct vchiq_instance *vchiq_instance;
|
|
+ struct vchiq_instance *vchiq_instance;
|
|
struct vchiq_service_params_kernel params = {
|
|
.version = VC_MMAL_VER,
|
|
.version_min = VC_MMAL_MIN_VER,
|
|
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_ddp.c b/drivers/target/iscsi/cxgbit/cxgbit_ddp.c
|
|
index af35251232eb3..b044999ad002b 100644
|
|
--- a/drivers/target/iscsi/cxgbit/cxgbit_ddp.c
|
|
+++ b/drivers/target/iscsi/cxgbit/cxgbit_ddp.c
|
|
@@ -265,12 +265,13 @@ void cxgbit_unmap_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
|
|
struct cxgbit_cmd *ccmd = iscsit_priv_cmd(cmd);
|
|
|
|
if (ccmd->release) {
|
|
- struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo;
|
|
-
|
|
- if (ttinfo->sgl) {
|
|
+ if (cmd->se_cmd.se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) {
|
|
+ put_page(sg_page(&ccmd->sg));
|
|
+ } else {
|
|
struct cxgbit_sock *csk = conn->context;
|
|
struct cxgbit_device *cdev = csk->com.cdev;
|
|
struct cxgbi_ppm *ppm = cdev2ppm(cdev);
|
|
+ struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo;
|
|
|
|
/* Abort the TCP conn if DDP is not complete to
|
|
* avoid any possibility of DDP after freeing
|
|
@@ -280,14 +281,14 @@ void cxgbit_unmap_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
|
|
cmd->se_cmd.data_length))
|
|
cxgbit_abort_conn(csk);
|
|
|
|
+ if (unlikely(ttinfo->sgl)) {
|
|
+ dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl,
|
|
+ ttinfo->nents, DMA_FROM_DEVICE);
|
|
+ ttinfo->nents = 0;
|
|
+ ttinfo->sgl = NULL;
|
|
+ }
|
|
cxgbi_ppm_ppod_release(ppm, ttinfo->idx);
|
|
-
|
|
- dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl,
|
|
- ttinfo->nents, DMA_FROM_DEVICE);
|
|
- } else {
|
|
- put_page(sg_page(&ccmd->sg));
|
|
}
|
|
-
|
|
ccmd->release = false;
|
|
}
|
|
}
|
|
diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c
|
|
index b926e1d6c7b8e..282297ffc4044 100644
|
|
--- a/drivers/target/iscsi/cxgbit/cxgbit_target.c
|
|
+++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c
|
|
@@ -997,17 +997,18 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
|
|
struct scatterlist *sg_start;
|
|
struct iscsi_conn *conn = csk->conn;
|
|
struct iscsi_cmd *cmd = NULL;
|
|
+ struct cxgbit_cmd *ccmd;
|
|
+ struct cxgbi_task_tag_info *ttinfo;
|
|
struct cxgbit_lro_pdu_cb *pdu_cb = cxgbit_rx_pdu_cb(csk->skb);
|
|
struct iscsi_data *hdr = (struct iscsi_data *)pdu_cb->hdr;
|
|
u32 data_offset = be32_to_cpu(hdr->offset);
|
|
- u32 data_len = pdu_cb->dlen;
|
|
+ u32 data_len = ntoh24(hdr->dlength);
|
|
int rc, sg_nents, sg_off;
|
|
bool dcrc_err = false;
|
|
|
|
if (pdu_cb->flags & PDUCBF_RX_DDP_CMP) {
|
|
u32 offset = be32_to_cpu(hdr->offset);
|
|
u32 ddp_data_len;
|
|
- u32 payload_length = ntoh24(hdr->dlength);
|
|
bool success = false;
|
|
|
|
cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, 0);
|
|
@@ -1022,7 +1023,7 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
|
|
cmd->data_sn = be32_to_cpu(hdr->datasn);
|
|
|
|
rc = __iscsit_check_dataout_hdr(conn, (unsigned char *)hdr,
|
|
- cmd, payload_length, &success);
|
|
+ cmd, data_len, &success);
|
|
if (rc < 0)
|
|
return rc;
|
|
else if (!success)
|
|
@@ -1060,6 +1061,20 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk)
|
|
cxgbit_skb_copy_to_sg(csk->skb, sg_start, sg_nents, skip);
|
|
}
|
|
|
|
+ ccmd = iscsit_priv_cmd(cmd);
|
|
+ ttinfo = &ccmd->ttinfo;
|
|
+
|
|
+ if (ccmd->release && ttinfo->sgl &&
|
|
+ (cmd->se_cmd.data_length == (cmd->write_data_done + data_len))) {
|
|
+ struct cxgbit_device *cdev = csk->com.cdev;
|
|
+ struct cxgbi_ppm *ppm = cdev2ppm(cdev);
|
|
+
|
|
+ dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl, ttinfo->nents,
|
|
+ DMA_FROM_DEVICE);
|
|
+ ttinfo->nents = 0;
|
|
+ ttinfo->sgl = NULL;
|
|
+ }
|
|
+
|
|
check_payload:
|
|
|
|
rc = iscsit_check_dataout_payload(cmd, hdr, dcrc_err);
|
|
diff --git a/drivers/thermal/cpufreq_cooling.c b/drivers/thermal/cpufreq_cooling.c
|
|
index 3f6a69ccc1737..6e1d6a31ee4fb 100644
|
|
--- a/drivers/thermal/cpufreq_cooling.c
|
|
+++ b/drivers/thermal/cpufreq_cooling.c
|
|
@@ -443,7 +443,7 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
|
|
ret = freq_qos_update_request(&cpufreq_cdev->qos_req, frequency);
|
|
if (ret >= 0) {
|
|
cpufreq_cdev->cpufreq_state = state;
|
|
- cpus = cpufreq_cdev->policy->cpus;
|
|
+ cpus = cpufreq_cdev->policy->related_cpus;
|
|
max_capacity = arch_scale_cpu_capacity(cpumask_first(cpus));
|
|
capacity = frequency * max_capacity;
|
|
capacity /= cpufreq_cdev->policy->cpuinfo.max_freq;
|
|
diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c
|
|
index 464c2d37b992e..e254f8c37cb73 100644
|
|
--- a/drivers/thunderbolt/test.c
|
|
+++ b/drivers/thunderbolt/test.c
|
|
@@ -259,14 +259,14 @@ static struct tb_switch *alloc_dev_default(struct kunit *test,
|
|
if (port->dual_link_port && upstream_port->dual_link_port) {
|
|
port->dual_link_port->remote = upstream_port->dual_link_port;
|
|
upstream_port->dual_link_port->remote = port->dual_link_port;
|
|
- }
|
|
|
|
- if (bonded) {
|
|
- /* Bonding is used */
|
|
- port->bonded = true;
|
|
- port->dual_link_port->bonded = true;
|
|
- upstream_port->bonded = true;
|
|
- upstream_port->dual_link_port->bonded = true;
|
|
+ if (bonded) {
|
|
+ /* Bonding is used */
|
|
+ port->bonded = true;
|
|
+ port->dual_link_port->bonded = true;
|
|
+ upstream_port->bonded = true;
|
|
+ upstream_port->dual_link_port->bonded = true;
|
|
+ }
|
|
}
|
|
|
|
return sw;
|
|
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
|
|
index d42b854cb7df2..6890418a29a40 100644
|
|
--- a/drivers/tty/nozomi.c
|
|
+++ b/drivers/tty/nozomi.c
|
|
@@ -1394,7 +1394,7 @@ static int nozomi_card_init(struct pci_dev *pdev,
|
|
NOZOMI_NAME, dc);
|
|
if (unlikely(ret)) {
|
|
dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq);
|
|
- goto err_free_kfifo;
|
|
+ goto err_free_all_kfifo;
|
|
}
|
|
|
|
DBG1("base_addr: %p", dc->base_addr);
|
|
@@ -1432,12 +1432,15 @@ static int nozomi_card_init(struct pci_dev *pdev,
|
|
return 0;
|
|
|
|
err_free_tty:
|
|
- for (i = 0; i < MAX_PORT; ++i) {
|
|
+ for (i--; i >= 0; i--) {
|
|
tty_unregister_device(ntty_driver, dc->index_start + i);
|
|
tty_port_destroy(&dc->port[i].port);
|
|
}
|
|
+ free_irq(pdev->irq, dc);
|
|
+err_free_all_kfifo:
|
|
+ i = MAX_PORT;
|
|
err_free_kfifo:
|
|
- for (i = 0; i < MAX_PORT; i++)
|
|
+ for (i--; i >= PORT_MDM; i--)
|
|
kfifo_free(&dc->port[i].fifo_ul);
|
|
err_free_sbuf:
|
|
kfree(dc->send_buf);
|
|
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
|
|
index 0cc6d35a08156..95e2d6de4f213 100644
|
|
--- a/drivers/tty/serial/8250/8250_omap.c
|
|
+++ b/drivers/tty/serial/8250/8250_omap.c
|
|
@@ -27,6 +27,7 @@
|
|
#include <linux/pm_qos.h>
|
|
#include <linux/pm_wakeirq.h>
|
|
#include <linux/dma-mapping.h>
|
|
+#include <linux/sys_soc.h>
|
|
|
|
#include "8250.h"
|
|
|
|
@@ -41,6 +42,8 @@
|
|
*/
|
|
#define UART_ERRATA_CLOCK_DISABLE (1 << 3)
|
|
#define UART_HAS_EFR2 BIT(4)
|
|
+#define UART_HAS_RHR_IT_DIS BIT(5)
|
|
+#define UART_RX_TIMEOUT_QUIRK BIT(6)
|
|
|
|
#define OMAP_UART_FCR_RX_TRIG 6
|
|
#define OMAP_UART_FCR_TX_TRIG 4
|
|
@@ -94,10 +97,17 @@
|
|
#define OMAP_UART_REV_52 0x0502
|
|
#define OMAP_UART_REV_63 0x0603
|
|
|
|
+/* Interrupt Enable Register 2 */
|
|
+#define UART_OMAP_IER2 0x1B
|
|
+#define UART_OMAP_IER2_RHR_IT_DIS BIT(2)
|
|
+
|
|
/* Enhanced features register 2 */
|
|
#define UART_OMAP_EFR2 0x23
|
|
#define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6)
|
|
|
|
+/* RX FIFO occupancy indicator */
|
|
+#define UART_OMAP_RX_LVL 0x64
|
|
+
|
|
struct omap8250_priv {
|
|
int line;
|
|
u8 habit;
|
|
@@ -592,6 +602,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port);
|
|
static irqreturn_t omap8250_irq(int irq, void *dev_id)
|
|
{
|
|
struct uart_port *port = dev_id;
|
|
+ struct omap8250_priv *priv = port->private_data;
|
|
struct uart_8250_port *up = up_to_u8250p(port);
|
|
unsigned int iir;
|
|
int ret;
|
|
@@ -606,6 +617,18 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
|
|
serial8250_rpm_get(up);
|
|
iir = serial_port_in(port, UART_IIR);
|
|
ret = serial8250_handle_irq(port, iir);
|
|
+
|
|
+ /*
|
|
+ * On K3 SoCs, it is observed that RX TIMEOUT is signalled after
|
|
+ * FIFO has been drained, in which case a dummy read of RX FIFO
|
|
+ * is required to clear RX TIMEOUT condition.
|
|
+ */
|
|
+ if (priv->habit & UART_RX_TIMEOUT_QUIRK &&
|
|
+ (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT &&
|
|
+ serial_port_in(port, UART_OMAP_RX_LVL) == 0) {
|
|
+ serial_port_in(port, UART_RX);
|
|
+ }
|
|
+
|
|
serial8250_rpm_put(up);
|
|
|
|
return IRQ_RETVAL(ret);
|
|
@@ -756,17 +779,27 @@ static void __dma_rx_do_complete(struct uart_8250_port *p)
|
|
{
|
|
struct uart_8250_dma *dma = p->dma;
|
|
struct tty_port *tty_port = &p->port.state->port;
|
|
+ struct omap8250_priv *priv = p->port.private_data;
|
|
struct dma_chan *rxchan = dma->rxchan;
|
|
dma_cookie_t cookie;
|
|
struct dma_tx_state state;
|
|
int count;
|
|
int ret;
|
|
+ u32 reg;
|
|
|
|
if (!dma->rx_running)
|
|
goto out;
|
|
|
|
cookie = dma->rx_cookie;
|
|
dma->rx_running = 0;
|
|
+
|
|
+ /* Re-enable RX FIFO interrupt now that transfer is complete */
|
|
+ if (priv->habit & UART_HAS_RHR_IT_DIS) {
|
|
+ reg = serial_in(p, UART_OMAP_IER2);
|
|
+ reg &= ~UART_OMAP_IER2_RHR_IT_DIS;
|
|
+ serial_out(p, UART_OMAP_IER2, UART_OMAP_IER2_RHR_IT_DIS);
|
|
+ }
|
|
+
|
|
dmaengine_tx_status(rxchan, cookie, &state);
|
|
|
|
count = dma->rx_size - state.residue + state.in_flight_bytes;
|
|
@@ -784,7 +817,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p)
|
|
poll_count--)
|
|
cpu_relax();
|
|
|
|
- if (!poll_count)
|
|
+ if (poll_count == -1)
|
|
dev_err(p->port.dev, "teardown incomplete\n");
|
|
}
|
|
}
|
|
@@ -862,6 +895,7 @@ static int omap_8250_rx_dma(struct uart_8250_port *p)
|
|
int err = 0;
|
|
struct dma_async_tx_descriptor *desc;
|
|
unsigned long flags;
|
|
+ u32 reg;
|
|
|
|
if (priv->rx_dma_broken)
|
|
return -EINVAL;
|
|
@@ -897,6 +931,17 @@ static int omap_8250_rx_dma(struct uart_8250_port *p)
|
|
|
|
dma->rx_cookie = dmaengine_submit(desc);
|
|
|
|
+ /*
|
|
+ * Disable RX FIFO interrupt while RX DMA is enabled, else
|
|
+ * spurious interrupt may be raised when data is in the RX FIFO
|
|
+ * but is yet to be drained by DMA.
|
|
+ */
|
|
+ if (priv->habit & UART_HAS_RHR_IT_DIS) {
|
|
+ reg = serial_in(p, UART_OMAP_IER2);
|
|
+ reg |= UART_OMAP_IER2_RHR_IT_DIS;
|
|
+ serial_out(p, UART_OMAP_IER2, UART_OMAP_IER2_RHR_IT_DIS);
|
|
+ }
|
|
+
|
|
dma_async_issue_pending(dma->rxchan);
|
|
out:
|
|
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
|
|
@@ -1163,6 +1208,11 @@ static int omap8250_no_handle_irq(struct uart_port *port)
|
|
return 0;
|
|
}
|
|
|
|
+static const struct soc_device_attribute k3_soc_devices[] = {
|
|
+ { .family = "AM65X", },
|
|
+ { .family = "J721E", .revision = "SR1.0" },
|
|
+};
|
|
+
|
|
static struct omap8250_dma_params am654_dma = {
|
|
.rx_size = SZ_2K,
|
|
.rx_trigger = 1,
|
|
@@ -1177,7 +1227,8 @@ static struct omap8250_dma_params am33xx_dma = {
|
|
|
|
static struct omap8250_platdata am654_platdata = {
|
|
.dma_params = &am654_dma,
|
|
- .habit = UART_HAS_EFR2,
|
|
+ .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS |
|
|
+ UART_RX_TIMEOUT_QUIRK,
|
|
};
|
|
|
|
static struct omap8250_platdata am33xx_platdata = {
|
|
@@ -1367,6 +1418,13 @@ static int omap8250_probe(struct platform_device *pdev)
|
|
up.dma->rxconf.src_maxburst = RX_TRIGGER;
|
|
up.dma->txconf.dst_maxburst = TX_TRIGGER;
|
|
}
|
|
+
|
|
+ /*
|
|
+ * AM65x SR1.0, AM65x SR2.0 and J721e SR1.0 don't
|
|
+ * don't have RHR_IT_DIS bit in IER2 register
|
|
+ */
|
|
+ if (soc_device_match(k3_soc_devices))
|
|
+ priv->habit &= ~UART_HAS_RHR_IT_DIS;
|
|
}
|
|
#endif
|
|
ret = serial8250_register_8250_port(&up);
|
|
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
|
|
index 6e141429c9808..6d9c494bed7d2 100644
|
|
--- a/drivers/tty/serial/8250/8250_port.c
|
|
+++ b/drivers/tty/serial/8250/8250_port.c
|
|
@@ -2635,6 +2635,21 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
|
|
struct ktermios *old)
|
|
{
|
|
unsigned int tolerance = port->uartclk / 100;
|
|
+ unsigned int min;
|
|
+ unsigned int max;
|
|
+
|
|
+ /*
|
|
+ * Handle magic divisors for baud rates above baud_base on SMSC
|
|
+ * Super I/O chips. Enable custom rates of clk/4 and clk/8, but
|
|
+ * disable divisor values beyond 32767, which are unavailable.
|
|
+ */
|
|
+ if (port->flags & UPF_MAGIC_MULTIPLIER) {
|
|
+ min = port->uartclk / 16 / UART_DIV_MAX >> 1;
|
|
+ max = (port->uartclk + tolerance) / 4;
|
|
+ } else {
|
|
+ min = port->uartclk / 16 / UART_DIV_MAX;
|
|
+ max = (port->uartclk + tolerance) / 16;
|
|
+ }
|
|
|
|
/*
|
|
* Ask the core to calculate the divisor for us.
|
|
@@ -2642,9 +2657,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
|
|
* slower than nominal still match standard baud rates without
|
|
* causing transmission errors.
|
|
*/
|
|
- return uart_get_baud_rate(port, termios, old,
|
|
- port->uartclk / 16 / UART_DIV_MAX,
|
|
- (port->uartclk + tolerance) / 16);
|
|
+ return uart_get_baud_rate(port, termios, old, min, max);
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
|
|
index e3d10794dbba3..1d3ec8503cef3 100644
|
|
--- a/drivers/tty/serial/8250/serial_cs.c
|
|
+++ b/drivers/tty/serial/8250/serial_cs.c
|
|
@@ -780,6 +780,7 @@ static const struct pcmcia_device_id serial_ids[] = {
|
|
PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e),
|
|
PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a),
|
|
PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41),
|
|
+ PCMCIA_DEVICE_PROD_ID12("Option International", "GSM-Ready 56K/ISDN", 0x9d7cd6f5, 0xb23844aa),
|
|
PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab),
|
|
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f),
|
|
PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d),
|
|
@@ -807,7 +808,6 @@ static const struct pcmcia_device_id serial_ids[] = {
|
|
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
|
|
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"),
|
|
PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"),
|
|
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"),
|
|
PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100 1.00.", 0x19ca78af, 0xf964f42b),
|
|
PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100", 0x19ca78af, 0x71d98e83),
|
|
PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232 1.00.", 0x19ca78af, 0x69fb7490),
|
|
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
|
|
index bd047e1f9bea7..de5ee4aad9f34 100644
|
|
--- a/drivers/tty/serial/fsl_lpuart.c
|
|
+++ b/drivers/tty/serial/fsl_lpuart.c
|
|
@@ -1408,17 +1408,7 @@ static unsigned int lpuart_get_mctrl(struct uart_port *port)
|
|
|
|
static unsigned int lpuart32_get_mctrl(struct uart_port *port)
|
|
{
|
|
- unsigned int temp = 0;
|
|
- unsigned long reg;
|
|
-
|
|
- reg = lpuart32_read(port, UARTMODIR);
|
|
- if (reg & UARTMODIR_TXCTSE)
|
|
- temp |= TIOCM_CTS;
|
|
-
|
|
- if (reg & UARTMODIR_RXRTSE)
|
|
- temp |= TIOCM_RTS;
|
|
-
|
|
- return temp;
|
|
+ return 0;
|
|
}
|
|
|
|
static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
|
@@ -1625,7 +1615,7 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport)
|
|
sport->lpuart_dma_rx_use = true;
|
|
rx_dma_timer_init(sport);
|
|
|
|
- if (sport->port.has_sysrq) {
|
|
+ if (sport->port.has_sysrq && !lpuart_is_32(sport)) {
|
|
cr3 = readb(sport->port.membase + UARTCR3);
|
|
cr3 |= UARTCR3_FEIE;
|
|
writeb(cr3, sport->port.membase + UARTCR3);
|
|
diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c
|
|
index 51b0ecabf2ec9..1e26220c78527 100644
|
|
--- a/drivers/tty/serial/mvebu-uart.c
|
|
+++ b/drivers/tty/serial/mvebu-uart.c
|
|
@@ -445,12 +445,11 @@ static void mvebu_uart_shutdown(struct uart_port *port)
|
|
|
|
static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
|
|
{
|
|
- struct mvebu_uart *mvuart = to_mvuart(port);
|
|
unsigned int d_divisor, m_divisor;
|
|
u32 brdv, osamp;
|
|
|
|
- if (IS_ERR(mvuart->clk))
|
|
- return -PTR_ERR(mvuart->clk);
|
|
+ if (!port->uartclk)
|
|
+ return -EOPNOTSUPP;
|
|
|
|
/*
|
|
* The baudrate is derived from the UART clock thanks to two divisors:
|
|
@@ -463,7 +462,7 @@ static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud)
|
|
* makes use of D to configure the desired baudrate.
|
|
*/
|
|
m_divisor = OSAMP_DEFAULT_DIVISOR;
|
|
- d_divisor = DIV_ROUND_UP(port->uartclk, baud * m_divisor);
|
|
+ d_divisor = DIV_ROUND_CLOSEST(port->uartclk, baud * m_divisor);
|
|
|
|
brdv = readl(port->membase + UART_BRDV);
|
|
brdv &= ~BRDV_BAUD_MASK;
|
|
@@ -482,7 +481,7 @@ static void mvebu_uart_set_termios(struct uart_port *port,
|
|
struct ktermios *old)
|
|
{
|
|
unsigned long flags;
|
|
- unsigned int baud;
|
|
+ unsigned int baud, min_baud, max_baud;
|
|
|
|
spin_lock_irqsave(&port->lock, flags);
|
|
|
|
@@ -501,16 +500,21 @@ static void mvebu_uart_set_termios(struct uart_port *port,
|
|
port->ignore_status_mask |= STAT_RX_RDY(port) | STAT_BRK_ERR;
|
|
|
|
/*
|
|
+ * Maximal divisor is 1023 * 16 when using default (x16) scheme.
|
|
* Maximum achievable frequency with simple baudrate divisor is 230400.
|
|
* Since the error per bit frame would be of more than 15%, achieving
|
|
* higher frequencies would require to implement the fractional divisor
|
|
* feature.
|
|
*/
|
|
- baud = uart_get_baud_rate(port, termios, old, 0, 230400);
|
|
+ min_baud = DIV_ROUND_UP(port->uartclk, 1023 * 16);
|
|
+ max_baud = 230400;
|
|
+
|
|
+ baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud);
|
|
if (mvebu_uart_baud_rate_set(port, baud)) {
|
|
/* No clock available, baudrate cannot be changed */
|
|
if (old)
|
|
- baud = uart_get_baud_rate(port, old, NULL, 0, 230400);
|
|
+ baud = uart_get_baud_rate(port, old, NULL,
|
|
+ min_baud, max_baud);
|
|
} else {
|
|
tty_termios_encode_baud_rate(termios, baud, baud);
|
|
uart_update_timeout(port, termios->c_cflag, baud);
|
|
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
|
|
index 3b1aaa93d750e..70898a999a498 100644
|
|
--- a/drivers/tty/serial/sh-sci.c
|
|
+++ b/drivers/tty/serial/sh-sci.c
|
|
@@ -610,6 +610,14 @@ static void sci_stop_tx(struct uart_port *port)
|
|
ctrl &= ~SCSCR_TIE;
|
|
|
|
serial_port_out(port, SCSCR, ctrl);
|
|
+
|
|
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
|
+ if (to_sci_port(port)->chan_tx &&
|
|
+ !dma_submit_error(to_sci_port(port)->cookie_tx)) {
|
|
+ dmaengine_terminate_async(to_sci_port(port)->chan_tx);
|
|
+ to_sci_port(port)->cookie_tx = -EINVAL;
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
static void sci_start_rx(struct uart_port *port)
|
|
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
|
|
index 6fbabf56dbb76..df5b2d1e214f1 100644
|
|
--- a/drivers/usb/class/cdc-acm.c
|
|
+++ b/drivers/usb/class/cdc-acm.c
|
|
@@ -1948,6 +1948,11 @@ static const struct usb_device_id acm_ids[] = {
|
|
.driver_info = IGNORE_DEVICE,
|
|
},
|
|
|
|
+ /* Exclude Heimann Sensor GmbH USB appset demo */
|
|
+ { USB_DEVICE(0x32a7, 0x0000),
|
|
+ .driver_info = IGNORE_DEVICE,
|
|
+ },
|
|
+
|
|
/* control interfaces without any protocol set */
|
|
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
|
|
USB_CDC_PROTO_NONE) },
|
|
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
|
|
index fec17a2d2447d..15911ac7582b4 100644
|
|
--- a/drivers/usb/dwc2/core.c
|
|
+++ b/drivers/usb/dwc2/core.c
|
|
@@ -1167,15 +1167,6 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
|
|
usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16);
|
|
if (hsotg->params.phy_utmi_width == 16)
|
|
usbcfg |= GUSBCFG_PHYIF16;
|
|
-
|
|
- /* Set turnaround time */
|
|
- if (dwc2_is_device_mode(hsotg)) {
|
|
- usbcfg &= ~GUSBCFG_USBTRDTIM_MASK;
|
|
- if (hsotg->params.phy_utmi_width == 16)
|
|
- usbcfg |= 5 << GUSBCFG_USBTRDTIM_SHIFT;
|
|
- else
|
|
- usbcfg |= 9 << GUSBCFG_USBTRDTIM_SHIFT;
|
|
- }
|
|
break;
|
|
default:
|
|
dev_err(hsotg->dev, "FS PHY selected at HS!\n");
|
|
@@ -1197,6 +1188,24 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
|
|
return retval;
|
|
}
|
|
|
|
+static void dwc2_set_turnaround_time(struct dwc2_hsotg *hsotg)
|
|
+{
|
|
+ u32 usbcfg;
|
|
+
|
|
+ if (hsotg->params.phy_type != DWC2_PHY_TYPE_PARAM_UTMI)
|
|
+ return;
|
|
+
|
|
+ usbcfg = dwc2_readl(hsotg, GUSBCFG);
|
|
+
|
|
+ usbcfg &= ~GUSBCFG_USBTRDTIM_MASK;
|
|
+ if (hsotg->params.phy_utmi_width == 16)
|
|
+ usbcfg |= 5 << GUSBCFG_USBTRDTIM_SHIFT;
|
|
+ else
|
|
+ usbcfg |= 9 << GUSBCFG_USBTRDTIM_SHIFT;
|
|
+
|
|
+ dwc2_writel(hsotg, usbcfg, GUSBCFG);
|
|
+}
|
|
+
|
|
int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
|
|
{
|
|
u32 usbcfg;
|
|
@@ -1214,6 +1223,9 @@ int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
|
|
retval = dwc2_hs_phy_init(hsotg, select_phy);
|
|
if (retval)
|
|
return retval;
|
|
+
|
|
+ if (dwc2_is_device_mode(hsotg))
|
|
+ dwc2_set_turnaround_time(hsotg);
|
|
}
|
|
|
|
if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
|
|
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
|
|
index 7537dd50ad533..bfb72902f3a68 100644
|
|
--- a/drivers/usb/dwc3/core.c
|
|
+++ b/drivers/usb/dwc3/core.c
|
|
@@ -1590,17 +1590,18 @@ static int dwc3_probe(struct platform_device *pdev)
|
|
}
|
|
|
|
dwc3_check_params(dwc);
|
|
+ dwc3_debugfs_init(dwc);
|
|
|
|
ret = dwc3_core_init_mode(dwc);
|
|
if (ret)
|
|
goto err5;
|
|
|
|
- dwc3_debugfs_init(dwc);
|
|
pm_runtime_put(dev);
|
|
|
|
return 0;
|
|
|
|
err5:
|
|
+ dwc3_debugfs_exit(dwc);
|
|
dwc3_event_buffers_cleanup(dwc);
|
|
|
|
usb_phy_shutdown(dwc->usb2_phy);
|
|
diff --git a/drivers/usb/gadget/function/f_eem.c b/drivers/usb/gadget/function/f_eem.c
|
|
index 2cd9942707b46..5d38f29bda720 100644
|
|
--- a/drivers/usb/gadget/function/f_eem.c
|
|
+++ b/drivers/usb/gadget/function/f_eem.c
|
|
@@ -30,6 +30,11 @@ struct f_eem {
|
|
u8 ctrl_id;
|
|
};
|
|
|
|
+struct in_context {
|
|
+ struct sk_buff *skb;
|
|
+ struct usb_ep *ep;
|
|
+};
|
|
+
|
|
static inline struct f_eem *func_to_eem(struct usb_function *f)
|
|
{
|
|
return container_of(f, struct f_eem, port.func);
|
|
@@ -320,9 +325,12 @@ fail:
|
|
|
|
static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req)
|
|
{
|
|
- struct sk_buff *skb = (struct sk_buff *)req->context;
|
|
+ struct in_context *ctx = req->context;
|
|
|
|
- dev_kfree_skb_any(skb);
|
|
+ dev_kfree_skb_any(ctx->skb);
|
|
+ kfree(req->buf);
|
|
+ usb_ep_free_request(ctx->ep, req);
|
|
+ kfree(ctx);
|
|
}
|
|
|
|
/*
|
|
@@ -410,7 +418,9 @@ static int eem_unwrap(struct gether *port,
|
|
* b15: bmType (0 == data, 1 == command)
|
|
*/
|
|
if (header & BIT(15)) {
|
|
- struct usb_request *req = cdev->req;
|
|
+ struct usb_request *req;
|
|
+ struct in_context *ctx;
|
|
+ struct usb_ep *ep;
|
|
u16 bmEEMCmd;
|
|
|
|
/* EEM command packet format:
|
|
@@ -439,11 +449,36 @@ static int eem_unwrap(struct gether *port,
|
|
skb_trim(skb2, len);
|
|
put_unaligned_le16(BIT(15) | BIT(11) | len,
|
|
skb_push(skb2, 2));
|
|
+
|
|
+ ep = port->in_ep;
|
|
+ req = usb_ep_alloc_request(ep, GFP_ATOMIC);
|
|
+ if (!req) {
|
|
+ dev_kfree_skb_any(skb2);
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ req->buf = kmalloc(skb2->len, GFP_KERNEL);
|
|
+ if (!req->buf) {
|
|
+ usb_ep_free_request(ep, req);
|
|
+ dev_kfree_skb_any(skb2);
|
|
+ goto next;
|
|
+ }
|
|
+
|
|
+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
|
|
+ if (!ctx) {
|
|
+ kfree(req->buf);
|
|
+ usb_ep_free_request(ep, req);
|
|
+ dev_kfree_skb_any(skb2);
|
|
+ goto next;
|
|
+ }
|
|
+ ctx->skb = skb2;
|
|
+ ctx->ep = ep;
|
|
+
|
|
skb_copy_bits(skb2, 0, req->buf, skb2->len);
|
|
req->length = skb2->len;
|
|
req->complete = eem_cmd_complete;
|
|
req->zero = 1;
|
|
- req->context = skb2;
|
|
+ req->context = ctx;
|
|
if (usb_ep_queue(port->in_ep, req, GFP_ATOMIC))
|
|
DBG(cdev, "echo response queue fail\n");
|
|
break;
|
|
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
|
|
index 7df180b110afc..725e35167837e 100644
|
|
--- a/drivers/usb/gadget/function/f_fs.c
|
|
+++ b/drivers/usb/gadget/function/f_fs.c
|
|
@@ -250,8 +250,8 @@ EXPORT_SYMBOL_GPL(ffs_lock);
|
|
static struct ffs_dev *_ffs_find_dev(const char *name);
|
|
static struct ffs_dev *_ffs_alloc_dev(void);
|
|
static void _ffs_free_dev(struct ffs_dev *dev);
|
|
-static void *ffs_acquire_dev(const char *dev_name);
|
|
-static void ffs_release_dev(struct ffs_data *ffs_data);
|
|
+static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data);
|
|
+static void ffs_release_dev(struct ffs_dev *ffs_dev);
|
|
static int ffs_ready(struct ffs_data *ffs);
|
|
static void ffs_closed(struct ffs_data *ffs);
|
|
|
|
@@ -1553,8 +1553,8 @@ unmapped_value:
|
|
static int ffs_fs_get_tree(struct fs_context *fc)
|
|
{
|
|
struct ffs_sb_fill_data *ctx = fc->fs_private;
|
|
- void *ffs_dev;
|
|
struct ffs_data *ffs;
|
|
+ int ret;
|
|
|
|
ENTER();
|
|
|
|
@@ -1573,13 +1573,12 @@ static int ffs_fs_get_tree(struct fs_context *fc)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- ffs_dev = ffs_acquire_dev(ffs->dev_name);
|
|
- if (IS_ERR(ffs_dev)) {
|
|
+ ret = ffs_acquire_dev(ffs->dev_name, ffs);
|
|
+ if (ret) {
|
|
ffs_data_put(ffs);
|
|
- return PTR_ERR(ffs_dev);
|
|
+ return ret;
|
|
}
|
|
|
|
- ffs->private_data = ffs_dev;
|
|
ctx->ffs_data = ffs;
|
|
return get_tree_nodev(fc, ffs_sb_fill);
|
|
}
|
|
@@ -1590,7 +1589,6 @@ static void ffs_fs_free_fc(struct fs_context *fc)
|
|
|
|
if (ctx) {
|
|
if (ctx->ffs_data) {
|
|
- ffs_release_dev(ctx->ffs_data);
|
|
ffs_data_put(ctx->ffs_data);
|
|
}
|
|
|
|
@@ -1629,10 +1627,8 @@ ffs_fs_kill_sb(struct super_block *sb)
|
|
ENTER();
|
|
|
|
kill_litter_super(sb);
|
|
- if (sb->s_fs_info) {
|
|
- ffs_release_dev(sb->s_fs_info);
|
|
+ if (sb->s_fs_info)
|
|
ffs_data_closed(sb->s_fs_info);
|
|
- }
|
|
}
|
|
|
|
static struct file_system_type ffs_fs_type = {
|
|
@@ -1702,6 +1698,7 @@ static void ffs_data_put(struct ffs_data *ffs)
|
|
if (unlikely(refcount_dec_and_test(&ffs->ref))) {
|
|
pr_info("%s(): freeing\n", __func__);
|
|
ffs_data_clear(ffs);
|
|
+ ffs_release_dev(ffs->private_data);
|
|
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
|
|
swait_active(&ffs->ep0req_completion.wait) ||
|
|
waitqueue_active(&ffs->wait));
|
|
@@ -3031,6 +3028,7 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
|
|
struct ffs_function *func = ffs_func_from_usb(f);
|
|
struct f_fs_opts *ffs_opts =
|
|
container_of(f->fi, struct f_fs_opts, func_inst);
|
|
+ struct ffs_data *ffs_data;
|
|
int ret;
|
|
|
|
ENTER();
|
|
@@ -3045,12 +3043,13 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
|
|
if (!ffs_opts->no_configfs)
|
|
ffs_dev_lock();
|
|
ret = ffs_opts->dev->desc_ready ? 0 : -ENODEV;
|
|
- func->ffs = ffs_opts->dev->ffs_data;
|
|
+ ffs_data = ffs_opts->dev->ffs_data;
|
|
if (!ffs_opts->no_configfs)
|
|
ffs_dev_unlock();
|
|
if (ret)
|
|
return ERR_PTR(ret);
|
|
|
|
+ func->ffs = ffs_data;
|
|
func->conf = c;
|
|
func->gadget = c->cdev->gadget;
|
|
|
|
@@ -3505,6 +3504,7 @@ static void ffs_free_inst(struct usb_function_instance *f)
|
|
struct f_fs_opts *opts;
|
|
|
|
opts = to_f_fs_opts(f);
|
|
+ ffs_release_dev(opts->dev);
|
|
ffs_dev_lock();
|
|
_ffs_free_dev(opts->dev);
|
|
ffs_dev_unlock();
|
|
@@ -3692,47 +3692,48 @@ static void _ffs_free_dev(struct ffs_dev *dev)
|
|
{
|
|
list_del(&dev->entry);
|
|
|
|
- /* Clear the private_data pointer to stop incorrect dev access */
|
|
- if (dev->ffs_data)
|
|
- dev->ffs_data->private_data = NULL;
|
|
-
|
|
kfree(dev);
|
|
if (list_empty(&ffs_devices))
|
|
functionfs_cleanup();
|
|
}
|
|
|
|
-static void *ffs_acquire_dev(const char *dev_name)
|
|
+static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data)
|
|
{
|
|
+ int ret = 0;
|
|
struct ffs_dev *ffs_dev;
|
|
|
|
ENTER();
|
|
ffs_dev_lock();
|
|
|
|
ffs_dev = _ffs_find_dev(dev_name);
|
|
- if (!ffs_dev)
|
|
- ffs_dev = ERR_PTR(-ENOENT);
|
|
- else if (ffs_dev->mounted)
|
|
- ffs_dev = ERR_PTR(-EBUSY);
|
|
- else if (ffs_dev->ffs_acquire_dev_callback &&
|
|
- ffs_dev->ffs_acquire_dev_callback(ffs_dev))
|
|
- ffs_dev = ERR_PTR(-ENOENT);
|
|
- else
|
|
+ if (!ffs_dev) {
|
|
+ ret = -ENOENT;
|
|
+ } else if (ffs_dev->mounted) {
|
|
+ ret = -EBUSY;
|
|
+ } else if (ffs_dev->ffs_acquire_dev_callback &&
|
|
+ ffs_dev->ffs_acquire_dev_callback(ffs_dev)) {
|
|
+ ret = -ENOENT;
|
|
+ } else {
|
|
ffs_dev->mounted = true;
|
|
+ ffs_dev->ffs_data = ffs_data;
|
|
+ ffs_data->private_data = ffs_dev;
|
|
+ }
|
|
|
|
ffs_dev_unlock();
|
|
- return ffs_dev;
|
|
+ return ret;
|
|
}
|
|
|
|
-static void ffs_release_dev(struct ffs_data *ffs_data)
|
|
+static void ffs_release_dev(struct ffs_dev *ffs_dev)
|
|
{
|
|
- struct ffs_dev *ffs_dev;
|
|
-
|
|
ENTER();
|
|
ffs_dev_lock();
|
|
|
|
- ffs_dev = ffs_data->private_data;
|
|
- if (ffs_dev) {
|
|
+ if (ffs_dev && ffs_dev->mounted) {
|
|
ffs_dev->mounted = false;
|
|
+ if (ffs_dev->ffs_data) {
|
|
+ ffs_dev->ffs_data->private_data = NULL;
|
|
+ ffs_dev->ffs_data = NULL;
|
|
+ }
|
|
|
|
if (ffs_dev->ffs_release_dev_callback)
|
|
ffs_dev->ffs_release_dev_callback(ffs_dev);
|
|
@@ -3760,7 +3761,6 @@ static int ffs_ready(struct ffs_data *ffs)
|
|
}
|
|
|
|
ffs_obj->desc_ready = true;
|
|
- ffs_obj->ffs_data = ffs;
|
|
|
|
if (ffs_obj->ffs_ready_callback) {
|
|
ret = ffs_obj->ffs_ready_callback(ffs);
|
|
@@ -3788,7 +3788,6 @@ static void ffs_closed(struct ffs_data *ffs)
|
|
goto done;
|
|
|
|
ffs_obj->desc_ready = false;
|
|
- ffs_obj->ffs_data = NULL;
|
|
|
|
if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags) &&
|
|
ffs_obj->ffs_closed_callback)
|
|
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
|
|
index 8ce043e6ed872..ed380ee58ab5d 100644
|
|
--- a/drivers/usb/host/xhci-mem.c
|
|
+++ b/drivers/usb/host/xhci-mem.c
|
|
@@ -1938,6 +1938,7 @@ no_bw:
|
|
xhci->hw_ports = NULL;
|
|
xhci->rh_bw = NULL;
|
|
xhci->ext_caps = NULL;
|
|
+ xhci->port_caps = NULL;
|
|
|
|
xhci->page_size = 0;
|
|
xhci->page_shift = 0;
|
|
diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c
|
|
index f97ac9f52bf4d..431213cdf9e0e 100644
|
|
--- a/drivers/usb/host/xhci-pci-renesas.c
|
|
+++ b/drivers/usb/host/xhci-pci-renesas.c
|
|
@@ -207,7 +207,8 @@ static int renesas_check_rom_state(struct pci_dev *pdev)
|
|
return 0;
|
|
|
|
case RENESAS_ROM_STATUS_NO_RESULT: /* No result yet */
|
|
- return 0;
|
|
+ dev_dbg(&pdev->dev, "Unknown ROM status ...\n");
|
|
+ break;
|
|
|
|
case RENESAS_ROM_STATUS_ERROR: /* Error State */
|
|
default: /* All other states are marked as "Reserved states" */
|
|
@@ -224,13 +225,12 @@ static int renesas_fw_check_running(struct pci_dev *pdev)
|
|
u8 fw_state;
|
|
int err;
|
|
|
|
- /* Check if device has ROM and loaded, if so skip everything */
|
|
- err = renesas_check_rom(pdev);
|
|
- if (err) { /* we have rom */
|
|
- err = renesas_check_rom_state(pdev);
|
|
- if (!err)
|
|
- return err;
|
|
- }
|
|
+ /*
|
|
+ * Only if device has ROM and loaded FW we can skip loading and
|
|
+ * return success. Otherwise (even unknown state), attempt to load FW.
|
|
+ */
|
|
+ if (renesas_check_rom(pdev) && !renesas_check_rom_state(pdev))
|
|
+ return 0;
|
|
|
|
/*
|
|
* Test if the device is actually needing the firmware. As most
|
|
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
|
|
index 35eec707cb512..c7d44daa05c4a 100644
|
|
--- a/drivers/usb/typec/class.c
|
|
+++ b/drivers/usb/typec/class.c
|
|
@@ -446,8 +446,10 @@ typec_register_altmode(struct device *parent,
|
|
int ret;
|
|
|
|
alt = kzalloc(sizeof(*alt), GFP_KERNEL);
|
|
- if (!alt)
|
|
+ if (!alt) {
|
|
+ altmode_id_remove(parent, id);
|
|
return ERR_PTR(-ENOMEM);
|
|
+ }
|
|
|
|
alt->adev.svid = desc->svid;
|
|
alt->adev.mode = desc->mode;
|
|
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
|
|
index 48b048edf1ee8..57ae8b46b8361 100644
|
|
--- a/drivers/vfio/pci/vfio_pci.c
|
|
+++ b/drivers/vfio/pci/vfio_pci.c
|
|
@@ -1614,6 +1614,7 @@ static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf)
|
|
{
|
|
struct vm_area_struct *vma = vmf->vma;
|
|
struct vfio_pci_device *vdev = vma->vm_private_data;
|
|
+ struct vfio_pci_mmap_vma *mmap_vma;
|
|
vm_fault_t ret = VM_FAULT_NOPAGE;
|
|
|
|
mutex_lock(&vdev->vma_lock);
|
|
@@ -1621,24 +1622,36 @@ static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf)
|
|
|
|
if (!__vfio_pci_memory_enabled(vdev)) {
|
|
ret = VM_FAULT_SIGBUS;
|
|
- mutex_unlock(&vdev->vma_lock);
|
|
goto up_out;
|
|
}
|
|
|
|
- if (__vfio_pci_add_vma(vdev, vma)) {
|
|
- ret = VM_FAULT_OOM;
|
|
- mutex_unlock(&vdev->vma_lock);
|
|
- goto up_out;
|
|
+ /*
|
|
+ * We populate the whole vma on fault, so we need to test whether
|
|
+ * the vma has already been mapped, such as for concurrent faults
|
|
+ * to the same vma. io_remap_pfn_range() will trigger a BUG_ON if
|
|
+ * we ask it to fill the same range again.
|
|
+ */
|
|
+ list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) {
|
|
+ if (mmap_vma->vma == vma)
|
|
+ goto up_out;
|
|
}
|
|
|
|
- mutex_unlock(&vdev->vma_lock);
|
|
-
|
|
if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
|
- vma->vm_end - vma->vm_start, vma->vm_page_prot))
|
|
+ vma->vm_end - vma->vm_start,
|
|
+ vma->vm_page_prot)) {
|
|
ret = VM_FAULT_SIGBUS;
|
|
+ zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
|
|
+ goto up_out;
|
|
+ }
|
|
+
|
|
+ if (__vfio_pci_add_vma(vdev, vma)) {
|
|
+ ret = VM_FAULT_OOM;
|
|
+ zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
|
|
+ }
|
|
|
|
up_out:
|
|
up_read(&vdev->memory_lock);
|
|
+ mutex_unlock(&vdev->vma_lock);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c
|
|
index e88a2b0e59046..662029d6a3dc9 100644
|
|
--- a/drivers/video/backlight/lm3630a_bl.c
|
|
+++ b/drivers/video/backlight/lm3630a_bl.c
|
|
@@ -482,8 +482,10 @@ static int lm3630a_parse_node(struct lm3630a_chip *pchip,
|
|
|
|
device_for_each_child_node(pchip->dev, node) {
|
|
ret = lm3630a_parse_bank(pdata, node, &seen_led_sources);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
+ fwnode_handle_put(node);
|
|
return ret;
|
|
+ }
|
|
}
|
|
|
|
return ret;
|
|
diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
|
|
index 884b16efa7e8a..564bd0407ed81 100644
|
|
--- a/drivers/video/fbdev/imxfb.c
|
|
+++ b/drivers/video/fbdev/imxfb.c
|
|
@@ -992,7 +992,7 @@ static int imxfb_probe(struct platform_device *pdev)
|
|
info->screen_buffer = dma_alloc_wc(&pdev->dev, fbi->map_size,
|
|
&fbi->map_dma, GFP_KERNEL);
|
|
if (!info->screen_buffer) {
|
|
- dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
|
|
+ dev_err(&pdev->dev, "Failed to allocate video RAM\n");
|
|
ret = -ENOMEM;
|
|
goto failed_map;
|
|
}
|
|
diff --git a/drivers/visorbus/visorchipset.c b/drivers/visorbus/visorchipset.c
|
|
index cb1eb7e05f871..5668cad86e374 100644
|
|
--- a/drivers/visorbus/visorchipset.c
|
|
+++ b/drivers/visorbus/visorchipset.c
|
|
@@ -1561,7 +1561,7 @@ schedule_out:
|
|
|
|
static int visorchipset_init(struct acpi_device *acpi_device)
|
|
{
|
|
- int err = -ENODEV;
|
|
+ int err = -ENOMEM;
|
|
struct visorchannel *controlvm_channel;
|
|
|
|
chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL);
|
|
@@ -1584,8 +1584,10 @@ static int visorchipset_init(struct acpi_device *acpi_device)
|
|
"controlvm",
|
|
sizeof(struct visor_controlvm_channel),
|
|
VISOR_CONTROLVM_CHANNEL_VERSIONID,
|
|
- VISOR_CHANNEL_SIGNATURE))
|
|
+ VISOR_CHANNEL_SIGNATURE)) {
|
|
+ err = -ENODEV;
|
|
goto error_delete_groups;
|
|
+ }
|
|
/* if booting in a crash kernel */
|
|
if (is_kdump_kernel())
|
|
INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work,
|
|
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
|
|
index 68b95ad82126e..520a0f6a7d9e9 100644
|
|
--- a/fs/btrfs/Kconfig
|
|
+++ b/fs/btrfs/Kconfig
|
|
@@ -18,6 +18,8 @@ config BTRFS_FS
|
|
select RAID6_PQ
|
|
select XOR_BLOCKS
|
|
select SRCU
|
|
+ depends on !PPC_256K_PAGES # powerpc
|
|
+ depends on !PAGE_SIZE_256KB # hexagon
|
|
|
|
help
|
|
Btrfs is a general purpose copy-on-write filesystem with extents,
|
|
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
|
|
index 4e2cce5ca7f6a..04422d929c232 100644
|
|
--- a/fs/btrfs/delayed-inode.c
|
|
+++ b/fs/btrfs/delayed-inode.c
|
|
@@ -1032,12 +1032,10 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
|
|
nofs_flag = memalloc_nofs_save();
|
|
ret = btrfs_lookup_inode(trans, root, path, &key, mod);
|
|
memalloc_nofs_restore(nofs_flag);
|
|
- if (ret > 0) {
|
|
- btrfs_release_path(path);
|
|
- return -ENOENT;
|
|
- } else if (ret < 0) {
|
|
- return ret;
|
|
- }
|
|
+ if (ret > 0)
|
|
+ ret = -ENOENT;
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
|
|
leaf = path->nodes[0];
|
|
inode_item = btrfs_item_ptr(leaf, path->slots[0],
|
|
@@ -1075,6 +1073,14 @@ err_out:
|
|
btrfs_delayed_inode_release_metadata(fs_info, node, (ret < 0));
|
|
btrfs_release_delayed_inode(node);
|
|
|
|
+ /*
|
|
+ * If we fail to update the delayed inode we need to abort the
|
|
+ * transaction, because we could leave the inode with the improper
|
|
+ * counts behind.
|
|
+ */
|
|
+ if (ret && ret != -ENOENT)
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
+
|
|
return ret;
|
|
|
|
search:
|
|
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
|
|
index 4f26dae63b64a..4f21b8fbfd4bc 100644
|
|
--- a/fs/btrfs/inode.c
|
|
+++ b/fs/btrfs/inode.c
|
|
@@ -547,7 +547,7 @@ again:
|
|
* inode has not been flagged as nocompress. This flag can
|
|
* change at any time if we discover bad compression ratios.
|
|
*/
|
|
- if (inode_need_compress(BTRFS_I(inode), start, end)) {
|
|
+ if (nr_pages > 1 && inode_need_compress(BTRFS_I(inode), start, end)) {
|
|
WARN_ON(pages);
|
|
pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
|
|
if (!pages) {
|
|
@@ -8213,7 +8213,19 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
|
|
*/
|
|
wait_on_page_writeback(page);
|
|
|
|
- if (offset) {
|
|
+ /*
|
|
+ * For subpage case, we have call sites like
|
|
+ * btrfs_punch_hole_lock_range() which passes range not aligned to
|
|
+ * sectorsize.
|
|
+ * If the range doesn't cover the full page, we don't need to and
|
|
+ * shouldn't clear page extent mapped, as page->private can still
|
|
+ * record subpage dirty bits for other part of the range.
|
|
+ *
|
|
+ * For cases that can invalidate the full even the range doesn't
|
|
+ * cover the full page, like invalidating the last page, we're
|
|
+ * still safe to wait for ordered extent to finish.
|
|
+ */
|
|
+ if (!(offset == 0 && length == PAGE_SIZE)) {
|
|
btrfs_releasepage(page, GFP_NOFS);
|
|
return;
|
|
}
|
|
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
|
|
index 9e5809118c34d..10f020ab1186f 100644
|
|
--- a/fs/btrfs/send.c
|
|
+++ b/fs/btrfs/send.c
|
|
@@ -4080,6 +4080,17 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
|
|
if (ret < 0)
|
|
goto out;
|
|
} else {
|
|
+ /*
|
|
+ * If we previously orphanized a directory that
|
|
+ * collided with a new reference that we already
|
|
+ * processed, recompute the current path because
|
|
+ * that directory may be part of the path.
|
|
+ */
|
|
+ if (orphanized_dir) {
|
|
+ ret = refresh_ref_path(sctx, cur);
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
+ }
|
|
ret = send_unlink(sctx, cur->full_path);
|
|
if (ret < 0)
|
|
goto out;
|
|
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
|
|
index 279d9262b676d..3bb6b688ece52 100644
|
|
--- a/fs/btrfs/sysfs.c
|
|
+++ b/fs/btrfs/sysfs.c
|
|
@@ -382,7 +382,7 @@ static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj,
|
|
{
|
|
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%lld\n",
|
|
+ return scnprintf(buf, PAGE_SIZE, "%llu\n",
|
|
fs_info->discard_ctl.discard_bitmap_bytes);
|
|
}
|
|
BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show);
|
|
@@ -404,7 +404,7 @@ static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj,
|
|
{
|
|
struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
|
|
|
|
- return scnprintf(buf, PAGE_SIZE, "%lld\n",
|
|
+ return scnprintf(buf, PAGE_SIZE, "%llu\n",
|
|
fs_info->discard_ctl.discard_extent_bytes);
|
|
}
|
|
BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show);
|
|
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
|
|
index af2f2f8704d8b..8daa9e4eb1d2e 100644
|
|
--- a/fs/btrfs/transaction.c
|
|
+++ b/fs/btrfs/transaction.c
|
|
@@ -1382,8 +1382,10 @@ int btrfs_defrag_root(struct btrfs_root *root)
|
|
|
|
while (1) {
|
|
trans = btrfs_start_transaction(root, 0);
|
|
- if (IS_ERR(trans))
|
|
- return PTR_ERR(trans);
|
|
+ if (IS_ERR(trans)) {
|
|
+ ret = PTR_ERR(trans);
|
|
+ break;
|
|
+ }
|
|
|
|
ret = btrfs_defrag_leaves(trans, root);
|
|
|
|
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
|
|
index 300951088a11c..4b913de2f24fb 100644
|
|
--- a/fs/btrfs/tree-log.c
|
|
+++ b/fs/btrfs/tree-log.c
|
|
@@ -6348,6 +6348,7 @@ next:
|
|
error:
|
|
if (wc.trans)
|
|
btrfs_end_transaction(wc.trans);
|
|
+ clear_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags);
|
|
btrfs_free_path(path);
|
|
return ret;
|
|
}
|
|
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
|
|
index 248ee81e01516..6599069be690e 100644
|
|
--- a/fs/cifs/cifsglob.h
|
|
+++ b/fs/cifs/cifsglob.h
|
|
@@ -979,7 +979,7 @@ struct cifs_ses {
|
|
struct mutex session_mutex;
|
|
struct TCP_Server_Info *server; /* pointer to server info */
|
|
int ses_count; /* reference counter */
|
|
- enum statusEnum status;
|
|
+ enum statusEnum status; /* updates protected by GlobalMid_Lock */
|
|
unsigned overrideSecFlg; /* if non-zero override global sec flags */
|
|
char *serverOS; /* name of operating system underlying server */
|
|
char *serverNOS; /* name of network operating system of server */
|
|
@@ -1863,6 +1863,7 @@ require use of the stronger protocol */
|
|
* list operations on pending_mid_q and oplockQ
|
|
* updates to XID counters, multiplex id and SMB sequence numbers
|
|
* list operations on global DnotifyReqList
|
|
+ * updates to ses->status
|
|
* tcp_ses_lock protects:
|
|
* list operations on tcp and SMB session lists
|
|
* tcon->open_file_lock protects the list of open files hanging off the tcon
|
|
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
|
|
index aabaebd1535f0..fb7088d57e46f 100644
|
|
--- a/fs/cifs/connect.c
|
|
+++ b/fs/cifs/connect.c
|
|
@@ -2829,9 +2829,12 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
|
|
spin_unlock(&cifs_tcp_ses_lock);
|
|
return;
|
|
}
|
|
+ spin_unlock(&cifs_tcp_ses_lock);
|
|
+
|
|
+ spin_lock(&GlobalMid_Lock);
|
|
if (ses->status == CifsGood)
|
|
ses->status = CifsExiting;
|
|
- spin_unlock(&cifs_tcp_ses_lock);
|
|
+ spin_unlock(&GlobalMid_Lock);
|
|
|
|
cifs_free_ipc(ses);
|
|
|
|
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
|
|
index a9d1555301446..f6ceb79a995d0 100644
|
|
--- a/fs/cifs/smb2ops.c
|
|
+++ b/fs/cifs/smb2ops.c
|
|
@@ -3459,6 +3459,119 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
|
|
return rc;
|
|
}
|
|
|
|
+static int smb3_simple_fallocate_write_range(unsigned int xid,
|
|
+ struct cifs_tcon *tcon,
|
|
+ struct cifsFileInfo *cfile,
|
|
+ loff_t off, loff_t len,
|
|
+ char *buf)
|
|
+{
|
|
+ struct cifs_io_parms io_parms = {0};
|
|
+ int nbytes;
|
|
+ struct kvec iov[2];
|
|
+
|
|
+ io_parms.netfid = cfile->fid.netfid;
|
|
+ io_parms.pid = current->tgid;
|
|
+ io_parms.tcon = tcon;
|
|
+ io_parms.persistent_fid = cfile->fid.persistent_fid;
|
|
+ io_parms.volatile_fid = cfile->fid.volatile_fid;
|
|
+ io_parms.offset = off;
|
|
+ io_parms.length = len;
|
|
+
|
|
+ /* iov[0] is reserved for smb header */
|
|
+ iov[1].iov_base = buf;
|
|
+ iov[1].iov_len = io_parms.length;
|
|
+ return SMB2_write(xid, &io_parms, &nbytes, iov, 1);
|
|
+}
|
|
+
|
|
+static int smb3_simple_fallocate_range(unsigned int xid,
|
|
+ struct cifs_tcon *tcon,
|
|
+ struct cifsFileInfo *cfile,
|
|
+ loff_t off, loff_t len)
|
|
+{
|
|
+ struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data;
|
|
+ u32 out_data_len;
|
|
+ char *buf = NULL;
|
|
+ loff_t l;
|
|
+ int rc;
|
|
+
|
|
+ in_data.file_offset = cpu_to_le64(off);
|
|
+ in_data.length = cpu_to_le64(len);
|
|
+ rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
|
|
+ cfile->fid.volatile_fid,
|
|
+ FSCTL_QUERY_ALLOCATED_RANGES, true,
|
|
+ (char *)&in_data, sizeof(in_data),
|
|
+ 1024 * sizeof(struct file_allocated_range_buffer),
|
|
+ (char **)&out_data, &out_data_len);
|
|
+ if (rc)
|
|
+ goto out;
|
|
+ /*
|
|
+ * It is already all allocated
|
|
+ */
|
|
+ if (out_data_len == 0)
|
|
+ goto out;
|
|
+
|
|
+ buf = kzalloc(1024 * 1024, GFP_KERNEL);
|
|
+ if (buf == NULL) {
|
|
+ rc = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ tmp_data = out_data;
|
|
+ while (len) {
|
|
+ /*
|
|
+ * The rest of the region is unmapped so write it all.
|
|
+ */
|
|
+ if (out_data_len == 0) {
|
|
+ rc = smb3_simple_fallocate_write_range(xid, tcon,
|
|
+ cfile, off, len, buf);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (out_data_len < sizeof(struct file_allocated_range_buffer)) {
|
|
+ rc = -EINVAL;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (off < le64_to_cpu(tmp_data->file_offset)) {
|
|
+ /*
|
|
+ * We are at a hole. Write until the end of the region
|
|
+ * or until the next allocated data,
|
|
+ * whichever comes next.
|
|
+ */
|
|
+ l = le64_to_cpu(tmp_data->file_offset) - off;
|
|
+ if (len < l)
|
|
+ l = len;
|
|
+ rc = smb3_simple_fallocate_write_range(xid, tcon,
|
|
+ cfile, off, l, buf);
|
|
+ if (rc)
|
|
+ goto out;
|
|
+ off = off + l;
|
|
+ len = len - l;
|
|
+ if (len == 0)
|
|
+ goto out;
|
|
+ }
|
|
+ /*
|
|
+ * We are at a section of allocated data, just skip forward
|
|
+ * until the end of the data or the end of the region
|
|
+ * we are supposed to fallocate, whichever comes first.
|
|
+ */
|
|
+ l = le64_to_cpu(tmp_data->length);
|
|
+ if (len < l)
|
|
+ l = len;
|
|
+ off += l;
|
|
+ len -= l;
|
|
+
|
|
+ tmp_data = &tmp_data[1];
|
|
+ out_data_len -= sizeof(struct file_allocated_range_buffer);
|
|
+ }
|
|
+
|
|
+ out:
|
|
+ kfree(out_data);
|
|
+ kfree(buf);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+
|
|
static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
|
|
loff_t off, loff_t len, bool keep_size)
|
|
{
|
|
@@ -3519,6 +3632,26 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
|
|
}
|
|
|
|
if ((keep_size == true) || (i_size_read(inode) >= off + len)) {
|
|
+ /*
|
|
+ * At this point, we are trying to fallocate an internal
|
|
+ * regions of a sparse file. Since smb2 does not have a
|
|
+ * fallocate command we have two otions on how to emulate this.
|
|
+ * We can either turn the entire file to become non-sparse
|
|
+ * which we only do if the fallocate is for virtually
|
|
+ * the whole file, or we can overwrite the region with zeroes
|
|
+ * using SMB2_write, which could be prohibitevly expensive
|
|
+ * if len is large.
|
|
+ */
|
|
+ /*
|
|
+ * We are only trying to fallocate a small region so
|
|
+ * just write it with zero.
|
|
+ */
|
|
+ if (len <= 1024 * 1024) {
|
|
+ rc = smb3_simple_fallocate_range(xid, tcon, cfile,
|
|
+ off, len);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
/*
|
|
* Check if falloc starts within first few pages of file
|
|
* and ends within a few pages of the end of file to
|
|
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
|
|
index da8351d1e4552..4d0825213116a 100644
|
|
--- a/fs/configfs/file.c
|
|
+++ b/fs/configfs/file.c
|
|
@@ -482,13 +482,13 @@ static int configfs_release_bin_file(struct inode *inode, struct file *file)
|
|
buffer->bin_buffer_size);
|
|
}
|
|
up_read(&frag->frag_sem);
|
|
- /* vfree on NULL is safe */
|
|
- vfree(buffer->bin_buffer);
|
|
- buffer->bin_buffer = NULL;
|
|
- buffer->bin_buffer_size = 0;
|
|
- buffer->needs_read_fill = 1;
|
|
}
|
|
|
|
+ vfree(buffer->bin_buffer);
|
|
+ buffer->bin_buffer = NULL;
|
|
+ buffer->bin_buffer_size = 0;
|
|
+ buffer->needs_read_fill = 1;
|
|
+
|
|
configfs_release(inode, file);
|
|
return 0;
|
|
}
|
|
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
|
|
index 1fbe6c24d7052..9fa871e287ba3 100644
|
|
--- a/fs/crypto/fname.c
|
|
+++ b/fs/crypto/fname.c
|
|
@@ -344,13 +344,9 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
|
|
offsetof(struct fscrypt_nokey_name, sha256));
|
|
BUILD_BUG_ON(BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX) > NAME_MAX);
|
|
|
|
- if (hash) {
|
|
- nokey_name.dirhash[0] = hash;
|
|
- nokey_name.dirhash[1] = minor_hash;
|
|
- } else {
|
|
- nokey_name.dirhash[0] = 0;
|
|
- nokey_name.dirhash[1] = 0;
|
|
- }
|
|
+ nokey_name.dirhash[0] = hash;
|
|
+ nokey_name.dirhash[1] = minor_hash;
|
|
+
|
|
if (iname->len <= sizeof(nokey_name.bytes)) {
|
|
memcpy(nokey_name.bytes, iname->name, iname->len);
|
|
size = offsetof(struct fscrypt_nokey_name, bytes[iname->len]);
|
|
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
|
|
index 31fb08d94f874..9a6f9a188efb9 100644
|
|
--- a/fs/crypto/keysetup.c
|
|
+++ b/fs/crypto/keysetup.c
|
|
@@ -210,15 +210,40 @@ out_unlock:
|
|
return err;
|
|
}
|
|
|
|
+/*
|
|
+ * Derive a SipHash key from the given fscrypt master key and the given
|
|
+ * application-specific information string.
|
|
+ *
|
|
+ * Note that the KDF produces a byte array, but the SipHash APIs expect the key
|
|
+ * as a pair of 64-bit words. Therefore, on big endian CPUs we have to do an
|
|
+ * endianness swap in order to get the same results as on little endian CPUs.
|
|
+ */
|
|
+static int fscrypt_derive_siphash_key(const struct fscrypt_master_key *mk,
|
|
+ u8 context, const u8 *info,
|
|
+ unsigned int infolen, siphash_key_t *key)
|
|
+{
|
|
+ int err;
|
|
+
|
|
+ err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, context, info, infolen,
|
|
+ (u8 *)key, sizeof(*key));
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ BUILD_BUG_ON(sizeof(*key) != 16);
|
|
+ BUILD_BUG_ON(ARRAY_SIZE(key->key) != 2);
|
|
+ le64_to_cpus(&key->key[0]);
|
|
+ le64_to_cpus(&key->key[1]);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
|
|
const struct fscrypt_master_key *mk)
|
|
{
|
|
int err;
|
|
|
|
- err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY,
|
|
- ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
|
|
- (u8 *)&ci->ci_dirhash_key,
|
|
- sizeof(ci->ci_dirhash_key));
|
|
+ err = fscrypt_derive_siphash_key(mk, HKDF_CONTEXT_DIRHASH_KEY,
|
|
+ ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
|
|
+ &ci->ci_dirhash_key);
|
|
if (err)
|
|
return err;
|
|
ci->ci_dirhash_key_initialized = true;
|
|
@@ -253,10 +278,9 @@ static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci,
|
|
if (mk->mk_ino_hash_key_initialized)
|
|
goto unlock;
|
|
|
|
- err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
|
|
- HKDF_CONTEXT_INODE_HASH_KEY, NULL, 0,
|
|
- (u8 *)&mk->mk_ino_hash_key,
|
|
- sizeof(mk->mk_ino_hash_key));
|
|
+ err = fscrypt_derive_siphash_key(mk,
|
|
+ HKDF_CONTEXT_INODE_HASH_KEY,
|
|
+ NULL, 0, &mk->mk_ino_hash_key);
|
|
if (err)
|
|
goto unlock;
|
|
/* pairs with smp_load_acquire() above */
|
|
diff --git a/fs/dax.c b/fs/dax.c
|
|
index df5485b4bddf1..d5d7b9393bcaa 100644
|
|
--- a/fs/dax.c
|
|
+++ b/fs/dax.c
|
|
@@ -488,10 +488,11 @@ static void *grab_mapping_entry(struct xa_state *xas,
|
|
struct address_space *mapping, unsigned int order)
|
|
{
|
|
unsigned long index = xas->xa_index;
|
|
- bool pmd_downgrade = false; /* splitting PMD entry into PTE entries? */
|
|
+ bool pmd_downgrade; /* splitting PMD entry into PTE entries? */
|
|
void *entry;
|
|
|
|
retry:
|
|
+ pmd_downgrade = false;
|
|
xas_lock_irq(xas);
|
|
entry = get_unlocked_entry(xas, order);
|
|
|
|
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
|
|
index 73e6643903af5..18a8ffcea0aa4 100644
|
|
--- a/fs/dlm/config.c
|
|
+++ b/fs/dlm/config.c
|
|
@@ -79,6 +79,9 @@ struct dlm_cluster {
|
|
unsigned int cl_new_rsb_count;
|
|
unsigned int cl_recover_callbacks;
|
|
char cl_cluster_name[DLM_LOCKSPACE_LEN];
|
|
+
|
|
+ struct dlm_spaces *sps;
|
|
+ struct dlm_comms *cms;
|
|
};
|
|
|
|
static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
|
|
@@ -379,6 +382,9 @@ static struct config_group *make_cluster(struct config_group *g,
|
|
if (!cl || !sps || !cms)
|
|
goto fail;
|
|
|
|
+ cl->sps = sps;
|
|
+ cl->cms = cms;
|
|
+
|
|
config_group_init_type_name(&cl->group, name, &cluster_type);
|
|
config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type);
|
|
config_group_init_type_name(&cms->cs_group, "comms", &comms_type);
|
|
@@ -428,6 +434,9 @@ static void drop_cluster(struct config_group *g, struct config_item *i)
|
|
static void release_cluster(struct config_item *i)
|
|
{
|
|
struct dlm_cluster *cl = config_item_to_cluster(i);
|
|
+
|
|
+ kfree(cl->sps);
|
|
+ kfree(cl->cms);
|
|
kfree(cl);
|
|
}
|
|
|
|
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
|
|
index 44e2716ac1580..0c78fdfb1f6fa 100644
|
|
--- a/fs/dlm/lowcomms.c
|
|
+++ b/fs/dlm/lowcomms.c
|
|
@@ -599,7 +599,7 @@ static void close_connection(struct connection *con, bool and_other,
|
|
}
|
|
if (con->othercon && and_other) {
|
|
/* Will only re-enter once. */
|
|
- close_connection(con->othercon, false, true, true);
|
|
+ close_connection(con->othercon, false, tx, rx);
|
|
}
|
|
|
|
con->rx_leftover = 0;
|
|
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
|
|
index d5a6b9b888a56..f31a08d86be89 100644
|
|
--- a/fs/erofs/super.c
|
|
+++ b/fs/erofs/super.c
|
|
@@ -155,6 +155,7 @@ static int erofs_read_superblock(struct super_block *sb)
|
|
goto out;
|
|
}
|
|
|
|
+ ret = -EINVAL;
|
|
blkszbits = dsb->blkszbits;
|
|
/* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */
|
|
if (blkszbits != LOG_BLOCK_SIZE) {
|
|
diff --git a/fs/exec.c b/fs/exec.c
|
|
index ca89e0e3ef10f..c7a4ef8df3058 100644
|
|
--- a/fs/exec.c
|
|
+++ b/fs/exec.c
|
|
@@ -1347,6 +1347,10 @@ int begin_new_exec(struct linux_binprm * bprm)
|
|
WRITE_ONCE(me->self_exec_id, me->self_exec_id + 1);
|
|
flush_signal_handlers(me, 0);
|
|
|
|
+ retval = set_cred_ucounts(bprm->cred);
|
|
+ if (retval < 0)
|
|
+ goto out_unlock;
|
|
+
|
|
/*
|
|
* install the new credentials for this executable
|
|
*/
|
|
diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
|
|
index 916797077aad4..dedbc55cd48f5 100644
|
|
--- a/fs/exfat/dir.c
|
|
+++ b/fs/exfat/dir.c
|
|
@@ -62,7 +62,7 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
|
|
static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_entry *dir_entry)
|
|
{
|
|
int i, dentries_per_clu, dentries_per_clu_bits = 0, num_ext;
|
|
- unsigned int type, clu_offset;
|
|
+ unsigned int type, clu_offset, max_dentries;
|
|
sector_t sector;
|
|
struct exfat_chain dir, clu;
|
|
struct exfat_uni_name uni_name;
|
|
@@ -85,6 +85,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
|
|
|
|
dentries_per_clu = sbi->dentries_per_clu;
|
|
dentries_per_clu_bits = ilog2(dentries_per_clu);
|
|
+ max_dentries = (unsigned int)min_t(u64, MAX_EXFAT_DENTRIES,
|
|
+ (u64)sbi->num_clusters << dentries_per_clu_bits);
|
|
|
|
clu_offset = dentry >> dentries_per_clu_bits;
|
|
exfat_chain_dup(&clu, &dir);
|
|
@@ -108,7 +110,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
|
|
}
|
|
}
|
|
|
|
- while (clu.dir != EXFAT_EOF_CLUSTER) {
|
|
+ while (clu.dir != EXFAT_EOF_CLUSTER && dentry < max_dentries) {
|
|
i = dentry & (dentries_per_clu - 1);
|
|
|
|
for ( ; i < dentries_per_clu; i++, dentry++) {
|
|
@@ -244,7 +246,7 @@ static int exfat_iterate(struct file *filp, struct dir_context *ctx)
|
|
if (err)
|
|
goto unlock;
|
|
get_new:
|
|
- if (cpos >= i_size_read(inode))
|
|
+ if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode))
|
|
goto end_of_dir;
|
|
|
|
err = exfat_readdir(inode, &cpos, &de);
|
|
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
|
|
index e6542ba264330..e00a35530a4e0 100644
|
|
--- a/fs/ext4/extents.c
|
|
+++ b/fs/ext4/extents.c
|
|
@@ -825,6 +825,7 @@ void ext4_ext_tree_init(handle_t *handle, struct inode *inode)
|
|
eh->eh_entries = 0;
|
|
eh->eh_magic = EXT4_EXT_MAGIC;
|
|
eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0));
|
|
+ eh->eh_generation = 0;
|
|
ext4_mark_inode_dirty(handle, inode);
|
|
}
|
|
|
|
@@ -1090,6 +1091,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
|
|
neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0));
|
|
neh->eh_magic = EXT4_EXT_MAGIC;
|
|
neh->eh_depth = 0;
|
|
+ neh->eh_generation = 0;
|
|
|
|
/* move remainder of path[depth] to the new leaf */
|
|
if (unlikely(path[depth].p_hdr->eh_entries !=
|
|
@@ -1167,6 +1169,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
|
|
neh->eh_magic = EXT4_EXT_MAGIC;
|
|
neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0));
|
|
neh->eh_depth = cpu_to_le16(depth - i);
|
|
+ neh->eh_generation = 0;
|
|
fidx = EXT_FIRST_INDEX(neh);
|
|
fidx->ei_block = border;
|
|
ext4_idx_store_pblock(fidx, oldblock);
|
|
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
|
|
index 0a729027322dd..9a3a8996aacf7 100644
|
|
--- a/fs/ext4/extents_status.c
|
|
+++ b/fs/ext4/extents_status.c
|
|
@@ -1574,11 +1574,9 @@ static unsigned long ext4_es_scan(struct shrinker *shrink,
|
|
ret = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_shk_cnt);
|
|
trace_ext4_es_shrink_scan_enter(sbi->s_sb, nr_to_scan, ret);
|
|
|
|
- if (!nr_to_scan)
|
|
- return ret;
|
|
-
|
|
nr_shrunk = __es_shrink(sbi, nr_to_scan, NULL);
|
|
|
|
+ ret = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_shk_cnt);
|
|
trace_ext4_es_shrink_scan_exit(sbi->s_sb, nr_shrunk, ret);
|
|
return nr_shrunk;
|
|
}
|
|
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
|
|
index b294ebcb4db4b..875af329c43ec 100644
|
|
--- a/fs/ext4/ialloc.c
|
|
+++ b/fs/ext4/ialloc.c
|
|
@@ -402,7 +402,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
|
|
*
|
|
* We always try to spread first-level directories.
|
|
*
|
|
- * If there are blockgroups with both free inodes and free blocks counts
|
|
+ * If there are blockgroups with both free inodes and free clusters counts
|
|
* not worse than average we return one with smallest directory count.
|
|
* Otherwise we simply return a random group.
|
|
*
|
|
@@ -411,7 +411,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
|
|
* It's OK to put directory into a group unless
|
|
* it has too many directories already (max_dirs) or
|
|
* it has too few free inodes left (min_inodes) or
|
|
- * it has too few free blocks left (min_blocks) or
|
|
+ * it has too few free clusters left (min_clusters) or
|
|
* Parent's group is preferred, if it doesn't satisfy these
|
|
* conditions we search cyclically through the rest. If none
|
|
* of the groups look good we just look for a group with more
|
|
@@ -427,7 +427,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
|
ext4_group_t real_ngroups = ext4_get_groups_count(sb);
|
|
int inodes_per_group = EXT4_INODES_PER_GROUP(sb);
|
|
unsigned int freei, avefreei, grp_free;
|
|
- ext4_fsblk_t freeb, avefreec;
|
|
+ ext4_fsblk_t freec, avefreec;
|
|
unsigned int ndirs;
|
|
int max_dirs, min_inodes;
|
|
ext4_grpblk_t min_clusters;
|
|
@@ -446,9 +446,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
|
|
|
|
freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
|
|
avefreei = freei / ngroups;
|
|
- freeb = EXT4_C2B(sbi,
|
|
- percpu_counter_read_positive(&sbi->s_freeclusters_counter));
|
|
- avefreec = freeb;
|
|
+ freec = percpu_counter_read_positive(&sbi->s_freeclusters_counter);
|
|
+ avefreec = freec;
|
|
do_div(avefreec, ngroups);
|
|
ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
|
|
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index 3f11c948feb02..18a5321b5ef37 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -3419,7 +3419,7 @@ retry:
|
|
* i_disksize out to i_size. This could be beyond where direct I/O is
|
|
* happening and thus expose allocated blocks to direct I/O reads.
|
|
*/
|
|
- else if ((map->m_lblk * (1 << blkbits)) >= i_size_read(inode))
|
|
+ else if (((loff_t)map->m_lblk << blkbits) >= i_size_read(inode))
|
|
m_flags = EXT4_GET_BLOCKS_CREATE;
|
|
else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
|
|
m_flags = EXT4_GET_BLOCKS_IO_CREATE_EXT;
|
|
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
|
|
index 9c390c3d7fb15..d7cb7d719ee58 100644
|
|
--- a/fs/ext4/mballoc.c
|
|
+++ b/fs/ext4/mballoc.c
|
|
@@ -1597,10 +1597,11 @@ static int mb_find_extent(struct ext4_buddy *e4b, int block,
|
|
if (ex->fe_start + ex->fe_len > EXT4_CLUSTERS_PER_GROUP(e4b->bd_sb)) {
|
|
/* Should never happen! (but apparently sometimes does?!?) */
|
|
WARN_ON(1);
|
|
- ext4_error(e4b->bd_sb, "corruption or bug in mb_find_extent "
|
|
- "block=%d, order=%d needed=%d ex=%u/%d/%d@%u",
|
|
- block, order, needed, ex->fe_group, ex->fe_start,
|
|
- ex->fe_len, ex->fe_logical);
|
|
+ ext4_grp_locked_error(e4b->bd_sb, e4b->bd_group, 0, 0,
|
|
+ "corruption or bug in mb_find_extent "
|
|
+ "block=%d, order=%d needed=%d ex=%u/%d/%d@%u",
|
|
+ block, order, needed, ex->fe_group, ex->fe_start,
|
|
+ ex->fe_len, ex->fe_logical);
|
|
ex->fe_len = 0;
|
|
ex->fe_start = 0;
|
|
ex->fe_group = 0;
|
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
index 21c4ba2513ce5..4956917b7cc2b 100644
|
|
--- a/fs/ext4/super.c
|
|
+++ b/fs/ext4/super.c
|
|
@@ -3099,8 +3099,15 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
|
inode_lock(inode);
|
|
truncate_inode_pages(inode->i_mapping, inode->i_size);
|
|
ret = ext4_truncate(inode);
|
|
- if (ret)
|
|
+ if (ret) {
|
|
+ /*
|
|
+ * We need to clean up the in-core orphan list
|
|
+ * manually if ext4_truncate() failed to get a
|
|
+ * transaction handle.
|
|
+ */
|
|
+ ext4_orphan_del(NULL, inode);
|
|
ext4_std_error(inode->i_sb, ret);
|
|
+ }
|
|
inode_unlock(inode);
|
|
nr_truncates++;
|
|
} else {
|
|
@@ -5039,6 +5046,7 @@ no_journal:
|
|
ext4_msg(sb, KERN_ERR,
|
|
"unable to initialize "
|
|
"flex_bg meta info!");
|
|
+ ret = -ENOMEM;
|
|
goto failed_mount6;
|
|
}
|
|
|
|
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
|
|
index bdc0f3b2d7abf..cfae2dddb0bae 100644
|
|
--- a/fs/f2fs/data.c
|
|
+++ b/fs/f2fs/data.c
|
|
@@ -4112,6 +4112,12 @@ static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file,
|
|
if (f2fs_readonly(F2FS_I_SB(inode)->sb))
|
|
return -EROFS;
|
|
|
|
+ if (f2fs_lfs_mode(F2FS_I_SB(inode))) {
|
|
+ f2fs_err(F2FS_I_SB(inode),
|
|
+ "Swapfile not supported in LFS mode");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
ret = f2fs_convert_inline_inode(inode);
|
|
if (ret)
|
|
return ret;
|
|
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
|
|
index 90dddb507e4af..a0869194ab739 100644
|
|
--- a/fs/fs-writeback.c
|
|
+++ b/fs/fs-writeback.c
|
|
@@ -505,12 +505,19 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
|
|
if (!isw)
|
|
return;
|
|
|
|
+ atomic_inc(&isw_nr_in_flight);
|
|
+
|
|
/* find and pin the new wb */
|
|
rcu_read_lock();
|
|
memcg_css = css_from_id(new_wb_id, &memory_cgrp_subsys);
|
|
- if (memcg_css)
|
|
- isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
|
|
+ if (memcg_css && !css_tryget(memcg_css))
|
|
+ memcg_css = NULL;
|
|
rcu_read_unlock();
|
|
+ if (!memcg_css)
|
|
+ goto out_free;
|
|
+
|
|
+ isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
|
|
+ css_put(memcg_css);
|
|
if (!isw->new_wb)
|
|
goto out_free;
|
|
|
|
@@ -535,11 +542,10 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
|
|
* Let's continue after I_WB_SWITCH is guaranteed to be visible.
|
|
*/
|
|
call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
|
|
-
|
|
- atomic_inc(&isw_nr_in_flight);
|
|
return;
|
|
|
|
out_free:
|
|
+ atomic_dec(&isw_nr_in_flight);
|
|
if (isw->new_wb)
|
|
wb_put(isw->new_wb);
|
|
kfree(isw);
|
|
@@ -2196,28 +2202,6 @@ int dirtytime_interval_handler(struct ctl_table *table, int write,
|
|
return ret;
|
|
}
|
|
|
|
-static noinline void block_dump___mark_inode_dirty(struct inode *inode)
|
|
-{
|
|
- if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) {
|
|
- struct dentry *dentry;
|
|
- const char *name = "?";
|
|
-
|
|
- dentry = d_find_alias(inode);
|
|
- if (dentry) {
|
|
- spin_lock(&dentry->d_lock);
|
|
- name = (const char *) dentry->d_name.name;
|
|
- }
|
|
- printk(KERN_DEBUG
|
|
- "%s(%d): dirtied inode %lu (%s) on %s\n",
|
|
- current->comm, task_pid_nr(current), inode->i_ino,
|
|
- name, inode->i_sb->s_id);
|
|
- if (dentry) {
|
|
- spin_unlock(&dentry->d_lock);
|
|
- dput(dentry);
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
/**
|
|
* __mark_inode_dirty - internal function
|
|
*
|
|
@@ -2277,9 +2261,6 @@ void __mark_inode_dirty(struct inode *inode, int flags)
|
|
(dirtytime && (inode->i_state & I_DIRTY_INODE)))
|
|
return;
|
|
|
|
- if (unlikely(block_dump))
|
|
- block_dump___mark_inode_dirty(inode);
|
|
-
|
|
spin_lock(&inode->i_lock);
|
|
if (dirtytime && (inode->i_state & I_DIRTY_INODE))
|
|
goto out_unlock_inode;
|
|
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
|
|
index 588f8d1240aab..4140d5c3ab5a5 100644
|
|
--- a/fs/fuse/dev.c
|
|
+++ b/fs/fuse/dev.c
|
|
@@ -783,6 +783,7 @@ static int fuse_check_page(struct page *page)
|
|
1 << PG_uptodate |
|
|
1 << PG_lru |
|
|
1 << PG_active |
|
|
+ 1 << PG_workingset |
|
|
1 << PG_reclaim |
|
|
1 << PG_waiters))) {
|
|
dump_page(page, "fuse: trying to steal weird page");
|
|
@@ -1275,6 +1276,15 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
|
|
goto restart;
|
|
}
|
|
spin_lock(&fpq->lock);
|
|
+ /*
|
|
+ * Must not put request on fpq->io queue after having been shut down by
|
|
+ * fuse_abort_conn()
|
|
+ */
|
|
+ if (!fpq->connected) {
|
|
+ req->out.h.error = err = -ECONNABORTED;
|
|
+ goto out_end;
|
|
+
|
|
+ }
|
|
list_add(&req->list, &fpq->io);
|
|
spin_unlock(&fpq->lock);
|
|
cs->req = req;
|
|
@@ -1861,7 +1871,7 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
|
|
}
|
|
|
|
err = -EINVAL;
|
|
- if (oh.error <= -1000 || oh.error > 0)
|
|
+ if (oh.error <= -512 || oh.error > 0)
|
|
goto copy_finish;
|
|
|
|
spin_lock(&fpq->lock);
|
|
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
|
|
index ffa031fe52933..756bbdd563e08 100644
|
|
--- a/fs/fuse/dir.c
|
|
+++ b/fs/fuse/dir.c
|
|
@@ -340,18 +340,33 @@ static struct vfsmount *fuse_dentry_automount(struct path *path)
|
|
|
|
/* Initialize superblock, making @mp_fi its root */
|
|
err = fuse_fill_super_submount(sb, mp_fi);
|
|
- if (err)
|
|
+ if (err) {
|
|
+ fuse_conn_put(fc);
|
|
+ kfree(fm);
|
|
+ sb->s_fs_info = NULL;
|
|
goto out_put_sb;
|
|
+ }
|
|
+
|
|
+ down_write(&fc->killsb);
|
|
+ list_add_tail(&fm->fc_entry, &fc->mounts);
|
|
+ up_write(&fc->killsb);
|
|
|
|
sb->s_flags |= SB_ACTIVE;
|
|
fsc->root = dget(sb->s_root);
|
|
+
|
|
+ /*
|
|
+ * FIXME: setting SB_BORN requires a write barrier for
|
|
+ * super_cache_count(). We should actually come
|
|
+ * up with a proper ->get_tree() implementation
|
|
+ * for submounts and call vfs_get_tree() to take
|
|
+ * care of the write barrier.
|
|
+ */
|
|
+ smp_wmb();
|
|
+ sb->s_flags |= SB_BORN;
|
|
+
|
|
/* We are done configuring the superblock, so unlock it */
|
|
up_write(&sb->s_umount);
|
|
|
|
- down_write(&fc->killsb);
|
|
- list_add_tail(&fm->fc_entry, &fc->mounts);
|
|
- up_write(&fc->killsb);
|
|
-
|
|
/* Create the submount */
|
|
mnt = vfs_create_mount(fsc);
|
|
if (IS_ERR(mnt)) {
|
|
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
|
|
index 16fb0184ce5e1..cfd9d03f604fe 100644
|
|
--- a/fs/gfs2/file.c
|
|
+++ b/fs/gfs2/file.c
|
|
@@ -474,8 +474,8 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
|
|
file_update_time(vmf->vma->vm_file);
|
|
|
|
/* page is wholly or partially inside EOF */
|
|
- if (offset > size - PAGE_SIZE)
|
|
- length = offset_in_page(size);
|
|
+ if (size - offset < PAGE_SIZE)
|
|
+ length = size - offset;
|
|
else
|
|
length = PAGE_SIZE;
|
|
|
|
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
|
|
index f2c6bbe5cdb81..ae9c5c1bdc508 100644
|
|
--- a/fs/gfs2/ops_fstype.c
|
|
+++ b/fs/gfs2/ops_fstype.c
|
|
@@ -670,6 +670,7 @@ static int init_statfs(struct gfs2_sbd *sdp)
|
|
}
|
|
|
|
iput(pn);
|
|
+ pn = NULL;
|
|
ip = GFS2_I(sdp->sd_sc_inode);
|
|
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0,
|
|
&sdp->sd_sc_gh);
|
|
diff --git a/fs/io_uring.c b/fs/io_uring.c
|
|
index fdbaaf579cc60..0138aa7133172 100644
|
|
--- a/fs/io_uring.c
|
|
+++ b/fs/io_uring.c
|
|
@@ -2770,7 +2770,7 @@ static bool io_file_supports_async(struct file *file, int rw)
|
|
return true;
|
|
return false;
|
|
}
|
|
- if (S_ISCHR(mode) || S_ISSOCK(mode))
|
|
+ if (S_ISSOCK(mode))
|
|
return true;
|
|
if (S_ISREG(mode)) {
|
|
if (io_bdev_nowait(file->f_inode->i_sb->s_bdev) &&
|
|
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
|
|
index e9d5c8e638b01..ea18e4a2a691d 100644
|
|
--- a/fs/ntfs/inode.c
|
|
+++ b/fs/ntfs/inode.c
|
|
@@ -477,7 +477,7 @@ err_corrupt_attr:
|
|
}
|
|
file_name_attr = (FILE_NAME_ATTR*)((u8*)attr +
|
|
le16_to_cpu(attr->data.resident.value_offset));
|
|
- p2 = (u8*)attr + le32_to_cpu(attr->data.resident.value_length);
|
|
+ p2 = (u8 *)file_name_attr + le32_to_cpu(attr->data.resident.value_length);
|
|
if (p2 < (u8*)attr || p2 > p)
|
|
goto err_corrupt_attr;
|
|
/* This attribute is ok, but is it in the $Extend directory? */
|
|
diff --git a/fs/ocfs2/filecheck.c b/fs/ocfs2/filecheck.c
|
|
index 50f11bfdc8c2d..82a3edc4aea4b 100644
|
|
--- a/fs/ocfs2/filecheck.c
|
|
+++ b/fs/ocfs2/filecheck.c
|
|
@@ -328,11 +328,7 @@ static ssize_t ocfs2_filecheck_attr_show(struct kobject *kobj,
|
|
ret = snprintf(buf + total, remain, "%lu\t\t%u\t%s\n",
|
|
p->fe_ino, p->fe_done,
|
|
ocfs2_filecheck_error(p->fe_status));
|
|
- if (ret < 0) {
|
|
- total = ret;
|
|
- break;
|
|
- }
|
|
- if (ret == remain) {
|
|
+ if (ret >= remain) {
|
|
/* snprintf() didn't fit */
|
|
total = -E2BIG;
|
|
break;
|
|
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
|
|
index a191094694c61..03eacb249f379 100644
|
|
--- a/fs/ocfs2/stackglue.c
|
|
+++ b/fs/ocfs2/stackglue.c
|
|
@@ -502,11 +502,7 @@ static ssize_t ocfs2_loaded_cluster_plugins_show(struct kobject *kobj,
|
|
list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
|
|
ret = snprintf(buf, remain, "%s\n",
|
|
p->sp_name);
|
|
- if (ret < 0) {
|
|
- total = ret;
|
|
- break;
|
|
- }
|
|
- if (ret == remain) {
|
|
+ if (ret >= remain) {
|
|
/* snprintf() didn't fit */
|
|
total = -E2BIG;
|
|
break;
|
|
@@ -533,7 +529,7 @@ static ssize_t ocfs2_active_cluster_plugin_show(struct kobject *kobj,
|
|
if (active_stack) {
|
|
ret = snprintf(buf, PAGE_SIZE, "%s\n",
|
|
active_stack->sp_name);
|
|
- if (ret == PAGE_SIZE)
|
|
+ if (ret >= PAGE_SIZE)
|
|
ret = -E2BIG;
|
|
}
|
|
spin_unlock(&ocfs2_stack_lock);
|
|
diff --git a/fs/open.c b/fs/open.c
|
|
index 4d7537ae59df5..3aaaad47d9cac 100644
|
|
--- a/fs/open.c
|
|
+++ b/fs/open.c
|
|
@@ -993,12 +993,20 @@ inline struct open_how build_open_how(int flags, umode_t mode)
|
|
|
|
inline int build_open_flags(const struct open_how *how, struct open_flags *op)
|
|
{
|
|
- int flags = how->flags;
|
|
+ u64 flags = how->flags;
|
|
+ u64 strip = FMODE_NONOTIFY | O_CLOEXEC;
|
|
int lookup_flags = 0;
|
|
int acc_mode = ACC_MODE(flags);
|
|
|
|
- /* Must never be set by userspace */
|
|
- flags &= ~(FMODE_NONOTIFY | O_CLOEXEC);
|
|
+ BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPEN_FLAGS),
|
|
+ "struct open_flags doesn't yet handle flags > 32 bits");
|
|
+
|
|
+ /*
|
|
+ * Strip flags that either shouldn't be set by userspace like
|
|
+ * FMODE_NONOTIFY or that aren't relevant in determining struct
|
|
+ * open_flags like O_CLOEXEC.
|
|
+ */
|
|
+ flags &= ~strip;
|
|
|
|
/*
|
|
* Older syscalls implicitly clear all of the invalid flags or argument
|
|
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
|
|
index 3cec6fbef725e..3931f60e421f7 100644
|
|
--- a/fs/proc/task_mmu.c
|
|
+++ b/fs/proc/task_mmu.c
|
|
@@ -829,7 +829,7 @@ static int show_smap(struct seq_file *m, void *v)
|
|
__show_smap(m, &mss, false);
|
|
|
|
seq_printf(m, "THPeligible: %d\n",
|
|
- transparent_hugepage_enabled(vma));
|
|
+ transparent_hugepage_active(vma));
|
|
|
|
if (arch_pkeys_enabled())
|
|
seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma));
|
|
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
|
|
index e16a49ebfe546..8efe60487b486 100644
|
|
--- a/fs/pstore/Kconfig
|
|
+++ b/fs/pstore/Kconfig
|
|
@@ -165,6 +165,7 @@ config PSTORE_BLK
|
|
tristate "Log panic/oops to a block device"
|
|
depends on PSTORE
|
|
depends on BLOCK
|
|
+ depends on BROKEN
|
|
select PSTORE_ZONE
|
|
default n
|
|
help
|
|
diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h
|
|
index d683f5e6d7913..b4d43a4af5f79 100644
|
|
--- a/include/asm-generic/preempt.h
|
|
+++ b/include/asm-generic/preempt.h
|
|
@@ -29,7 +29,7 @@ static __always_inline void preempt_count_set(int pc)
|
|
} while (0)
|
|
|
|
#define init_idle_preempt_count(p, cpu) do { \
|
|
- task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \
|
|
+ task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \
|
|
} while (0)
|
|
|
|
static __always_inline void set_preempt_need_resched(void)
|
|
diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h
|
|
index 4c61dade8835f..f6da8a1326398 100644
|
|
--- a/include/clocksource/timer-ti-dm.h
|
|
+++ b/include/clocksource/timer-ti-dm.h
|
|
@@ -74,6 +74,7 @@
|
|
#define OMAP_TIMER_ERRATA_I103_I767 0x80000000
|
|
|
|
struct timer_regs {
|
|
+ u32 ocp_cfg;
|
|
u32 tidr;
|
|
u32 tier;
|
|
u32 twer;
|
|
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
|
|
index 0a288dddcf5be..25806141db591 100644
|
|
--- a/include/crypto/internal/hash.h
|
|
+++ b/include/crypto/internal/hash.h
|
|
@@ -75,13 +75,7 @@ void crypto_unregister_ahashes(struct ahash_alg *algs, int count);
|
|
int ahash_register_instance(struct crypto_template *tmpl,
|
|
struct ahash_instance *inst);
|
|
|
|
-int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
|
|
- unsigned int keylen);
|
|
-
|
|
-static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg)
|
|
-{
|
|
- return alg->setkey != shash_no_setkey;
|
|
-}
|
|
+bool crypto_shash_alg_has_setkey(struct shash_alg *alg);
|
|
|
|
static inline bool crypto_shash_alg_needs_key(struct shash_alg *alg)
|
|
{
|
|
diff --git a/include/dt-bindings/clock/imx8mq-clock.h b/include/dt-bindings/clock/imx8mq-clock.h
|
|
index 9b8045d75b8b6..da62c9f61371b 100644
|
|
--- a/include/dt-bindings/clock/imx8mq-clock.h
|
|
+++ b/include/dt-bindings/clock/imx8mq-clock.h
|
|
@@ -405,25 +405,6 @@
|
|
|
|
#define IMX8MQ_VIDEO2_PLL1_REF_SEL 266
|
|
|
|
-#define IMX8MQ_SYS1_PLL_40M_CG 267
|
|
-#define IMX8MQ_SYS1_PLL_80M_CG 268
|
|
-#define IMX8MQ_SYS1_PLL_100M_CG 269
|
|
-#define IMX8MQ_SYS1_PLL_133M_CG 270
|
|
-#define IMX8MQ_SYS1_PLL_160M_CG 271
|
|
-#define IMX8MQ_SYS1_PLL_200M_CG 272
|
|
-#define IMX8MQ_SYS1_PLL_266M_CG 273
|
|
-#define IMX8MQ_SYS1_PLL_400M_CG 274
|
|
-#define IMX8MQ_SYS1_PLL_800M_CG 275
|
|
-#define IMX8MQ_SYS2_PLL_50M_CG 276
|
|
-#define IMX8MQ_SYS2_PLL_100M_CG 277
|
|
-#define IMX8MQ_SYS2_PLL_125M_CG 278
|
|
-#define IMX8MQ_SYS2_PLL_166M_CG 279
|
|
-#define IMX8MQ_SYS2_PLL_200M_CG 280
|
|
-#define IMX8MQ_SYS2_PLL_250M_CG 281
|
|
-#define IMX8MQ_SYS2_PLL_333M_CG 282
|
|
-#define IMX8MQ_SYS2_PLL_500M_CG 283
|
|
-#define IMX8MQ_SYS2_PLL_1000M_CG 284
|
|
-
|
|
#define IMX8MQ_CLK_GPU_CORE 285
|
|
#define IMX8MQ_CLK_GPU_SHADER 286
|
|
#define IMX8MQ_CLK_M4_CORE 287
|
|
diff --git a/include/linux/bio.h b/include/linux/bio.h
|
|
index c6d7653829264..23b7a73cd7575 100644
|
|
--- a/include/linux/bio.h
|
|
+++ b/include/linux/bio.h
|
|
@@ -38,9 +38,6 @@
|
|
#define bio_offset(bio) bio_iter_offset((bio), (bio)->bi_iter)
|
|
#define bio_iovec(bio) bio_iter_iovec((bio), (bio)->bi_iter)
|
|
|
|
-#define bio_multiple_segments(bio) \
|
|
- ((bio)->bi_iter.bi_size != bio_iovec(bio).bv_len)
|
|
-
|
|
#define bvec_iter_sectors(iter) ((iter).bi_size >> 9)
|
|
#define bvec_iter_end_sector(iter) ((iter).bi_sector + bvec_iter_sectors((iter)))
|
|
|
|
@@ -252,7 +249,7 @@ static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
|
|
|
|
static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv)
|
|
{
|
|
- *bv = bio_iovec(bio);
|
|
+ *bv = mp_bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
|
|
}
|
|
|
|
static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)
|
|
@@ -260,10 +257,9 @@ static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)
|
|
struct bvec_iter iter = bio->bi_iter;
|
|
int idx;
|
|
|
|
- if (unlikely(!bio_multiple_segments(bio))) {
|
|
- *bv = bio_iovec(bio);
|
|
- return;
|
|
- }
|
|
+ bio_get_first_bvec(bio, bv);
|
|
+ if (bv->bv_len == bio->bi_iter.bi_size)
|
|
+ return; /* this bio only has a single bvec */
|
|
|
|
bio_advance_iter(bio, &iter, iter.bi_size);
|
|
|
|
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
|
|
index 86d143db65231..83a3ebff74560 100644
|
|
--- a/include/linux/clocksource.h
|
|
+++ b/include/linux/clocksource.h
|
|
@@ -131,7 +131,7 @@ struct clocksource {
|
|
#define CLOCK_SOURCE_UNSTABLE 0x40
|
|
#define CLOCK_SOURCE_SUSPEND_NONSTOP 0x80
|
|
#define CLOCK_SOURCE_RESELECT 0x100
|
|
-
|
|
+#define CLOCK_SOURCE_VERIFY_PERCPU 0x200
|
|
/* simplify initialization of mask field */
|
|
#define CLOCKSOURCE_MASK(bits) GENMASK_ULL((bits) - 1, 0)
|
|
|
|
diff --git a/include/linux/cred.h b/include/linux/cred.h
|
|
index 18639c069263f..ad160e5fe5c64 100644
|
|
--- a/include/linux/cred.h
|
|
+++ b/include/linux/cred.h
|
|
@@ -144,6 +144,7 @@ struct cred {
|
|
#endif
|
|
struct user_struct *user; /* real user ID subscription */
|
|
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
|
|
+ struct ucounts *ucounts;
|
|
struct group_info *group_info; /* supplementary groups for euid/fsgid */
|
|
/* RCU deletion */
|
|
union {
|
|
@@ -170,6 +171,7 @@ extern int set_security_override_from_ctx(struct cred *, const char *);
|
|
extern int set_create_files_as(struct cred *, struct inode *);
|
|
extern int cred_fscmp(const struct cred *, const struct cred *);
|
|
extern void __init cred_init(void);
|
|
+extern int set_cred_ucounts(struct cred *);
|
|
|
|
/*
|
|
* check for validity of credentials
|
|
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
|
|
index ff55be0117397..e72787731a5b2 100644
|
|
--- a/include/linux/huge_mm.h
|
|
+++ b/include/linux/huge_mm.h
|
|
@@ -7,43 +7,37 @@
|
|
|
|
#include <linux/fs.h> /* only for vma_is_dax() */
|
|
|
|
-extern vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf);
|
|
-extern int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
|
- pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
|
|
- struct vm_area_struct *vma);
|
|
-extern void huge_pmd_set_accessed(struct vm_fault *vmf, pmd_t orig_pmd);
|
|
-extern int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
|
- pud_t *dst_pud, pud_t *src_pud, unsigned long addr,
|
|
- struct vm_area_struct *vma);
|
|
+vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf);
|
|
+int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
|
+ pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
|
|
+ struct vm_area_struct *vma);
|
|
+void huge_pmd_set_accessed(struct vm_fault *vmf, pmd_t orig_pmd);
|
|
+int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
|
+ pud_t *dst_pud, pud_t *src_pud, unsigned long addr,
|
|
+ struct vm_area_struct *vma);
|
|
|
|
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
|
|
-extern void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud);
|
|
+void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud);
|
|
#else
|
|
static inline void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
-extern vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd);
|
|
-extern struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
|
- unsigned long addr,
|
|
- pmd_t *pmd,
|
|
- unsigned int flags);
|
|
-extern bool madvise_free_huge_pmd(struct mmu_gather *tlb,
|
|
- struct vm_area_struct *vma,
|
|
- pmd_t *pmd, unsigned long addr, unsigned long next);
|
|
-extern int zap_huge_pmd(struct mmu_gather *tlb,
|
|
- struct vm_area_struct *vma,
|
|
- pmd_t *pmd, unsigned long addr);
|
|
-extern int zap_huge_pud(struct mmu_gather *tlb,
|
|
- struct vm_area_struct *vma,
|
|
- pud_t *pud, unsigned long addr);
|
|
-extern bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
|
|
- unsigned long new_addr,
|
|
- pmd_t *old_pmd, pmd_t *new_pmd);
|
|
-extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
|
|
- unsigned long addr, pgprot_t newprot,
|
|
- unsigned long cp_flags);
|
|
+vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd);
|
|
+struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
|
+ unsigned long addr, pmd_t *pmd,
|
|
+ unsigned int flags);
|
|
+bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
|
|
+ pmd_t *pmd, unsigned long addr, unsigned long next);
|
|
+int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, pmd_t *pmd,
|
|
+ unsigned long addr);
|
|
+int zap_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma, pud_t *pud,
|
|
+ unsigned long addr);
|
|
+bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
|
|
+ unsigned long new_addr, pmd_t *old_pmd, pmd_t *new_pmd);
|
|
+int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr,
|
|
+ pgprot_t newprot, unsigned long cp_flags);
|
|
vm_fault_t vmf_insert_pfn_pmd_prot(struct vm_fault *vmf, pfn_t pfn,
|
|
pgprot_t pgprot, bool write);
|
|
|
|
@@ -84,6 +78,7 @@ static inline vm_fault_t vmf_insert_pfn_pud(struct vm_fault *vmf, pfn_t pfn,
|
|
}
|
|
|
|
enum transparent_hugepage_flag {
|
|
+ TRANSPARENT_HUGEPAGE_NEVER_DAX,
|
|
TRANSPARENT_HUGEPAGE_FLAG,
|
|
TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG,
|
|
TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG,
|
|
@@ -100,13 +95,13 @@ enum transparent_hugepage_flag {
|
|
struct kobject;
|
|
struct kobj_attribute;
|
|
|
|
-extern ssize_t single_hugepage_flag_store(struct kobject *kobj,
|
|
- struct kobj_attribute *attr,
|
|
- const char *buf, size_t count,
|
|
- enum transparent_hugepage_flag flag);
|
|
-extern ssize_t single_hugepage_flag_show(struct kobject *kobj,
|
|
- struct kobj_attribute *attr, char *buf,
|
|
- enum transparent_hugepage_flag flag);
|
|
+ssize_t single_hugepage_flag_store(struct kobject *kobj,
|
|
+ struct kobj_attribute *attr,
|
|
+ const char *buf, size_t count,
|
|
+ enum transparent_hugepage_flag flag);
|
|
+ssize_t single_hugepage_flag_show(struct kobject *kobj,
|
|
+ struct kobj_attribute *attr, char *buf,
|
|
+ enum transparent_hugepage_flag flag);
|
|
extern struct kobj_attribute shmem_enabled_attr;
|
|
|
|
#define HPAGE_PMD_ORDER (HPAGE_PMD_SHIFT-PAGE_SHIFT)
|
|
@@ -123,29 +118,53 @@ extern struct kobj_attribute shmem_enabled_attr;
|
|
|
|
extern unsigned long transparent_hugepage_flags;
|
|
|
|
+static inline bool transhuge_vma_suitable(struct vm_area_struct *vma,
|
|
+ unsigned long haddr)
|
|
+{
|
|
+ /* Don't have to check pgoff for anonymous vma */
|
|
+ if (!vma_is_anonymous(vma)) {
|
|
+ if (!IS_ALIGNED((vma->vm_start >> PAGE_SHIFT) - vma->vm_pgoff,
|
|
+ HPAGE_PMD_NR))
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (haddr < vma->vm_start || haddr + HPAGE_PMD_SIZE > vma->vm_end)
|
|
+ return false;
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static inline bool transhuge_vma_enabled(struct vm_area_struct *vma,
|
|
+ unsigned long vm_flags)
|
|
+{
|
|
+ /* Explicitly disabled through madvise. */
|
|
+ if ((vm_flags & VM_NOHUGEPAGE) ||
|
|
+ test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags))
|
|
+ return false;
|
|
+ return true;
|
|
+}
|
|
+
|
|
/*
|
|
* to be used on vmas which are known to support THP.
|
|
- * Use transparent_hugepage_enabled otherwise
|
|
+ * Use transparent_hugepage_active otherwise
|
|
*/
|
|
static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma)
|
|
{
|
|
- if (vma->vm_flags & VM_NOHUGEPAGE)
|
|
+
|
|
+ /*
|
|
+ * If the hardware/firmware marked hugepage support disabled.
|
|
+ */
|
|
+ if (transparent_hugepage_flags & (1 << TRANSPARENT_HUGEPAGE_NEVER_DAX))
|
|
return false;
|
|
|
|
- if (vma_is_temporary_stack(vma))
|
|
+ if (!transhuge_vma_enabled(vma, vma->vm_flags))
|
|
return false;
|
|
|
|
- if (test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags))
|
|
+ if (vma_is_temporary_stack(vma))
|
|
return false;
|
|
|
|
if (transparent_hugepage_flags & (1 << TRANSPARENT_HUGEPAGE_FLAG))
|
|
return true;
|
|
- /*
|
|
- * For dax vmas, try to always use hugepage mappings. If the kernel does
|
|
- * not support hugepages, fsdax mappings will fallback to PAGE_SIZE
|
|
- * mappings, and device-dax namespaces, that try to guarantee a given
|
|
- * mapping size, will fail to enable
|
|
- */
|
|
+
|
|
if (vma_is_dax(vma))
|
|
return true;
|
|
|
|
@@ -156,35 +175,17 @@ static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma)
|
|
return false;
|
|
}
|
|
|
|
-bool transparent_hugepage_enabled(struct vm_area_struct *vma);
|
|
-
|
|
-#define HPAGE_CACHE_INDEX_MASK (HPAGE_PMD_NR - 1)
|
|
-
|
|
-static inline bool transhuge_vma_suitable(struct vm_area_struct *vma,
|
|
- unsigned long haddr)
|
|
-{
|
|
- /* Don't have to check pgoff for anonymous vma */
|
|
- if (!vma_is_anonymous(vma)) {
|
|
- if (((vma->vm_start >> PAGE_SHIFT) & HPAGE_CACHE_INDEX_MASK) !=
|
|
- (vma->vm_pgoff & HPAGE_CACHE_INDEX_MASK))
|
|
- return false;
|
|
- }
|
|
-
|
|
- if (haddr < vma->vm_start || haddr + HPAGE_PMD_SIZE > vma->vm_end)
|
|
- return false;
|
|
- return true;
|
|
-}
|
|
+bool transparent_hugepage_active(struct vm_area_struct *vma);
|
|
|
|
#define transparent_hugepage_use_zero_page() \
|
|
(transparent_hugepage_flags & \
|
|
(1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG))
|
|
|
|
-extern unsigned long thp_get_unmapped_area(struct file *filp,
|
|
- unsigned long addr, unsigned long len, unsigned long pgoff,
|
|
- unsigned long flags);
|
|
+unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
+ unsigned long len, unsigned long pgoff, unsigned long flags);
|
|
|
|
-extern void prep_transhuge_page(struct page *page);
|
|
-extern void free_transhuge_page(struct page *page);
|
|
+void prep_transhuge_page(struct page *page);
|
|
+void free_transhuge_page(struct page *page);
|
|
bool is_transparent_hugepage(struct page *page);
|
|
|
|
bool can_split_huge_page(struct page *page, int *pextra_pins);
|
|
@@ -222,16 +223,12 @@ void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud,
|
|
__split_huge_pud(__vma, __pud, __address); \
|
|
} while (0)
|
|
|
|
-extern int hugepage_madvise(struct vm_area_struct *vma,
|
|
- unsigned long *vm_flags, int advice);
|
|
-extern void vma_adjust_trans_huge(struct vm_area_struct *vma,
|
|
- unsigned long start,
|
|
- unsigned long end,
|
|
- long adjust_next);
|
|
-extern spinlock_t *__pmd_trans_huge_lock(pmd_t *pmd,
|
|
- struct vm_area_struct *vma);
|
|
-extern spinlock_t *__pud_trans_huge_lock(pud_t *pud,
|
|
- struct vm_area_struct *vma);
|
|
+int hugepage_madvise(struct vm_area_struct *vma, unsigned long *vm_flags,
|
|
+ int advice);
|
|
+void vma_adjust_trans_huge(struct vm_area_struct *vma, unsigned long start,
|
|
+ unsigned long end, long adjust_next);
|
|
+spinlock_t *__pmd_trans_huge_lock(pmd_t *pmd, struct vm_area_struct *vma);
|
|
+spinlock_t *__pud_trans_huge_lock(pud_t *pud, struct vm_area_struct *vma);
|
|
|
|
static inline int is_swap_pmd(pmd_t pmd)
|
|
{
|
|
@@ -294,7 +291,7 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,
|
|
struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr,
|
|
pud_t *pud, int flags, struct dev_pagemap **pgmap);
|
|
|
|
-extern vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd);
|
|
+vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd);
|
|
|
|
extern struct page *huge_zero_page;
|
|
extern unsigned long huge_zero_pfn;
|
|
@@ -365,7 +362,7 @@ static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma)
|
|
return false;
|
|
}
|
|
|
|
-static inline bool transparent_hugepage_enabled(struct vm_area_struct *vma)
|
|
+static inline bool transparent_hugepage_active(struct vm_area_struct *vma)
|
|
{
|
|
return false;
|
|
}
|
|
@@ -376,6 +373,12 @@ static inline bool transhuge_vma_suitable(struct vm_area_struct *vma,
|
|
return false;
|
|
}
|
|
|
|
+static inline bool transhuge_vma_enabled(struct vm_area_struct *vma,
|
|
+ unsigned long vm_flags)
|
|
+{
|
|
+ return false;
|
|
+}
|
|
+
|
|
static inline void prep_transhuge_page(struct page *page) {}
|
|
|
|
static inline bool is_transparent_hugepage(struct page *page)
|
|
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h
|
|
index c9b80be82440f..f82857bd693fd 100644
|
|
--- a/include/linux/iio/common/cros_ec_sensors_core.h
|
|
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
|
|
@@ -77,7 +77,7 @@ struct cros_ec_sensors_core_state {
|
|
u16 scale;
|
|
} calib[CROS_EC_SENSOR_MAX_AXIS];
|
|
s8 sign[CROS_EC_SENSOR_MAX_AXIS];
|
|
- u8 samples[CROS_EC_SAMPLE_SIZE];
|
|
+ u8 samples[CROS_EC_SAMPLE_SIZE] __aligned(8);
|
|
|
|
int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
|
|
unsigned long scan_mask, s16 *data);
|
|
diff --git a/include/linux/prandom.h b/include/linux/prandom.h
|
|
index bbf4b4ad61dfd..056d31317e499 100644
|
|
--- a/include/linux/prandom.h
|
|
+++ b/include/linux/prandom.h
|
|
@@ -111,7 +111,7 @@ static inline u32 __seed(u32 x, u32 m)
|
|
*/
|
|
static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
|
|
{
|
|
- u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
|
|
+ u32 i = ((seed >> 32) ^ (seed << 10) ^ seed) & 0xffffffffUL;
|
|
|
|
state->s1 = __seed(i, 2U);
|
|
state->s2 = __seed(i, 8U);
|
|
diff --git a/include/linux/swap.h b/include/linux/swap.h
|
|
index fbc6805358da0..dfabf4660a670 100644
|
|
--- a/include/linux/swap.h
|
|
+++ b/include/linux/swap.h
|
|
@@ -503,6 +503,15 @@ static inline struct swap_info_struct *swp_swap_info(swp_entry_t entry)
|
|
return NULL;
|
|
}
|
|
|
|
+static inline struct swap_info_struct *get_swap_device(swp_entry_t entry)
|
|
+{
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static inline void put_swap_device(struct swap_info_struct *si)
|
|
+{
|
|
+}
|
|
+
|
|
#define swap_address_space(entry) (NULL)
|
|
#define get_nr_swap_pages() 0L
|
|
#define total_swap_pages 0L
|
|
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
|
|
index 966ed89803274..e4c5df71f0e74 100644
|
|
--- a/include/linux/tracepoint.h
|
|
+++ b/include/linux/tracepoint.h
|
|
@@ -41,7 +41,17 @@ extern int
|
|
tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, void *data,
|
|
int prio);
|
|
extern int
|
|
+tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe, void *data,
|
|
+ int prio);
|
|
+extern int
|
|
tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data);
|
|
+static inline int
|
|
+tracepoint_probe_register_may_exist(struct tracepoint *tp, void *probe,
|
|
+ void *data)
|
|
+{
|
|
+ return tracepoint_probe_register_prio_may_exist(tp, probe, data,
|
|
+ TRACEPOINT_DEFAULT_PRIO);
|
|
+}
|
|
extern void
|
|
for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
|
|
void *priv);
|
|
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
|
|
index 7616c7bf4b241..e1bd560da1cd4 100644
|
|
--- a/include/linux/user_namespace.h
|
|
+++ b/include/linux/user_namespace.h
|
|
@@ -101,11 +101,15 @@ struct ucounts {
|
|
};
|
|
|
|
extern struct user_namespace init_user_ns;
|
|
+extern struct ucounts init_ucounts;
|
|
|
|
bool setup_userns_sysctls(struct user_namespace *ns);
|
|
void retire_userns_sysctls(struct user_namespace *ns);
|
|
struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type);
|
|
void dec_ucount(struct ucounts *ucounts, enum ucount_type type);
|
|
+struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid);
|
|
+struct ucounts *get_ucounts(struct ucounts *ucounts);
|
|
+void put_ucounts(struct ucounts *ucounts);
|
|
|
|
#ifdef CONFIG_USER_NS
|
|
|
|
diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h
|
|
index 1009cf0891cc6..a3b650ab00f66 100644
|
|
--- a/include/media/hevc-ctrls.h
|
|
+++ b/include/media/hevc-ctrls.h
|
|
@@ -81,7 +81,7 @@ struct v4l2_ctrl_hevc_sps {
|
|
__u64 flags;
|
|
};
|
|
|
|
-#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 0)
|
|
+#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED (1ULL << 0)
|
|
#define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1)
|
|
#define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2)
|
|
#define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3)
|
|
@@ -160,6 +160,7 @@ struct v4l2_hevc_pred_weight_table {
|
|
#define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6)
|
|
#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7)
|
|
#define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8)
|
|
+#define V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 9)
|
|
|
|
struct v4l2_ctrl_hevc_slice_params {
|
|
__u32 bit_size;
|
|
diff --git a/include/media/media-dev-allocator.h b/include/media/media-dev-allocator.h
|
|
index b35ea6062596b..2ab54d426c644 100644
|
|
--- a/include/media/media-dev-allocator.h
|
|
+++ b/include/media/media-dev-allocator.h
|
|
@@ -19,7 +19,7 @@
|
|
|
|
struct usb_device;
|
|
|
|
-#if defined(CONFIG_MEDIA_CONTROLLER) && defined(CONFIG_USB)
|
|
+#if defined(CONFIG_MEDIA_CONTROLLER) && IS_ENABLED(CONFIG_USB)
|
|
/**
|
|
* media_device_usb_allocate() - Allocate and return struct &media device
|
|
*
|
|
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
|
|
index d6e31234826f3..92cd9f038fed8 100644
|
|
--- a/include/media/v4l2-async.h
|
|
+++ b/include/media/v4l2-async.h
|
|
@@ -189,9 +189,11 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
|
|
*
|
|
* @notif: pointer to &struct v4l2_async_notifier
|
|
* @endpoint: local endpoint pointing to the remote sub-device to be matched
|
|
- * @asd: Async sub-device struct allocated by the caller. The &struct
|
|
- * v4l2_async_subdev shall be the first member of the driver's async
|
|
- * sub-device struct, i.e. both begin at the same memory address.
|
|
+ * @asd_struct_size: size of the driver's async sub-device struct, including
|
|
+ * sizeof(struct v4l2_async_subdev). The &struct
|
|
+ * v4l2_async_subdev shall be the first member of
|
|
+ * the driver's async sub-device struct, i.e. both
|
|
+ * begin at the same memory address.
|
|
*
|
|
* Gets the remote endpoint of a given local endpoint, set it up for fwnode
|
|
* matching and adds the async sub-device to the notifier's @asd_list. The
|
|
@@ -199,13 +201,12 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
|
|
* notifier cleanup time.
|
|
*
|
|
* This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the
|
|
- * exception that the fwnode refers to a local endpoint, not the remote one, and
|
|
- * the function relies on the caller to allocate the async sub-device struct.
|
|
+ * exception that the fwnode refers to a local endpoint, not the remote one.
|
|
*/
|
|
-int
|
|
+struct v4l2_async_subdev *
|
|
v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif,
|
|
struct fwnode_handle *endpoint,
|
|
- struct v4l2_async_subdev *asd);
|
|
+ unsigned int asd_struct_size);
|
|
|
|
/**
|
|
* v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async
|
|
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
|
|
index 6da4b3c5dd55d..243de74e118e7 100644
|
|
--- a/include/net/bluetooth/hci.h
|
|
+++ b/include/net/bluetooth/hci.h
|
|
@@ -1773,13 +1773,15 @@ struct hci_cp_ext_adv_set {
|
|
__u8 max_events;
|
|
} __packed;
|
|
|
|
+#define HCI_MAX_EXT_AD_LENGTH 251
|
|
+
|
|
#define HCI_OP_LE_SET_EXT_ADV_DATA 0x2037
|
|
struct hci_cp_le_set_ext_adv_data {
|
|
__u8 handle;
|
|
__u8 operation;
|
|
__u8 frag_pref;
|
|
__u8 length;
|
|
- __u8 data[HCI_MAX_AD_LENGTH];
|
|
+ __u8 data[];
|
|
} __packed;
|
|
|
|
#define HCI_OP_LE_SET_EXT_SCAN_RSP_DATA 0x2038
|
|
@@ -1788,7 +1790,7 @@ struct hci_cp_le_set_ext_scan_rsp_data {
|
|
__u8 operation;
|
|
__u8 frag_pref;
|
|
__u8 length;
|
|
- __u8 data[HCI_MAX_AD_LENGTH];
|
|
+ __u8 data[];
|
|
} __packed;
|
|
|
|
#define LE_SET_ADV_DATA_OP_COMPLETE 0x03
|
|
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
|
|
index df611c8b6b595..e534dff2874e1 100644
|
|
--- a/include/net/bluetooth/hci_core.h
|
|
+++ b/include/net/bluetooth/hci_core.h
|
|
@@ -226,9 +226,9 @@ struct adv_info {
|
|
__u16 remaining_time;
|
|
__u16 duration;
|
|
__u16 adv_data_len;
|
|
- __u8 adv_data[HCI_MAX_AD_LENGTH];
|
|
+ __u8 adv_data[HCI_MAX_EXT_AD_LENGTH];
|
|
__u16 scan_rsp_len;
|
|
- __u8 scan_rsp_data[HCI_MAX_AD_LENGTH];
|
|
+ __u8 scan_rsp_data[HCI_MAX_EXT_AD_LENGTH];
|
|
__s8 tx_power;
|
|
bdaddr_t random_addr;
|
|
bool rpa_expired;
|
|
@@ -523,9 +523,9 @@ struct hci_dev {
|
|
DECLARE_BITMAP(dev_flags, __HCI_NUM_FLAGS);
|
|
|
|
__s8 adv_tx_power;
|
|
- __u8 adv_data[HCI_MAX_AD_LENGTH];
|
|
+ __u8 adv_data[HCI_MAX_EXT_AD_LENGTH];
|
|
__u8 adv_data_len;
|
|
- __u8 scan_rsp_data[HCI_MAX_AD_LENGTH];
|
|
+ __u8 scan_rsp_data[HCI_MAX_EXT_AD_LENGTH];
|
|
__u8 scan_rsp_data_len;
|
|
|
|
struct list_head adv_instances;
|
|
diff --git a/include/net/ip.h b/include/net/ip.h
|
|
index 2d6b985d11cca..5538e54d4620c 100644
|
|
--- a/include/net/ip.h
|
|
+++ b/include/net/ip.h
|
|
@@ -31,6 +31,7 @@
|
|
#include <net/flow.h>
|
|
#include <net/flow_dissector.h>
|
|
#include <net/netns/hash.h>
|
|
+#include <net/lwtunnel.h>
|
|
|
|
#define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */
|
|
#define IPV4_MIN_MTU 68 /* RFC 791 */
|
|
@@ -445,22 +446,25 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
|
|
|
|
/* 'forwarding = true' case should always honour route mtu */
|
|
mtu = dst_metric_raw(dst, RTAX_MTU);
|
|
- if (mtu)
|
|
- return mtu;
|
|
+ if (!mtu)
|
|
+ mtu = min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
|
|
|
|
- return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
|
|
+ return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
|
}
|
|
|
|
static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
|
|
const struct sk_buff *skb)
|
|
{
|
|
+ unsigned int mtu;
|
|
+
|
|
if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
|
|
bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
|
|
|
|
return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
|
|
}
|
|
|
|
- return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
|
|
+ mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
|
|
+ return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
|
|
}
|
|
|
|
struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
|
|
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
|
|
index 2a5277758379e..37a7fb1969d6c 100644
|
|
--- a/include/net/ip6_route.h
|
|
+++ b/include/net/ip6_route.h
|
|
@@ -264,11 +264,18 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
|
|
|
|
static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
|
|
{
|
|
+ int mtu;
|
|
+
|
|
struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ?
|
|
inet6_sk(skb->sk) : NULL;
|
|
|
|
- return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ?
|
|
- skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
|
|
+ if (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) {
|
|
+ mtu = READ_ONCE(skb_dst(skb)->dev->mtu);
|
|
+ mtu -= lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
|
|
+ } else
|
|
+ mtu = dst_mtu(skb_dst(skb));
|
|
+
|
|
+ return mtu;
|
|
}
|
|
|
|
static inline bool ip6_sk_accept_pmtu(const struct sock *sk)
|
|
@@ -316,7 +323,7 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
|
|
if (dst_metric_locked(dst, RTAX_MTU)) {
|
|
mtu = dst_metric_raw(dst, RTAX_MTU);
|
|
if (mtu)
|
|
- return mtu;
|
|
+ goto out;
|
|
}
|
|
|
|
mtu = IPV6_MIN_MTU;
|
|
@@ -326,7 +333,8 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
|
|
mtu = idev->cnf.mtu6;
|
|
rcu_read_unlock();
|
|
|
|
- return mtu;
|
|
+out:
|
|
+ return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
|
}
|
|
|
|
u32 ip6_mtu_from_fib6(const struct fib6_result *res,
|
|
diff --git a/include/net/macsec.h b/include/net/macsec.h
|
|
index 52874cdfe2260..d6fa6b97f6efa 100644
|
|
--- a/include/net/macsec.h
|
|
+++ b/include/net/macsec.h
|
|
@@ -241,7 +241,7 @@ struct macsec_context {
|
|
struct macsec_rx_sc *rx_sc;
|
|
struct {
|
|
unsigned char assoc_num;
|
|
- u8 key[MACSEC_KEYID_LEN];
|
|
+ u8 key[MACSEC_MAX_KEY_LEN];
|
|
union {
|
|
struct macsec_rx_sa *rx_sa;
|
|
struct macsec_tx_sa *tx_sa;
|
|
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
|
|
index 4dd2c9e34976e..f8631ad3c8686 100644
|
|
--- a/include/net/sch_generic.h
|
|
+++ b/include/net/sch_generic.h
|
|
@@ -163,6 +163,12 @@ static inline bool qdisc_run_begin(struct Qdisc *qdisc)
|
|
if (spin_trylock(&qdisc->seqlock))
|
|
goto nolock_empty;
|
|
|
|
+ /* Paired with smp_mb__after_atomic() to make sure
|
|
+ * STATE_MISSED checking is synchronized with clearing
|
|
+ * in pfifo_fast_dequeue().
|
|
+ */
|
|
+ smp_mb__before_atomic();
|
|
+
|
|
/* If the MISSED flag is set, it means other thread has
|
|
* set the MISSED flag before second spin_trylock(), so
|
|
* we can return false here to avoid multi cpus doing
|
|
@@ -180,6 +186,12 @@ static inline bool qdisc_run_begin(struct Qdisc *qdisc)
|
|
*/
|
|
set_bit(__QDISC_STATE_MISSED, &qdisc->state);
|
|
|
|
+ /* spin_trylock() only has load-acquire semantic, so use
|
|
+ * smp_mb__after_atomic() to ensure STATE_MISSED is set
|
|
+ * before doing the second spin_trylock().
|
|
+ */
|
|
+ smp_mb__after_atomic();
|
|
+
|
|
/* Retry again in case other CPU may not see the new flag
|
|
* after it releases the lock at the end of qdisc_run_end().
|
|
*/
|
|
diff --git a/include/net/tc_act/tc_vlan.h b/include/net/tc_act/tc_vlan.h
|
|
index f051046ba0344..f94b8bc26f9ec 100644
|
|
--- a/include/net/tc_act/tc_vlan.h
|
|
+++ b/include/net/tc_act/tc_vlan.h
|
|
@@ -16,6 +16,7 @@ struct tcf_vlan_params {
|
|
u16 tcfv_push_vid;
|
|
__be16 tcfv_push_proto;
|
|
u8 tcfv_push_prio;
|
|
+ bool tcfv_push_prio_exists;
|
|
struct rcu_head rcu;
|
|
};
|
|
|
|
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
|
|
index c58a6d4eb6103..6232a5f048bde 100644
|
|
--- a/include/net/xfrm.h
|
|
+++ b/include/net/xfrm.h
|
|
@@ -1546,6 +1546,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
|
|
void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
|
|
u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
|
|
int xfrm_init_replay(struct xfrm_state *x);
|
|
+u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu);
|
|
u32 xfrm_state_mtu(struct xfrm_state *x, int mtu);
|
|
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload);
|
|
int xfrm_init_state(struct xfrm_state *x);
|
|
diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h
|
|
index eaa8386dbc630..7a9a23e7a604a 100644
|
|
--- a/include/net/xsk_buff_pool.h
|
|
+++ b/include/net/xsk_buff_pool.h
|
|
@@ -147,11 +147,16 @@ static inline bool xp_desc_crosses_non_contig_pg(struct xsk_buff_pool *pool,
|
|
{
|
|
bool cross_pg = (addr & (PAGE_SIZE - 1)) + len > PAGE_SIZE;
|
|
|
|
- if (pool->dma_pages_cnt && cross_pg) {
|
|
+ if (likely(!cross_pg))
|
|
+ return false;
|
|
+
|
|
+ if (pool->dma_pages_cnt) {
|
|
return !(pool->dma_pages[addr >> PAGE_SHIFT] &
|
|
XSK_NEXT_PG_CONTIG_MASK);
|
|
}
|
|
- return false;
|
|
+
|
|
+ /* skb path */
|
|
+ return addr + len > pool->addrs_cnt;
|
|
}
|
|
|
|
static inline u64 xp_aligned_extract_addr(struct xsk_buff_pool *pool, u64 addr)
|
|
diff --git a/include/scsi/fc/fc_ms.h b/include/scsi/fc/fc_ms.h
|
|
index 9e273fed0a85f..800d53dc94705 100644
|
|
--- a/include/scsi/fc/fc_ms.h
|
|
+++ b/include/scsi/fc/fc_ms.h
|
|
@@ -63,8 +63,8 @@ enum fc_fdmi_hba_attr_type {
|
|
* HBA Attribute Length
|
|
*/
|
|
#define FC_FDMI_HBA_ATTR_NODENAME_LEN 8
|
|
-#define FC_FDMI_HBA_ATTR_MANUFACTURER_LEN 80
|
|
-#define FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN 80
|
|
+#define FC_FDMI_HBA_ATTR_MANUFACTURER_LEN 64
|
|
+#define FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN 64
|
|
#define FC_FDMI_HBA_ATTR_MODEL_LEN 256
|
|
#define FC_FDMI_HBA_ATTR_MODELDESCR_LEN 256
|
|
#define FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN 256
|
|
diff --git a/init/main.c b/init/main.c
|
|
index b4449544390ca..dd26a42e80a87 100644
|
|
--- a/init/main.c
|
|
+++ b/init/main.c
|
|
@@ -914,11 +914,7 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
|
|
* time - but meanwhile we still have a functioning scheduler.
|
|
*/
|
|
sched_init();
|
|
- /*
|
|
- * Disable preemption - early bootup scheduling is extremely
|
|
- * fragile until we cpu_idle() for the first time.
|
|
- */
|
|
- preempt_disable();
|
|
+
|
|
if (WARN(!irqs_disabled(),
|
|
"Interrupts were enabled *very* early, fixing it\n"))
|
|
local_irq_disable();
|
|
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
|
|
index e97724e36dfb5..bf6798fb23319 100644
|
|
--- a/kernel/bpf/verifier.c
|
|
+++ b/kernel/bpf/verifier.c
|
|
@@ -10532,7 +10532,7 @@ static void adjust_subprog_starts(struct bpf_verifier_env *env, u32 off, u32 len
|
|
}
|
|
}
|
|
|
|
-static void adjust_poke_descs(struct bpf_prog *prog, u32 len)
|
|
+static void adjust_poke_descs(struct bpf_prog *prog, u32 off, u32 len)
|
|
{
|
|
struct bpf_jit_poke_descriptor *tab = prog->aux->poke_tab;
|
|
int i, sz = prog->aux->size_poke_tab;
|
|
@@ -10540,6 +10540,8 @@ static void adjust_poke_descs(struct bpf_prog *prog, u32 len)
|
|
|
|
for (i = 0; i < sz; i++) {
|
|
desc = &tab[i];
|
|
+ if (desc->insn_idx <= off)
|
|
+ continue;
|
|
desc->insn_idx += len - 1;
|
|
}
|
|
}
|
|
@@ -10560,7 +10562,7 @@ static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 of
|
|
if (adjust_insn_aux_data(env, new_prog, off, len))
|
|
return NULL;
|
|
adjust_subprog_starts(env, off, len);
|
|
- adjust_poke_descs(new_prog, len);
|
|
+ adjust_poke_descs(new_prog, off, len);
|
|
return new_prog;
|
|
}
|
|
|
|
diff --git a/kernel/cred.c b/kernel/cred.c
|
|
index 421b1149c6516..098213d4a39c3 100644
|
|
--- a/kernel/cred.c
|
|
+++ b/kernel/cred.c
|
|
@@ -60,6 +60,7 @@ struct cred init_cred = {
|
|
.user = INIT_USER,
|
|
.user_ns = &init_user_ns,
|
|
.group_info = &init_groups,
|
|
+ .ucounts = &init_ucounts,
|
|
};
|
|
|
|
static inline void set_cred_subscribers(struct cred *cred, int n)
|
|
@@ -119,6 +120,8 @@ static void put_cred_rcu(struct rcu_head *rcu)
|
|
if (cred->group_info)
|
|
put_group_info(cred->group_info);
|
|
free_uid(cred->user);
|
|
+ if (cred->ucounts)
|
|
+ put_ucounts(cred->ucounts);
|
|
put_user_ns(cred->user_ns);
|
|
kmem_cache_free(cred_jar, cred);
|
|
}
|
|
@@ -222,6 +225,7 @@ struct cred *cred_alloc_blank(void)
|
|
#ifdef CONFIG_DEBUG_CREDENTIALS
|
|
new->magic = CRED_MAGIC;
|
|
#endif
|
|
+ new->ucounts = get_ucounts(&init_ucounts);
|
|
|
|
if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0)
|
|
goto error;
|
|
@@ -284,6 +288,11 @@ struct cred *prepare_creds(void)
|
|
|
|
if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
|
|
goto error;
|
|
+
|
|
+ new->ucounts = get_ucounts(new->ucounts);
|
|
+ if (!new->ucounts)
|
|
+ goto error;
|
|
+
|
|
validate_creds(new);
|
|
return new;
|
|
|
|
@@ -363,6 +372,9 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
|
|
ret = create_user_ns(new);
|
|
if (ret < 0)
|
|
goto error_put;
|
|
+ ret = set_cred_ucounts(new);
|
|
+ if (ret < 0)
|
|
+ goto error_put;
|
|
}
|
|
|
|
#ifdef CONFIG_KEYS
|
|
@@ -653,6 +665,31 @@ int cred_fscmp(const struct cred *a, const struct cred *b)
|
|
}
|
|
EXPORT_SYMBOL(cred_fscmp);
|
|
|
|
+int set_cred_ucounts(struct cred *new)
|
|
+{
|
|
+ struct task_struct *task = current;
|
|
+ const struct cred *old = task->real_cred;
|
|
+ struct ucounts *old_ucounts = new->ucounts;
|
|
+
|
|
+ if (new->user == old->user && new->user_ns == old->user_ns)
|
|
+ return 0;
|
|
+
|
|
+ /*
|
|
+ * This optimization is needed because alloc_ucounts() uses locks
|
|
+ * for table lookups.
|
|
+ */
|
|
+ if (old_ucounts && old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->euid))
|
|
+ return 0;
|
|
+
|
|
+ if (!(new->ucounts = alloc_ucounts(new->user_ns, new->euid)))
|
|
+ return -EAGAIN;
|
|
+
|
|
+ if (old_ucounts)
|
|
+ put_ucounts(old_ucounts);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* initialise the credentials stuff
|
|
*/
|
|
@@ -719,6 +756,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
|
|
if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
|
|
goto error;
|
|
|
|
+ new->ucounts = get_ucounts(new->ucounts);
|
|
+ if (!new->ucounts)
|
|
+ goto error;
|
|
+
|
|
put_cred(old);
|
|
validate_creds(new);
|
|
return new;
|
|
diff --git a/kernel/fork.c b/kernel/fork.c
|
|
index 7c044d377926c..096945ef49ad7 100644
|
|
--- a/kernel/fork.c
|
|
+++ b/kernel/fork.c
|
|
@@ -2392,7 +2392,7 @@ static inline void init_idle_pids(struct task_struct *idle)
|
|
}
|
|
}
|
|
|
|
-struct task_struct *fork_idle(int cpu)
|
|
+struct task_struct * __init fork_idle(int cpu)
|
|
{
|
|
struct task_struct *task;
|
|
struct kernel_clone_args args = {
|
|
@@ -2960,6 +2960,12 @@ int ksys_unshare(unsigned long unshare_flags)
|
|
if (err)
|
|
goto bad_unshare_cleanup_cred;
|
|
|
|
+ if (new_cred) {
|
|
+ err = set_cred_ucounts(new_cred);
|
|
+ if (err)
|
|
+ goto bad_unshare_cleanup_cred;
|
|
+ }
|
|
+
|
|
if (new_fs || new_fd || do_sysvsem || new_cred || new_nsproxy) {
|
|
if (do_sysvsem) {
|
|
/*
|
|
diff --git a/kernel/kthread.c b/kernel/kthread.c
|
|
index 36be4364b313a..9825cf89c614d 100644
|
|
--- a/kernel/kthread.c
|
|
+++ b/kernel/kthread.c
|
|
@@ -1107,14 +1107,14 @@ static bool __kthread_cancel_work(struct kthread_work *work)
|
|
* modify @dwork's timer so that it expires after @delay. If @delay is zero,
|
|
* @work is guaranteed to be queued immediately.
|
|
*
|
|
- * Return: %true if @dwork was pending and its timer was modified,
|
|
- * %false otherwise.
|
|
+ * Return: %false if @dwork was idle and queued, %true otherwise.
|
|
*
|
|
* A special case is when the work is being canceled in parallel.
|
|
* It might be caused either by the real kthread_cancel_delayed_work_sync()
|
|
* or yet another kthread_mod_delayed_work() call. We let the other command
|
|
- * win and return %false here. The caller is supposed to synchronize these
|
|
- * operations a reasonable way.
|
|
+ * win and return %true here. The return value can be used for reference
|
|
+ * counting and the number of queued works stays the same. Anyway, the caller
|
|
+ * is supposed to synchronize these operations a reasonable way.
|
|
*
|
|
* This function is safe to call from any context including IRQ handler.
|
|
* See __kthread_cancel_work() and kthread_delayed_work_timer_fn()
|
|
@@ -1126,13 +1126,15 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
|
|
{
|
|
struct kthread_work *work = &dwork->work;
|
|
unsigned long flags;
|
|
- int ret = false;
|
|
+ int ret;
|
|
|
|
raw_spin_lock_irqsave(&worker->lock, flags);
|
|
|
|
/* Do not bother with canceling when never queued. */
|
|
- if (!work->worker)
|
|
+ if (!work->worker) {
|
|
+ ret = false;
|
|
goto fast_queue;
|
|
+ }
|
|
|
|
/* Work must not be used with >1 worker, see kthread_queue_work() */
|
|
WARN_ON_ONCE(work->worker != worker);
|
|
@@ -1150,8 +1152,11 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker,
|
|
* be used for reference counting.
|
|
*/
|
|
kthread_cancel_delayed_work_timer(work, &flags);
|
|
- if (work->canceling)
|
|
+ if (work->canceling) {
|
|
+ /* The number of works in the queue does not change. */
|
|
+ ret = true;
|
|
goto out;
|
|
+ }
|
|
ret = __kthread_cancel_work(work);
|
|
|
|
fast_queue:
|
|
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
|
|
index cdca007551e71..8ae9d7abebc08 100644
|
|
--- a/kernel/locking/lockdep.c
|
|
+++ b/kernel/locking/lockdep.c
|
|
@@ -2297,7 +2297,56 @@ static void print_lock_class_header(struct lock_class *class, int depth)
|
|
}
|
|
|
|
/*
|
|
- * printk the shortest lock dependencies from @start to @end in reverse order:
|
|
+ * Dependency path printing:
|
|
+ *
|
|
+ * After BFS we get a lock dependency path (linked via ->parent of lock_list),
|
|
+ * printing out each lock in the dependency path will help on understanding how
|
|
+ * the deadlock could happen. Here are some details about dependency path
|
|
+ * printing:
|
|
+ *
|
|
+ * 1) A lock_list can be either forwards or backwards for a lock dependency,
|
|
+ * for a lock dependency A -> B, there are two lock_lists:
|
|
+ *
|
|
+ * a) lock_list in the ->locks_after list of A, whose ->class is B and
|
|
+ * ->links_to is A. In this case, we can say the lock_list is
|
|
+ * "A -> B" (forwards case).
|
|
+ *
|
|
+ * b) lock_list in the ->locks_before list of B, whose ->class is A
|
|
+ * and ->links_to is B. In this case, we can say the lock_list is
|
|
+ * "B <- A" (bacwards case).
|
|
+ *
|
|
+ * The ->trace of both a) and b) point to the call trace where B was
|
|
+ * acquired with A held.
|
|
+ *
|
|
+ * 2) A "helper" lock_list is introduced during BFS, this lock_list doesn't
|
|
+ * represent a certain lock dependency, it only provides an initial entry
|
|
+ * for BFS. For example, BFS may introduce a "helper" lock_list whose
|
|
+ * ->class is A, as a result BFS will search all dependencies starting with
|
|
+ * A, e.g. A -> B or A -> C.
|
|
+ *
|
|
+ * The notation of a forwards helper lock_list is like "-> A", which means
|
|
+ * we should search the forwards dependencies starting with "A", e.g A -> B
|
|
+ * or A -> C.
|
|
+ *
|
|
+ * The notation of a bacwards helper lock_list is like "<- B", which means
|
|
+ * we should search the backwards dependencies ending with "B", e.g.
|
|
+ * B <- A or B <- C.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * printk the shortest lock dependencies from @root to @leaf in reverse order.
|
|
+ *
|
|
+ * We have a lock dependency path as follow:
|
|
+ *
|
|
+ * @root @leaf
|
|
+ * | |
|
|
+ * V V
|
|
+ * ->parent ->parent
|
|
+ * | lock_list | <--------- | lock_list | ... | lock_list | <--------- | lock_list |
|
|
+ * | -> L1 | | L1 -> L2 | ... |Ln-2 -> Ln-1| | Ln-1 -> Ln|
|
|
+ *
|
|
+ * , so it's natural that we start from @leaf and print every ->class and
|
|
+ * ->trace until we reach the @root.
|
|
*/
|
|
static void __used
|
|
print_shortest_lock_dependencies(struct lock_list *leaf,
|
|
@@ -2325,6 +2374,61 @@ print_shortest_lock_dependencies(struct lock_list *leaf,
|
|
} while (entry && (depth >= 0));
|
|
}
|
|
|
|
+/*
|
|
+ * printk the shortest lock dependencies from @leaf to @root.
|
|
+ *
|
|
+ * We have a lock dependency path (from a backwards search) as follow:
|
|
+ *
|
|
+ * @leaf @root
|
|
+ * | |
|
|
+ * V V
|
|
+ * ->parent ->parent
|
|
+ * | lock_list | ---------> | lock_list | ... | lock_list | ---------> | lock_list |
|
|
+ * | L2 <- L1 | | L3 <- L2 | ... | Ln <- Ln-1 | | <- Ln |
|
|
+ *
|
|
+ * , so when we iterate from @leaf to @root, we actually print the lock
|
|
+ * dependency path L1 -> L2 -> .. -> Ln in the non-reverse order.
|
|
+ *
|
|
+ * Another thing to notice here is that ->class of L2 <- L1 is L1, while the
|
|
+ * ->trace of L2 <- L1 is the call trace of L2, in fact we don't have the call
|
|
+ * trace of L1 in the dependency path, which is alright, because most of the
|
|
+ * time we can figure out where L1 is held from the call trace of L2.
|
|
+ */
|
|
+static void __used
|
|
+print_shortest_lock_dependencies_backwards(struct lock_list *leaf,
|
|
+ struct lock_list *root)
|
|
+{
|
|
+ struct lock_list *entry = leaf;
|
|
+ const struct lock_trace *trace = NULL;
|
|
+ int depth;
|
|
+
|
|
+ /*compute depth from generated tree by BFS*/
|
|
+ depth = get_lock_depth(leaf);
|
|
+
|
|
+ do {
|
|
+ print_lock_class_header(entry->class, depth);
|
|
+ if (trace) {
|
|
+ printk("%*s ... acquired at:\n", depth, "");
|
|
+ print_lock_trace(trace, 2);
|
|
+ printk("\n");
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Record the pointer to the trace for the next lock_list
|
|
+ * entry, see the comments for the function.
|
|
+ */
|
|
+ trace = entry->trace;
|
|
+
|
|
+ if (depth == 0 && (entry != root)) {
|
|
+ printk("lockdep:%s bad path found in chain graph\n", __func__);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ entry = get_lock_parent(entry);
|
|
+ depth--;
|
|
+ } while (entry && (depth >= 0));
|
|
+}
|
|
+
|
|
static void
|
|
print_irq_lock_scenario(struct lock_list *safe_entry,
|
|
struct lock_list *unsafe_entry,
|
|
@@ -2442,7 +2546,7 @@ print_bad_irq_dependency(struct task_struct *curr,
|
|
prev_root->trace = save_trace();
|
|
if (!prev_root->trace)
|
|
return;
|
|
- print_shortest_lock_dependencies(backwards_entry, prev_root);
|
|
+ print_shortest_lock_dependencies_backwards(backwards_entry, prev_root);
|
|
|
|
pr_warn("\nthe dependencies between the lock to be acquired");
|
|
pr_warn(" and %s-irq-unsafe lock:\n", irqclass);
|
|
@@ -2660,8 +2764,18 @@ static int check_irq_usage(struct task_struct *curr, struct held_lock *prev,
|
|
* Step 3: we found a bad match! Now retrieve a lock from the backward
|
|
* list whose usage mask matches the exclusive usage mask from the
|
|
* lock found on the forward list.
|
|
+ *
|
|
+ * Note, we should only keep the LOCKF_ENABLED_IRQ_ALL bits, considering
|
|
+ * the follow case:
|
|
+ *
|
|
+ * When trying to add A -> B to the graph, we find that there is a
|
|
+ * hardirq-safe L, that L -> ... -> A, and another hardirq-unsafe M,
|
|
+ * that B -> ... -> M. However M is **softirq-safe**, if we use exact
|
|
+ * invert bits of M's usage_mask, we will find another lock N that is
|
|
+ * **softirq-unsafe** and N -> ... -> A, however N -> .. -> M will not
|
|
+ * cause a inversion deadlock.
|
|
*/
|
|
- backward_mask = original_mask(target_entry1->class->usage_mask);
|
|
+ backward_mask = original_mask(target_entry1->class->usage_mask & LOCKF_ENABLED_IRQ_ALL);
|
|
|
|
ret = find_usage_backwards(&this, backward_mask, &target_entry);
|
|
if (bfs_error(ret)) {
|
|
@@ -4512,7 +4626,7 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
|
|
short curr_inner;
|
|
int depth;
|
|
|
|
- if (!curr->lockdep_depth || !next_inner || next->trylock)
|
|
+ if (!next_inner || next->trylock)
|
|
return 0;
|
|
|
|
if (!next_outer)
|
|
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
|
|
index 61e250cdd7c9c..45b60e9974610 100644
|
|
--- a/kernel/rcu/tree.c
|
|
+++ b/kernel/rcu/tree.c
|
|
@@ -2837,7 +2837,6 @@ static int __init rcu_spawn_core_kthreads(void)
|
|
"%s: Could not start rcuc kthread, OOM is now expected behavior\n", __func__);
|
|
return 0;
|
|
}
|
|
-early_initcall(rcu_spawn_core_kthreads);
|
|
|
|
/*
|
|
* Handle any core-RCU processing required by a call_rcu() invocation.
|
|
@@ -4273,6 +4272,7 @@ static int __init rcu_spawn_gp_kthread(void)
|
|
wake_up_process(t);
|
|
rcu_spawn_nocb_kthreads();
|
|
rcu_spawn_boost_kthreads();
|
|
+ rcu_spawn_core_kthreads();
|
|
return 0;
|
|
}
|
|
early_initcall(rcu_spawn_gp_kthread);
|
|
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
|
index 57b2362518849..679562d2f55d1 100644
|
|
--- a/kernel/sched/core.c
|
|
+++ b/kernel/sched/core.c
|
|
@@ -1063,9 +1063,10 @@ static void uclamp_sync_util_min_rt_default(void)
|
|
static inline struct uclamp_se
|
|
uclamp_tg_restrict(struct task_struct *p, enum uclamp_id clamp_id)
|
|
{
|
|
+ /* Copy by value as we could modify it */
|
|
struct uclamp_se uc_req = p->uclamp_req[clamp_id];
|
|
#ifdef CONFIG_UCLAMP_TASK_GROUP
|
|
- struct uclamp_se uc_max;
|
|
+ unsigned int tg_min, tg_max, value;
|
|
|
|
/*
|
|
* Tasks in autogroups or root task group will be
|
|
@@ -1076,9 +1077,11 @@ uclamp_tg_restrict(struct task_struct *p, enum uclamp_id clamp_id)
|
|
if (task_group(p) == &root_task_group)
|
|
return uc_req;
|
|
|
|
- uc_max = task_group(p)->uclamp[clamp_id];
|
|
- if (uc_req.value > uc_max.value || !uc_req.user_defined)
|
|
- return uc_max;
|
|
+ tg_min = task_group(p)->uclamp[UCLAMP_MIN].value;
|
|
+ tg_max = task_group(p)->uclamp[UCLAMP_MAX].value;
|
|
+ value = uc_req.value;
|
|
+ value = clamp(value, tg_min, tg_max);
|
|
+ uclamp_se_set(&uc_req, value, false);
|
|
#endif
|
|
|
|
return uc_req;
|
|
@@ -1277,8 +1280,9 @@ static inline void uclamp_rq_dec(struct rq *rq, struct task_struct *p)
|
|
}
|
|
|
|
static inline void
|
|
-uclamp_update_active(struct task_struct *p, enum uclamp_id clamp_id)
|
|
+uclamp_update_active(struct task_struct *p)
|
|
{
|
|
+ enum uclamp_id clamp_id;
|
|
struct rq_flags rf;
|
|
struct rq *rq;
|
|
|
|
@@ -1298,9 +1302,11 @@ uclamp_update_active(struct task_struct *p, enum uclamp_id clamp_id)
|
|
* affecting a valid clamp bucket, the next time it's enqueued,
|
|
* it will already see the updated clamp bucket value.
|
|
*/
|
|
- if (p->uclamp[clamp_id].active) {
|
|
- uclamp_rq_dec_id(rq, p, clamp_id);
|
|
- uclamp_rq_inc_id(rq, p, clamp_id);
|
|
+ for_each_clamp_id(clamp_id) {
|
|
+ if (p->uclamp[clamp_id].active) {
|
|
+ uclamp_rq_dec_id(rq, p, clamp_id);
|
|
+ uclamp_rq_inc_id(rq, p, clamp_id);
|
|
+ }
|
|
}
|
|
|
|
task_rq_unlock(rq, p, &rf);
|
|
@@ -1308,20 +1314,14 @@ uclamp_update_active(struct task_struct *p, enum uclamp_id clamp_id)
|
|
|
|
#ifdef CONFIG_UCLAMP_TASK_GROUP
|
|
static inline void
|
|
-uclamp_update_active_tasks(struct cgroup_subsys_state *css,
|
|
- unsigned int clamps)
|
|
+uclamp_update_active_tasks(struct cgroup_subsys_state *css)
|
|
{
|
|
- enum uclamp_id clamp_id;
|
|
struct css_task_iter it;
|
|
struct task_struct *p;
|
|
|
|
css_task_iter_start(css, 0, &it);
|
|
- while ((p = css_task_iter_next(&it))) {
|
|
- for_each_clamp_id(clamp_id) {
|
|
- if ((0x1 << clamp_id) & clamps)
|
|
- uclamp_update_active(p, clamp_id);
|
|
- }
|
|
- }
|
|
+ while ((p = css_task_iter_next(&it)))
|
|
+ uclamp_update_active(p);
|
|
css_task_iter_end(&it);
|
|
}
|
|
|
|
@@ -6512,7 +6512,7 @@ void show_state_filter(unsigned long state_filter)
|
|
* NOTE: this function does not set the idle thread's NEED_RESCHED
|
|
* flag, to make booting more robust.
|
|
*/
|
|
-void init_idle(struct task_struct *idle, int cpu)
|
|
+void __init init_idle(struct task_struct *idle, int cpu)
|
|
{
|
|
struct rq *rq = cpu_rq(cpu);
|
|
unsigned long flags;
|
|
@@ -7607,7 +7607,11 @@ static int cpu_cgroup_css_online(struct cgroup_subsys_state *css)
|
|
|
|
#ifdef CONFIG_UCLAMP_TASK_GROUP
|
|
/* Propagate the effective uclamp value for the new group */
|
|
+ mutex_lock(&uclamp_mutex);
|
|
+ rcu_read_lock();
|
|
cpu_util_update_eff(css);
|
|
+ rcu_read_unlock();
|
|
+ mutex_unlock(&uclamp_mutex);
|
|
#endif
|
|
|
|
return 0;
|
|
@@ -7697,6 +7701,9 @@ static void cpu_util_update_eff(struct cgroup_subsys_state *css)
|
|
enum uclamp_id clamp_id;
|
|
unsigned int clamps;
|
|
|
|
+ lockdep_assert_held(&uclamp_mutex);
|
|
+ SCHED_WARN_ON(!rcu_read_lock_held());
|
|
+
|
|
css_for_each_descendant_pre(css, top_css) {
|
|
uc_parent = css_tg(css)->parent
|
|
? css_tg(css)->parent->uclamp : NULL;
|
|
@@ -7729,7 +7736,7 @@ static void cpu_util_update_eff(struct cgroup_subsys_state *css)
|
|
}
|
|
|
|
/* Immediately update descendants RUNNABLE tasks */
|
|
- uclamp_update_active_tasks(css, clamps);
|
|
+ uclamp_update_active_tasks(css);
|
|
}
|
|
}
|
|
|
|
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
|
|
index 8d06d1f4e2f7b..6b98c1fe6e7f8 100644
|
|
--- a/kernel/sched/deadline.c
|
|
+++ b/kernel/sched/deadline.c
|
|
@@ -2470,6 +2470,8 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p)
|
|
check_preempt_curr_dl(rq, p, 0);
|
|
else
|
|
resched_curr(rq);
|
|
+ } else {
|
|
+ update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 0);
|
|
}
|
|
}
|
|
|
|
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
|
index d6e1c90de570a..3d92de7909bf4 100644
|
|
--- a/kernel/sched/fair.c
|
|
+++ b/kernel/sched/fair.c
|
|
@@ -3141,7 +3141,7 @@ void reweight_task(struct task_struct *p, int prio)
|
|
*
|
|
* tg->weight * grq->load.weight
|
|
* ge->load.weight = ----------------------------- (1)
|
|
- * \Sum grq->load.weight
|
|
+ * \Sum grq->load.weight
|
|
*
|
|
* Now, because computing that sum is prohibitively expensive to compute (been
|
|
* there, done that) we approximate it with this average stuff. The average
|
|
@@ -3155,7 +3155,7 @@ void reweight_task(struct task_struct *p, int prio)
|
|
*
|
|
* tg->weight * grq->avg.load_avg
|
|
* ge->load.weight = ------------------------------ (3)
|
|
- * tg->load_avg
|
|
+ * tg->load_avg
|
|
*
|
|
* Where: tg->load_avg ~= \Sum grq->avg.load_avg
|
|
*
|
|
@@ -3171,7 +3171,7 @@ void reweight_task(struct task_struct *p, int prio)
|
|
*
|
|
* tg->weight * grq->load.weight
|
|
* ge->load.weight = ----------------------------- = tg->weight (4)
|
|
- * grp->load.weight
|
|
+ * grp->load.weight
|
|
*
|
|
* That is, the sum collapses because all other CPUs are idle; the UP scenario.
|
|
*
|
|
@@ -3190,7 +3190,7 @@ void reweight_task(struct task_struct *p, int prio)
|
|
*
|
|
* tg->weight * grq->load.weight
|
|
* ge->load.weight = ----------------------------- (6)
|
|
- * tg_load_avg'
|
|
+ * tg_load_avg'
|
|
*
|
|
* Where:
|
|
*
|
|
diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c
|
|
index 651218ded9817..d50a31ecedeec 100644
|
|
--- a/kernel/sched/psi.c
|
|
+++ b/kernel/sched/psi.c
|
|
@@ -179,6 +179,8 @@ struct psi_group psi_system = {
|
|
|
|
static void psi_avgs_work(struct work_struct *work);
|
|
|
|
+static void poll_timer_fn(struct timer_list *t);
|
|
+
|
|
static void group_init(struct psi_group *group)
|
|
{
|
|
int cpu;
|
|
@@ -198,6 +200,8 @@ static void group_init(struct psi_group *group)
|
|
memset(group->polling_total, 0, sizeof(group->polling_total));
|
|
group->polling_next_update = ULLONG_MAX;
|
|
group->polling_until = 0;
|
|
+ init_waitqueue_head(&group->poll_wait);
|
|
+ timer_setup(&group->poll_timer, poll_timer_fn, 0);
|
|
rcu_assign_pointer(group->poll_task, NULL);
|
|
}
|
|
|
|
@@ -1126,9 +1130,7 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
|
|
return ERR_CAST(task);
|
|
}
|
|
atomic_set(&group->poll_wakeup, 0);
|
|
- init_waitqueue_head(&group->poll_wait);
|
|
wake_up_process(task);
|
|
- timer_setup(&group->poll_timer, poll_timer_fn, 0);
|
|
rcu_assign_pointer(group->poll_task, task);
|
|
}
|
|
|
|
@@ -1180,6 +1182,7 @@ static void psi_trigger_destroy(struct kref *ref)
|
|
group->poll_task,
|
|
lockdep_is_held(&group->trigger_lock));
|
|
rcu_assign_pointer(group->poll_task, NULL);
|
|
+ del_timer(&group->poll_timer);
|
|
}
|
|
}
|
|
|
|
@@ -1192,17 +1195,14 @@ static void psi_trigger_destroy(struct kref *ref)
|
|
*/
|
|
synchronize_rcu();
|
|
/*
|
|
- * Destroy the kworker after releasing trigger_lock to prevent a
|
|
+ * Stop kthread 'psimon' after releasing trigger_lock to prevent a
|
|
* deadlock while waiting for psi_poll_work to acquire trigger_lock
|
|
*/
|
|
if (task_to_destroy) {
|
|
/*
|
|
* After the RCU grace period has expired, the worker
|
|
* can no longer be found through group->poll_task.
|
|
- * But it might have been already scheduled before
|
|
- * that - deschedule it cleanly before destroying it.
|
|
*/
|
|
- del_timer_sync(&group->poll_timer);
|
|
kthread_stop(task_to_destroy);
|
|
}
|
|
kfree(t);
|
|
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
|
|
index 49ec096a8aa1f..b5cf418e2e3fe 100644
|
|
--- a/kernel/sched/rt.c
|
|
+++ b/kernel/sched/rt.c
|
|
@@ -2291,13 +2291,20 @@ void __init init_sched_rt_class(void)
|
|
static void switched_to_rt(struct rq *rq, struct task_struct *p)
|
|
{
|
|
/*
|
|
- * If we are already running, then there's nothing
|
|
- * that needs to be done. But if we are not running
|
|
- * we may need to preempt the current running task.
|
|
- * If that current running task is also an RT task
|
|
+ * If we are running, update the avg_rt tracking, as the running time
|
|
+ * will now on be accounted into the latter.
|
|
+ */
|
|
+ if (task_current(rq, p)) {
|
|
+ update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 0);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * If we are not running we may need to preempt the current
|
|
+ * running task. If that current running task is also an RT task
|
|
* then see if we can move to another run queue.
|
|
*/
|
|
- if (task_on_rq_queued(p) && rq->curr != p) {
|
|
+ if (task_on_rq_queued(p)) {
|
|
#ifdef CONFIG_SMP
|
|
if (p->nr_cpus_allowed > 1 && rq->rt.overloaded)
|
|
rt_queue_push_tasks(rq);
|
|
diff --git a/kernel/smpboot.c b/kernel/smpboot.c
|
|
index f25208e8df836..e4163042c4d66 100644
|
|
--- a/kernel/smpboot.c
|
|
+++ b/kernel/smpboot.c
|
|
@@ -33,7 +33,6 @@ struct task_struct *idle_thread_get(unsigned int cpu)
|
|
|
|
if (!tsk)
|
|
return ERR_PTR(-ENOMEM);
|
|
- init_idle(tsk, cpu);
|
|
return tsk;
|
|
}
|
|
|
|
diff --git a/kernel/sys.c b/kernel/sys.c
|
|
index a730c03ee607c..0670e824e0197 100644
|
|
--- a/kernel/sys.c
|
|
+++ b/kernel/sys.c
|
|
@@ -552,6 +552,10 @@ long __sys_setreuid(uid_t ruid, uid_t euid)
|
|
if (retval < 0)
|
|
goto error;
|
|
|
|
+ retval = set_cred_ucounts(new);
|
|
+ if (retval < 0)
|
|
+ goto error;
|
|
+
|
|
return commit_creds(new);
|
|
|
|
error:
|
|
@@ -610,6 +614,10 @@ long __sys_setuid(uid_t uid)
|
|
if (retval < 0)
|
|
goto error;
|
|
|
|
+ retval = set_cred_ucounts(new);
|
|
+ if (retval < 0)
|
|
+ goto error;
|
|
+
|
|
return commit_creds(new);
|
|
|
|
error:
|
|
@@ -685,6 +693,10 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
|
|
if (retval < 0)
|
|
goto error;
|
|
|
|
+ retval = set_cred_ucounts(new);
|
|
+ if (retval < 0)
|
|
+ goto error;
|
|
+
|
|
return commit_creds(new);
|
|
|
|
error:
|
|
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
|
|
index 02441ead3c3bb..74492f08660c4 100644
|
|
--- a/kernel/time/clocksource.c
|
|
+++ b/kernel/time/clocksource.c
|
|
@@ -124,6 +124,13 @@ static void __clocksource_change_rating(struct clocksource *cs, int rating);
|
|
#define WATCHDOG_INTERVAL (HZ >> 1)
|
|
#define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 4)
|
|
|
|
+/*
|
|
+ * Maximum permissible delay between two readouts of the watchdog
|
|
+ * clocksource surrounding a read of the clocksource being validated.
|
|
+ * This delay could be due to SMIs, NMIs, or to VCPU preemptions.
|
|
+ */
|
|
+#define WATCHDOG_MAX_SKEW (100 * NSEC_PER_USEC)
|
|
+
|
|
static void clocksource_watchdog_work(struct work_struct *work)
|
|
{
|
|
/*
|
|
@@ -184,12 +191,99 @@ void clocksource_mark_unstable(struct clocksource *cs)
|
|
spin_unlock_irqrestore(&watchdog_lock, flags);
|
|
}
|
|
|
|
+static ulong max_cswd_read_retries = 3;
|
|
+module_param(max_cswd_read_retries, ulong, 0644);
|
|
+
|
|
+static bool cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow)
|
|
+{
|
|
+ unsigned int nretries;
|
|
+ u64 wd_end, wd_delta;
|
|
+ int64_t wd_delay;
|
|
+
|
|
+ for (nretries = 0; nretries <= max_cswd_read_retries; nretries++) {
|
|
+ local_irq_disable();
|
|
+ *wdnow = watchdog->read(watchdog);
|
|
+ *csnow = cs->read(cs);
|
|
+ wd_end = watchdog->read(watchdog);
|
|
+ local_irq_enable();
|
|
+
|
|
+ wd_delta = clocksource_delta(wd_end, *wdnow, watchdog->mask);
|
|
+ wd_delay = clocksource_cyc2ns(wd_delta, watchdog->mult,
|
|
+ watchdog->shift);
|
|
+ if (wd_delay <= WATCHDOG_MAX_SKEW) {
|
|
+ if (nretries > 1 || nretries >= max_cswd_read_retries) {
|
|
+ pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n",
|
|
+ smp_processor_id(), watchdog->name, nretries);
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ pr_warn("timekeeping watchdog on CPU%d: %s read-back delay of %lldns, attempt %d, marking unstable\n",
|
|
+ smp_processor_id(), watchdog->name, wd_delay, nretries);
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static u64 csnow_mid;
|
|
+static cpumask_t cpus_ahead;
|
|
+static cpumask_t cpus_behind;
|
|
+
|
|
+static void clocksource_verify_one_cpu(void *csin)
|
|
+{
|
|
+ struct clocksource *cs = (struct clocksource *)csin;
|
|
+
|
|
+ csnow_mid = cs->read(cs);
|
|
+}
|
|
+
|
|
+static void clocksource_verify_percpu(struct clocksource *cs)
|
|
+{
|
|
+ int64_t cs_nsec, cs_nsec_max = 0, cs_nsec_min = LLONG_MAX;
|
|
+ u64 csnow_begin, csnow_end;
|
|
+ int cpu, testcpu;
|
|
+ s64 delta;
|
|
+
|
|
+ cpumask_clear(&cpus_ahead);
|
|
+ cpumask_clear(&cpus_behind);
|
|
+ preempt_disable();
|
|
+ testcpu = smp_processor_id();
|
|
+ pr_warn("Checking clocksource %s synchronization from CPU %d.\n", cs->name, testcpu);
|
|
+ for_each_online_cpu(cpu) {
|
|
+ if (cpu == testcpu)
|
|
+ continue;
|
|
+ csnow_begin = cs->read(cs);
|
|
+ smp_call_function_single(cpu, clocksource_verify_one_cpu, cs, 1);
|
|
+ csnow_end = cs->read(cs);
|
|
+ delta = (s64)((csnow_mid - csnow_begin) & cs->mask);
|
|
+ if (delta < 0)
|
|
+ cpumask_set_cpu(cpu, &cpus_behind);
|
|
+ delta = (csnow_end - csnow_mid) & cs->mask;
|
|
+ if (delta < 0)
|
|
+ cpumask_set_cpu(cpu, &cpus_ahead);
|
|
+ delta = clocksource_delta(csnow_end, csnow_begin, cs->mask);
|
|
+ cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift);
|
|
+ if (cs_nsec > cs_nsec_max)
|
|
+ cs_nsec_max = cs_nsec;
|
|
+ if (cs_nsec < cs_nsec_min)
|
|
+ cs_nsec_min = cs_nsec;
|
|
+ }
|
|
+ preempt_enable();
|
|
+ if (!cpumask_empty(&cpus_ahead))
|
|
+ pr_warn(" CPUs %*pbl ahead of CPU %d for clocksource %s.\n",
|
|
+ cpumask_pr_args(&cpus_ahead), testcpu, cs->name);
|
|
+ if (!cpumask_empty(&cpus_behind))
|
|
+ pr_warn(" CPUs %*pbl behind CPU %d for clocksource %s.\n",
|
|
+ cpumask_pr_args(&cpus_behind), testcpu, cs->name);
|
|
+ if (!cpumask_empty(&cpus_ahead) || !cpumask_empty(&cpus_behind))
|
|
+ pr_warn(" CPU %d check durations %lldns - %lldns for clocksource %s.\n",
|
|
+ testcpu, cs_nsec_min, cs_nsec_max, cs->name);
|
|
+}
|
|
+
|
|
static void clocksource_watchdog(struct timer_list *unused)
|
|
{
|
|
- struct clocksource *cs;
|
|
u64 csnow, wdnow, cslast, wdlast, delta;
|
|
- int64_t wd_nsec, cs_nsec;
|
|
int next_cpu, reset_pending;
|
|
+ int64_t wd_nsec, cs_nsec;
|
|
+ struct clocksource *cs;
|
|
|
|
spin_lock(&watchdog_lock);
|
|
if (!watchdog_running)
|
|
@@ -206,10 +300,11 @@ static void clocksource_watchdog(struct timer_list *unused)
|
|
continue;
|
|
}
|
|
|
|
- local_irq_disable();
|
|
- csnow = cs->read(cs);
|
|
- wdnow = watchdog->read(watchdog);
|
|
- local_irq_enable();
|
|
+ if (!cs_watchdog_read(cs, &csnow, &wdnow)) {
|
|
+ /* Clock readout unreliable, so give it up. */
|
|
+ __clocksource_unstable(cs);
|
|
+ continue;
|
|
+ }
|
|
|
|
/* Clocksource initialized ? */
|
|
if (!(cs->flags & CLOCK_SOURCE_WATCHDOG) ||
|
|
@@ -407,6 +502,12 @@ static int __clocksource_watchdog_kthread(void)
|
|
unsigned long flags;
|
|
int select = 0;
|
|
|
|
+ /* Do any required per-CPU skew verification. */
|
|
+ if (curr_clocksource &&
|
|
+ curr_clocksource->flags & CLOCK_SOURCE_UNSTABLE &&
|
|
+ curr_clocksource->flags & CLOCK_SOURCE_VERIFY_PERCPU)
|
|
+ clocksource_verify_percpu(curr_clocksource);
|
|
+
|
|
spin_lock_irqsave(&watchdog_lock, flags);
|
|
list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
|
|
if (cs->flags & CLOCK_SOURCE_UNSTABLE) {
|
|
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
|
|
index 01710831fd02f..216329c23f18a 100644
|
|
--- a/kernel/trace/bpf_trace.c
|
|
+++ b/kernel/trace/bpf_trace.c
|
|
@@ -2106,7 +2106,8 @@ static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *
|
|
if (prog->aux->max_tp_access > btp->writable_size)
|
|
return -EINVAL;
|
|
|
|
- return tracepoint_probe_register(tp, (void *)btp->bpf_func, prog);
|
|
+ return tracepoint_probe_register_may_exist(tp, (void *)btp->bpf_func,
|
|
+ prog);
|
|
}
|
|
|
|
int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
|
|
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
|
|
index 96c3f86b81c5f..0b24938cbe92e 100644
|
|
--- a/kernel/trace/trace_events_hist.c
|
|
+++ b/kernel/trace/trace_events_hist.c
|
|
@@ -1539,6 +1539,13 @@ static int contains_operator(char *str)
|
|
|
|
switch (*op) {
|
|
case '-':
|
|
+ /*
|
|
+ * Unfortunately, the modifier ".sym-offset"
|
|
+ * can confuse things.
|
|
+ */
|
|
+ if (op - str >= 4 && !strncmp(op - 4, ".sym-offset", 11))
|
|
+ return FIELD_OP_NONE;
|
|
+
|
|
if (*str == '-')
|
|
field_op = FIELD_OP_UNARY_MINUS;
|
|
else
|
|
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
|
|
index 3e261482296cf..f8b161edca5ea 100644
|
|
--- a/kernel/tracepoint.c
|
|
+++ b/kernel/tracepoint.c
|
|
@@ -294,7 +294,8 @@ static void tracepoint_update_call(struct tracepoint *tp, struct tracepoint_func
|
|
* Add the probe function to a tracepoint.
|
|
*/
|
|
static int tracepoint_add_func(struct tracepoint *tp,
|
|
- struct tracepoint_func *func, int prio)
|
|
+ struct tracepoint_func *func, int prio,
|
|
+ bool warn)
|
|
{
|
|
struct tracepoint_func *old, *tp_funcs;
|
|
int ret;
|
|
@@ -309,7 +310,7 @@ static int tracepoint_add_func(struct tracepoint *tp,
|
|
lockdep_is_held(&tracepoints_mutex));
|
|
old = func_add(&tp_funcs, func, prio);
|
|
if (IS_ERR(old)) {
|
|
- WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM);
|
|
+ WARN_ON_ONCE(warn && PTR_ERR(old) != -ENOMEM);
|
|
return PTR_ERR(old);
|
|
}
|
|
|
|
@@ -364,6 +365,32 @@ static int tracepoint_remove_func(struct tracepoint *tp,
|
|
return 0;
|
|
}
|
|
|
|
+/**
|
|
+ * tracepoint_probe_register_prio_may_exist - Connect a probe to a tracepoint with priority
|
|
+ * @tp: tracepoint
|
|
+ * @probe: probe handler
|
|
+ * @data: tracepoint data
|
|
+ * @prio: priority of this function over other registered functions
|
|
+ *
|
|
+ * Same as tracepoint_probe_register_prio() except that it will not warn
|
|
+ * if the tracepoint is already registered.
|
|
+ */
|
|
+int tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe,
|
|
+ void *data, int prio)
|
|
+{
|
|
+ struct tracepoint_func tp_func;
|
|
+ int ret;
|
|
+
|
|
+ mutex_lock(&tracepoints_mutex);
|
|
+ tp_func.func = probe;
|
|
+ tp_func.data = data;
|
|
+ tp_func.prio = prio;
|
|
+ ret = tracepoint_add_func(tp, &tp_func, prio, false);
|
|
+ mutex_unlock(&tracepoints_mutex);
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(tracepoint_probe_register_prio_may_exist);
|
|
+
|
|
/**
|
|
* tracepoint_probe_register_prio - Connect a probe to a tracepoint with priority
|
|
* @tp: tracepoint
|
|
@@ -387,7 +414,7 @@ int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe,
|
|
tp_func.func = probe;
|
|
tp_func.data = data;
|
|
tp_func.prio = prio;
|
|
- ret = tracepoint_add_func(tp, &tp_func, prio);
|
|
+ ret = tracepoint_add_func(tp, &tp_func, prio, true);
|
|
mutex_unlock(&tracepoints_mutex);
|
|
return ret;
|
|
}
|
|
diff --git a/kernel/ucount.c b/kernel/ucount.c
|
|
index 11b1596e2542a..9894795043c42 100644
|
|
--- a/kernel/ucount.c
|
|
+++ b/kernel/ucount.c
|
|
@@ -8,6 +8,12 @@
|
|
#include <linux/kmemleak.h>
|
|
#include <linux/user_namespace.h>
|
|
|
|
+struct ucounts init_ucounts = {
|
|
+ .ns = &init_user_ns,
|
|
+ .uid = GLOBAL_ROOT_UID,
|
|
+ .count = 1,
|
|
+};
|
|
+
|
|
#define UCOUNTS_HASHTABLE_BITS 10
|
|
static struct hlist_head ucounts_hashtable[(1 << UCOUNTS_HASHTABLE_BITS)];
|
|
static DEFINE_SPINLOCK(ucounts_lock);
|
|
@@ -125,7 +131,15 @@ static struct ucounts *find_ucounts(struct user_namespace *ns, kuid_t uid, struc
|
|
return NULL;
|
|
}
|
|
|
|
-static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
|
|
+static void hlist_add_ucounts(struct ucounts *ucounts)
|
|
+{
|
|
+ struct hlist_head *hashent = ucounts_hashentry(ucounts->ns, ucounts->uid);
|
|
+ spin_lock_irq(&ucounts_lock);
|
|
+ hlist_add_head(&ucounts->node, hashent);
|
|
+ spin_unlock_irq(&ucounts_lock);
|
|
+}
|
|
+
|
|
+struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid)
|
|
{
|
|
struct hlist_head *hashent = ucounts_hashentry(ns, uid);
|
|
struct ucounts *ucounts, *new;
|
|
@@ -160,7 +174,26 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
|
|
return ucounts;
|
|
}
|
|
|
|
-static void put_ucounts(struct ucounts *ucounts)
|
|
+struct ucounts *get_ucounts(struct ucounts *ucounts)
|
|
+{
|
|
+ unsigned long flags;
|
|
+
|
|
+ if (!ucounts)
|
|
+ return NULL;
|
|
+
|
|
+ spin_lock_irqsave(&ucounts_lock, flags);
|
|
+ if (ucounts->count == INT_MAX) {
|
|
+ WARN_ONCE(1, "ucounts: counter has reached its maximum value");
|
|
+ ucounts = NULL;
|
|
+ } else {
|
|
+ ucounts->count += 1;
|
|
+ }
|
|
+ spin_unlock_irqrestore(&ucounts_lock, flags);
|
|
+
|
|
+ return ucounts;
|
|
+}
|
|
+
|
|
+void put_ucounts(struct ucounts *ucounts)
|
|
{
|
|
unsigned long flags;
|
|
|
|
@@ -194,7 +227,7 @@ struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid,
|
|
{
|
|
struct ucounts *ucounts, *iter, *bad;
|
|
struct user_namespace *tns;
|
|
- ucounts = get_ucounts(ns, uid);
|
|
+ ucounts = alloc_ucounts(ns, uid);
|
|
for (iter = ucounts; iter; iter = tns->ucounts) {
|
|
int max;
|
|
tns = iter->ns;
|
|
@@ -237,6 +270,7 @@ static __init int user_namespace_sysctl_init(void)
|
|
BUG_ON(!user_header);
|
|
BUG_ON(!setup_userns_sysctls(&init_user_ns));
|
|
#endif
|
|
+ hlist_add_ucounts(&init_ucounts);
|
|
return 0;
|
|
}
|
|
subsys_initcall(user_namespace_sysctl_init);
|
|
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
|
|
index ce396ea4de608..8206a13c81ebc 100644
|
|
--- a/kernel/user_namespace.c
|
|
+++ b/kernel/user_namespace.c
|
|
@@ -1340,6 +1340,9 @@ static int userns_install(struct nsset *nsset, struct ns_common *ns)
|
|
put_user_ns(cred->user_ns);
|
|
set_cred_user_ns(cred, get_user_ns(user_ns));
|
|
|
|
+ if (set_cred_ucounts(cred) < 0)
|
|
+ return -EINVAL;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
|
|
index dcf4a9028e165..5b7f88a2876db 100644
|
|
--- a/lib/Kconfig.debug
|
|
+++ b/lib/Kconfig.debug
|
|
@@ -1302,7 +1302,6 @@ config LOCKDEP
|
|
bool
|
|
depends on DEBUG_KERNEL && LOCK_DEBUGGING_SUPPORT
|
|
select STACKTRACE
|
|
- depends on FRAME_POINTER || MIPS || PPC || S390 || MICROBLAZE || ARM || ARC || X86
|
|
select KALLSYMS
|
|
select KALLSYMS_ALL
|
|
|
|
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
|
|
index f0b2ccb1bb018..537bfdc8cd095 100644
|
|
--- a/lib/iov_iter.c
|
|
+++ b/lib/iov_iter.c
|
|
@@ -434,7 +434,7 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes)
|
|
int err;
|
|
struct iovec v;
|
|
|
|
- if (!(i->type & (ITER_BVEC|ITER_KVEC))) {
|
|
+ if (iter_is_iovec(i)) {
|
|
iterate_iovec(i, bytes, v, iov, skip, ({
|
|
err = fault_in_pages_readable(v.iov_base, v.iov_len);
|
|
if (unlikely(err))
|
|
@@ -922,9 +922,12 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes,
|
|
size_t wanted = copy_to_iter(kaddr + offset, bytes, i);
|
|
kunmap_atomic(kaddr);
|
|
return wanted;
|
|
- } else if (unlikely(iov_iter_is_discard(i)))
|
|
+ } else if (unlikely(iov_iter_is_discard(i))) {
|
|
+ if (unlikely(i->count < bytes))
|
|
+ bytes = i->count;
|
|
+ i->count -= bytes;
|
|
return bytes;
|
|
- else if (likely(!iov_iter_is_pipe(i)))
|
|
+ } else if (likely(!iov_iter_is_pipe(i)))
|
|
return copy_page_to_iter_iovec(page, offset, bytes, i);
|
|
else
|
|
return copy_page_to_iter_pipe(page, offset, bytes, i);
|
|
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
|
|
index a14ccf9050552..8504526541c13 100644
|
|
--- a/lib/kstrtox.c
|
|
+++ b/lib/kstrtox.c
|
|
@@ -39,20 +39,22 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
|
|
|
|
/*
|
|
* Convert non-negative integer string representation in explicitly given radix
|
|
- * to an integer.
|
|
+ * to an integer. A maximum of max_chars characters will be converted.
|
|
+ *
|
|
* Return number of characters consumed maybe or-ed with overflow bit.
|
|
* If overflow occurs, result integer (incorrect) is still returned.
|
|
*
|
|
* Don't you dare use this function.
|
|
*/
|
|
-unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
|
|
+unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
|
|
+ size_t max_chars)
|
|
{
|
|
unsigned long long res;
|
|
unsigned int rv;
|
|
|
|
res = 0;
|
|
rv = 0;
|
|
- while (1) {
|
|
+ while (max_chars--) {
|
|
unsigned int c = *s;
|
|
unsigned int lc = c | 0x20; /* don't tolower() this line */
|
|
unsigned int val;
|
|
@@ -82,6 +84,11 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long
|
|
return rv;
|
|
}
|
|
|
|
+unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
|
|
+{
|
|
+ return _parse_integer_limit(s, base, p, INT_MAX);
|
|
+}
|
|
+
|
|
static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
|
|
{
|
|
unsigned long long _res;
|
|
diff --git a/lib/kstrtox.h b/lib/kstrtox.h
|
|
index 3b4637bcd2540..158c400ca8658 100644
|
|
--- a/lib/kstrtox.h
|
|
+++ b/lib/kstrtox.h
|
|
@@ -4,6 +4,8 @@
|
|
|
|
#define KSTRTOX_OVERFLOW (1U << 31)
|
|
const char *_parse_integer_fixup_radix(const char *s, unsigned int *base);
|
|
+unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *res,
|
|
+ size_t max_chars);
|
|
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res);
|
|
|
|
#endif
|
|
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
|
|
index a899b3f0e2e53..76c52b0b76d38 100644
|
|
--- a/lib/locking-selftest.c
|
|
+++ b/lib/locking-selftest.c
|
|
@@ -186,6 +186,7 @@ static void init_shared_classes(void)
|
|
#define HARDIRQ_ENTER() \
|
|
local_irq_disable(); \
|
|
__irq_enter(); \
|
|
+ lockdep_hardirq_threaded(); \
|
|
WARN_ON(!in_irq());
|
|
|
|
#define HARDIRQ_EXIT() \
|
|
diff --git a/lib/math/rational.c b/lib/math/rational.c
|
|
index 9781d521963d1..c0ab51d8fbb98 100644
|
|
--- a/lib/math/rational.c
|
|
+++ b/lib/math/rational.c
|
|
@@ -12,6 +12,7 @@
|
|
#include <linux/compiler.h>
|
|
#include <linux/export.h>
|
|
#include <linux/minmax.h>
|
|
+#include <linux/limits.h>
|
|
|
|
/*
|
|
* calculate best rational approximation for a given fraction
|
|
@@ -78,13 +79,18 @@ void rational_best_approximation(
|
|
* found below as 't'.
|
|
*/
|
|
if ((n2 > max_numerator) || (d2 > max_denominator)) {
|
|
- unsigned long t = min((max_numerator - n0) / n1,
|
|
- (max_denominator - d0) / d1);
|
|
+ unsigned long t = ULONG_MAX;
|
|
|
|
- /* This tests if the semi-convergent is closer
|
|
- * than the previous convergent.
|
|
+ if (d1)
|
|
+ t = (max_denominator - d0) / d1;
|
|
+ if (n1)
|
|
+ t = min(t, (max_numerator - n0) / n1);
|
|
+
|
|
+ /* This tests if the semi-convergent is closer than the previous
|
|
+ * convergent. If d1 is zero there is no previous convergent as this
|
|
+ * is the 1st iteration, so always choose the semi-convergent.
|
|
*/
|
|
- if (2u * t > a || (2u * t == a && d0 * dp > d1 * d)) {
|
|
+ if (!d1 || 2u * t > a || (2u * t == a && d0 * dp > d1 * d)) {
|
|
n1 = n0 + t * n1;
|
|
d1 = d0 + t * d1;
|
|
}
|
|
diff --git a/lib/seq_buf.c b/lib/seq_buf.c
|
|
index 707453f5d58ee..89c26c393bdba 100644
|
|
--- a/lib/seq_buf.c
|
|
+++ b/lib/seq_buf.c
|
|
@@ -243,12 +243,14 @@ int seq_buf_putmem_hex(struct seq_buf *s, const void *mem,
|
|
break;
|
|
|
|
/* j increments twice per loop */
|
|
- len -= j / 2;
|
|
hex[j++] = ' ';
|
|
|
|
seq_buf_putmem(s, hex, j);
|
|
if (seq_buf_has_overflowed(s))
|
|
return -1;
|
|
+
|
|
+ len -= start_len;
|
|
+ data += start_len;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
|
|
index fd0fde639ec91..8ade1a86d8187 100644
|
|
--- a/lib/vsprintf.c
|
|
+++ b/lib/vsprintf.c
|
|
@@ -53,6 +53,31 @@
|
|
#include <linux/string_helpers.h>
|
|
#include "kstrtox.h"
|
|
|
|
+static unsigned long long simple_strntoull(const char *startp, size_t max_chars,
|
|
+ char **endp, unsigned int base)
|
|
+{
|
|
+ const char *cp;
|
|
+ unsigned long long result = 0ULL;
|
|
+ size_t prefix_chars;
|
|
+ unsigned int rv;
|
|
+
|
|
+ cp = _parse_integer_fixup_radix(startp, &base);
|
|
+ prefix_chars = cp - startp;
|
|
+ if (prefix_chars < max_chars) {
|
|
+ rv = _parse_integer_limit(cp, base, &result, max_chars - prefix_chars);
|
|
+ /* FIXME */
|
|
+ cp += (rv & ~KSTRTOX_OVERFLOW);
|
|
+ } else {
|
|
+ /* Field too short for prefix + digit, skip over without converting */
|
|
+ cp = startp + max_chars;
|
|
+ }
|
|
+
|
|
+ if (endp)
|
|
+ *endp = (char *)cp;
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
/**
|
|
* simple_strtoull - convert a string to an unsigned long long
|
|
* @cp: The start of the string
|
|
@@ -63,18 +88,7 @@
|
|
*/
|
|
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
|
|
{
|
|
- unsigned long long result;
|
|
- unsigned int rv;
|
|
-
|
|
- cp = _parse_integer_fixup_radix(cp, &base);
|
|
- rv = _parse_integer(cp, base, &result);
|
|
- /* FIXME */
|
|
- cp += (rv & ~KSTRTOX_OVERFLOW);
|
|
-
|
|
- if (endp)
|
|
- *endp = (char *)cp;
|
|
-
|
|
- return result;
|
|
+ return simple_strntoull(cp, INT_MAX, endp, base);
|
|
}
|
|
EXPORT_SYMBOL(simple_strtoull);
|
|
|
|
@@ -109,6 +123,21 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)
|
|
}
|
|
EXPORT_SYMBOL(simple_strtol);
|
|
|
|
+static long long simple_strntoll(const char *cp, size_t max_chars, char **endp,
|
|
+ unsigned int base)
|
|
+{
|
|
+ /*
|
|
+ * simple_strntoull() safely handles receiving max_chars==0 in the
|
|
+ * case cp[0] == '-' && max_chars == 1.
|
|
+ * If max_chars == 0 we can drop through and pass it to simple_strntoull()
|
|
+ * and the content of *cp is irrelevant.
|
|
+ */
|
|
+ if (*cp == '-' && max_chars > 0)
|
|
+ return -simple_strntoull(cp + 1, max_chars - 1, endp, base);
|
|
+
|
|
+ return simple_strntoull(cp, max_chars, endp, base);
|
|
+}
|
|
+
|
|
/**
|
|
* simple_strtoll - convert a string to a signed long long
|
|
* @cp: The start of the string
|
|
@@ -119,10 +148,7 @@ EXPORT_SYMBOL(simple_strtol);
|
|
*/
|
|
long long simple_strtoll(const char *cp, char **endp, unsigned int base)
|
|
{
|
|
- if (*cp == '-')
|
|
- return -simple_strtoull(cp + 1, endp, base);
|
|
-
|
|
- return simple_strtoull(cp, endp, base);
|
|
+ return simple_strntoll(cp, INT_MAX, endp, base);
|
|
}
|
|
EXPORT_SYMBOL(simple_strtoll);
|
|
|
|
@@ -3442,25 +3468,13 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
|
|
break;
|
|
|
|
if (is_sign)
|
|
- val.s = qualifier != 'L' ?
|
|
- simple_strtol(str, &next, base) :
|
|
- simple_strtoll(str, &next, base);
|
|
+ val.s = simple_strntoll(str,
|
|
+ field_width >= 0 ? field_width : INT_MAX,
|
|
+ &next, base);
|
|
else
|
|
- val.u = qualifier != 'L' ?
|
|
- simple_strtoul(str, &next, base) :
|
|
- simple_strtoull(str, &next, base);
|
|
-
|
|
- if (field_width > 0 && next - str > field_width) {
|
|
- if (base == 0)
|
|
- _parse_integer_fixup_radix(str, &base);
|
|
- while (next - str > field_width) {
|
|
- if (is_sign)
|
|
- val.s = div_s64(val.s, base);
|
|
- else
|
|
- val.u = div_u64(val.u, base);
|
|
- --next;
|
|
- }
|
|
- }
|
|
+ val.u = simple_strntoull(str,
|
|
+ field_width >= 0 ? field_width : INT_MAX,
|
|
+ &next, base);
|
|
|
|
switch (qualifier) {
|
|
case 'H': /* that's 'hh' in format */
|
|
diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
|
|
index 750bfef26be37..12ebc97e8b435 100644
|
|
--- a/mm/debug_vm_pgtable.c
|
|
+++ b/mm/debug_vm_pgtable.c
|
|
@@ -58,11 +58,23 @@
|
|
#define RANDOM_ORVALUE (GENMASK(BITS_PER_LONG - 1, 0) & ~ARCH_SKIP_MASK)
|
|
#define RANDOM_NZVALUE GENMASK(7, 0)
|
|
|
|
-static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot)
|
|
+static void __init pte_basic_tests(unsigned long pfn, int idx)
|
|
{
|
|
+ pgprot_t prot = protection_map[idx];
|
|
pte_t pte = pfn_pte(pfn, prot);
|
|
+ unsigned long val = idx, *ptr = &val;
|
|
+
|
|
+ pr_debug("Validating PTE basic (%pGv)\n", ptr);
|
|
+
|
|
+ /*
|
|
+ * This test needs to be executed after the given page table entry
|
|
+ * is created with pfn_pte() to make sure that protection_map[idx]
|
|
+ * does not have the dirty bit enabled from the beginning. This is
|
|
+ * important for platforms like arm64 where (!PTE_RDONLY) indicate
|
|
+ * dirty bit being set.
|
|
+ */
|
|
+ WARN_ON(pte_dirty(pte_wrprotect(pte)));
|
|
|
|
- pr_debug("Validating PTE basic\n");
|
|
WARN_ON(!pte_same(pte, pte));
|
|
WARN_ON(!pte_young(pte_mkyoung(pte_mkold(pte))));
|
|
WARN_ON(!pte_dirty(pte_mkdirty(pte_mkclean(pte))));
|
|
@@ -70,6 +82,8 @@ static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot)
|
|
WARN_ON(pte_young(pte_mkold(pte_mkyoung(pte))));
|
|
WARN_ON(pte_dirty(pte_mkclean(pte_mkdirty(pte))));
|
|
WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte))));
|
|
+ WARN_ON(pte_dirty(pte_wrprotect(pte_mkclean(pte))));
|
|
+ WARN_ON(!pte_dirty(pte_wrprotect(pte_mkdirty(pte))));
|
|
}
|
|
|
|
static void __init pte_advanced_tests(struct mm_struct *mm,
|
|
@@ -129,14 +143,28 @@ static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot)
|
|
}
|
|
|
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
-static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot)
|
|
+static void __init pmd_basic_tests(unsigned long pfn, int idx)
|
|
{
|
|
- pmd_t pmd = pfn_pmd(pfn, prot);
|
|
+ pgprot_t prot = protection_map[idx];
|
|
+ unsigned long val = idx, *ptr = &val;
|
|
+ pmd_t pmd;
|
|
|
|
if (!has_transparent_hugepage())
|
|
return;
|
|
|
|
- pr_debug("Validating PMD basic\n");
|
|
+ pr_debug("Validating PMD basic (%pGv)\n", ptr);
|
|
+ pmd = pfn_pmd(pfn, prot);
|
|
+
|
|
+ /*
|
|
+ * This test needs to be executed after the given page table entry
|
|
+ * is created with pfn_pmd() to make sure that protection_map[idx]
|
|
+ * does not have the dirty bit enabled from the beginning. This is
|
|
+ * important for platforms like arm64 where (!PTE_RDONLY) indicate
|
|
+ * dirty bit being set.
|
|
+ */
|
|
+ WARN_ON(pmd_dirty(pmd_wrprotect(pmd)));
|
|
+
|
|
+
|
|
WARN_ON(!pmd_same(pmd, pmd));
|
|
WARN_ON(!pmd_young(pmd_mkyoung(pmd_mkold(pmd))));
|
|
WARN_ON(!pmd_dirty(pmd_mkdirty(pmd_mkclean(pmd))));
|
|
@@ -144,6 +172,8 @@ static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot)
|
|
WARN_ON(pmd_young(pmd_mkold(pmd_mkyoung(pmd))));
|
|
WARN_ON(pmd_dirty(pmd_mkclean(pmd_mkdirty(pmd))));
|
|
WARN_ON(pmd_write(pmd_wrprotect(pmd_mkwrite(pmd))));
|
|
+ WARN_ON(pmd_dirty(pmd_wrprotect(pmd_mkclean(pmd))));
|
|
+ WARN_ON(!pmd_dirty(pmd_wrprotect(pmd_mkdirty(pmd))));
|
|
/*
|
|
* A huge page does not point to next level page table
|
|
* entry. Hence this must qualify as pmd_bad().
|
|
@@ -156,7 +186,7 @@ static void __init pmd_advanced_tests(struct mm_struct *mm,
|
|
unsigned long pfn, unsigned long vaddr,
|
|
pgprot_t prot, pgtable_t pgtable)
|
|
{
|
|
- pmd_t pmd = pfn_pmd(pfn, prot);
|
|
+ pmd_t pmd;
|
|
|
|
if (!has_transparent_hugepage())
|
|
return;
|
|
@@ -203,9 +233,14 @@ static void __init pmd_advanced_tests(struct mm_struct *mm,
|
|
|
|
static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
- pmd_t pmd = pfn_pmd(pfn, prot);
|
|
+ pmd_t pmd;
|
|
+
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
|
|
pr_debug("Validating PMD leaf\n");
|
|
+ pmd = pfn_pmd(pfn, prot);
|
|
+
|
|
/*
|
|
* PMD based THP is a leaf entry.
|
|
*/
|
|
@@ -238,30 +273,51 @@ static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
|
|
|
|
static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
- pmd_t pmd = pfn_pmd(pfn, prot);
|
|
+ pmd_t pmd;
|
|
|
|
if (!IS_ENABLED(CONFIG_NUMA_BALANCING))
|
|
return;
|
|
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
+
|
|
pr_debug("Validating PMD saved write\n");
|
|
+ pmd = pfn_pmd(pfn, prot);
|
|
WARN_ON(!pmd_savedwrite(pmd_mk_savedwrite(pmd_clear_savedwrite(pmd))));
|
|
WARN_ON(pmd_savedwrite(pmd_clear_savedwrite(pmd_mk_savedwrite(pmd))));
|
|
}
|
|
|
|
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
|
|
-static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot)
|
|
+static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx)
|
|
{
|
|
- pud_t pud = pfn_pud(pfn, prot);
|
|
+ pgprot_t prot = protection_map[idx];
|
|
+ unsigned long val = idx, *ptr = &val;
|
|
+ pud_t pud;
|
|
|
|
if (!has_transparent_hugepage())
|
|
return;
|
|
|
|
- pr_debug("Validating PUD basic\n");
|
|
+ pr_debug("Validating PUD basic (%pGv)\n", ptr);
|
|
+ pud = pfn_pud(pfn, prot);
|
|
+
|
|
+ /*
|
|
+ * This test needs to be executed after the given page table entry
|
|
+ * is created with pfn_pud() to make sure that protection_map[idx]
|
|
+ * does not have the dirty bit enabled from the beginning. This is
|
|
+ * important for platforms like arm64 where (!PTE_RDONLY) indicate
|
|
+ * dirty bit being set.
|
|
+ */
|
|
+ WARN_ON(pud_dirty(pud_wrprotect(pud)));
|
|
+
|
|
WARN_ON(!pud_same(pud, pud));
|
|
WARN_ON(!pud_young(pud_mkyoung(pud_mkold(pud))));
|
|
+ WARN_ON(!pud_dirty(pud_mkdirty(pud_mkclean(pud))));
|
|
+ WARN_ON(pud_dirty(pud_mkclean(pud_mkdirty(pud))));
|
|
WARN_ON(!pud_write(pud_mkwrite(pud_wrprotect(pud))));
|
|
WARN_ON(pud_write(pud_wrprotect(pud_mkwrite(pud))));
|
|
WARN_ON(pud_young(pud_mkold(pud_mkyoung(pud))));
|
|
+ WARN_ON(pud_dirty(pud_wrprotect(pud_mkclean(pud))));
|
|
+ WARN_ON(!pud_dirty(pud_wrprotect(pud_mkdirty(pud))));
|
|
|
|
if (mm_pmd_folded(mm))
|
|
return;
|
|
@@ -278,7 +334,7 @@ static void __init pud_advanced_tests(struct mm_struct *mm,
|
|
unsigned long pfn, unsigned long vaddr,
|
|
pgprot_t prot)
|
|
{
|
|
- pud_t pud = pfn_pud(pfn, prot);
|
|
+ pud_t pud;
|
|
|
|
if (!has_transparent_hugepage())
|
|
return;
|
|
@@ -287,6 +343,7 @@ static void __init pud_advanced_tests(struct mm_struct *mm,
|
|
/* Align the address wrt HPAGE_PUD_SIZE */
|
|
vaddr &= HPAGE_PUD_MASK;
|
|
|
|
+ pud = pfn_pud(pfn, prot);
|
|
set_pud_at(mm, vaddr, pudp, pud);
|
|
pudp_set_wrprotect(mm, vaddr, pudp);
|
|
pud = READ_ONCE(*pudp);
|
|
@@ -325,9 +382,13 @@ static void __init pud_advanced_tests(struct mm_struct *mm,
|
|
|
|
static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
- pud_t pud = pfn_pud(pfn, prot);
|
|
+ pud_t pud;
|
|
+
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
|
|
pr_debug("Validating PUD leaf\n");
|
|
+ pud = pfn_pud(pfn, prot);
|
|
/*
|
|
* PUD based THP is a leaf entry.
|
|
*/
|
|
@@ -359,7 +420,7 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
|
|
#endif /* !CONFIG_HAVE_ARCH_HUGE_VMAP */
|
|
|
|
#else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
|
|
-static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) { }
|
|
+static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx) { }
|
|
static void __init pud_advanced_tests(struct mm_struct *mm,
|
|
struct vm_area_struct *vma, pud_t *pudp,
|
|
unsigned long pfn, unsigned long vaddr,
|
|
@@ -372,8 +433,8 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
|
|
}
|
|
#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
|
|
#else /* !CONFIG_TRANSPARENT_HUGEPAGE */
|
|
-static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) { }
|
|
-static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) { }
|
|
+static void __init pmd_basic_tests(unsigned long pfn, int idx) { }
|
|
+static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx) { }
|
|
static void __init pmd_advanced_tests(struct mm_struct *mm,
|
|
struct vm_area_struct *vma, pmd_t *pmdp,
|
|
unsigned long pfn, unsigned long vaddr,
|
|
@@ -609,12 +670,16 @@ static void __init pte_protnone_tests(unsigned long pfn, pgprot_t prot)
|
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
static void __init pmd_protnone_tests(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
- pmd_t pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
|
|
+ pmd_t pmd;
|
|
|
|
if (!IS_ENABLED(CONFIG_NUMA_BALANCING))
|
|
return;
|
|
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
+
|
|
pr_debug("Validating PMD protnone\n");
|
|
+ pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
|
|
WARN_ON(!pmd_protnone(pmd));
|
|
WARN_ON(!pmd_present(pmd));
|
|
}
|
|
@@ -634,18 +699,26 @@ static void __init pte_devmap_tests(unsigned long pfn, pgprot_t prot)
|
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
- pmd_t pmd = pfn_pmd(pfn, prot);
|
|
+ pmd_t pmd;
|
|
+
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
|
|
pr_debug("Validating PMD devmap\n");
|
|
+ pmd = pfn_pmd(pfn, prot);
|
|
WARN_ON(!pmd_devmap(pmd_mkdevmap(pmd)));
|
|
}
|
|
|
|
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
|
|
static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
- pud_t pud = pfn_pud(pfn, prot);
|
|
+ pud_t pud;
|
|
+
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
|
|
pr_debug("Validating PUD devmap\n");
|
|
+ pud = pfn_pud(pfn, prot);
|
|
WARN_ON(!pud_devmap(pud_mkdevmap(pud)));
|
|
}
|
|
#else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
|
|
@@ -688,25 +761,33 @@ static void __init pte_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
|
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
static void __init pmd_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
- pmd_t pmd = pfn_pmd(pfn, prot);
|
|
+ pmd_t pmd;
|
|
|
|
if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY))
|
|
return;
|
|
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
+
|
|
pr_debug("Validating PMD soft dirty\n");
|
|
+ pmd = pfn_pmd(pfn, prot);
|
|
WARN_ON(!pmd_soft_dirty(pmd_mksoft_dirty(pmd)));
|
|
WARN_ON(pmd_soft_dirty(pmd_clear_soft_dirty(pmd)));
|
|
}
|
|
|
|
static void __init pmd_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
- pmd_t pmd = pfn_pmd(pfn, prot);
|
|
+ pmd_t pmd;
|
|
|
|
if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY) ||
|
|
!IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION))
|
|
return;
|
|
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
+
|
|
pr_debug("Validating PMD swap soft dirty\n");
|
|
+ pmd = pfn_pmd(pfn, prot);
|
|
WARN_ON(!pmd_swp_soft_dirty(pmd_swp_mksoft_dirty(pmd)));
|
|
WARN_ON(pmd_swp_soft_dirty(pmd_swp_clear_soft_dirty(pmd)));
|
|
}
|
|
@@ -735,6 +816,9 @@ static void __init pmd_swap_tests(unsigned long pfn, pgprot_t prot)
|
|
swp_entry_t swp;
|
|
pmd_t pmd;
|
|
|
|
+ if (!has_transparent_hugepage())
|
|
+ return;
|
|
+
|
|
pr_debug("Validating PMD swap\n");
|
|
pmd = pfn_pmd(pfn, prot);
|
|
swp = __pmd_to_swp_entry(pmd);
|
|
@@ -899,6 +983,7 @@ static int __init debug_vm_pgtable(void)
|
|
unsigned long vaddr, pte_aligned, pmd_aligned;
|
|
unsigned long pud_aligned, p4d_aligned, pgd_aligned;
|
|
spinlock_t *ptl = NULL;
|
|
+ int idx;
|
|
|
|
pr_info("Validating architecture page table helpers\n");
|
|
prot = vm_get_page_prot(VMFLAGS);
|
|
@@ -963,9 +1048,25 @@ static int __init debug_vm_pgtable(void)
|
|
saved_pmdp = pmd_offset(pudp, 0UL);
|
|
saved_ptep = pmd_pgtable(pmd);
|
|
|
|
- pte_basic_tests(pte_aligned, prot);
|
|
- pmd_basic_tests(pmd_aligned, prot);
|
|
- pud_basic_tests(pud_aligned, prot);
|
|
+ /*
|
|
+ * Iterate over the protection_map[] to make sure that all
|
|
+ * the basic page table transformation validations just hold
|
|
+ * true irrespective of the starting protection value for a
|
|
+ * given page table entry.
|
|
+ */
|
|
+ for (idx = 0; idx < ARRAY_SIZE(protection_map); idx++) {
|
|
+ pte_basic_tests(pte_aligned, idx);
|
|
+ pmd_basic_tests(pmd_aligned, idx);
|
|
+ pud_basic_tests(mm, pud_aligned, idx);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Both P4D and PGD level tests are very basic which do not
|
|
+ * involve creating page table entries from the protection
|
|
+ * value and the given pfn. Hence just keep them out from
|
|
+ * the above iteration for now to save some test execution
|
|
+ * time.
|
|
+ */
|
|
p4d_basic_tests(p4d_aligned, prot);
|
|
pgd_basic_tests(pgd_aligned, prot);
|
|
|
|
diff --git a/mm/gup.c b/mm/gup.c
|
|
index c2826f3afe722..6cb7d8ae56f66 100644
|
|
--- a/mm/gup.c
|
|
+++ b/mm/gup.c
|
|
@@ -44,6 +44,23 @@ static void hpage_pincount_sub(struct page *page, int refs)
|
|
atomic_sub(refs, compound_pincount_ptr(page));
|
|
}
|
|
|
|
+/* Equivalent to calling put_page() @refs times. */
|
|
+static void put_page_refs(struct page *page, int refs)
|
|
+{
|
|
+#ifdef CONFIG_DEBUG_VM
|
|
+ if (VM_WARN_ON_ONCE_PAGE(page_ref_count(page) < refs, page))
|
|
+ return;
|
|
+#endif
|
|
+
|
|
+ /*
|
|
+ * Calling put_page() for each ref is unnecessarily slow. Only the last
|
|
+ * ref needs a put_page().
|
|
+ */
|
|
+ if (refs > 1)
|
|
+ page_ref_sub(page, refs - 1);
|
|
+ put_page(page);
|
|
+}
|
|
+
|
|
/*
|
|
* Return the compound head page with ref appropriately incremented,
|
|
* or NULL if that failed.
|
|
@@ -56,6 +73,21 @@ static inline struct page *try_get_compound_head(struct page *page, int refs)
|
|
return NULL;
|
|
if (unlikely(!page_cache_add_speculative(head, refs)))
|
|
return NULL;
|
|
+
|
|
+ /*
|
|
+ * At this point we have a stable reference to the head page; but it
|
|
+ * could be that between the compound_head() lookup and the refcount
|
|
+ * increment, the compound page was split, in which case we'd end up
|
|
+ * holding a reference on a page that has nothing to do with the page
|
|
+ * we were given anymore.
|
|
+ * So now that the head page is stable, recheck that the pages still
|
|
+ * belong together.
|
|
+ */
|
|
+ if (unlikely(compound_head(page) != head)) {
|
|
+ put_page_refs(head, refs);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
return head;
|
|
}
|
|
|
|
@@ -95,6 +127,14 @@ static __maybe_unused struct page *try_grab_compound_head(struct page *page,
|
|
is_migrate_cma_page(page))
|
|
return NULL;
|
|
|
|
+ /*
|
|
+ * CAUTION: Don't use compound_head() on the page before this
|
|
+ * point, the result won't be stable.
|
|
+ */
|
|
+ page = try_get_compound_head(page, refs);
|
|
+ if (!page)
|
|
+ return NULL;
|
|
+
|
|
/*
|
|
* When pinning a compound page of order > 1 (which is what
|
|
* hpage_pincount_available() checks for), use an exact count to
|
|
@@ -103,15 +143,10 @@ static __maybe_unused struct page *try_grab_compound_head(struct page *page,
|
|
* However, be sure to *also* increment the normal page refcount
|
|
* field at least once, so that the page really is pinned.
|
|
*/
|
|
- if (!hpage_pincount_available(page))
|
|
- refs *= GUP_PIN_COUNTING_BIAS;
|
|
-
|
|
- page = try_get_compound_head(page, refs);
|
|
- if (!page)
|
|
- return NULL;
|
|
-
|
|
if (hpage_pincount_available(page))
|
|
hpage_pincount_add(page, refs);
|
|
+ else
|
|
+ page_ref_add(page, refs * (GUP_PIN_COUNTING_BIAS - 1));
|
|
|
|
mod_node_page_state(page_pgdat(page), NR_FOLL_PIN_ACQUIRED,
|
|
orig_refs);
|
|
@@ -135,14 +170,7 @@ static void put_compound_head(struct page *page, int refs, unsigned int flags)
|
|
refs *= GUP_PIN_COUNTING_BIAS;
|
|
}
|
|
|
|
- VM_BUG_ON_PAGE(page_ref_count(page) < refs, page);
|
|
- /*
|
|
- * Calling put_page() for each ref is unnecessarily slow. Only the last
|
|
- * ref needs a put_page().
|
|
- */
|
|
- if (refs > 1)
|
|
- page_ref_sub(page, refs - 1);
|
|
- put_page(page);
|
|
+ put_page_refs(page, refs);
|
|
}
|
|
|
|
/**
|
|
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
|
|
index 6301ecc1f679a..9fe622ff2fc4a 100644
|
|
--- a/mm/huge_memory.c
|
|
+++ b/mm/huge_memory.c
|
|
@@ -63,7 +63,14 @@ static atomic_t huge_zero_refcount;
|
|
struct page *huge_zero_page __read_mostly;
|
|
unsigned long huge_zero_pfn __read_mostly = ~0UL;
|
|
|
|
-bool transparent_hugepage_enabled(struct vm_area_struct *vma)
|
|
+static inline bool file_thp_enabled(struct vm_area_struct *vma)
|
|
+{
|
|
+ return transhuge_vma_enabled(vma, vma->vm_flags) && vma->vm_file &&
|
|
+ !inode_is_open_for_write(vma->vm_file->f_inode) &&
|
|
+ (vma->vm_flags & VM_EXEC);
|
|
+}
|
|
+
|
|
+bool transparent_hugepage_active(struct vm_area_struct *vma)
|
|
{
|
|
/* The addr is used to check if the vma size fits */
|
|
unsigned long addr = (vma->vm_end & HPAGE_PMD_MASK) - HPAGE_PMD_SIZE;
|
|
@@ -74,6 +81,8 @@ bool transparent_hugepage_enabled(struct vm_area_struct *vma)
|
|
return __transparent_hugepage_enabled(vma);
|
|
if (vma_is_shmem(vma))
|
|
return shmem_huge_enabled(vma);
|
|
+ if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS))
|
|
+ return file_thp_enabled(vma);
|
|
|
|
return false;
|
|
}
|
|
@@ -375,7 +384,11 @@ static int __init hugepage_init(void)
|
|
struct kobject *hugepage_kobj;
|
|
|
|
if (!has_transparent_hugepage()) {
|
|
- transparent_hugepage_flags = 0;
|
|
+ /*
|
|
+ * Hardware doesn't support hugepages, hence disable
|
|
+ * DAX PMD support.
|
|
+ */
|
|
+ transparent_hugepage_flags = 1 << TRANSPARENT_HUGEPAGE_NEVER_DAX;
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -1591,7 +1604,7 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
|
|
* If other processes are mapping this page, we couldn't discard
|
|
* the page unless they all do MADV_FREE so let's skip the page.
|
|
*/
|
|
- if (page_mapcount(page) != 1)
|
|
+ if (total_mapcount(page) != 1)
|
|
goto out;
|
|
|
|
if (!trylock_page(page))
|
|
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
|
|
index d4f89c2f95446..fa6b0ac6c280d 100644
|
|
--- a/mm/hugetlb.c
|
|
+++ b/mm/hugetlb.c
|
|
@@ -1252,8 +1252,7 @@ static void destroy_compound_gigantic_page(struct page *page,
|
|
struct page *p = page + 1;
|
|
|
|
atomic_set(compound_mapcount_ptr(page), 0);
|
|
- if (hpage_pincount_available(page))
|
|
- atomic_set(compound_pincount_ptr(page), 0);
|
|
+ atomic_set(compound_pincount_ptr(page), 0);
|
|
|
|
for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
|
|
clear_compound_head(p);
|
|
@@ -1316,8 +1315,6 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
|
|
return alloc_contig_pages(nr_pages, gfp_mask, nid, nodemask);
|
|
}
|
|
|
|
-static void prep_new_huge_page(struct hstate *h, struct page *page, int nid);
|
|
-static void prep_compound_gigantic_page(struct page *page, unsigned int order);
|
|
#else /* !CONFIG_CONTIG_ALLOC */
|
|
static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
|
|
int nid, nodemask_t *nodemask)
|
|
@@ -1583,9 +1580,7 @@ static void prep_compound_gigantic_page(struct page *page, unsigned int order)
|
|
set_compound_head(p, page);
|
|
}
|
|
atomic_set(compound_mapcount_ptr(page), -1);
|
|
-
|
|
- if (hpage_pincount_available(page))
|
|
- atomic_set(compound_pincount_ptr(page), 0);
|
|
+ atomic_set(compound_pincount_ptr(page), 0);
|
|
}
|
|
|
|
/*
|
|
@@ -2481,16 +2476,10 @@ found:
|
|
return 1;
|
|
}
|
|
|
|
-static void __init prep_compound_huge_page(struct page *page,
|
|
- unsigned int order)
|
|
-{
|
|
- if (unlikely(order > (MAX_ORDER - 1)))
|
|
- prep_compound_gigantic_page(page, order);
|
|
- else
|
|
- prep_compound_page(page, order);
|
|
-}
|
|
-
|
|
-/* Put bootmem huge pages into the standard lists after mem_map is up */
|
|
+/*
|
|
+ * Put bootmem huge pages into the standard lists after mem_map is up.
|
|
+ * Note: This only applies to gigantic (order > MAX_ORDER) pages.
|
|
+ */
|
|
static void __init gather_bootmem_prealloc(void)
|
|
{
|
|
struct huge_bootmem_page *m;
|
|
@@ -2499,20 +2488,19 @@ static void __init gather_bootmem_prealloc(void)
|
|
struct page *page = virt_to_page(m);
|
|
struct hstate *h = m->hstate;
|
|
|
|
+ VM_BUG_ON(!hstate_is_gigantic(h));
|
|
WARN_ON(page_count(page) != 1);
|
|
- prep_compound_huge_page(page, h->order);
|
|
+ prep_compound_gigantic_page(page, huge_page_order(h));
|
|
WARN_ON(PageReserved(page));
|
|
prep_new_huge_page(h, page, page_to_nid(page));
|
|
put_page(page); /* free it into the hugepage allocator */
|
|
|
|
/*
|
|
- * If we had gigantic hugepages allocated at boot time, we need
|
|
- * to restore the 'stolen' pages to totalram_pages in order to
|
|
- * fix confusing memory reports from free(1) and another
|
|
- * side-effects, like CommitLimit going negative.
|
|
+ * We need to restore the 'stolen' pages to totalram_pages
|
|
+ * in order to fix confusing memory reports from free(1) and
|
|
+ * other side-effects, like CommitLimit going negative.
|
|
*/
|
|
- if (hstate_is_gigantic(h))
|
|
- adjust_managed_page_count(page, 1 << h->order);
|
|
+ adjust_managed_page_count(page, pages_per_huge_page(h));
|
|
cond_resched();
|
|
}
|
|
}
|
|
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
|
|
index a6238118ac4c7..ee88125785638 100644
|
|
--- a/mm/khugepaged.c
|
|
+++ b/mm/khugepaged.c
|
|
@@ -440,9 +440,7 @@ static inline int khugepaged_test_exit(struct mm_struct *mm)
|
|
static bool hugepage_vma_check(struct vm_area_struct *vma,
|
|
unsigned long vm_flags)
|
|
{
|
|
- /* Explicitly disabled through madvise. */
|
|
- if ((vm_flags & VM_NOHUGEPAGE) ||
|
|
- test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags))
|
|
+ if (!transhuge_vma_enabled(vma, vm_flags))
|
|
return false;
|
|
|
|
/* Enabled via shmem mount options or sysfs settings. */
|
|
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
|
|
index 8d9f5fa4c6d39..92bf987d0a410 100644
|
|
--- a/mm/memcontrol.c
|
|
+++ b/mm/memcontrol.c
|
|
@@ -2898,12 +2898,20 @@ static void commit_charge(struct page *page, struct mem_cgroup *memcg)
|
|
}
|
|
|
|
#ifdef CONFIG_MEMCG_KMEM
|
|
+/*
|
|
+ * The allocated objcg pointers array is not accounted directly.
|
|
+ * Moreover, it should not come from DMA buffer and is not readily
|
|
+ * reclaimable. So those GFP bits should be masked off.
|
|
+ */
|
|
+#define OBJCGS_CLEAR_MASK (__GFP_DMA | __GFP_RECLAIMABLE | __GFP_ACCOUNT)
|
|
+
|
|
int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s,
|
|
gfp_t gfp)
|
|
{
|
|
unsigned int objects = objs_per_slab_page(s, page);
|
|
void *vec;
|
|
|
|
+ gfp &= ~OBJCGS_CLEAR_MASK;
|
|
vec = kcalloc_node(objects, sizeof(struct obj_cgroup *), gfp,
|
|
page_to_nid(page));
|
|
if (!vec)
|
|
diff --git a/mm/memory.c b/mm/memory.c
|
|
index eb31b3e4ef93b..0a905e0a7e672 100644
|
|
--- a/mm/memory.c
|
|
+++ b/mm/memory.c
|
|
@@ -3302,6 +3302,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
|
|
{
|
|
struct vm_area_struct *vma = vmf->vma;
|
|
struct page *page = NULL, *swapcache;
|
|
+ struct swap_info_struct *si = NULL;
|
|
swp_entry_t entry;
|
|
pte_t pte;
|
|
int locked;
|
|
@@ -3329,14 +3330,16 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
|
|
goto out;
|
|
}
|
|
|
|
+ /* Prevent swapoff from happening to us. */
|
|
+ si = get_swap_device(entry);
|
|
+ if (unlikely(!si))
|
|
+ goto out;
|
|
|
|
delayacct_set_flag(DELAYACCT_PF_SWAPIN);
|
|
page = lookup_swap_cache(entry, vma, vmf->address);
|
|
swapcache = page;
|
|
|
|
if (!page) {
|
|
- struct swap_info_struct *si = swp_swap_info(entry);
|
|
-
|
|
if (data_race(si->flags & SWP_SYNCHRONOUS_IO) &&
|
|
__swap_count(entry) == 1) {
|
|
/* skip swapcache */
|
|
@@ -3507,6 +3510,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
|
|
unlock:
|
|
pte_unmap_unlock(vmf->pte, vmf->ptl);
|
|
out:
|
|
+ if (si)
|
|
+ put_swap_device(si);
|
|
return ret;
|
|
out_nomap:
|
|
pte_unmap_unlock(vmf->pte, vmf->ptl);
|
|
@@ -3518,6 +3523,8 @@ out_release:
|
|
unlock_page(swapcache);
|
|
put_page(swapcache);
|
|
}
|
|
+ if (si)
|
|
+ put_swap_device(si);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
|
|
index 81cc7fdc9c8fd..e30d88efd7fbb 100644
|
|
--- a/mm/page_alloc.c
|
|
+++ b/mm/page_alloc.c
|
|
@@ -7788,31 +7788,24 @@ static void calculate_totalreserve_pages(void)
|
|
static void setup_per_zone_lowmem_reserve(void)
|
|
{
|
|
struct pglist_data *pgdat;
|
|
- enum zone_type j, idx;
|
|
+ enum zone_type i, j;
|
|
|
|
for_each_online_pgdat(pgdat) {
|
|
- for (j = 0; j < MAX_NR_ZONES; j++) {
|
|
- struct zone *zone = pgdat->node_zones + j;
|
|
- unsigned long managed_pages = zone_managed_pages(zone);
|
|
-
|
|
- zone->lowmem_reserve[j] = 0;
|
|
+ for (i = 0; i < MAX_NR_ZONES - 1; i++) {
|
|
+ struct zone *zone = &pgdat->node_zones[i];
|
|
+ int ratio = sysctl_lowmem_reserve_ratio[i];
|
|
+ bool clear = !ratio || !zone_managed_pages(zone);
|
|
+ unsigned long managed_pages = 0;
|
|
|
|
- idx = j;
|
|
- while (idx) {
|
|
- struct zone *lower_zone;
|
|
+ for (j = i + 1; j < MAX_NR_ZONES; j++) {
|
|
+ struct zone *upper_zone = &pgdat->node_zones[j];
|
|
|
|
- idx--;
|
|
- lower_zone = pgdat->node_zones + idx;
|
|
+ managed_pages += zone_managed_pages(upper_zone);
|
|
|
|
- if (!sysctl_lowmem_reserve_ratio[idx] ||
|
|
- !zone_managed_pages(lower_zone)) {
|
|
- lower_zone->lowmem_reserve[j] = 0;
|
|
- continue;
|
|
- } else {
|
|
- lower_zone->lowmem_reserve[j] =
|
|
- managed_pages / sysctl_lowmem_reserve_ratio[idx];
|
|
- }
|
|
- managed_pages += zone_managed_pages(lower_zone);
|
|
+ if (clear)
|
|
+ zone->lowmem_reserve[j] = 0;
|
|
+ else
|
|
+ zone->lowmem_reserve[j] = managed_pages / ratio;
|
|
}
|
|
}
|
|
}
|
|
diff --git a/mm/shmem.c b/mm/shmem.c
|
|
index 6e487bf555f9e..96df61c8af653 100644
|
|
--- a/mm/shmem.c
|
|
+++ b/mm/shmem.c
|
|
@@ -1698,7 +1698,8 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
|
|
struct address_space *mapping = inode->i_mapping;
|
|
struct shmem_inode_info *info = SHMEM_I(inode);
|
|
struct mm_struct *charge_mm = vma ? vma->vm_mm : current->mm;
|
|
- struct page *page;
|
|
+ struct swap_info_struct *si;
|
|
+ struct page *page = NULL;
|
|
swp_entry_t swap;
|
|
int error;
|
|
|
|
@@ -1706,6 +1707,12 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
|
|
swap = radix_to_swp_entry(*pagep);
|
|
*pagep = NULL;
|
|
|
|
+ /* Prevent swapoff from happening to us. */
|
|
+ si = get_swap_device(swap);
|
|
+ if (!si) {
|
|
+ error = EINVAL;
|
|
+ goto failed;
|
|
+ }
|
|
/* Look it up and read it in.. */
|
|
page = lookup_swap_cache(swap, NULL, 0);
|
|
if (!page) {
|
|
@@ -1767,6 +1774,8 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
|
|
swap_free(swap);
|
|
|
|
*pagep = page;
|
|
+ if (si)
|
|
+ put_swap_device(si);
|
|
return 0;
|
|
failed:
|
|
if (!shmem_confirm_swap(mapping, index, swap))
|
|
@@ -1777,6 +1786,9 @@ unlock:
|
|
put_page(page);
|
|
}
|
|
|
|
+ if (si)
|
|
+ put_swap_device(si);
|
|
+
|
|
return error;
|
|
}
|
|
|
|
@@ -4080,8 +4092,7 @@ bool shmem_huge_enabled(struct vm_area_struct *vma)
|
|
loff_t i_size;
|
|
pgoff_t off;
|
|
|
|
- if ((vma->vm_flags & VM_NOHUGEPAGE) ||
|
|
- test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags))
|
|
+ if (!transhuge_vma_enabled(vma, vma->vm_flags))
|
|
return false;
|
|
if (shmem_huge == SHMEM_HUGE_FORCE)
|
|
return true;
|
|
diff --git a/mm/slab.h b/mm/slab.h
|
|
index e258ffcfb0ef2..944e8b2040ae2 100644
|
|
--- a/mm/slab.h
|
|
+++ b/mm/slab.h
|
|
@@ -326,7 +326,6 @@ static inline void memcg_slab_post_alloc_hook(struct kmem_cache *s,
|
|
if (!memcg_kmem_enabled() || !objcg)
|
|
return;
|
|
|
|
- flags &= ~__GFP_ACCOUNT;
|
|
for (i = 0; i < size; i++) {
|
|
if (likely(p[i])) {
|
|
page = virt_to_head_page(p[i]);
|
|
diff --git a/mm/z3fold.c b/mm/z3fold.c
|
|
index 8ae944eeb8e20..912ac9a64a155 100644
|
|
--- a/mm/z3fold.c
|
|
+++ b/mm/z3fold.c
|
|
@@ -1063,6 +1063,7 @@ static void z3fold_destroy_pool(struct z3fold_pool *pool)
|
|
destroy_workqueue(pool->compact_wq);
|
|
destroy_workqueue(pool->release_wq);
|
|
z3fold_unregister_migration(pool);
|
|
+ free_percpu(pool->unbuddied);
|
|
kfree(pool);
|
|
}
|
|
|
|
@@ -1386,7 +1387,7 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
|
|
if (zhdr->foreign_handles ||
|
|
test_and_set_bit(PAGE_CLAIMED, &page->private)) {
|
|
if (kref_put(&zhdr->refcount,
|
|
- release_z3fold_page))
|
|
+ release_z3fold_page_locked))
|
|
atomic64_dec(&pool->pages_nr);
|
|
else
|
|
z3fold_page_unlock(zhdr);
|
|
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
|
|
index 4676e4b0be2bf..d62ac4b737099 100644
|
|
--- a/net/bluetooth/hci_event.c
|
|
+++ b/net/bluetooth/hci_event.c
|
|
@@ -5256,8 +5256,19 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
|
|
|
|
- if (ev->status)
|
|
+ if (ev->status) {
|
|
+ struct adv_info *adv;
|
|
+
|
|
+ adv = hci_find_adv_instance(hdev, ev->handle);
|
|
+ if (!adv)
|
|
+ return;
|
|
+
|
|
+ /* Remove advertising as it has been terminated */
|
|
+ hci_remove_adv_instance(hdev, ev->handle);
|
|
+ mgmt_advertising_removed(NULL, hdev, ev->handle);
|
|
+
|
|
return;
|
|
+ }
|
|
|
|
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle));
|
|
if (conn) {
|
|
@@ -5401,7 +5412,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
|
|
struct hci_conn *conn;
|
|
bool match;
|
|
u32 flags;
|
|
- u8 *ptr, real_len;
|
|
+ u8 *ptr;
|
|
|
|
switch (type) {
|
|
case LE_ADV_IND:
|
|
@@ -5432,14 +5443,10 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
|
|
break;
|
|
}
|
|
|
|
- real_len = ptr - data;
|
|
-
|
|
- /* Adjust for actual length */
|
|
- if (len != real_len) {
|
|
- bt_dev_err_ratelimited(hdev, "advertising data len corrected %u -> %u",
|
|
- len, real_len);
|
|
- len = real_len;
|
|
- }
|
|
+ /* Adjust for actual length. This handles the case when remote
|
|
+ * device is advertising with incorrect data length.
|
|
+ */
|
|
+ len = ptr - data;
|
|
|
|
/* If the direct address is present, then this report is from
|
|
* a LE Direct Advertising Report event. In that case it is
|
|
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
|
|
index 161ea93a53828..1a94ed2f8a4f8 100644
|
|
--- a/net/bluetooth/hci_request.c
|
|
+++ b/net/bluetooth/hci_request.c
|
|
@@ -1060,9 +1060,10 @@ static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance)
|
|
if (!adv_instance)
|
|
return 0;
|
|
|
|
- /* TODO: Take into account the "appearance" and "local-name" flags here.
|
|
- * These are currently being ignored as they are not supported.
|
|
- */
|
|
+ if (adv_instance->flags & MGMT_ADV_FLAG_APPEARANCE ||
|
|
+ adv_instance->flags & MGMT_ADV_FLAG_LOCAL_NAME)
|
|
+ return 1;
|
|
+
|
|
return adv_instance->scan_rsp_len;
|
|
}
|
|
|
|
@@ -1595,33 +1596,33 @@ void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance)
|
|
return;
|
|
|
|
if (ext_adv_capable(hdev)) {
|
|
- struct hci_cp_le_set_ext_scan_rsp_data cp;
|
|
+ struct {
|
|
+ struct hci_cp_le_set_ext_scan_rsp_data cp;
|
|
+ u8 data[HCI_MAX_EXT_AD_LENGTH];
|
|
+ } pdu;
|
|
|
|
- memset(&cp, 0, sizeof(cp));
|
|
+ memset(&pdu, 0, sizeof(pdu));
|
|
|
|
- /* Extended scan response data doesn't allow a response to be
|
|
- * set if the instance isn't scannable.
|
|
- */
|
|
- if (get_adv_instance_scan_rsp_len(hdev, instance))
|
|
+ if (instance)
|
|
len = create_instance_scan_rsp_data(hdev, instance,
|
|
- cp.data);
|
|
+ pdu.data);
|
|
else
|
|
- len = 0;
|
|
+ len = create_default_scan_rsp_data(hdev, pdu.data);
|
|
|
|
if (hdev->scan_rsp_data_len == len &&
|
|
- !memcmp(cp.data, hdev->scan_rsp_data, len))
|
|
+ !memcmp(pdu.data, hdev->scan_rsp_data, len))
|
|
return;
|
|
|
|
- memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
|
|
+ memcpy(hdev->scan_rsp_data, pdu.data, len);
|
|
hdev->scan_rsp_data_len = len;
|
|
|
|
- cp.handle = instance;
|
|
- cp.length = len;
|
|
- cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
|
|
- cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
|
|
+ pdu.cp.handle = instance;
|
|
+ pdu.cp.length = len;
|
|
+ pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
|
|
+ pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
|
|
|
|
- hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, sizeof(cp),
|
|
- &cp);
|
|
+ hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA,
|
|
+ sizeof(pdu.cp) + len, &pdu.cp);
|
|
} else {
|
|
struct hci_cp_le_set_scan_rsp_data cp;
|
|
|
|
@@ -1744,26 +1745,30 @@ void __hci_req_update_adv_data(struct hci_request *req, u8 instance)
|
|
return;
|
|
|
|
if (ext_adv_capable(hdev)) {
|
|
- struct hci_cp_le_set_ext_adv_data cp;
|
|
+ struct {
|
|
+ struct hci_cp_le_set_ext_adv_data cp;
|
|
+ u8 data[HCI_MAX_EXT_AD_LENGTH];
|
|
+ } pdu;
|
|
|
|
- memset(&cp, 0, sizeof(cp));
|
|
+ memset(&pdu, 0, sizeof(pdu));
|
|
|
|
- len = create_instance_adv_data(hdev, instance, cp.data);
|
|
+ len = create_instance_adv_data(hdev, instance, pdu.data);
|
|
|
|
/* There's nothing to do if the data hasn't changed */
|
|
if (hdev->adv_data_len == len &&
|
|
- memcmp(cp.data, hdev->adv_data, len) == 0)
|
|
+ memcmp(pdu.data, hdev->adv_data, len) == 0)
|
|
return;
|
|
|
|
- memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
|
|
+ memcpy(hdev->adv_data, pdu.data, len);
|
|
hdev->adv_data_len = len;
|
|
|
|
- cp.length = len;
|
|
- cp.handle = instance;
|
|
- cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
|
|
- cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
|
|
+ pdu.cp.length = len;
|
|
+ pdu.cp.handle = instance;
|
|
+ pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
|
|
+ pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
|
|
|
|
- hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA, sizeof(cp), &cp);
|
|
+ hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA,
|
|
+ sizeof(pdu.cp) + len, &pdu.cp);
|
|
} else {
|
|
struct hci_cp_le_set_adv_data cp;
|
|
|
|
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
|
|
index 12d7b368b428e..13520c7b4f2fb 100644
|
|
--- a/net/bluetooth/mgmt.c
|
|
+++ b/net/bluetooth/mgmt.c
|
|
@@ -7350,6 +7350,9 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
|
|
for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) {
|
|
cur_len = data[i];
|
|
|
|
+ if (!cur_len)
|
|
+ continue;
|
|
+
|
|
if (data[i + 1] == EIR_FLAGS &&
|
|
(!is_adv_data || flags_managed(adv_flags)))
|
|
return false;
|
|
diff --git a/net/bpfilter/main.c b/net/bpfilter/main.c
|
|
index 05e1cfc1e5cd1..291a925462463 100644
|
|
--- a/net/bpfilter/main.c
|
|
+++ b/net/bpfilter/main.c
|
|
@@ -57,7 +57,7 @@ int main(void)
|
|
{
|
|
debug_f = fopen("/dev/kmsg", "w");
|
|
setvbuf(debug_f, 0, _IOLBF, 0);
|
|
- fprintf(debug_f, "Started bpfilter\n");
|
|
+ fprintf(debug_f, "<5>Started bpfilter\n");
|
|
loop();
|
|
fclose(debug_f);
|
|
return 0;
|
|
diff --git a/net/can/bcm.c b/net/can/bcm.c
|
|
index f3e4d9528fa38..0928a39c4423b 100644
|
|
--- a/net/can/bcm.c
|
|
+++ b/net/can/bcm.c
|
|
@@ -785,6 +785,7 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
|
|
bcm_rx_handler, op);
|
|
|
|
list_del(&op->list);
|
|
+ synchronize_rcu();
|
|
bcm_remove_op(op);
|
|
return 1; /* done */
|
|
}
|
|
@@ -1533,9 +1534,13 @@ static int bcm_release(struct socket *sock)
|
|
REGMASK(op->can_id),
|
|
bcm_rx_handler, op);
|
|
|
|
- bcm_remove_op(op);
|
|
}
|
|
|
|
+ synchronize_rcu();
|
|
+
|
|
+ list_for_each_entry_safe(op, next, &bo->rx_ops, list)
|
|
+ bcm_remove_op(op);
|
|
+
|
|
#if IS_ENABLED(CONFIG_PROC_FS)
|
|
/* remove procfs entry */
|
|
if (net->can.bcmproc_dir && bo->bcm_proc_read)
|
|
diff --git a/net/can/gw.c b/net/can/gw.c
|
|
index 6b790b6ff8d26..cbb46d3aa9634 100644
|
|
--- a/net/can/gw.c
|
|
+++ b/net/can/gw.c
|
|
@@ -534,6 +534,7 @@ static int cgw_notifier(struct notifier_block *nb,
|
|
if (gwj->src.dev == dev || gwj->dst.dev == dev) {
|
|
hlist_del(&gwj->list);
|
|
cgw_unregister_filter(net, gwj);
|
|
+ synchronize_rcu();
|
|
kmem_cache_free(cgw_cache, gwj);
|
|
}
|
|
}
|
|
@@ -1092,6 +1093,7 @@ static void cgw_remove_all_jobs(struct net *net)
|
|
hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) {
|
|
hlist_del(&gwj->list);
|
|
cgw_unregister_filter(net, gwj);
|
|
+ synchronize_rcu();
|
|
kmem_cache_free(cgw_cache, gwj);
|
|
}
|
|
}
|
|
@@ -1160,6 +1162,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
|
|
hlist_del(&gwj->list);
|
|
cgw_unregister_filter(net, gwj);
|
|
+ synchronize_rcu();
|
|
kmem_cache_free(cgw_cache, gwj);
|
|
err = 0;
|
|
break;
|
|
diff --git a/net/can/isotp.c b/net/can/isotp.c
|
|
index 1adefb14527d8..5fc28f190677b 100644
|
|
--- a/net/can/isotp.c
|
|
+++ b/net/can/isotp.c
|
|
@@ -1023,9 +1023,6 @@ static int isotp_release(struct socket *sock)
|
|
|
|
lock_sock(sk);
|
|
|
|
- hrtimer_cancel(&so->txtimer);
|
|
- hrtimer_cancel(&so->rxtimer);
|
|
-
|
|
/* remove current filters & unregister */
|
|
if (so->bound) {
|
|
if (so->ifindex) {
|
|
@@ -1037,10 +1034,14 @@ static int isotp_release(struct socket *sock)
|
|
SINGLE_MASK(so->rxid),
|
|
isotp_rcv, sk);
|
|
dev_put(dev);
|
|
+ synchronize_rcu();
|
|
}
|
|
}
|
|
}
|
|
|
|
+ hrtimer_cancel(&so->txtimer);
|
|
+ hrtimer_cancel(&so->rxtimer);
|
|
+
|
|
so->ifindex = 0;
|
|
so->bound = 0;
|
|
|
|
diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c
|
|
index e52330f628c9f..6884d18f919c7 100644
|
|
--- a/net/can/j1939/main.c
|
|
+++ b/net/can/j1939/main.c
|
|
@@ -193,6 +193,10 @@ static void j1939_can_rx_unregister(struct j1939_priv *priv)
|
|
can_rx_unregister(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK,
|
|
j1939_can_recv, priv);
|
|
|
|
+ /* The last reference of priv is dropped by the RCU deferred
|
|
+ * j1939_sk_sock_destruct() of the last socket, so we can
|
|
+ * safely drop this reference here.
|
|
+ */
|
|
j1939_priv_put(priv);
|
|
}
|
|
|
|
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
|
|
index 56aa66147d5ac..e1a399821238f 100644
|
|
--- a/net/can/j1939/socket.c
|
|
+++ b/net/can/j1939/socket.c
|
|
@@ -398,6 +398,9 @@ static int j1939_sk_init(struct sock *sk)
|
|
atomic_set(&jsk->skb_pending, 0);
|
|
spin_lock_init(&jsk->sk_session_queue_lock);
|
|
INIT_LIST_HEAD(&jsk->sk_session_queue);
|
|
+
|
|
+ /* j1939_sk_sock_destruct() depends on SOCK_RCU_FREE flag */
|
|
+ sock_set_flag(sk, SOCK_RCU_FREE);
|
|
sk->sk_destruct = j1939_sk_sock_destruct;
|
|
sk->sk_protocol = CAN_J1939;
|
|
|
|
@@ -673,7 +676,7 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname,
|
|
|
|
switch (optname) {
|
|
case SO_J1939_FILTER:
|
|
- if (!sockptr_is_null(optval)) {
|
|
+ if (!sockptr_is_null(optval) && optlen != 0) {
|
|
struct j1939_filter *f;
|
|
int c;
|
|
|
|
diff --git a/net/core/filter.c b/net/core/filter.c
|
|
index ef6bdbb63ecbb..7ea752af7894d 100644
|
|
--- a/net/core/filter.c
|
|
+++ b/net/core/filter.c
|
|
@@ -3266,8 +3266,6 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
|
|
shinfo->gso_type |= SKB_GSO_TCPV6;
|
|
}
|
|
|
|
- /* Due to IPv6 header, MSS needs to be downgraded. */
|
|
- skb_decrease_gso_size(shinfo, len_diff);
|
|
/* Header must be checked, and gso_segs recomputed. */
|
|
shinfo->gso_type |= SKB_GSO_DODGY;
|
|
shinfo->gso_segs = 0;
|
|
@@ -3307,8 +3305,6 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
|
|
shinfo->gso_type |= SKB_GSO_TCPV4;
|
|
}
|
|
|
|
- /* Due to IPv4 header, MSS can be upgraded. */
|
|
- skb_increase_gso_size(shinfo, len_diff);
|
|
/* Header must be checked, and gso_segs recomputed. */
|
|
shinfo->gso_type |= SKB_GSO_DODGY;
|
|
shinfo->gso_segs = 0;
|
|
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
|
|
index 4b834bbf95e07..ed9857b2875dc 100644
|
|
--- a/net/ipv4/esp4.c
|
|
+++ b/net/ipv4/esp4.c
|
|
@@ -673,7 +673,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
|
|
struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
|
|
u32 padto;
|
|
|
|
- padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached));
|
|
+ padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached));
|
|
if (skb->len < padto)
|
|
esp.tfclen = padto - skb->len;
|
|
}
|
|
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
|
|
index 84bb707bd88d8..647bceab56c2d 100644
|
|
--- a/net/ipv4/fib_frontend.c
|
|
+++ b/net/ipv4/fib_frontend.c
|
|
@@ -371,6 +371,8 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
|
|
fl4.flowi4_proto = 0;
|
|
fl4.fl4_sport = 0;
|
|
fl4.fl4_dport = 0;
|
|
+ } else {
|
|
+ swap(fl4.fl4_sport, fl4.fl4_dport);
|
|
}
|
|
|
|
if (fib_lookup(net, &fl4, &res, 0))
|
|
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
|
|
index e968bb47d5bd8..e15c1d8b7c8de 100644
|
|
--- a/net/ipv4/route.c
|
|
+++ b/net/ipv4/route.c
|
|
@@ -1327,7 +1327,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
|
|
mtu = dst_metric_raw(dst, RTAX_MTU);
|
|
|
|
if (mtu)
|
|
- return mtu;
|
|
+ goto out;
|
|
|
|
mtu = READ_ONCE(dst->dev->mtu);
|
|
|
|
@@ -1336,6 +1336,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
|
|
mtu = 576;
|
|
}
|
|
|
|
+out:
|
|
mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
|
|
|
|
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
|
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
|
|
index 4071cb7c7a154..8d001f665fb15 100644
|
|
--- a/net/ipv6/esp6.c
|
|
+++ b/net/ipv6/esp6.c
|
|
@@ -708,7 +708,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
|
|
struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
|
|
u32 padto;
|
|
|
|
- padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached));
|
|
+ padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached));
|
|
if (skb->len < padto)
|
|
esp.tfclen = padto - skb->len;
|
|
}
|
|
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
|
|
index 374105e4394f8..4932dea9820ba 100644
|
|
--- a/net/ipv6/exthdrs.c
|
|
+++ b/net/ipv6/exthdrs.c
|
|
@@ -135,18 +135,23 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
|
|
len -= 2;
|
|
|
|
while (len > 0) {
|
|
- int optlen = nh[off + 1] + 2;
|
|
- int i;
|
|
+ int optlen, i;
|
|
|
|
- switch (nh[off]) {
|
|
- case IPV6_TLV_PAD1:
|
|
- optlen = 1;
|
|
+ if (nh[off] == IPV6_TLV_PAD1) {
|
|
padlen++;
|
|
if (padlen > 7)
|
|
goto bad;
|
|
- break;
|
|
+ off++;
|
|
+ len--;
|
|
+ continue;
|
|
+ }
|
|
+ if (len < 2)
|
|
+ goto bad;
|
|
+ optlen = nh[off + 1] + 2;
|
|
+ if (optlen > len)
|
|
+ goto bad;
|
|
|
|
- case IPV6_TLV_PADN:
|
|
+ if (nh[off] == IPV6_TLV_PADN) {
|
|
/* RFC 2460 states that the purpose of PadN is
|
|
* to align the containing header to multiples
|
|
* of 8. 7 is therefore the highest valid value.
|
|
@@ -163,12 +168,7 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
|
|
if (nh[off + i] != 0)
|
|
goto bad;
|
|
}
|
|
- break;
|
|
-
|
|
- default: /* Other TLV code so scan list */
|
|
- if (optlen > len)
|
|
- goto bad;
|
|
-
|
|
+ } else {
|
|
tlv_count++;
|
|
if (tlv_count > max_count)
|
|
goto bad;
|
|
@@ -188,7 +188,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
|
|
return false;
|
|
|
|
padlen = 0;
|
|
- break;
|
|
}
|
|
off += optlen;
|
|
len -= optlen;
|
|
@@ -306,7 +305,7 @@ fail_and_free:
|
|
#endif
|
|
|
|
if (ip6_parse_tlv(tlvprocdestopt_lst, skb,
|
|
- init_net.ipv6.sysctl.max_dst_opts_cnt)) {
|
|
+ net->ipv6.sysctl.max_dst_opts_cnt)) {
|
|
skb->transport_header += extlen;
|
|
opt = IP6CB(skb);
|
|
#if IS_ENABLED(CONFIG_IPV6_MIP6)
|
|
@@ -1041,7 +1040,7 @@ fail_and_free:
|
|
|
|
opt->flags |= IP6SKB_HOPBYHOP;
|
|
if (ip6_parse_tlv(tlvprochopopt_lst, skb,
|
|
- init_net.ipv6.sysctl.max_hbh_opts_cnt)) {
|
|
+ net->ipv6.sysctl.max_hbh_opts_cnt)) {
|
|
skb->transport_header += extlen;
|
|
opt = IP6CB(skb);
|
|
opt->nhoff = sizeof(struct ipv6hdr);
|
|
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
|
|
index 42ca2d05c480d..08441f06afd48 100644
|
|
--- a/net/ipv6/ip6_tunnel.c
|
|
+++ b/net/ipv6/ip6_tunnel.c
|
|
@@ -1270,8 +1270,6 @@ route_lookup:
|
|
if (max_headroom > dev->needed_headroom)
|
|
dev->needed_headroom = max_headroom;
|
|
|
|
- skb_set_inner_ipproto(skb, proto);
|
|
-
|
|
err = ip6_tnl_encap(skb, t, &proto, fl6);
|
|
if (err)
|
|
return err;
|
|
@@ -1408,6 +1406,8 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev,
|
|
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
|
|
return -1;
|
|
|
|
+ skb_set_inner_ipproto(skb, protocol);
|
|
+
|
|
err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
|
|
protocol);
|
|
if (err != 0) {
|
|
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
|
|
index fbe26e912300d..142bb28199c48 100644
|
|
--- a/net/mac80211/mlme.c
|
|
+++ b/net/mac80211/mlme.c
|
|
@@ -1094,11 +1094,6 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
|
|
struct ieee80211_hdr_3addr *nullfunc;
|
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
|
|
- /* Don't send NDPs when STA is connected HE */
|
|
- if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
|
- !(ifmgd->flags & IEEE80211_STA_DISABLE_HE))
|
|
- return;
|
|
-
|
|
skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif,
|
|
!ieee80211_hw_check(&local->hw, DOESNT_SUPPORT_QOS_NDP));
|
|
if (!skb)
|
|
@@ -1130,10 +1125,6 @@ static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
|
|
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
|
|
return;
|
|
|
|
- /* Don't send NDPs when connected HE */
|
|
- if (!(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE))
|
|
- return;
|
|
-
|
|
skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30);
|
|
if (!skb)
|
|
return;
|
|
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
|
|
index f2fb69da9b6e1..13250cadb4202 100644
|
|
--- a/net/mac80211/sta_info.c
|
|
+++ b/net/mac80211/sta_info.c
|
|
@@ -1398,11 +1398,6 @@ static void ieee80211_send_null_response(struct sta_info *sta, int tid,
|
|
struct ieee80211_tx_info *info;
|
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
|
|
|
- /* Don't send NDPs when STA is connected HE */
|
|
- if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
|
- !(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE))
|
|
- return;
|
|
-
|
|
if (qos) {
|
|
fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
|
|
IEEE80211_STYPE_QOS_NULLFUNC |
|
|
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
|
|
index 851fb3d8c791d..bba5696fee36d 100644
|
|
--- a/net/mptcp/subflow.c
|
|
+++ b/net/mptcp/subflow.c
|
|
@@ -338,15 +338,15 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
|
|
goto do_reset;
|
|
}
|
|
|
|
+ if (!mptcp_finish_join(sk))
|
|
+ goto do_reset;
|
|
+
|
|
subflow_generate_hmac(subflow->local_key, subflow->remote_key,
|
|
subflow->local_nonce,
|
|
subflow->remote_nonce,
|
|
hmac);
|
|
memcpy(subflow->hmac, hmac, MPTCPOPT_HMAC_LEN);
|
|
|
|
- if (!mptcp_finish_join(sk))
|
|
- goto do_reset;
|
|
-
|
|
subflow->mp_join = 1;
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX);
|
|
} else if (mptcp_check_fallback(sk)) {
|
|
diff --git a/net/mptcp/token.c b/net/mptcp/token.c
|
|
index feb4b9ffd4625..0691a4883f3ab 100644
|
|
--- a/net/mptcp/token.c
|
|
+++ b/net/mptcp/token.c
|
|
@@ -156,9 +156,6 @@ int mptcp_token_new_connect(struct sock *sk)
|
|
int retries = TOKEN_MAX_RETRIES;
|
|
struct token_bucket *bucket;
|
|
|
|
- pr_debug("ssk=%p, local_key=%llu, token=%u, idsn=%llu\n",
|
|
- sk, subflow->local_key, subflow->token, subflow->idsn);
|
|
-
|
|
again:
|
|
mptcp_crypto_key_gen_sha(&subflow->local_key, &subflow->token,
|
|
&subflow->idsn);
|
|
@@ -172,6 +169,9 @@ again:
|
|
goto again;
|
|
}
|
|
|
|
+ pr_debug("ssk=%p, local_key=%llu, token=%u, idsn=%llu\n",
|
|
+ sk, subflow->local_key, subflow->token, subflow->idsn);
|
|
+
|
|
WRITE_ONCE(msk->token, subflow->token);
|
|
__sk_nulls_add_node_rcu((struct sock *)msk, &bucket->msk_chain);
|
|
bucket->chain_len++;
|
|
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
|
|
index 2b00f7f47693b..9ce776175214c 100644
|
|
--- a/net/netfilter/nf_tables_offload.c
|
|
+++ b/net/netfilter/nf_tables_offload.c
|
|
@@ -54,15 +54,10 @@ static void nft_flow_rule_transfer_vlan(struct nft_offload_ctx *ctx,
|
|
struct nft_flow_rule *flow)
|
|
{
|
|
struct nft_flow_match *match = &flow->match;
|
|
- struct nft_offload_ethertype ethertype;
|
|
-
|
|
- if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL) &&
|
|
- match->key.basic.n_proto != htons(ETH_P_8021Q) &&
|
|
- match->key.basic.n_proto != htons(ETH_P_8021AD))
|
|
- return;
|
|
-
|
|
- ethertype.value = match->key.basic.n_proto;
|
|
- ethertype.mask = match->mask.basic.n_proto;
|
|
+ struct nft_offload_ethertype ethertype = {
|
|
+ .value = match->key.basic.n_proto,
|
|
+ .mask = match->mask.basic.n_proto,
|
|
+ };
|
|
|
|
if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_VLAN) &&
|
|
(match->key.vlan.vlan_tpid == htons(ETH_P_8021Q) ||
|
|
@@ -76,7 +71,9 @@ static void nft_flow_rule_transfer_vlan(struct nft_offload_ctx *ctx,
|
|
match->dissector.offset[FLOW_DISSECTOR_KEY_CVLAN] =
|
|
offsetof(struct nft_flow_key, cvlan);
|
|
match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CVLAN);
|
|
- } else {
|
|
+ } else if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC) &&
|
|
+ (match->key.basic.n_proto == htons(ETH_P_8021Q) ||
|
|
+ match->key.basic.n_proto == htons(ETH_P_8021AD))) {
|
|
match->key.basic.n_proto = match->key.vlan.vlan_tpid;
|
|
match->mask.basic.n_proto = match->mask.vlan.vlan_tpid;
|
|
match->key.vlan.vlan_tpid = ethertype.value;
|
|
diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c
|
|
index 3c48cdc8935df..faa0844c01fb8 100644
|
|
--- a/net/netfilter/nft_exthdr.c
|
|
+++ b/net/netfilter/nft_exthdr.c
|
|
@@ -42,6 +42,9 @@ static void nft_exthdr_ipv6_eval(const struct nft_expr *expr,
|
|
unsigned int offset = 0;
|
|
int err;
|
|
|
|
+ if (pkt->skb->protocol != htons(ETH_P_IPV6))
|
|
+ goto err;
|
|
+
|
|
err = ipv6_find_hdr(pkt->skb, &offset, priv->type, NULL, NULL);
|
|
if (priv->flags & NFT_EXTHDR_F_PRESENT) {
|
|
nft_reg_store8(dest, err >= 0);
|
|
diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c
|
|
index c261d57a666ab..2c957629ea660 100644
|
|
--- a/net/netfilter/nft_osf.c
|
|
+++ b/net/netfilter/nft_osf.c
|
|
@@ -28,6 +28,11 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
|
struct nf_osf_data data;
|
|
struct tcphdr _tcph;
|
|
|
|
+ if (pkt->tprot != IPPROTO_TCP) {
|
|
+ regs->verdict.code = NFT_BREAK;
|
|
+ return;
|
|
+ }
|
|
+
|
|
tcp = skb_header_pointer(skb, ip_hdrlen(skb),
|
|
sizeof(struct tcphdr), &_tcph);
|
|
if (!tcp) {
|
|
diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c
|
|
index d67f83a0958d3..242222dc52c3c 100644
|
|
--- a/net/netfilter/nft_tproxy.c
|
|
+++ b/net/netfilter/nft_tproxy.c
|
|
@@ -30,6 +30,12 @@ static void nft_tproxy_eval_v4(const struct nft_expr *expr,
|
|
__be16 tport = 0;
|
|
struct sock *sk;
|
|
|
|
+ if (pkt->tprot != IPPROTO_TCP &&
|
|
+ pkt->tprot != IPPROTO_UDP) {
|
|
+ regs->verdict.code = NFT_BREAK;
|
|
+ return;
|
|
+ }
|
|
+
|
|
hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
|
|
if (!hp) {
|
|
regs->verdict.code = NFT_BREAK;
|
|
@@ -91,7 +97,8 @@ static void nft_tproxy_eval_v6(const struct nft_expr *expr,
|
|
|
|
memset(&taddr, 0, sizeof(taddr));
|
|
|
|
- if (!pkt->tprot_set) {
|
|
+ if (pkt->tprot != IPPROTO_TCP &&
|
|
+ pkt->tprot != IPPROTO_UDP) {
|
|
regs->verdict.code = NFT_BREAK;
|
|
return;
|
|
}
|
|
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
|
|
index eb1d66d20afbb..02a97bca1a1a2 100644
|
|
--- a/net/netlabel/netlabel_mgmt.c
|
|
+++ b/net/netlabel/netlabel_mgmt.c
|
|
@@ -76,6 +76,7 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
|
|
static int netlbl_mgmt_add_common(struct genl_info *info,
|
|
struct netlbl_audit *audit_info)
|
|
{
|
|
+ void *pmap = NULL;
|
|
int ret_val = -EINVAL;
|
|
struct netlbl_domaddr_map *addrmap = NULL;
|
|
struct cipso_v4_doi *cipsov4 = NULL;
|
|
@@ -175,6 +176,7 @@ static int netlbl_mgmt_add_common(struct genl_info *info,
|
|
ret_val = -ENOMEM;
|
|
goto add_free_addrmap;
|
|
}
|
|
+ pmap = map;
|
|
map->list.addr = addr->s_addr & mask->s_addr;
|
|
map->list.mask = mask->s_addr;
|
|
map->list.valid = 1;
|
|
@@ -183,10 +185,8 @@ static int netlbl_mgmt_add_common(struct genl_info *info,
|
|
map->def.cipso = cipsov4;
|
|
|
|
ret_val = netlbl_af4list_add(&map->list, &addrmap->list4);
|
|
- if (ret_val != 0) {
|
|
- kfree(map);
|
|
- goto add_free_addrmap;
|
|
- }
|
|
+ if (ret_val != 0)
|
|
+ goto add_free_map;
|
|
|
|
entry->family = AF_INET;
|
|
entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
|
|
@@ -223,6 +223,7 @@ static int netlbl_mgmt_add_common(struct genl_info *info,
|
|
ret_val = -ENOMEM;
|
|
goto add_free_addrmap;
|
|
}
|
|
+ pmap = map;
|
|
map->list.addr = *addr;
|
|
map->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
|
|
map->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
|
|
@@ -235,10 +236,8 @@ static int netlbl_mgmt_add_common(struct genl_info *info,
|
|
map->def.calipso = calipso;
|
|
|
|
ret_val = netlbl_af6list_add(&map->list, &addrmap->list6);
|
|
- if (ret_val != 0) {
|
|
- kfree(map);
|
|
- goto add_free_addrmap;
|
|
- }
|
|
+ if (ret_val != 0)
|
|
+ goto add_free_map;
|
|
|
|
entry->family = AF_INET6;
|
|
entry->def.type = NETLBL_NLTYPE_ADDRSELECT;
|
|
@@ -248,10 +247,12 @@ static int netlbl_mgmt_add_common(struct genl_info *info,
|
|
|
|
ret_val = netlbl_domhsh_add(entry, audit_info);
|
|
if (ret_val != 0)
|
|
- goto add_free_addrmap;
|
|
+ goto add_free_map;
|
|
|
|
return 0;
|
|
|
|
+add_free_map:
|
|
+ kfree(pmap);
|
|
add_free_addrmap:
|
|
kfree(addrmap);
|
|
add_doi_put_def:
|
|
diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
|
|
index b8559c8824318..e760d4a38fafd 100644
|
|
--- a/net/qrtr/ns.c
|
|
+++ b/net/qrtr/ns.c
|
|
@@ -783,8 +783,10 @@ void qrtr_ns_init(void)
|
|
}
|
|
|
|
qrtr_ns.workqueue = alloc_workqueue("qrtr_ns_handler", WQ_UNBOUND, 1);
|
|
- if (!qrtr_ns.workqueue)
|
|
+ if (!qrtr_ns.workqueue) {
|
|
+ ret = -ENOMEM;
|
|
goto err_sock;
|
|
+ }
|
|
|
|
qrtr_ns.sock->sk->sk_data_ready = qrtr_ns_data_ready;
|
|
|
|
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
|
|
index 1cac3c6fbb49c..a108469c664f7 100644
|
|
--- a/net/sched/act_vlan.c
|
|
+++ b/net/sched/act_vlan.c
|
|
@@ -70,7 +70,7 @@ static int tcf_vlan_act(struct sk_buff *skb, const struct tc_action *a,
|
|
/* replace the vid */
|
|
tci = (tci & ~VLAN_VID_MASK) | p->tcfv_push_vid;
|
|
/* replace prio bits, if tcfv_push_prio specified */
|
|
- if (p->tcfv_push_prio) {
|
|
+ if (p->tcfv_push_prio_exists) {
|
|
tci &= ~VLAN_PRIO_MASK;
|
|
tci |= p->tcfv_push_prio << VLAN_PRIO_SHIFT;
|
|
}
|
|
@@ -121,6 +121,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
|
|
struct tc_action_net *tn = net_generic(net, vlan_net_id);
|
|
struct nlattr *tb[TCA_VLAN_MAX + 1];
|
|
struct tcf_chain *goto_ch = NULL;
|
|
+ bool push_prio_exists = false;
|
|
struct tcf_vlan_params *p;
|
|
struct tc_vlan *parm;
|
|
struct tcf_vlan *v;
|
|
@@ -189,7 +190,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
|
|
push_proto = htons(ETH_P_8021Q);
|
|
}
|
|
|
|
- if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY])
|
|
+ push_prio_exists = !!tb[TCA_VLAN_PUSH_VLAN_PRIORITY];
|
|
+ if (push_prio_exists)
|
|
push_prio = nla_get_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]);
|
|
break;
|
|
case TCA_VLAN_ACT_POP_ETH:
|
|
@@ -241,6 +243,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
|
|
p->tcfv_action = action;
|
|
p->tcfv_push_vid = push_vid;
|
|
p->tcfv_push_prio = push_prio;
|
|
+ p->tcfv_push_prio_exists = push_prio_exists || action == TCA_VLAN_ACT_PUSH;
|
|
p->tcfv_push_proto = push_proto;
|
|
|
|
if (action == TCA_VLAN_ACT_PUSH_ETH) {
|
|
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
|
|
index c4007b9cd16d6..5b274534264c2 100644
|
|
--- a/net/sched/cls_tcindex.c
|
|
+++ b/net/sched/cls_tcindex.c
|
|
@@ -304,7 +304,7 @@ static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp)
|
|
int i, err = 0;
|
|
|
|
cp->perfect = kcalloc(cp->hash, sizeof(struct tcindex_filter_result),
|
|
- GFP_KERNEL);
|
|
+ GFP_KERNEL | __GFP_NOWARN);
|
|
if (!cp->perfect)
|
|
return -ENOMEM;
|
|
|
|
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
|
|
index 6335230a971e2..ade2d6ddc9148 100644
|
|
--- a/net/sched/sch_qfq.c
|
|
+++ b/net/sched/sch_qfq.c
|
|
@@ -485,11 +485,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
|
|
|
|
if (cl->qdisc != &noop_qdisc)
|
|
qdisc_hash_add(cl->qdisc, true);
|
|
- sch_tree_lock(sch);
|
|
- qdisc_class_hash_insert(&q->clhash, &cl->common);
|
|
- sch_tree_unlock(sch);
|
|
-
|
|
- qdisc_class_hash_grow(sch, &q->clhash);
|
|
|
|
set_change_agg:
|
|
sch_tree_lock(sch);
|
|
@@ -507,8 +502,11 @@ set_change_agg:
|
|
}
|
|
if (existing)
|
|
qfq_deact_rm_from_agg(q, cl);
|
|
+ else
|
|
+ qdisc_class_hash_insert(&q->clhash, &cl->common);
|
|
qfq_add_to_agg(q, new_agg, cl);
|
|
sch_tree_unlock(sch);
|
|
+ qdisc_class_hash_grow(sch, &q->clhash);
|
|
|
|
*arg = (unsigned long)cl;
|
|
return 0;
|
|
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
|
|
index 39ed0e0afe6d9..c045f63d11fa6 100644
|
|
--- a/net/sunrpc/sched.c
|
|
+++ b/net/sunrpc/sched.c
|
|
@@ -591,11 +591,21 @@ static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *q
|
|
struct list_head *q;
|
|
struct rpc_task *task;
|
|
|
|
+ /*
|
|
+ * Service the privileged queue.
|
|
+ */
|
|
+ q = &queue->tasks[RPC_NR_PRIORITY - 1];
|
|
+ if (queue->maxpriority > RPC_PRIORITY_PRIVILEGED && !list_empty(q)) {
|
|
+ task = list_first_entry(q, struct rpc_task, u.tk_wait.list);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
/*
|
|
* Service a batch of tasks from a single owner.
|
|
*/
|
|
q = &queue->tasks[queue->priority];
|
|
- if (!list_empty(q) && --queue->nr) {
|
|
+ if (!list_empty(q) && queue->nr) {
|
|
+ queue->nr--;
|
|
task = list_first_entry(q, struct rpc_task, u.tk_wait.list);
|
|
goto out;
|
|
}
|
|
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
|
|
index d4beca895992d..593846d252143 100644
|
|
--- a/net/tipc/bcast.c
|
|
+++ b/net/tipc/bcast.c
|
|
@@ -699,7 +699,7 @@ int tipc_bcast_init(struct net *net)
|
|
spin_lock_init(&tipc_net(net)->bclock);
|
|
|
|
if (!tipc_link_bc_create(net, 0, 0, NULL,
|
|
- FB_MTU,
|
|
+ one_page_mtu,
|
|
BCLINK_WIN_DEFAULT,
|
|
BCLINK_WIN_DEFAULT,
|
|
0,
|
|
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
|
|
index 88a3ed80094cd..91dcf648d32bb 100644
|
|
--- a/net/tipc/msg.c
|
|
+++ b/net/tipc/msg.c
|
|
@@ -44,12 +44,15 @@
|
|
#define MAX_FORWARD_SIZE 1024
|
|
#ifdef CONFIG_TIPC_CRYPTO
|
|
#define BUF_HEADROOM ALIGN(((LL_MAX_HEADER + 48) + EHDR_MAX_SIZE), 16)
|
|
-#define BUF_TAILROOM (TIPC_AES_GCM_TAG_SIZE)
|
|
+#define BUF_OVERHEAD (BUF_HEADROOM + TIPC_AES_GCM_TAG_SIZE)
|
|
#else
|
|
#define BUF_HEADROOM (LL_MAX_HEADER + 48)
|
|
-#define BUF_TAILROOM 16
|
|
+#define BUF_OVERHEAD BUF_HEADROOM
|
|
#endif
|
|
|
|
+const int one_page_mtu = PAGE_SIZE - SKB_DATA_ALIGN(BUF_OVERHEAD) -
|
|
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
|
+
|
|
static unsigned int align(unsigned int i)
|
|
{
|
|
return (i + 3) & ~3u;
|
|
@@ -67,13 +70,8 @@ static unsigned int align(unsigned int i)
|
|
struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp)
|
|
{
|
|
struct sk_buff *skb;
|
|
-#ifdef CONFIG_TIPC_CRYPTO
|
|
- unsigned int buf_size = (BUF_HEADROOM + size + BUF_TAILROOM + 3) & ~3u;
|
|
-#else
|
|
- unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
|
|
-#endif
|
|
|
|
- skb = alloc_skb_fclone(buf_size, gfp);
|
|
+ skb = alloc_skb_fclone(BUF_OVERHEAD + size, gfp);
|
|
if (skb) {
|
|
skb_reserve(skb, BUF_HEADROOM);
|
|
skb_put(skb, size);
|
|
@@ -395,7 +393,8 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
|
|
if (unlikely(!skb)) {
|
|
if (pktmax != MAX_MSG_SIZE)
|
|
return -ENOMEM;
|
|
- rc = tipc_msg_build(mhdr, m, offset, dsz, FB_MTU, list);
|
|
+ rc = tipc_msg_build(mhdr, m, offset, dsz,
|
|
+ one_page_mtu, list);
|
|
if (rc != dsz)
|
|
return rc;
|
|
if (tipc_msg_assemble(list))
|
|
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
|
|
index 5d64596ba9877..64ae4c4c44f8c 100644
|
|
--- a/net/tipc/msg.h
|
|
+++ b/net/tipc/msg.h
|
|
@@ -99,9 +99,10 @@ struct plist;
|
|
#define MAX_H_SIZE 60 /* Largest possible TIPC header size */
|
|
|
|
#define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
|
|
-#define FB_MTU 3744
|
|
#define TIPC_MEDIA_INFO_OFFSET 5
|
|
|
|
+extern const int one_page_mtu;
|
|
+
|
|
struct tipc_skb_cb {
|
|
union {
|
|
struct {
|
|
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
|
|
index 3abe5257f7577..15395683b8e2a 100644
|
|
--- a/net/tls/tls_sw.c
|
|
+++ b/net/tls/tls_sw.c
|
|
@@ -1154,7 +1154,7 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page,
|
|
int ret = 0;
|
|
bool eor;
|
|
|
|
- eor = !(flags & (MSG_MORE | MSG_SENDPAGE_NOTLAST));
|
|
+ eor = !(flags & MSG_SENDPAGE_NOTLAST);
|
|
sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
|
|
|
|
/* Call the sk_stream functions to manage the sndbuf mem. */
|
|
diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h
|
|
index be9fd5a720117..3c7ce60fe9a5a 100644
|
|
--- a/net/xdp/xsk_queue.h
|
|
+++ b/net/xdp/xsk_queue.h
|
|
@@ -126,12 +126,15 @@ static inline bool xskq_cons_read_addr_unchecked(struct xsk_queue *q, u64 *addr)
|
|
static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool,
|
|
struct xdp_desc *desc)
|
|
{
|
|
- u64 chunk;
|
|
-
|
|
- if (desc->len > pool->chunk_size)
|
|
- return false;
|
|
+ u64 chunk, chunk_end;
|
|
|
|
chunk = xp_aligned_extract_addr(pool, desc->addr);
|
|
+ if (likely(desc->len)) {
|
|
+ chunk_end = xp_aligned_extract_addr(pool, desc->addr + desc->len - 1);
|
|
+ if (chunk != chunk_end)
|
|
+ return false;
|
|
+ }
|
|
+
|
|
if (chunk >= pool->addrs_cnt)
|
|
return false;
|
|
|
|
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
|
|
index 6d6917b68856f..e843b0d9e2a61 100644
|
|
--- a/net/xfrm/xfrm_device.c
|
|
+++ b/net/xfrm/xfrm_device.c
|
|
@@ -268,6 +268,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
|
|
xso->num_exthdrs = 0;
|
|
xso->flags = 0;
|
|
xso->dev = NULL;
|
|
+ xso->real_dev = NULL;
|
|
dev_put(dev);
|
|
|
|
if (err != -EOPNOTSUPP)
|
|
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
|
|
index e4cb0ff4dcf41..ac907b9d32d1e 100644
|
|
--- a/net/xfrm/xfrm_output.c
|
|
+++ b/net/xfrm/xfrm_output.c
|
|
@@ -711,15 +711,8 @@ out:
|
|
static int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb)
|
|
{
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
- unsigned int ptr = 0;
|
|
int err;
|
|
|
|
- if (x->outer_mode.encap == XFRM_MODE_BEET &&
|
|
- ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL, NULL) >= 0) {
|
|
- net_warn_ratelimited("BEET mode doesn't support inner IPv6 fragments\n");
|
|
- return -EAFNOSUPPORT;
|
|
- }
|
|
-
|
|
err = xfrm6_tunnel_check_size(skb);
|
|
if (err)
|
|
return err;
|
|
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
|
|
index 77499abd9f992..c158e70e8ae10 100644
|
|
--- a/net/xfrm/xfrm_state.c
|
|
+++ b/net/xfrm/xfrm_state.c
|
|
@@ -2516,7 +2516,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
|
|
}
|
|
EXPORT_SYMBOL(xfrm_state_delete_tunnel);
|
|
|
|
-u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
|
|
+u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu)
|
|
{
|
|
const struct xfrm_type *type = READ_ONCE(x->type);
|
|
struct crypto_aead *aead;
|
|
@@ -2547,7 +2547,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
|
|
return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
|
|
net_adj) & ~(blksize - 1)) + net_adj - 2;
|
|
}
|
|
-EXPORT_SYMBOL_GPL(xfrm_state_mtu);
|
|
+EXPORT_SYMBOL_GPL(__xfrm_state_mtu);
|
|
+
|
|
+u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
|
|
+{
|
|
+ mtu = __xfrm_state_mtu(x, mtu);
|
|
+
|
|
+ if (x->props.family == AF_INET6 && mtu < IPV6_MIN_MTU)
|
|
+ return IPV6_MIN_MTU;
|
|
+
|
|
+ return mtu;
|
|
+}
|
|
|
|
int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
|
|
{
|
|
diff --git a/samples/bpf/xdp_redirect_user.c b/samples/bpf/xdp_redirect_user.c
|
|
index 9ca2bf457cdae..3c92adc2a7bd0 100644
|
|
--- a/samples/bpf/xdp_redirect_user.c
|
|
+++ b/samples/bpf/xdp_redirect_user.c
|
|
@@ -131,7 +131,7 @@ int main(int argc, char **argv)
|
|
if (!(xdp_flags & XDP_FLAGS_SKB_MODE))
|
|
xdp_flags |= XDP_FLAGS_DRV_MODE;
|
|
|
|
- if (optind == argc) {
|
|
+ if (optind + 2 != argc) {
|
|
printf("usage: %s <IFNAME|IFINDEX>_IN <IFNAME|IFINDEX>_OUT\n", argv[0]);
|
|
return 1;
|
|
}
|
|
@@ -219,5 +219,5 @@ int main(int argc, char **argv)
|
|
poll_stats(2, ifindex_out);
|
|
|
|
out:
|
|
- return 0;
|
|
+ return ret;
|
|
}
|
|
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
|
|
index 4c058f12dd73c..8bd4e673383f3 100644
|
|
--- a/scripts/Makefile.build
|
|
+++ b/scripts/Makefile.build
|
|
@@ -275,7 +275,8 @@ define rule_as_o_S
|
|
endef
|
|
|
|
# Built-in and composite module parts
|
|
-$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE
|
|
+.SECONDEXPANSION:
|
|
+$(obj)/%.o: $(src)/%.c $(recordmcount_source) $$(objtool_dep) FORCE
|
|
$(call if_changed_rule,cc_o_c)
|
|
$(call cmd,force_checksrc)
|
|
|
|
@@ -356,7 +357,7 @@ cmd_modversions_S = \
|
|
fi
|
|
endif
|
|
|
|
-$(obj)/%.o: $(src)/%.S $(objtool_dep) FORCE
|
|
+$(obj)/%.o: $(src)/%.S $$(objtool_dep) FORCE
|
|
$(call if_changed_rule,as_o_S)
|
|
|
|
targets += $(filter-out $(subdir-builtin), $(real-obj-y))
|
|
diff --git a/scripts/tools-support-relr.sh b/scripts/tools-support-relr.sh
|
|
index 45e8aa360b457..cb55878bd5b81 100755
|
|
--- a/scripts/tools-support-relr.sh
|
|
+++ b/scripts/tools-support-relr.sh
|
|
@@ -7,7 +7,8 @@ trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT
|
|
cat << "END" | $CC -c -x c - -o $tmp_file.o >/dev/null 2>&1
|
|
void *p = &p;
|
|
END
|
|
-$LD $tmp_file.o -shared -Bsymbolic --pack-dyn-relocs=relr -o $tmp_file
|
|
+$LD $tmp_file.o -shared -Bsymbolic --pack-dyn-relocs=relr \
|
|
+ --use-android-relr-tags -o $tmp_file
|
|
|
|
# Despite printing an error message, GNU nm still exits with exit code 0 if it
|
|
# sees a relr section. So we need to check that nothing is printed to stderr.
|
|
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
|
|
index 76d19146d74bc..f1ca3cac9b861 100644
|
|
--- a/security/integrity/evm/evm_main.c
|
|
+++ b/security/integrity/evm/evm_main.c
|
|
@@ -521,7 +521,7 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
|
|
}
|
|
|
|
/*
|
|
- * evm_inode_init_security - initializes security.evm
|
|
+ * evm_inode_init_security - initializes security.evm HMAC value
|
|
*/
|
|
int evm_inode_init_security(struct inode *inode,
|
|
const struct xattr *lsm_xattr,
|
|
@@ -530,7 +530,8 @@ int evm_inode_init_security(struct inode *inode,
|
|
struct evm_xattr *xattr_data;
|
|
int rc;
|
|
|
|
- if (!evm_key_loaded() || !evm_protected_xattr(lsm_xattr->name))
|
|
+ if (!(evm_initialized & EVM_INIT_HMAC) ||
|
|
+ !evm_protected_xattr(lsm_xattr->name))
|
|
return 0;
|
|
|
|
xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
|
|
diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c
|
|
index cfc3075769bb0..bc10c945f3ed5 100644
|
|
--- a/security/integrity/evm/evm_secfs.c
|
|
+++ b/security/integrity/evm/evm_secfs.c
|
|
@@ -66,12 +66,13 @@ static ssize_t evm_read_key(struct file *filp, char __user *buf,
|
|
static ssize_t evm_write_key(struct file *file, const char __user *buf,
|
|
size_t count, loff_t *ppos)
|
|
{
|
|
- int i, ret;
|
|
+ unsigned int i;
|
|
+ int ret;
|
|
|
|
if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP_COMPLETE))
|
|
return -EPERM;
|
|
|
|
- ret = kstrtoint_from_user(buf, count, 0, &i);
|
|
+ ret = kstrtouint_from_user(buf, count, 0, &i);
|
|
|
|
if (ret)
|
|
return ret;
|
|
@@ -80,12 +81,12 @@ static ssize_t evm_write_key(struct file *file, const char __user *buf,
|
|
if (!i || (i & ~EVM_INIT_MASK) != 0)
|
|
return -EINVAL;
|
|
|
|
- /* Don't allow a request to freshly enable metadata writes if
|
|
- * keys are loaded.
|
|
+ /*
|
|
+ * Don't allow a request to enable metadata writes if
|
|
+ * an HMAC key is loaded.
|
|
*/
|
|
if ((i & EVM_ALLOW_METADATA_WRITES) &&
|
|
- ((evm_initialized & EVM_KEY_MASK) != 0) &&
|
|
- !(evm_initialized & EVM_ALLOW_METADATA_WRITES))
|
|
+ (evm_initialized & EVM_INIT_HMAC) != 0)
|
|
return -EPERM;
|
|
|
|
if (i & EVM_INIT_HMAC) {
|
|
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
|
|
index 5805c5de39fbf..7a282d8e71485 100644
|
|
--- a/sound/firewire/amdtp-stream.c
|
|
+++ b/sound/firewire/amdtp-stream.c
|
|
@@ -1404,14 +1404,17 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle)
|
|
unsigned int queue_size;
|
|
struct amdtp_stream *s;
|
|
int cycle;
|
|
+ bool found = false;
|
|
int err;
|
|
|
|
// Select an IT context as IRQ target.
|
|
list_for_each_entry(s, &d->streams, list) {
|
|
- if (s->direction == AMDTP_OUT_STREAM)
|
|
+ if (s->direction == AMDTP_OUT_STREAM) {
|
|
+ found = true;
|
|
break;
|
|
+ }
|
|
}
|
|
- if (!s)
|
|
+ if (!found)
|
|
return -ENXIO;
|
|
d->irq_target = s;
|
|
|
|
diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c
|
|
index e59e69ab1538b..784073aa10265 100644
|
|
--- a/sound/firewire/motu/motu-protocol-v2.c
|
|
+++ b/sound/firewire/motu/motu-protocol-v2.c
|
|
@@ -353,6 +353,7 @@ const struct snd_motu_spec snd_motu_spec_8pre = {
|
|
.protocol_version = SND_MOTU_PROTOCOL_V2,
|
|
.flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q |
|
|
SND_MOTU_SPEC_TX_MIDI_2ND_Q,
|
|
- .tx_fixed_pcm_chunks = {10, 6, 0},
|
|
- .rx_fixed_pcm_chunks = {10, 6, 0},
|
|
+ // Two dummy chunks always in the end of data block.
|
|
+ .tx_fixed_pcm_chunks = {10, 10, 0},
|
|
+ .rx_fixed_pcm_chunks = {6, 6, 0},
|
|
};
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index e46e43dac6bfd..1cc83344c2ecf 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -385,6 +385,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
|
alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
|
|
fallthrough;
|
|
case 0x10ec0215:
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0233:
|
|
case 0x10ec0235:
|
|
case 0x10ec0236:
|
|
@@ -3153,6 +3154,7 @@ static void alc_disable_headset_jack_key(struct hda_codec *codec)
|
|
alc_update_coef_idx(codec, 0x49, 0x0045, 0x0);
|
|
alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_write_coef_idx(codec, 0x48, 0x0);
|
|
@@ -3180,6 +3182,7 @@ static void alc_enable_headset_jack_key(struct hda_codec *codec)
|
|
alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
|
|
alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_write_coef_idx(codec, 0x48, 0xd011);
|
|
@@ -4737,6 +4740,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
|
|
case 0x10ec0255:
|
|
alc_process_coef_fw(codec, coef0255);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_process_coef_fw(codec, coef0256);
|
|
@@ -4851,6 +4855,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
|
|
alc_process_coef_fw(codec, coef0255);
|
|
snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_write_coef_idx(codec, 0x45, 0xc489);
|
|
@@ -5000,6 +5005,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
|
|
case 0x10ec0255:
|
|
alc_process_coef_fw(codec, coef0255);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_write_coef_idx(codec, 0x1b, 0x0e4b);
|
|
@@ -5098,6 +5104,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
|
|
case 0x10ec0255:
|
|
alc_process_coef_fw(codec, coef0255);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_process_coef_fw(codec, coef0256);
|
|
@@ -5211,6 +5218,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
|
|
case 0x10ec0255:
|
|
alc_process_coef_fw(codec, coef0255);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_process_coef_fw(codec, coef0256);
|
|
@@ -5311,6 +5319,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
|
|
val = alc_read_coef_idx(codec, 0x46);
|
|
is_ctia = (val & 0x0070) == 0x0070;
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_write_coef_idx(codec, 0x1b, 0x0e4b);
|
|
@@ -5604,6 +5613,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
|
|
case 0x10ec0255:
|
|
alc_process_coef_fw(codec, alc255fw);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
alc_process_coef_fw(codec, alc256fw);
|
|
@@ -6204,6 +6214,7 @@ static void alc_combo_jack_hp_jd_restart(struct hda_codec *codec)
|
|
alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */
|
|
alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15);
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0235:
|
|
case 0x10ec0236:
|
|
case 0x10ec0255:
|
|
@@ -6336,6 +6347,24 @@ static void alc_fixup_no_int_mic(struct hda_codec *codec,
|
|
}
|
|
}
|
|
|
|
+static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec,
|
|
+ const struct hda_fixup *fix, int action)
|
|
+{
|
|
+ static const hda_nid_t conn[] = { 0x02 };
|
|
+ static const struct hda_pintbl pincfgs[] = {
|
|
+ { 0x14, 0x90170110 }, /* rear speaker */
|
|
+ { }
|
|
+ };
|
|
+
|
|
+ switch (action) {
|
|
+ case HDA_FIXUP_ACT_PRE_PROBE:
|
|
+ snd_hda_apply_pincfgs(codec, pincfgs);
|
|
+ /* force front speaker to DAC1 */
|
|
+ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
/* for hda_fixup_thinkpad_acpi() */
|
|
#include "thinkpad_helper.c"
|
|
|
|
@@ -7802,6 +7831,8 @@ static const struct hda_fixup alc269_fixups[] = {
|
|
{ 0x20, AC_VERB_SET_PROC_COEF, 0x4e4b },
|
|
{ }
|
|
},
|
|
+ .chained = true,
|
|
+ .chain_id = ALC289_FIXUP_ASUS_GA401,
|
|
},
|
|
[ALC285_FIXUP_HP_GPIO_LED] = {
|
|
.type = HDA_FIXUP_FUNC,
|
|
@@ -8113,13 +8144,8 @@ static const struct hda_fixup alc269_fixups[] = {
|
|
.chain_id = ALC269_FIXUP_HP_LINE1_MIC1_LED,
|
|
},
|
|
[ALC285_FIXUP_HP_SPECTRE_X360] = {
|
|
- .type = HDA_FIXUP_PINS,
|
|
- .v.pins = (const struct hda_pintbl[]) {
|
|
- { 0x14, 0x90170110 }, /* enable top speaker */
|
|
- {}
|
|
- },
|
|
- .chained = true,
|
|
- .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1,
|
|
+ .type = HDA_FIXUP_FUNC,
|
|
+ .v.func = alc285_fixup_hp_spectre_x360,
|
|
},
|
|
[ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP] = {
|
|
.type = HDA_FIXUP_FUNC,
|
|
@@ -8305,6 +8331,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
|
|
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
|
|
SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
|
|
+ SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
|
SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
|
|
SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
|
@@ -8322,13 +8349,19 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
|
SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x87f1, "HP ProBook 630 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x87f2, "HP ProBook 640 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
|
|
+ SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
|
SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
|
|
+ SND_PCI_QUIRK(0x103c, 0x8862, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
|
+ SND_PCI_QUIRK(0x103c, 0x8863, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
|
|
SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
|
SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
|
SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
|
|
@@ -9326,6 +9359,7 @@ static int patch_alc269(struct hda_codec *codec)
|
|
spec->shutup = alc256_shutup;
|
|
spec->init_hook = alc256_init;
|
|
break;
|
|
+ case 0x10ec0230:
|
|
case 0x10ec0236:
|
|
case 0x10ec0256:
|
|
spec->codec_variant = ALC269_TYPE_ALC256;
|
|
@@ -10617,6 +10651,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
|
|
HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269),
|
|
HDA_CODEC_ENTRY(0x10ec0222, "ALC222", patch_alc269),
|
|
HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
|
|
+ HDA_CODEC_ENTRY(0x10ec0230, "ALC236", patch_alc269),
|
|
HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
|
|
HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
|
|
HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269),
|
|
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
|
|
index 6fb6f36d0d377..3707dc27324d2 100644
|
|
--- a/sound/pci/intel8x0.c
|
|
+++ b/sound/pci/intel8x0.c
|
|
@@ -715,7 +715,7 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich
|
|
int status, civ, i, step;
|
|
int ack = 0;
|
|
|
|
- if (!ichdev->prepared || ichdev->suspended)
|
|
+ if (!(ichdev->prepared || chip->in_measurement) || ichdev->suspended)
|
|
return;
|
|
|
|
spin_lock_irqsave(&chip->reg_lock, flags);
|
|
diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c
|
|
index bbe2b638abb58..d870f56c44cfc 100644
|
|
--- a/sound/soc/atmel/atmel-i2s.c
|
|
+++ b/sound/soc/atmel/atmel-i2s.c
|
|
@@ -200,6 +200,7 @@ struct atmel_i2s_dev {
|
|
unsigned int fmt;
|
|
const struct atmel_i2s_gck_param *gck_param;
|
|
const struct atmel_i2s_caps *caps;
|
|
+ int clk_use_no;
|
|
};
|
|
|
|
static irqreturn_t atmel_i2s_interrupt(int irq, void *dev_id)
|
|
@@ -321,9 +322,16 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
|
|
{
|
|
struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
|
|
bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
|
|
- unsigned int mr = 0;
|
|
+ unsigned int mr = 0, mr_mask;
|
|
int ret;
|
|
|
|
+ mr_mask = ATMEL_I2SC_MR_FORMAT_MASK | ATMEL_I2SC_MR_MODE_MASK |
|
|
+ ATMEL_I2SC_MR_DATALENGTH_MASK;
|
|
+ if (is_playback)
|
|
+ mr_mask |= ATMEL_I2SC_MR_TXMONO;
|
|
+ else
|
|
+ mr_mask |= ATMEL_I2SC_MR_RXMONO;
|
|
+
|
|
switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
|
case SND_SOC_DAIFMT_I2S:
|
|
mr |= ATMEL_I2SC_MR_FORMAT_I2S;
|
|
@@ -402,7 +410,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- return regmap_write(dev->regmap, ATMEL_I2SC_MR, mr);
|
|
+ return regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr);
|
|
}
|
|
|
|
static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev,
|
|
@@ -495,18 +503,28 @@ static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
|
|
is_master = (mr & ATMEL_I2SC_MR_MODE_MASK) == ATMEL_I2SC_MR_MODE_MASTER;
|
|
|
|
/* If master starts, enable the audio clock. */
|
|
- if (is_master && mck_enabled)
|
|
- err = atmel_i2s_switch_mck_generator(dev, true);
|
|
- if (err)
|
|
- return err;
|
|
+ if (is_master && mck_enabled) {
|
|
+ if (!dev->clk_use_no) {
|
|
+ err = atmel_i2s_switch_mck_generator(dev, true);
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
+ dev->clk_use_no++;
|
|
+ }
|
|
|
|
err = regmap_write(dev->regmap, ATMEL_I2SC_CR, cr);
|
|
if (err)
|
|
return err;
|
|
|
|
/* If master stops, disable the audio clock. */
|
|
- if (is_master && !mck_enabled)
|
|
- err = atmel_i2s_switch_mck_generator(dev, false);
|
|
+ if (is_master && !mck_enabled) {
|
|
+ if (dev->clk_use_no == 1) {
|
|
+ err = atmel_i2s_switch_mck_generator(dev, false);
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
+ dev->clk_use_no--;
|
|
+ }
|
|
|
|
return err;
|
|
}
|
|
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
|
|
index 866d7c873e3c9..ca2019732013e 100644
|
|
--- a/sound/soc/codecs/cs42l42.h
|
|
+++ b/sound/soc/codecs/cs42l42.h
|
|
@@ -77,7 +77,7 @@
|
|
#define CS42L42_HP_PDN_SHIFT 3
|
|
#define CS42L42_HP_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT)
|
|
#define CS42L42_ADC_PDN_SHIFT 2
|
|
-#define CS42L42_ADC_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT)
|
|
+#define CS42L42_ADC_PDN_MASK (1 << CS42L42_ADC_PDN_SHIFT)
|
|
#define CS42L42_PDN_ALL_SHIFT 0
|
|
#define CS42L42_PDN_ALL_MASK (1 << CS42L42_PDN_ALL_SHIFT)
|
|
|
|
diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c
|
|
index 14fd2f9a0bf3a..39afa011f0e27 100644
|
|
--- a/sound/soc/codecs/max98373-sdw.c
|
|
+++ b/sound/soc/codecs/max98373-sdw.c
|
|
@@ -258,7 +258,7 @@ static __maybe_unused int max98373_resume(struct device *dev)
|
|
struct max98373_priv *max98373 = dev_get_drvdata(dev);
|
|
unsigned long time;
|
|
|
|
- if (!max98373->hw_init)
|
|
+ if (!max98373->first_hw_init)
|
|
return 0;
|
|
|
|
if (!slave->unattach_request)
|
|
@@ -349,7 +349,7 @@ static int max98373_io_init(struct sdw_slave *slave)
|
|
struct device *dev = &slave->dev;
|
|
struct max98373_priv *max98373 = dev_get_drvdata(dev);
|
|
|
|
- if (max98373->pm_init_once) {
|
|
+ if (max98373->first_hw_init) {
|
|
regcache_cache_only(max98373->regmap, false);
|
|
regcache_cache_bypass(max98373->regmap, true);
|
|
}
|
|
@@ -357,7 +357,7 @@ static int max98373_io_init(struct sdw_slave *slave)
|
|
/*
|
|
* PM runtime is only enabled when a Slave reports as Attached
|
|
*/
|
|
- if (!max98373->pm_init_once) {
|
|
+ if (!max98373->first_hw_init) {
|
|
/* set autosuspend parameters */
|
|
pm_runtime_set_autosuspend_delay(dev, 3000);
|
|
pm_runtime_use_autosuspend(dev);
|
|
@@ -449,12 +449,12 @@ static int max98373_io_init(struct sdw_slave *slave)
|
|
regmap_write(max98373->regmap, MAX98373_R20B5_BDE_EN, 1);
|
|
regmap_write(max98373->regmap, MAX98373_R20E2_LIMITER_EN, 1);
|
|
|
|
- if (max98373->pm_init_once) {
|
|
+ if (max98373->first_hw_init) {
|
|
regcache_cache_bypass(max98373->regmap, false);
|
|
regcache_mark_dirty(max98373->regmap);
|
|
}
|
|
|
|
- max98373->pm_init_once = true;
|
|
+ max98373->first_hw_init = true;
|
|
max98373->hw_init = true;
|
|
|
|
pm_runtime_mark_last_busy(dev);
|
|
@@ -773,7 +773,7 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap)
|
|
max98373_slot_config(dev, max98373);
|
|
|
|
max98373->hw_init = false;
|
|
- max98373->pm_init_once = false;
|
|
+ max98373->first_hw_init = false;
|
|
|
|
/* codec registration */
|
|
ret = devm_snd_soc_register_component(dev, &soc_codec_dev_max98373_sdw,
|
|
diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h
|
|
index 4ab29b9d51c74..010f6bb21e9a1 100644
|
|
--- a/sound/soc/codecs/max98373.h
|
|
+++ b/sound/soc/codecs/max98373.h
|
|
@@ -215,7 +215,7 @@ struct max98373_priv {
|
|
/* variables to support soundwire */
|
|
struct sdw_slave *slave;
|
|
bool hw_init;
|
|
- bool pm_init_once;
|
|
+ bool first_hw_init;
|
|
int slot;
|
|
unsigned int rx_mask;
|
|
};
|
|
diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c
|
|
index 940a2fa933edb..aed18cbb9f68e 100644
|
|
--- a/sound/soc/codecs/rk3328_codec.c
|
|
+++ b/sound/soc/codecs/rk3328_codec.c
|
|
@@ -474,7 +474,8 @@ static int rk3328_platform_probe(struct platform_device *pdev)
|
|
rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
|
|
if (IS_ERR(rk3328->pclk)) {
|
|
dev_err(&pdev->dev, "can't get acodec pclk\n");
|
|
- return PTR_ERR(rk3328->pclk);
|
|
+ ret = PTR_ERR(rk3328->pclk);
|
|
+ goto err_unprepare_mclk;
|
|
}
|
|
|
|
ret = clk_prepare_enable(rk3328->pclk);
|
|
@@ -484,19 +485,34 @@ static int rk3328_platform_probe(struct platform_device *pdev)
|
|
}
|
|
|
|
base = devm_platform_ioremap_resource(pdev, 0);
|
|
- if (IS_ERR(base))
|
|
- return PTR_ERR(base);
|
|
+ if (IS_ERR(base)) {
|
|
+ ret = PTR_ERR(base);
|
|
+ goto err_unprepare_pclk;
|
|
+ }
|
|
|
|
rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
|
|
&rk3328_codec_regmap_config);
|
|
- if (IS_ERR(rk3328->regmap))
|
|
- return PTR_ERR(rk3328->regmap);
|
|
+ if (IS_ERR(rk3328->regmap)) {
|
|
+ ret = PTR_ERR(rk3328->regmap);
|
|
+ goto err_unprepare_pclk;
|
|
+ }
|
|
|
|
platform_set_drvdata(pdev, rk3328);
|
|
|
|
- return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
|
|
+ ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
|
|
rk3328_dai,
|
|
ARRAY_SIZE(rk3328_dai));
|
|
+ if (ret)
|
|
+ goto err_unprepare_pclk;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_unprepare_pclk:
|
|
+ clk_disable_unprepare(rk3328->pclk);
|
|
+
|
|
+err_unprepare_mclk:
|
|
+ clk_disable_unprepare(rk3328->mclk);
|
|
+ return ret;
|
|
}
|
|
|
|
static const struct of_device_id rk3328_codec_of_match[] = {
|
|
diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c
|
|
index c2621b0afe6c1..31daa749c3db4 100644
|
|
--- a/sound/soc/codecs/rt1308-sdw.c
|
|
+++ b/sound/soc/codecs/rt1308-sdw.c
|
|
@@ -709,7 +709,7 @@ static int __maybe_unused rt1308_dev_resume(struct device *dev)
|
|
struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev);
|
|
unsigned long time;
|
|
|
|
- if (!rt1308->hw_init)
|
|
+ if (!rt1308->first_hw_init)
|
|
return 0;
|
|
|
|
if (!slave->unattach_request)
|
|
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c
|
|
index 7e652843c57d9..547445d1e3c69 100644
|
|
--- a/sound/soc/codecs/rt5682-i2c.c
|
|
+++ b/sound/soc/codecs/rt5682-i2c.c
|
|
@@ -268,6 +268,7 @@ static void rt5682_i2c_shutdown(struct i2c_client *client)
|
|
{
|
|
struct rt5682_priv *rt5682 = i2c_get_clientdata(client);
|
|
|
|
+ disable_irq(client->irq);
|
|
cancel_delayed_work_sync(&rt5682->jack_detect_work);
|
|
cancel_delayed_work_sync(&rt5682->jd_check_work);
|
|
|
|
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
|
|
index aa6c325faeab2..c9868dd096fcd 100644
|
|
--- a/sound/soc/codecs/rt5682-sdw.c
|
|
+++ b/sound/soc/codecs/rt5682-sdw.c
|
|
@@ -375,18 +375,12 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap,
|
|
static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
|
|
{
|
|
struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
|
|
- int ret = 0;
|
|
+ int ret = 0, loop = 10;
|
|
unsigned int val;
|
|
|
|
if (rt5682->hw_init)
|
|
return 0;
|
|
|
|
- regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
|
|
- if (val != DEVICE_ID) {
|
|
- dev_err(dev, "Device with ID register %x is not rt5682\n", val);
|
|
- return -ENODEV;
|
|
- }
|
|
-
|
|
/*
|
|
* PM runtime is only enabled when a Slave reports as Attached
|
|
*/
|
|
@@ -411,6 +405,19 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave)
|
|
regcache_cache_bypass(rt5682->regmap, true);
|
|
}
|
|
|
|
+ while (loop > 0) {
|
|
+ regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val);
|
|
+ if (val == DEVICE_ID)
|
|
+ break;
|
|
+ dev_warn(dev, "Device with ID register %x is not rt5682\n", val);
|
|
+ usleep_range(30000, 30005);
|
|
+ loop--;
|
|
+ }
|
|
+ if (val != DEVICE_ID) {
|
|
+ dev_err(dev, "Device with ID register %x is not rt5682\n", val);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
rt5682_calibrate(rt5682);
|
|
|
|
if (rt5682->first_hw_init) {
|
|
@@ -734,7 +741,7 @@ static int __maybe_unused rt5682_dev_resume(struct device *dev)
|
|
struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
|
|
unsigned long time;
|
|
|
|
- if (!rt5682->hw_init)
|
|
+ if (!rt5682->first_hw_init)
|
|
return 0;
|
|
|
|
if (!slave->unattach_request)
|
|
diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c
|
|
index fb77e77a4ebd5..3a1db79030d71 100644
|
|
--- a/sound/soc/codecs/rt700-sdw.c
|
|
+++ b/sound/soc/codecs/rt700-sdw.c
|
|
@@ -498,7 +498,7 @@ static int __maybe_unused rt700_dev_resume(struct device *dev)
|
|
struct rt700_priv *rt700 = dev_get_drvdata(dev);
|
|
unsigned long time;
|
|
|
|
- if (!rt700->hw_init)
|
|
+ if (!rt700->first_hw_init)
|
|
return 0;
|
|
|
|
if (!slave->unattach_request)
|
|
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
|
|
index f0a0691bd31cc..eb54e90c1c604 100644
|
|
--- a/sound/soc/codecs/rt711-sdw.c
|
|
+++ b/sound/soc/codecs/rt711-sdw.c
|
|
@@ -500,7 +500,7 @@ static int __maybe_unused rt711_dev_resume(struct device *dev)
|
|
struct rt711_priv *rt711 = dev_get_drvdata(dev);
|
|
unsigned long time;
|
|
|
|
- if (!rt711->hw_init)
|
|
+ if (!rt711->first_hw_init)
|
|
return 0;
|
|
|
|
if (!slave->unattach_request)
|
|
diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c
|
|
index 8f0aa1e8a2737..361a90ae594cd 100644
|
|
--- a/sound/soc/codecs/rt715-sdw.c
|
|
+++ b/sound/soc/codecs/rt715-sdw.c
|
|
@@ -541,7 +541,7 @@ static int __maybe_unused rt715_dev_resume(struct device *dev)
|
|
struct rt715_priv *rt715 = dev_get_drvdata(dev);
|
|
unsigned long time;
|
|
|
|
- if (!rt715->hw_init)
|
|
+ if (!rt715->first_hw_init)
|
|
return 0;
|
|
|
|
if (!slave->unattach_request)
|
|
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
|
|
index b0f643fefe1e8..15bcb0f38ec9e 100644
|
|
--- a/sound/soc/fsl/fsl_spdif.c
|
|
+++ b/sound/soc/fsl/fsl_spdif.c
|
|
@@ -1358,14 +1358,27 @@ static int fsl_spdif_probe(struct platform_device *pdev)
|
|
&spdif_priv->cpu_dai_drv, 1);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
|
|
- return ret;
|
|
+ goto err_pm_disable;
|
|
}
|
|
|
|
ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE);
|
|
- if (ret && ret != -EPROBE_DEFER)
|
|
- dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
|
|
+ if (ret) {
|
|
+ dev_err_probe(&pdev->dev, ret, "imx_pcm_dma_init failed\n");
|
|
+ goto err_pm_disable;
|
|
+ }
|
|
|
|
return ret;
|
|
+
|
|
+err_pm_disable:
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int fsl_spdif_remove(struct platform_device *pdev)
|
|
+{
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_PM
|
|
@@ -1374,6 +1387,9 @@ static int fsl_spdif_runtime_suspend(struct device *dev)
|
|
struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev);
|
|
int i;
|
|
|
|
+ /* Disable all the interrupts */
|
|
+ regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SIE, 0xffffff, 0);
|
|
+
|
|
regmap_read(spdif_priv->regmap, REG_SPDIF_SRPC,
|
|
&spdif_priv->regcache_srpc);
|
|
regcache_cache_only(spdif_priv->regmap, true);
|
|
@@ -1469,6 +1485,7 @@ static struct platform_driver fsl_spdif_driver = {
|
|
.pm = &fsl_spdif_pm,
|
|
},
|
|
.probe = fsl_spdif_probe,
|
|
+ .remove = fsl_spdif_remove,
|
|
};
|
|
|
|
module_platform_driver(fsl_spdif_driver);
|
|
diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c
|
|
index 907f5f1f7b445..ff05b9779e4be 100644
|
|
--- a/sound/soc/hisilicon/hi6210-i2s.c
|
|
+++ b/sound/soc/hisilicon/hi6210-i2s.c
|
|
@@ -102,18 +102,15 @@ static int hi6210_i2s_startup(struct snd_pcm_substream *substream,
|
|
|
|
for (n = 0; n < i2s->clocks; n++) {
|
|
ret = clk_prepare_enable(i2s->clk[n]);
|
|
- if (ret) {
|
|
- while (n--)
|
|
- clk_disable_unprepare(i2s->clk[n]);
|
|
- return ret;
|
|
- }
|
|
+ if (ret)
|
|
+ goto err_unprepare_clk;
|
|
}
|
|
|
|
ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000);
|
|
if (ret) {
|
|
dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n",
|
|
__func__, ret);
|
|
- return ret;
|
|
+ goto err_unprepare_clk;
|
|
}
|
|
|
|
/* enable clock before frequency division */
|
|
@@ -165,6 +162,11 @@ static int hi6210_i2s_startup(struct snd_pcm_substream *substream,
|
|
hi6210_write_reg(i2s, HII2S_SW_RST_N, val);
|
|
|
|
return 0;
|
|
+
|
|
+err_unprepare_clk:
|
|
+ while (n--)
|
|
+ clk_disable_unprepare(i2s->clk[n]);
|
|
+ return ret;
|
|
}
|
|
|
|
static void hi6210_i2s_shutdown(struct snd_pcm_substream *substream,
|
|
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
|
|
index 9dc982c2c7760..75a0bfedb4493 100644
|
|
--- a/sound/soc/intel/boards/sof_sdw.c
|
|
+++ b/sound/soc/intel/boards/sof_sdw.c
|
|
@@ -196,6 +196,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|
},
|
|
.driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
|
|
SOF_SDW_TGL_HDMI |
|
|
+ SOF_RT715_DAI_ID_FIX |
|
|
SOF_SDW_PCH_DMIC),
|
|
},
|
|
{}
|
|
diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c
|
|
index 668fef3e319a0..86e982e3209ed 100644
|
|
--- a/sound/soc/mediatek/common/mtk-btcvsd.c
|
|
+++ b/sound/soc/mediatek/common/mtk-btcvsd.c
|
|
@@ -1281,7 +1281,7 @@ static const struct snd_soc_component_driver mtk_btcvsd_snd_platform = {
|
|
|
|
static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
|
|
{
|
|
- int ret = 0;
|
|
+ int ret;
|
|
int irq_id;
|
|
u32 offset[5] = {0, 0, 0, 0, 0};
|
|
struct mtk_btcvsd_snd *btcvsd;
|
|
@@ -1337,7 +1337,8 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
|
|
btcvsd->bt_sram_bank2_base = of_iomap(dev->of_node, 1);
|
|
if (!btcvsd->bt_sram_bank2_base) {
|
|
dev_err(dev, "iomap bt_sram_bank2_base fail\n");
|
|
- return -EIO;
|
|
+ ret = -EIO;
|
|
+ goto unmap_pkv_err;
|
|
}
|
|
|
|
btcvsd->infra = syscon_regmap_lookup_by_phandle(dev->of_node,
|
|
@@ -1345,7 +1346,8 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
|
|
if (IS_ERR(btcvsd->infra)) {
|
|
dev_err(dev, "cannot find infra controller: %ld\n",
|
|
PTR_ERR(btcvsd->infra));
|
|
- return PTR_ERR(btcvsd->infra);
|
|
+ ret = PTR_ERR(btcvsd->infra);
|
|
+ goto unmap_bank2_err;
|
|
}
|
|
|
|
/* get offset */
|
|
@@ -1354,7 +1356,7 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
|
|
ARRAY_SIZE(offset));
|
|
if (ret) {
|
|
dev_warn(dev, "%s(), get offset fail, ret %d\n", __func__, ret);
|
|
- return ret;
|
|
+ goto unmap_bank2_err;
|
|
}
|
|
btcvsd->infra_misc_offset = offset[0];
|
|
btcvsd->conn_bt_cvsd_mask = offset[1];
|
|
@@ -1373,8 +1375,18 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev)
|
|
mtk_btcvsd_snd_set_state(btcvsd, btcvsd->tx, BT_SCO_STATE_IDLE);
|
|
mtk_btcvsd_snd_set_state(btcvsd, btcvsd->rx, BT_SCO_STATE_IDLE);
|
|
|
|
- return devm_snd_soc_register_component(dev, &mtk_btcvsd_snd_platform,
|
|
- NULL, 0);
|
|
+ ret = devm_snd_soc_register_component(dev, &mtk_btcvsd_snd_platform,
|
|
+ NULL, 0);
|
|
+ if (ret)
|
|
+ goto unmap_bank2_err;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+unmap_bank2_err:
|
|
+ iounmap(btcvsd->bt_sram_bank2_base);
|
|
+unmap_pkv_err:
|
|
+ iounmap(btcvsd->bt_pkv_base);
|
|
+ return ret;
|
|
}
|
|
|
|
static int mtk_btcvsd_snd_remove(struct platform_device *pdev)
|
|
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
|
|
index b9aacf3d3b29c..7532ab27a48df 100644
|
|
--- a/sound/soc/sh/rcar/adg.c
|
|
+++ b/sound/soc/sh/rcar/adg.c
|
|
@@ -289,7 +289,6 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val)
|
|
int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
|
|
{
|
|
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
|
|
- struct clk *clk;
|
|
int i;
|
|
int sel_table[] = {
|
|
[CLKA] = 0x1,
|
|
@@ -302,10 +301,9 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
|
|
* find suitable clock from
|
|
* AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
|
|
*/
|
|
- for_each_rsnd_clk(clk, adg, i) {
|
|
+ for (i = 0; i < CLKMAX; i++)
|
|
if (rate == adg->clk_rate[i])
|
|
return sel_table[i];
|
|
- }
|
|
|
|
/*
|
|
* find divided clock from BRGA/BRGB
|
|
diff --git a/sound/usb/format.c b/sound/usb/format.c
|
|
index 91f0ed4a2e7eb..5c5b76c611480 100644
|
|
--- a/sound/usb/format.c
|
|
+++ b/sound/usb/format.c
|
|
@@ -208,9 +208,11 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
|
|
continue;
|
|
/* C-Media CM6501 mislabels its 96 kHz altsetting */
|
|
/* Terratec Aureon 7.1 USB C-Media 6206, too */
|
|
+ /* Ozone Z90 USB C-Media, too */
|
|
if (rate == 48000 && nr_rates == 1 &&
|
|
(chip->usb_id == USB_ID(0x0d8c, 0x0201) ||
|
|
chip->usb_id == USB_ID(0x0d8c, 0x0102) ||
|
|
+ chip->usb_id == USB_ID(0x0d8c, 0x0078) ||
|
|
chip->usb_id == USB_ID(0x0ccd, 0x00b1)) &&
|
|
fp->altsetting == 5 && fp->maxpacksize == 392)
|
|
rate = 96000;
|
|
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
|
|
index 375cfb9c9ab7e..8e11582fbae98 100644
|
|
--- a/sound/usb/mixer.c
|
|
+++ b/sound/usb/mixer.c
|
|
@@ -3273,8 +3273,9 @@ static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
|
|
struct usb_mixer_elem_list *list)
|
|
{
|
|
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
|
|
- static const char * const val_types[] = {"BOOLEAN", "INV_BOOLEAN",
|
|
- "S8", "U8", "S16", "U16"};
|
|
+ static const char * const val_types[] = {
|
|
+ "BOOLEAN", "INV_BOOLEAN", "S8", "U8", "S16", "U16", "S32", "U32",
|
|
+ };
|
|
snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
|
|
"channels=%i, type=\"%s\"\n", cval->head.id,
|
|
cval->control, cval->cmask, cval->channels,
|
|
@@ -3630,6 +3631,9 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list)
|
|
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
|
|
int c, err, idx;
|
|
|
|
+ if (cval->val_type == USB_MIXER_BESPOKEN)
|
|
+ return 0;
|
|
+
|
|
if (cval->cmask) {
|
|
idx = 0;
|
|
for (c = 0; c < MAX_CHANNELS; c++) {
|
|
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
|
|
index c29e27ac43a7a..6d20ba7ee88fd 100644
|
|
--- a/sound/usb/mixer.h
|
|
+++ b/sound/usb/mixer.h
|
|
@@ -55,6 +55,7 @@ enum {
|
|
USB_MIXER_U16,
|
|
USB_MIXER_S32,
|
|
USB_MIXER_U32,
|
|
+ USB_MIXER_BESPOKEN, /* non-standard type */
|
|
};
|
|
|
|
typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer,
|
|
diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
|
|
index 9a98b0c048e33..97e72b3e06c26 100644
|
|
--- a/sound/usb/mixer_scarlett_gen2.c
|
|
+++ b/sound/usb/mixer_scarlett_gen2.c
|
|
@@ -949,10 +949,15 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer,
|
|
if (!elem)
|
|
return -ENOMEM;
|
|
|
|
+ /* We set USB_MIXER_BESPOKEN type, so that the core USB mixer code
|
|
+ * ignores them for resume and other operations.
|
|
+ * Also, the head.id field is set to 0, as we don't use this field.
|
|
+ */
|
|
elem->head.mixer = mixer;
|
|
elem->control = index;
|
|
- elem->head.id = index;
|
|
+ elem->head.id = 0;
|
|
elem->channels = channels;
|
|
+ elem->val_type = USB_MIXER_BESPOKEN;
|
|
|
|
kctl = snd_ctl_new1(ncontrol, elem);
|
|
if (!kctl) {
|
|
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
|
|
index 33068d6ed5d6c..c58a135dc355e 100644
|
|
--- a/tools/bpf/bpftool/main.c
|
|
+++ b/tools/bpf/bpftool/main.c
|
|
@@ -338,8 +338,10 @@ static int do_batch(int argc, char **argv)
|
|
n_argc = make_args(buf, n_argv, BATCH_ARG_NB_MAX, lines);
|
|
if (!n_argc)
|
|
continue;
|
|
- if (n_argc < 0)
|
|
+ if (n_argc < 0) {
|
|
+ err = n_argc;
|
|
goto err_close;
|
|
+ }
|
|
|
|
if (json_output) {
|
|
jsonw_start_object(json_wtr);
|
|
diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
|
|
index d636643ddd358..f32c059fbfb4f 100644
|
|
--- a/tools/bpf/resolve_btfids/main.c
|
|
+++ b/tools/bpf/resolve_btfids/main.c
|
|
@@ -649,6 +649,9 @@ static int symbols_patch(struct object *obj)
|
|
if (sets_patch(obj))
|
|
return -1;
|
|
|
|
+ /* Set type to ensure endian translation occurs. */
|
|
+ obj->efile.idlist->d_type = ELF_T_WORD;
|
|
+
|
|
elf_flagdata(obj->efile.idlist, ELF_C_SET, ELF_F_DIRTY);
|
|
|
|
err = elf_update(obj->efile.elf, ELF_C_WRITE);
|
|
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
|
|
index dbdffb6673feb..0bf6b4d4c90a7 100644
|
|
--- a/tools/perf/util/llvm-utils.c
|
|
+++ b/tools/perf/util/llvm-utils.c
|
|
@@ -504,6 +504,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
|
|
goto errout;
|
|
}
|
|
|
|
+ err = -ENOMEM;
|
|
if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
|
|
template, llc_path, opts) < 0) {
|
|
pr_err("ERROR:\tnot enough memory to setup command line\n");
|
|
@@ -524,6 +525,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
|
|
|
|
pr_debug("llvm compiling command template: %s\n", template);
|
|
|
|
+ err = -ENOMEM;
|
|
if (asprintf(&command_echo, "echo -n \"%s\"", template) < 0)
|
|
goto errout;
|
|
|
|
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
|
|
index c83c2c6564e01..23dc5014e7119 100644
|
|
--- a/tools/perf/util/scripting-engines/trace-event-python.c
|
|
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
|
|
@@ -934,7 +934,7 @@ static PyObject *tuple_new(unsigned int sz)
|
|
return t;
|
|
}
|
|
|
|
-static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
|
|
+static int tuple_set_s64(PyObject *t, unsigned int pos, s64 val)
|
|
{
|
|
#if BITS_PER_LONG == 64
|
|
return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
|
|
@@ -944,6 +944,22 @@ static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
|
|
#endif
|
|
}
|
|
|
|
+/*
|
|
+ * Databases support only signed 64-bit numbers, so even though we are
|
|
+ * exporting a u64, it must be as s64.
|
|
+ */
|
|
+#define tuple_set_d64 tuple_set_s64
|
|
+
|
|
+static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
|
|
+{
|
|
+#if BITS_PER_LONG == 64
|
|
+ return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLong(val));
|
|
+#endif
|
|
+#if BITS_PER_LONG == 32
|
|
+ return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLongLong(val));
|
|
+#endif
|
|
+}
|
|
+
|
|
static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
|
|
{
|
|
return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
|
|
@@ -967,7 +983,7 @@ static int python_export_evsel(struct db_export *dbe, struct evsel *evsel)
|
|
|
|
t = tuple_new(2);
|
|
|
|
- tuple_set_u64(t, 0, evsel->db_id);
|
|
+ tuple_set_d64(t, 0, evsel->db_id);
|
|
tuple_set_string(t, 1, evsel__name(evsel));
|
|
|
|
call_object(tables->evsel_handler, t, "evsel_table");
|
|
@@ -985,7 +1001,7 @@ static int python_export_machine(struct db_export *dbe,
|
|
|
|
t = tuple_new(3);
|
|
|
|
- tuple_set_u64(t, 0, machine->db_id);
|
|
+ tuple_set_d64(t, 0, machine->db_id);
|
|
tuple_set_s32(t, 1, machine->pid);
|
|
tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : "");
|
|
|
|
@@ -1004,9 +1020,9 @@ static int python_export_thread(struct db_export *dbe, struct thread *thread,
|
|
|
|
t = tuple_new(5);
|
|
|
|
- tuple_set_u64(t, 0, thread->db_id);
|
|
- tuple_set_u64(t, 1, machine->db_id);
|
|
- tuple_set_u64(t, 2, main_thread_db_id);
|
|
+ tuple_set_d64(t, 0, thread->db_id);
|
|
+ tuple_set_d64(t, 1, machine->db_id);
|
|
+ tuple_set_d64(t, 2, main_thread_db_id);
|
|
tuple_set_s32(t, 3, thread->pid_);
|
|
tuple_set_s32(t, 4, thread->tid);
|
|
|
|
@@ -1025,10 +1041,10 @@ static int python_export_comm(struct db_export *dbe, struct comm *comm,
|
|
|
|
t = tuple_new(5);
|
|
|
|
- tuple_set_u64(t, 0, comm->db_id);
|
|
+ tuple_set_d64(t, 0, comm->db_id);
|
|
tuple_set_string(t, 1, comm__str(comm));
|
|
- tuple_set_u64(t, 2, thread->db_id);
|
|
- tuple_set_u64(t, 3, comm->start);
|
|
+ tuple_set_d64(t, 2, thread->db_id);
|
|
+ tuple_set_d64(t, 3, comm->start);
|
|
tuple_set_s32(t, 4, comm->exec);
|
|
|
|
call_object(tables->comm_handler, t, "comm_table");
|
|
@@ -1046,9 +1062,9 @@ static int python_export_comm_thread(struct db_export *dbe, u64 db_id,
|
|
|
|
t = tuple_new(3);
|
|
|
|
- tuple_set_u64(t, 0, db_id);
|
|
- tuple_set_u64(t, 1, comm->db_id);
|
|
- tuple_set_u64(t, 2, thread->db_id);
|
|
+ tuple_set_d64(t, 0, db_id);
|
|
+ tuple_set_d64(t, 1, comm->db_id);
|
|
+ tuple_set_d64(t, 2, thread->db_id);
|
|
|
|
call_object(tables->comm_thread_handler, t, "comm_thread_table");
|
|
|
|
@@ -1068,8 +1084,8 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso,
|
|
|
|
t = tuple_new(5);
|
|
|
|
- tuple_set_u64(t, 0, dso->db_id);
|
|
- tuple_set_u64(t, 1, machine->db_id);
|
|
+ tuple_set_d64(t, 0, dso->db_id);
|
|
+ tuple_set_d64(t, 1, machine->db_id);
|
|
tuple_set_string(t, 2, dso->short_name);
|
|
tuple_set_string(t, 3, dso->long_name);
|
|
tuple_set_string(t, 4, sbuild_id);
|
|
@@ -1090,10 +1106,10 @@ static int python_export_symbol(struct db_export *dbe, struct symbol *sym,
|
|
|
|
t = tuple_new(6);
|
|
|
|
- tuple_set_u64(t, 0, *sym_db_id);
|
|
- tuple_set_u64(t, 1, dso->db_id);
|
|
- tuple_set_u64(t, 2, sym->start);
|
|
- tuple_set_u64(t, 3, sym->end);
|
|
+ tuple_set_d64(t, 0, *sym_db_id);
|
|
+ tuple_set_d64(t, 1, dso->db_id);
|
|
+ tuple_set_d64(t, 2, sym->start);
|
|
+ tuple_set_d64(t, 3, sym->end);
|
|
tuple_set_s32(t, 4, sym->binding);
|
|
tuple_set_string(t, 5, sym->name);
|
|
|
|
@@ -1130,30 +1146,30 @@ static void python_export_sample_table(struct db_export *dbe,
|
|
|
|
t = tuple_new(24);
|
|
|
|
- tuple_set_u64(t, 0, es->db_id);
|
|
- tuple_set_u64(t, 1, es->evsel->db_id);
|
|
- tuple_set_u64(t, 2, es->al->maps->machine->db_id);
|
|
- tuple_set_u64(t, 3, es->al->thread->db_id);
|
|
- tuple_set_u64(t, 4, es->comm_db_id);
|
|
- tuple_set_u64(t, 5, es->dso_db_id);
|
|
- tuple_set_u64(t, 6, es->sym_db_id);
|
|
- tuple_set_u64(t, 7, es->offset);
|
|
- tuple_set_u64(t, 8, es->sample->ip);
|
|
- tuple_set_u64(t, 9, es->sample->time);
|
|
+ tuple_set_d64(t, 0, es->db_id);
|
|
+ tuple_set_d64(t, 1, es->evsel->db_id);
|
|
+ tuple_set_d64(t, 2, es->al->maps->machine->db_id);
|
|
+ tuple_set_d64(t, 3, es->al->thread->db_id);
|
|
+ tuple_set_d64(t, 4, es->comm_db_id);
|
|
+ tuple_set_d64(t, 5, es->dso_db_id);
|
|
+ tuple_set_d64(t, 6, es->sym_db_id);
|
|
+ tuple_set_d64(t, 7, es->offset);
|
|
+ tuple_set_d64(t, 8, es->sample->ip);
|
|
+ tuple_set_d64(t, 9, es->sample->time);
|
|
tuple_set_s32(t, 10, es->sample->cpu);
|
|
- tuple_set_u64(t, 11, es->addr_dso_db_id);
|
|
- tuple_set_u64(t, 12, es->addr_sym_db_id);
|
|
- tuple_set_u64(t, 13, es->addr_offset);
|
|
- tuple_set_u64(t, 14, es->sample->addr);
|
|
- tuple_set_u64(t, 15, es->sample->period);
|
|
- tuple_set_u64(t, 16, es->sample->weight);
|
|
- tuple_set_u64(t, 17, es->sample->transaction);
|
|
- tuple_set_u64(t, 18, es->sample->data_src);
|
|
+ tuple_set_d64(t, 11, es->addr_dso_db_id);
|
|
+ tuple_set_d64(t, 12, es->addr_sym_db_id);
|
|
+ tuple_set_d64(t, 13, es->addr_offset);
|
|
+ tuple_set_d64(t, 14, es->sample->addr);
|
|
+ tuple_set_d64(t, 15, es->sample->period);
|
|
+ tuple_set_d64(t, 16, es->sample->weight);
|
|
+ tuple_set_d64(t, 17, es->sample->transaction);
|
|
+ tuple_set_d64(t, 18, es->sample->data_src);
|
|
tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
|
|
tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
|
|
- tuple_set_u64(t, 21, es->call_path_id);
|
|
- tuple_set_u64(t, 22, es->sample->insn_cnt);
|
|
- tuple_set_u64(t, 23, es->sample->cyc_cnt);
|
|
+ tuple_set_d64(t, 21, es->call_path_id);
|
|
+ tuple_set_d64(t, 22, es->sample->insn_cnt);
|
|
+ tuple_set_d64(t, 23, es->sample->cyc_cnt);
|
|
|
|
call_object(tables->sample_handler, t, "sample_table");
|
|
|
|
@@ -1167,8 +1183,8 @@ static void python_export_synth(struct db_export *dbe, struct export_sample *es)
|
|
|
|
t = tuple_new(3);
|
|
|
|
- tuple_set_u64(t, 0, es->db_id);
|
|
- tuple_set_u64(t, 1, es->evsel->core.attr.config);
|
|
+ tuple_set_d64(t, 0, es->db_id);
|
|
+ tuple_set_d64(t, 1, es->evsel->core.attr.config);
|
|
tuple_set_bytes(t, 2, es->sample->raw_data, es->sample->raw_size);
|
|
|
|
call_object(tables->synth_handler, t, "synth_data");
|
|
@@ -1200,10 +1216,10 @@ static int python_export_call_path(struct db_export *dbe, struct call_path *cp)
|
|
|
|
t = tuple_new(4);
|
|
|
|
- tuple_set_u64(t, 0, cp->db_id);
|
|
- tuple_set_u64(t, 1, parent_db_id);
|
|
- tuple_set_u64(t, 2, sym_db_id);
|
|
- tuple_set_u64(t, 3, cp->ip);
|
|
+ tuple_set_d64(t, 0, cp->db_id);
|
|
+ tuple_set_d64(t, 1, parent_db_id);
|
|
+ tuple_set_d64(t, 2, sym_db_id);
|
|
+ tuple_set_d64(t, 3, cp->ip);
|
|
|
|
call_object(tables->call_path_handler, t, "call_path_table");
|
|
|
|
@@ -1221,20 +1237,20 @@ static int python_export_call_return(struct db_export *dbe,
|
|
|
|
t = tuple_new(14);
|
|
|
|
- tuple_set_u64(t, 0, cr->db_id);
|
|
- tuple_set_u64(t, 1, cr->thread->db_id);
|
|
- tuple_set_u64(t, 2, comm_db_id);
|
|
- tuple_set_u64(t, 3, cr->cp->db_id);
|
|
- tuple_set_u64(t, 4, cr->call_time);
|
|
- tuple_set_u64(t, 5, cr->return_time);
|
|
- tuple_set_u64(t, 6, cr->branch_count);
|
|
- tuple_set_u64(t, 7, cr->call_ref);
|
|
- tuple_set_u64(t, 8, cr->return_ref);
|
|
- tuple_set_u64(t, 9, cr->cp->parent->db_id);
|
|
+ tuple_set_d64(t, 0, cr->db_id);
|
|
+ tuple_set_d64(t, 1, cr->thread->db_id);
|
|
+ tuple_set_d64(t, 2, comm_db_id);
|
|
+ tuple_set_d64(t, 3, cr->cp->db_id);
|
|
+ tuple_set_d64(t, 4, cr->call_time);
|
|
+ tuple_set_d64(t, 5, cr->return_time);
|
|
+ tuple_set_d64(t, 6, cr->branch_count);
|
|
+ tuple_set_d64(t, 7, cr->call_ref);
|
|
+ tuple_set_d64(t, 8, cr->return_ref);
|
|
+ tuple_set_d64(t, 9, cr->cp->parent->db_id);
|
|
tuple_set_s32(t, 10, cr->flags);
|
|
- tuple_set_u64(t, 11, cr->parent_db_id);
|
|
- tuple_set_u64(t, 12, cr->insn_count);
|
|
- tuple_set_u64(t, 13, cr->cyc_count);
|
|
+ tuple_set_d64(t, 11, cr->parent_db_id);
|
|
+ tuple_set_d64(t, 12, cr->insn_count);
|
|
+ tuple_set_d64(t, 13, cr->cyc_count);
|
|
|
|
call_object(tables->call_return_handler, t, "call_return_table");
|
|
|
|
@@ -1254,14 +1270,14 @@ static int python_export_context_switch(struct db_export *dbe, u64 db_id,
|
|
|
|
t = tuple_new(9);
|
|
|
|
- tuple_set_u64(t, 0, db_id);
|
|
- tuple_set_u64(t, 1, machine->db_id);
|
|
- tuple_set_u64(t, 2, sample->time);
|
|
+ tuple_set_d64(t, 0, db_id);
|
|
+ tuple_set_d64(t, 1, machine->db_id);
|
|
+ tuple_set_d64(t, 2, sample->time);
|
|
tuple_set_s32(t, 3, sample->cpu);
|
|
- tuple_set_u64(t, 4, th_out_id);
|
|
- tuple_set_u64(t, 5, comm_out_id);
|
|
- tuple_set_u64(t, 6, th_in_id);
|
|
- tuple_set_u64(t, 7, comm_in_id);
|
|
+ tuple_set_d64(t, 4, th_out_id);
|
|
+ tuple_set_d64(t, 5, comm_out_id);
|
|
+ tuple_set_d64(t, 6, th_in_id);
|
|
+ tuple_set_d64(t, 7, comm_in_id);
|
|
tuple_set_s32(t, 8, flags);
|
|
|
|
call_object(tables->context_switch_handler, t, "context_switch");
|
|
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
|
|
index 3ab1200e172fa..b1b37dcade9f2 100644
|
|
--- a/tools/testing/selftests/bpf/.gitignore
|
|
+++ b/tools/testing/selftests/bpf/.gitignore
|
|
@@ -9,6 +9,7 @@ fixdep
|
|
test_dev_cgroup
|
|
/test_progs*
|
|
test_tcpbpf_user
|
|
+!test_progs.h
|
|
test_verifier_log
|
|
feature
|
|
test_sock
|
|
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc b/tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc
|
|
index e6eb78f0b9545..9933ed24f9012 100644
|
|
--- a/tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc
|
|
+++ b/tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc
|
|
@@ -57,6 +57,10 @@ enable_events() {
|
|
echo 1 > tracing_on
|
|
}
|
|
|
|
+other_task() {
|
|
+ sleep .001 || usleep 1 || sleep 1
|
|
+}
|
|
+
|
|
echo 0 > options/event-fork
|
|
|
|
do_reset
|
|
@@ -94,6 +98,9 @@ child=$!
|
|
echo "child = $child"
|
|
wait $child
|
|
|
|
+# Be sure some other events will happen for small systems (e.g. 1 core)
|
|
+other_task
|
|
+
|
|
echo 0 > tracing_on
|
|
|
|
cnt=`count_pid $mypid`
|
|
diff --git a/tools/testing/selftests/lkdtm/run.sh b/tools/testing/selftests/lkdtm/run.sh
|
|
index bb7a1775307b8..e95e79bd31268 100755
|
|
--- a/tools/testing/selftests/lkdtm/run.sh
|
|
+++ b/tools/testing/selftests/lkdtm/run.sh
|
|
@@ -76,10 +76,14 @@ fi
|
|
# Save existing dmesg so we can detect new content below
|
|
dmesg > "$DMESG"
|
|
|
|
-# Most shells yell about signals and we're expecting the "cat" process
|
|
-# to usually be killed by the kernel. So we have to run it in a sub-shell
|
|
-# and silence errors.
|
|
-($SHELL -c 'cat <(echo '"$test"') >'"$TRIGGER" 2>/dev/null) || true
|
|
+# Since the kernel is likely killing the process writing to the trigger
|
|
+# file, it must not be the script's shell itself. i.e. we cannot do:
|
|
+# echo "$test" >"$TRIGGER"
|
|
+# Instead, use "cat" to take the signal. Since the shell will yell about
|
|
+# the signal that killed the subprocess, we must ignore the failure and
|
|
+# continue. However we don't silence stderr since there might be other
|
|
+# useful details reported there in the case of other unexpected conditions.
|
|
+echo "$test" | cat >"$TRIGGER" || true
|
|
|
|
# Record and dump the results
|
|
dmesg | comm --nocheck-order -13 "$DMESG" - > "$LOG" || true
|
|
diff --git a/tools/testing/selftests/splice/short_splice_read.sh b/tools/testing/selftests/splice/short_splice_read.sh
|
|
index 7810d3589d9ab..22b6c8910b182 100755
|
|
--- a/tools/testing/selftests/splice/short_splice_read.sh
|
|
+++ b/tools/testing/selftests/splice/short_splice_read.sh
|
|
@@ -1,21 +1,87 @@
|
|
#!/bin/sh
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
+#
|
|
+# Test for mishandling of splice() on pseudofilesystems, which should catch
|
|
+# bugs like 11990a5bd7e5 ("module: Correctly truncate sysfs sections output")
|
|
+#
|
|
+# Since splice fallback was removed as part of the set_fs() rework, many of these
|
|
+# tests expect to fail now. See https://lore.kernel.org/lkml/202009181443.C2179FB@keescook/
|
|
set -e
|
|
|
|
+DIR=$(dirname "$0")
|
|
+
|
|
ret=0
|
|
|
|
+expect_success()
|
|
+{
|
|
+ title="$1"
|
|
+ shift
|
|
+
|
|
+ echo "" >&2
|
|
+ echo "$title ..." >&2
|
|
+
|
|
+ set +e
|
|
+ "$@"
|
|
+ rc=$?
|
|
+ set -e
|
|
+
|
|
+ case "$rc" in
|
|
+ 0)
|
|
+ echo "ok: $title succeeded" >&2
|
|
+ ;;
|
|
+ 1)
|
|
+ echo "FAIL: $title should work" >&2
|
|
+ ret=$(( ret + 1 ))
|
|
+ ;;
|
|
+ *)
|
|
+ echo "FAIL: something else went wrong" >&2
|
|
+ ret=$(( ret + 1 ))
|
|
+ ;;
|
|
+ esac
|
|
+}
|
|
+
|
|
+expect_failure()
|
|
+{
|
|
+ title="$1"
|
|
+ shift
|
|
+
|
|
+ echo "" >&2
|
|
+ echo "$title ..." >&2
|
|
+
|
|
+ set +e
|
|
+ "$@"
|
|
+ rc=$?
|
|
+ set -e
|
|
+
|
|
+ case "$rc" in
|
|
+ 0)
|
|
+ echo "FAIL: $title unexpectedly worked" >&2
|
|
+ ret=$(( ret + 1 ))
|
|
+ ;;
|
|
+ 1)
|
|
+ echo "ok: $title correctly failed" >&2
|
|
+ ;;
|
|
+ *)
|
|
+ echo "FAIL: something else went wrong" >&2
|
|
+ ret=$(( ret + 1 ))
|
|
+ ;;
|
|
+ esac
|
|
+}
|
|
+
|
|
do_splice()
|
|
{
|
|
filename="$1"
|
|
bytes="$2"
|
|
expected="$3"
|
|
+ report="$4"
|
|
|
|
- out=$(./splice_read "$filename" "$bytes" | cat)
|
|
+ out=$("$DIR"/splice_read "$filename" "$bytes" | cat)
|
|
if [ "$out" = "$expected" ] ; then
|
|
- echo "ok: $filename $bytes"
|
|
+ echo " matched $report" >&2
|
|
+ return 0
|
|
else
|
|
- echo "FAIL: $filename $bytes"
|
|
- ret=1
|
|
+ echo " no match: '$out' vs $report" >&2
|
|
+ return 1
|
|
fi
|
|
}
|
|
|
|
@@ -23,34 +89,45 @@ test_splice()
|
|
{
|
|
filename="$1"
|
|
|
|
+ echo " checking $filename ..." >&2
|
|
+
|
|
full=$(cat "$filename")
|
|
+ rc=$?
|
|
+ if [ $rc -ne 0 ] ; then
|
|
+ return 2
|
|
+ fi
|
|
+
|
|
two=$(echo "$full" | grep -m1 . | cut -c-2)
|
|
|
|
# Make sure full splice has the same contents as a standard read.
|
|
- do_splice "$filename" 4096 "$full"
|
|
+ echo " splicing 4096 bytes ..." >&2
|
|
+ if ! do_splice "$filename" 4096 "$full" "full read" ; then
|
|
+ return 1
|
|
+ fi
|
|
|
|
# Make sure a partial splice see the first two characters.
|
|
- do_splice "$filename" 2 "$two"
|
|
+ echo " splicing 2 bytes ..." >&2
|
|
+ if ! do_splice "$filename" 2 "$two" "'$two'" ; then
|
|
+ return 1
|
|
+ fi
|
|
+
|
|
+ return 0
|
|
}
|
|
|
|
-# proc_single_open(), seq_read()
|
|
-test_splice /proc/$$/limits
|
|
-# special open, seq_read()
|
|
-test_splice /proc/$$/comm
|
|
+### /proc/$pid/ has no splice interface; these should all fail.
|
|
+expect_failure "proc_single_open(), seq_read() splice" test_splice /proc/$$/limits
|
|
+expect_failure "special open(), seq_read() splice" test_splice /proc/$$/comm
|
|
|
|
-# proc_handler, proc_dointvec_minmax
|
|
-test_splice /proc/sys/fs/nr_open
|
|
-# proc_handler, proc_dostring
|
|
-test_splice /proc/sys/kernel/modprobe
|
|
-# proc_handler, special read
|
|
-test_splice /proc/sys/kernel/version
|
|
+### /proc/sys/ has a splice interface; these should all succeed.
|
|
+expect_success "proc_handler: proc_dointvec_minmax() splice" test_splice /proc/sys/fs/nr_open
|
|
+expect_success "proc_handler: proc_dostring() splice" test_splice /proc/sys/kernel/modprobe
|
|
+expect_success "proc_handler: special read splice" test_splice /proc/sys/kernel/version
|
|
|
|
+### /sys/ has no splice interface; these should all fail.
|
|
if ! [ -d /sys/module/test_module/sections ] ; then
|
|
- modprobe test_module
|
|
+ expect_success "test_module kernel module load" modprobe test_module
|
|
fi
|
|
-# kernfs, attr
|
|
-test_splice /sys/module/test_module/coresize
|
|
-# kernfs, binattr
|
|
-test_splice /sys/module/test_module/sections/.init.text
|
|
+expect_failure "kernfs attr splice" test_splice /sys/module/test_module/coresize
|
|
+expect_failure "kernfs binattr splice" test_splice /sys/module/test_module/sections/.init.text
|
|
|
|
exit $ret
|
|
diff --git a/tools/testing/selftests/tc-testing/plugin-lib/scapyPlugin.py b/tools/testing/selftests/tc-testing/plugin-lib/scapyPlugin.py
|
|
index 229ee185b27e1..a7b21658af9b4 100644
|
|
--- a/tools/testing/selftests/tc-testing/plugin-lib/scapyPlugin.py
|
|
+++ b/tools/testing/selftests/tc-testing/plugin-lib/scapyPlugin.py
|
|
@@ -36,7 +36,7 @@ class SubPlugin(TdcPlugin):
|
|
for k in scapy_keys:
|
|
if k not in scapyinfo:
|
|
keyfail = True
|
|
- missing_keys.add(k)
|
|
+ missing_keys.append(k)
|
|
if keyfail:
|
|
print('{}: Scapy block present in the test, but is missing info:'
|
|
.format(self.sub_class))
|
|
diff --git a/tools/testing/selftests/vm/protection_keys.c b/tools/testing/selftests/vm/protection_keys.c
|
|
index fdbb602ecf325..87eecd5ba577b 100644
|
|
--- a/tools/testing/selftests/vm/protection_keys.c
|
|
+++ b/tools/testing/selftests/vm/protection_keys.c
|
|
@@ -510,7 +510,7 @@ int alloc_pkey(void)
|
|
" shadow: 0x%016llx\n",
|
|
__func__, __LINE__, ret, __read_pkey_reg(),
|
|
shadow_pkey_reg);
|
|
- if (ret) {
|
|
+ if (ret > 0) {
|
|
/* clear both the bits: */
|
|
shadow_pkey_reg = set_pkey_bits(shadow_pkey_reg, ret,
|
|
~PKEY_MASK);
|
|
@@ -561,7 +561,6 @@ int alloc_random_pkey(void)
|
|
int nr_alloced = 0;
|
|
int random_index;
|
|
memset(alloced_pkeys, 0, sizeof(alloced_pkeys));
|
|
- srand((unsigned int)time(NULL));
|
|
|
|
/* allocate every possible key and make a note of which ones we got */
|
|
max_nr_pkey_allocs = NR_PKEYS;
|
|
@@ -1449,6 +1448,13 @@ void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)
|
|
ret = mprotect(p1, PAGE_SIZE, PROT_EXEC);
|
|
pkey_assert(!ret);
|
|
|
|
+ /*
|
|
+ * Reset the shadow, assuming that the above mprotect()
|
|
+ * correctly changed PKRU, but to an unknown value since
|
|
+ * the actual alllocated pkey is unknown.
|
|
+ */
|
|
+ shadow_pkey_reg = __read_pkey_reg();
|
|
+
|
|
dprintf2("pkey_reg: %016llx\n", read_pkey_reg());
|
|
|
|
/* Make sure this is an *instruction* fault */
|
|
@@ -1552,6 +1558,8 @@ int main(void)
|
|
int nr_iterations = 22;
|
|
int pkeys_supported = is_pkeys_supported();
|
|
|
|
+ srand((unsigned int)time(NULL));
|
|
+
|
|
setup_handlers();
|
|
|
|
printf("has pkeys: %d\n", pkeys_supported);
|