28469 lines
936 KiB
Diff
28469 lines
936 KiB
Diff
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
|
|
index 36c3cb5479013a..33675e718a3766 100644
|
|
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
|
|
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
|
|
@@ -311,10 +311,13 @@ Description: Do background GC aggressively when set. Set to 0 by default.
|
|
GC approach and turns SSR mode on.
|
|
gc urgent low(2): lowers the bar of checking I/O idling in
|
|
order to process outstanding discard commands and GC a
|
|
- little bit aggressively. uses cost benefit GC approach.
|
|
+ little bit aggressively. always uses cost benefit GC approach,
|
|
+ and will override age-threshold GC approach if ATGC is enabled
|
|
+ at the same time.
|
|
gc urgent mid(3): does GC forcibly in a period of given
|
|
gc_urgent_sleep_time and executes a mid level of I/O idling check.
|
|
- uses cost benefit GC approach.
|
|
+ always uses cost benefit GC approach, and will override
|
|
+ age-threshold GC approach if ATGC is enabled at the same time.
|
|
|
|
What: /sys/fs/f2fs/<disk>/gc_urgent_sleep_time
|
|
Date: August 2017
|
|
diff --git a/Documentation/RCU/stallwarn.rst b/Documentation/RCU/stallwarn.rst
|
|
index ca7b7cd806a16c..30080ff6f4062d 100644
|
|
--- a/Documentation/RCU/stallwarn.rst
|
|
+++ b/Documentation/RCU/stallwarn.rst
|
|
@@ -249,7 +249,7 @@ ticks this GP)" indicates that this CPU has not taken any scheduling-clock
|
|
interrupts during the current stalled grace period.
|
|
|
|
The "idle=" portion of the message prints the dyntick-idle state.
|
|
-The hex number before the first "/" is the low-order 12 bits of the
|
|
+The hex number before the first "/" is the low-order 16 bits of the
|
|
dynticks counter, which will have an even-numbered value if the CPU
|
|
is in dyntick-idle mode and an odd-numbered value otherwise. The hex
|
|
number between the two "/"s is the value of the nesting, which will be
|
|
diff --git a/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml b/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
|
|
index 5e942bccf27787..2b2041818a0a44 100644
|
|
--- a/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
|
|
+++ b/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
|
|
@@ -26,9 +26,21 @@ properties:
|
|
description:
|
|
Specifies the reference clock(s) from which the output frequency is
|
|
derived. This must either reference one clock if only the first clock
|
|
- input is connected or two if both clock inputs are connected.
|
|
- minItems: 1
|
|
- maxItems: 2
|
|
+ input is connected or two if both clock inputs are connected. The last
|
|
+ clock is the AXI bus clock that needs to be enabled so we can access the
|
|
+ core registers.
|
|
+ minItems: 2
|
|
+ maxItems: 3
|
|
+
|
|
+ clock-names:
|
|
+ oneOf:
|
|
+ - items:
|
|
+ - const: clkin1
|
|
+ - const: s_axi_aclk
|
|
+ - items:
|
|
+ - const: clkin1
|
|
+ - const: clkin2
|
|
+ - const: s_axi_aclk
|
|
|
|
'#clock-cells':
|
|
const: 0
|
|
@@ -40,6 +52,7 @@ required:
|
|
- compatible
|
|
- reg
|
|
- clocks
|
|
+ - clock-names
|
|
- '#clock-cells'
|
|
|
|
additionalProperties: false
|
|
@@ -50,5 +63,6 @@ examples:
|
|
compatible = "adi,axi-clkgen-2.00.a";
|
|
#clock-cells = <0>;
|
|
reg = <0xff000000 0x1000>;
|
|
- clocks = <&osc 1>;
|
|
+ clocks = <&osc 1>, <&clkc 15>;
|
|
+ clock-names = "clkin1", "s_axi_aclk";
|
|
};
|
|
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
|
|
index 96340a05754ce6..2beed2e2406c4e 100644
|
|
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
|
|
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
|
|
@@ -26,7 +26,7 @@ properties:
|
|
maxItems: 1
|
|
|
|
spi-max-frequency:
|
|
- maximum: 30000000
|
|
+ maximum: 66000000
|
|
|
|
reset-gpios:
|
|
maxItems: 1
|
|
diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml
|
|
index 9418fd66a8e95a..b93254ad2a287a 100644
|
|
--- a/Documentation/devicetree/bindings/serial/rs485.yaml
|
|
+++ b/Documentation/devicetree/bindings/serial/rs485.yaml
|
|
@@ -18,16 +18,15 @@ properties:
|
|
description: prop-encoded-array <a b>
|
|
$ref: /schemas/types.yaml#/definitions/uint32-array
|
|
items:
|
|
- items:
|
|
- - description: Delay between rts signal and beginning of data sent in
|
|
- milliseconds. It corresponds to the delay before sending data.
|
|
- default: 0
|
|
- maximum: 100
|
|
- - description: Delay between end of data sent and rts signal in milliseconds.
|
|
- It corresponds to the delay after sending data and actual release
|
|
- of the line.
|
|
- default: 0
|
|
- maximum: 100
|
|
+ - description: Delay between rts signal and beginning of data sent in
|
|
+ milliseconds. It corresponds to the delay before sending data.
|
|
+ default: 0
|
|
+ maximum: 100
|
|
+ - description: Delay between end of data sent and rts signal in milliseconds.
|
|
+ It corresponds to the delay after sending data and actual release
|
|
+ of the line.
|
|
+ default: 0
|
|
+ maximum: 100
|
|
|
|
rs485-rts-active-high:
|
|
description: drive RTS high when sending (this is the default).
|
|
diff --git a/Documentation/devicetree/bindings/sound/mt6359.yaml b/Documentation/devicetree/bindings/sound/mt6359.yaml
|
|
index 23d411fc4200e6..128698630c865f 100644
|
|
--- a/Documentation/devicetree/bindings/sound/mt6359.yaml
|
|
+++ b/Documentation/devicetree/bindings/sound/mt6359.yaml
|
|
@@ -23,8 +23,8 @@ properties:
|
|
Indicates how many data pins are used to transmit two channels of PDM
|
|
signal. 0 means two wires, 1 means one wire. Default value is 0.
|
|
enum:
|
|
- - 0 # one wire
|
|
- - 1 # two wires
|
|
+ - 0 # two wires
|
|
+ - 1 # one wire
|
|
|
|
mediatek,mic-type-0:
|
|
$ref: /schemas/types.yaml#/definitions/uint32
|
|
@@ -53,9 +53,9 @@ additionalProperties: false
|
|
|
|
examples:
|
|
- |
|
|
- mt6359codec: mt6359codec {
|
|
- mediatek,dmic-mode = <0>;
|
|
- mediatek,mic-type-0 = <2>;
|
|
+ mt6359codec: audio-codec {
|
|
+ mediatek,dmic-mode = <0>;
|
|
+ mediatek,mic-type-0 = <2>;
|
|
};
|
|
|
|
...
|
|
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
|
|
index 573578db950910..12a16031d7b6d0 100644
|
|
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
|
|
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
|
|
@@ -923,6 +923,8 @@ patternProperties:
|
|
description: National Semiconductor
|
|
"^nec,.*":
|
|
description: NEC LCD Technologies, Ltd.
|
|
+ "^neofidelity,.*":
|
|
+ description: Neofidelity Inc.
|
|
"^neonode,.*":
|
|
description: Neonode Inc.
|
|
"^netgear,.*":
|
|
diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst
|
|
index 9aaf6ef75eb53b..0c69aa574ab9af 100644
|
|
--- a/Documentation/filesystems/mount_api.rst
|
|
+++ b/Documentation/filesystems/mount_api.rst
|
|
@@ -766,7 +766,8 @@ process the parameters it is given.
|
|
|
|
* ::
|
|
|
|
- bool fs_validate_description(const struct fs_parameter_description *desc);
|
|
+ bool fs_validate_description(const char *name,
|
|
+ const struct fs_parameter_description *desc);
|
|
|
|
This performs some validation checks on a parameter description. It
|
|
returns true if the description is good and false if it is not. It will
|
|
diff --git a/Documentation/locking/seqlock.rst b/Documentation/locking/seqlock.rst
|
|
index bfda1a5fecadc6..ec6411d02ac8f5 100644
|
|
--- a/Documentation/locking/seqlock.rst
|
|
+++ b/Documentation/locking/seqlock.rst
|
|
@@ -153,7 +153,7 @@ Use seqcount_latch_t when the write side sections cannot be protected
|
|
from interruption by readers. This is typically the case when the read
|
|
side can be invoked from NMI handlers.
|
|
|
|
-Check `raw_write_seqcount_latch()` for more information.
|
|
+Check `write_seqcount_latch()` for more information.
|
|
|
|
|
|
.. _seqlock_t:
|
|
diff --git a/Documentation/networking/j1939.rst b/Documentation/networking/j1939.rst
|
|
index e4bd7aa1f5aa9d..544bad175aae2d 100644
|
|
--- a/Documentation/networking/j1939.rst
|
|
+++ b/Documentation/networking/j1939.rst
|
|
@@ -121,7 +121,7 @@ format, the Group Extension is set in the PS-field.
|
|
|
|
On the other hand, when using PDU1 format, the PS-field contains a so-called
|
|
Destination Address, which is _not_ part of the PGN. When communicating a PGN
|
|
-from user space to kernel (or vice versa) and PDU2 format is used, the PS-field
|
|
+from user space to kernel (or vice versa) and PDU1 format is used, the PS-field
|
|
of the PGN shall be set to zero. The Destination Address shall be set
|
|
elsewhere.
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 611d7de2e3a22a..74f3867461a0ec 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 6
|
|
PATCHLEVEL = 6
|
|
-SUBLEVEL = 63
|
|
+SUBLEVEL = 64
|
|
EXTRAVERSION =
|
|
NAME = Pinguïn Aangedreven
|
|
|
|
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
|
|
index 4c9e61457b2f69..cc6ac7d128aa1a 100644
|
|
--- a/arch/arc/kernel/devtree.c
|
|
+++ b/arch/arc/kernel/devtree.c
|
|
@@ -62,7 +62,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt)
|
|
const struct machine_desc *mdesc;
|
|
unsigned long dt_root;
|
|
|
|
- if (!early_init_dt_scan(dt))
|
|
+ if (!early_init_dt_scan(dt, __pa(dt)))
|
|
return NULL;
|
|
|
|
mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach);
|
|
diff --git a/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts b/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts
|
|
index c8ca8cb7f5c94e..52ad95a2063aaf 100644
|
|
--- a/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts
|
|
+++ b/arch/arm/boot/dts/allwinner/sun9i-a80-cubieboard4.dts
|
|
@@ -280,8 +280,8 @@ reg_dcdc4: dcdc4 {
|
|
|
|
reg_dcdc5: dcdc5 {
|
|
regulator-always-on;
|
|
- regulator-min-microvolt = <1425000>;
|
|
- regulator-max-microvolt = <1575000>;
|
|
+ regulator-min-microvolt = <1450000>;
|
|
+ regulator-max-microvolt = <1550000>;
|
|
regulator-name = "vcc-dram";
|
|
};
|
|
|
|
diff --git a/arch/arm/boot/dts/microchip/sam9x60.dtsi b/arch/arm/boot/dts/microchip/sam9x60.dtsi
|
|
index 1705c96f4221e8..ae089d4bd660ed 100644
|
|
--- a/arch/arm/boot/dts/microchip/sam9x60.dtsi
|
|
+++ b/arch/arm/boot/dts/microchip/sam9x60.dtsi
|
|
@@ -186,6 +186,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 13>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -384,6 +385,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 32>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -433,6 +435,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 33>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -590,6 +593,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 9>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -639,6 +643,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 10>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -688,6 +693,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 11>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -737,6 +743,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 5>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -805,6 +812,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 6>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -873,6 +881,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 7>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -941,6 +950,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 8>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -1064,6 +1074,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 15>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
@@ -1113,6 +1124,7 @@ AT91_XDMAC_DT_PER_IF(1) |
|
|
dma-names = "tx", "rx";
|
|
clocks = <&pmc PMC_TYPE_PERIPHERAL 16>;
|
|
clock-names = "usart";
|
|
+ atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
|
|
atmel,use-dma-rx;
|
|
atmel,use-dma-tx;
|
|
atmel,fifo-size = <16>;
|
|
diff --git a/arch/arm/boot/dts/ti/omap/omap36xx.dtsi b/arch/arm/boot/dts/ti/omap/omap36xx.dtsi
|
|
index e6d8070c1bf88d..cba8ba51657bb7 100644
|
|
--- a/arch/arm/boot/dts/ti/omap/omap36xx.dtsi
|
|
+++ b/arch/arm/boot/dts/ti/omap/omap36xx.dtsi
|
|
@@ -72,6 +72,7 @@ opp-1000000000 {
|
|
<1375000 1375000 1375000>;
|
|
/* only on am/dm37x with speed-binned bit set */
|
|
opp-supported-hw = <0xffffffff 2>;
|
|
+ turbo-mode;
|
|
};
|
|
};
|
|
|
|
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
|
|
index 264827281113b0..abf13b21ba76fd 100644
|
|
--- a/arch/arm/kernel/devtree.c
|
|
+++ b/arch/arm/kernel/devtree.c
|
|
@@ -201,7 +201,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt_virt)
|
|
|
|
mdesc_best = &__mach_desc_GENERIC_DT;
|
|
|
|
- if (!dt_virt || !early_init_dt_verify(dt_virt))
|
|
+ if (!dt_virt || !early_init_dt_verify(dt_virt, __pa(dt_virt)))
|
|
return NULL;
|
|
|
|
mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
|
|
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
|
|
index 6150a716828c3e..0384fbbdc28d83 100644
|
|
--- a/arch/arm/kernel/entry-armv.S
|
|
+++ b/arch/arm/kernel/entry-armv.S
|
|
@@ -25,6 +25,7 @@
|
|
#include <asm/tls.h>
|
|
#include <asm/system_info.h>
|
|
#include <asm/uaccess-asm.h>
|
|
+#include <asm/kasan_def.h>
|
|
|
|
#include "entry-header.S"
|
|
#include <asm/probes.h>
|
|
@@ -555,6 +556,13 @@ ENTRY(__switch_to)
|
|
@ entries covering the vmalloc region.
|
|
@
|
|
ldr r2, [ip]
|
|
+#ifdef CONFIG_KASAN_VMALLOC
|
|
+ @ Also dummy read from the KASAN shadow memory for the new stack if we
|
|
+ @ are using KASAN
|
|
+ mov_l r2, KASAN_SHADOW_OFFSET
|
|
+ add r2, r2, ip, lsr #KASAN_SHADOW_SCALE_SHIFT
|
|
+ ldr r2, [r2]
|
|
+#endif
|
|
#endif
|
|
|
|
@ When CONFIG_THREAD_INFO_IN_TASK=n, the update of SP itself is what
|
|
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
|
|
index 28873cda464f51..f22c50d4bd4173 100644
|
|
--- a/arch/arm/kernel/head.S
|
|
+++ b/arch/arm/kernel/head.S
|
|
@@ -411,7 +411,11 @@ ENTRY(secondary_startup)
|
|
/*
|
|
* Use the page tables supplied from __cpu_up.
|
|
*/
|
|
+#ifdef CONFIG_XIP_KERNEL
|
|
+ ldr r3, =(secondary_data + PLAT_PHYS_OFFSET - PAGE_OFFSET)
|
|
+#else
|
|
adr_l r3, secondary_data
|
|
+#endif
|
|
mov_l r12, __secondary_switched
|
|
ldrd r4, r5, [r3, #0] @ get secondary_data.pgdir
|
|
ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE:
|
|
diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c
|
|
index d4392e1774848d..3bb0c4dcfc5c95 100644
|
|
--- a/arch/arm/kernel/psci_smp.c
|
|
+++ b/arch/arm/kernel/psci_smp.c
|
|
@@ -45,8 +45,15 @@ extern void secondary_startup(void);
|
|
static int psci_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|
{
|
|
if (psci_ops.cpu_on)
|
|
+#ifdef CONFIG_XIP_KERNEL
|
|
+ return psci_ops.cpu_on(cpu_logical_map(cpu),
|
|
+ ((phys_addr_t)(&secondary_startup)
|
|
+ - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
|
|
+ + CONFIG_XIP_PHYS_ADDR));
|
|
+#else
|
|
return psci_ops.cpu_on(cpu_logical_map(cpu),
|
|
virt_to_idmap(&secondary_startup));
|
|
+#endif
|
|
return -ENODEV;
|
|
}
|
|
|
|
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
|
|
index 448e57c6f65344..4a833e89782aa2 100644
|
|
--- a/arch/arm/mm/idmap.c
|
|
+++ b/arch/arm/mm/idmap.c
|
|
@@ -84,8 +84,15 @@ static void identity_mapping_add(pgd_t *pgd, const char *text_start,
|
|
unsigned long addr, end;
|
|
unsigned long next;
|
|
|
|
+#ifdef CONFIG_XIP_KERNEL
|
|
+ addr = (phys_addr_t)(text_start) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
|
|
+ + CONFIG_XIP_PHYS_ADDR;
|
|
+ end = (phys_addr_t)(text_end) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
|
|
+ + CONFIG_XIP_PHYS_ADDR;
|
|
+#else
|
|
addr = virt_to_idmap(text_start);
|
|
end = virt_to_idmap(text_end);
|
|
+#endif
|
|
pr_info("Setting up static identity map for 0x%lx - 0x%lx\n", addr, end);
|
|
|
|
prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
|
|
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
|
|
index 2129070065c323..1c5aeba9bc27f3 100644
|
|
--- a/arch/arm/mm/ioremap.c
|
|
+++ b/arch/arm/mm/ioremap.c
|
|
@@ -23,6 +23,7 @@
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/errno.h>
|
|
+#include <linux/kasan.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/io.h>
|
|
@@ -115,16 +116,40 @@ int ioremap_page(unsigned long virt, unsigned long phys,
|
|
}
|
|
EXPORT_SYMBOL(ioremap_page);
|
|
|
|
+#ifdef CONFIG_KASAN
|
|
+static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
|
|
+{
|
|
+ return (unsigned long)kasan_mem_to_shadow((void *)addr);
|
|
+}
|
|
+#else
|
|
+static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static void memcpy_pgd(struct mm_struct *mm, unsigned long start,
|
|
+ unsigned long end)
|
|
+{
|
|
+ end = ALIGN(end, PGDIR_SIZE);
|
|
+ memcpy(pgd_offset(mm, start), pgd_offset_k(start),
|
|
+ sizeof(pgd_t) * (pgd_index(end) - pgd_index(start)));
|
|
+}
|
|
+
|
|
void __check_vmalloc_seq(struct mm_struct *mm)
|
|
{
|
|
int seq;
|
|
|
|
do {
|
|
- seq = atomic_read(&init_mm.context.vmalloc_seq);
|
|
- memcpy(pgd_offset(mm, VMALLOC_START),
|
|
- pgd_offset_k(VMALLOC_START),
|
|
- sizeof(pgd_t) * (pgd_index(VMALLOC_END) -
|
|
- pgd_index(VMALLOC_START)));
|
|
+ seq = atomic_read_acquire(&init_mm.context.vmalloc_seq);
|
|
+ memcpy_pgd(mm, VMALLOC_START, VMALLOC_END);
|
|
+ if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
|
|
+ unsigned long start =
|
|
+ arm_kasan_mem_to_shadow(VMALLOC_START);
|
|
+ unsigned long end =
|
|
+ arm_kasan_mem_to_shadow(VMALLOC_END);
|
|
+ memcpy_pgd(mm, start, end);
|
|
+ }
|
|
/*
|
|
* Use a store-release so that other CPUs that observe the
|
|
* counter's new value are guaranteed to see the results of the
|
|
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
|
index 87847116ab6d9b..b0885a38995102 100644
|
|
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
|
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
|
@@ -202,6 +202,9 @@ accelerometer@68 {
|
|
interrupts = <7 5 IRQ_TYPE_EDGE_RISING>; /* PH5 */
|
|
vdd-supply = <®_dldo1>;
|
|
vddio-supply = <®_dldo1>;
|
|
+ mount-matrix = "0", "1", "0",
|
|
+ "-1", "0", "0",
|
|
+ "0", "0", "1";
|
|
};
|
|
};
|
|
|
|
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
|
|
index 14d20a33af8e15..6c48fa4b0d0c4f 100644
|
|
--- a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
|
|
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
|
|
@@ -145,7 +145,7 @@ reg_usdhc2_vmmc: regulator-usdhc2 {
|
|
regulator-max-microvolt = <3300000>;
|
|
regulator-min-microvolt = <3300000>;
|
|
regulator-name = "+V3.3_SD";
|
|
- startup-delay-us = <2000>;
|
|
+ startup-delay-us = <20000>;
|
|
};
|
|
|
|
reserved-memory {
|
|
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
|
|
index e9e4fcb562f10c..b9902adbfe6248 100644
|
|
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
|
|
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
|
|
@@ -134,7 +134,7 @@ reg_usdhc2_vmmc: regulator-usdhc2 {
|
|
regulator-max-microvolt = <3300000>;
|
|
regulator-min-microvolt = <3300000>;
|
|
regulator-name = "+V3.3_SD";
|
|
- startup-delay-us = <2000>;
|
|
+ startup-delay-us = <20000>;
|
|
};
|
|
|
|
reserved-memory {
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt6357.dtsi b/arch/arm64/boot/dts/mediatek/mt6357.dtsi
|
|
index 3330a03c2f7453..5fafa842d312f3 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt6357.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt6357.dtsi
|
|
@@ -10,6 +10,11 @@ &pwrap {
|
|
mt6357_pmic: pmic {
|
|
compatible = "mediatek,mt6357";
|
|
|
|
+ pmic_adc: adc {
|
|
+ compatible = "mediatek,mt6357-auxadc";
|
|
+ #io-channel-cells = <1>;
|
|
+ };
|
|
+
|
|
regulators {
|
|
mt6357_vproc_reg: buck-vproc {
|
|
regulator-name = "vproc";
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt6358.dtsi b/arch/arm64/boot/dts/mediatek/mt6358.dtsi
|
|
index b605313bed99d1..9a549069a483ea 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt6358.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt6358.dtsi
|
|
@@ -12,12 +12,17 @@ pmic: pmic {
|
|
interrupts = <182 IRQ_TYPE_LEVEL_HIGH>;
|
|
#interrupt-cells = <2>;
|
|
|
|
- mt6358codec: mt6358codec {
|
|
+ pmic_adc: adc {
|
|
+ compatible = "mediatek,mt6358-auxadc";
|
|
+ #io-channel-cells = <1>;
|
|
+ };
|
|
+
|
|
+ mt6358codec: audio-codec {
|
|
compatible = "mediatek,mt6358-sound";
|
|
mediatek,dmic-mode = <0>; /* two-wires */
|
|
};
|
|
|
|
- mt6358regulator: mt6358regulator {
|
|
+ mt6358regulator: regulators {
|
|
compatible = "mediatek,mt6358-regulator";
|
|
|
|
mt6358_vdram1_reg: buck_vdram1 {
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt6359.dtsi b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
|
|
index df3e822232d340..8e1b8c85c6ede9 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt6359.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt6359.dtsi
|
|
@@ -9,6 +9,11 @@ pmic: pmic {
|
|
interrupt-controller;
|
|
#interrupt-cells = <2>;
|
|
|
|
+ pmic_adc: adc {
|
|
+ compatible = "mediatek,mt6359-auxadc";
|
|
+ #io-channel-cells = <1>;
|
|
+ };
|
|
+
|
|
mt6359codec: mt6359codec {
|
|
};
|
|
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
|
|
index bdcd35cecad908..fd6230352f4fd1 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
|
|
@@ -43,6 +43,14 @@ trackpad2: trackpad@2c {
|
|
interrupts = <117 IRQ_TYPE_LEVEL_LOW>;
|
|
reg = <0x2c>;
|
|
hid-descr-addr = <0x0020>;
|
|
+ /*
|
|
+ * The trackpad needs a post-power-on delay of 100ms,
|
|
+ * but at time of writing, the power supply for it on
|
|
+ * this board is always on. The delay is therefore not
|
|
+ * added to avoid impacting the readiness of the
|
|
+ * trackpad.
|
|
+ */
|
|
+ vdd-supply = <&mt6397_vgp6_reg>;
|
|
wakeup-source;
|
|
};
|
|
};
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts
|
|
index 19c1e2bee494c9..20b71f2e7159ad 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dts
|
|
@@ -30,3 +30,6 @@ touchscreen@2c {
|
|
};
|
|
};
|
|
|
|
+&i2c2 {
|
|
+ i2c-scl-internal-delay-ns = <4100>;
|
|
+};
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts
|
|
index 072133fb0f0162..47905f84bc1613 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-cozmo.dts
|
|
@@ -17,6 +17,8 @@ &i2c_tunnel {
|
|
};
|
|
|
|
&i2c2 {
|
|
+ i2c-scl-internal-delay-ns = <25000>;
|
|
+
|
|
trackpad@2c {
|
|
compatible = "hid-over-i2c";
|
|
reg = <0x2c>;
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts
|
|
index 552bfc72699945..9a166dccd727c7 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dts
|
|
@@ -31,3 +31,6 @@ &qca_wifi {
|
|
qcom,ath10k-calibration-variant = "GO_DAMU";
|
|
};
|
|
|
|
+&i2c2 {
|
|
+ i2c-scl-internal-delay-ns = <20000>;
|
|
+};
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi
|
|
index bbe6c338f465ee..f9c1ec366b2660 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel.dtsi
|
|
@@ -25,3 +25,6 @@ trackpad@2c {
|
|
};
|
|
};
|
|
|
|
+&i2c2 {
|
|
+ i2c-scl-internal-delay-ns = <21500>;
|
|
+};
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
|
|
index 32f6899f885ef7..629c4b7ecbc629 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi.dtsi
|
|
@@ -8,28 +8,32 @@
|
|
#include <arm/cros-ec-keyboard.dtsi>
|
|
|
|
/ {
|
|
- pp1200_mipibrdg: pp1200-mipibrdg {
|
|
+ pp1000_mipibrdg: pp1000-mipibrdg {
|
|
compatible = "regulator-fixed";
|
|
- regulator-name = "pp1200_mipibrdg";
|
|
+ regulator-name = "pp1000_mipibrdg";
|
|
+ regulator-min-microvolt = <1000000>;
|
|
+ regulator-max-microvolt = <1000000>;
|
|
pinctrl-names = "default";
|
|
- pinctrl-0 = <&pp1200_mipibrdg_en>;
|
|
+ pinctrl-0 = <&pp1000_mipibrdg_en>;
|
|
|
|
enable-active-high;
|
|
regulator-boot-on;
|
|
|
|
gpio = <&pio 54 GPIO_ACTIVE_HIGH>;
|
|
+ vin-supply = <&pp1800_alw>;
|
|
};
|
|
|
|
pp1800_mipibrdg: pp1800-mipibrdg {
|
|
compatible = "regulator-fixed";
|
|
regulator-name = "pp1800_mipibrdg";
|
|
pinctrl-names = "default";
|
|
- pinctrl-0 = <&pp1800_lcd_en>;
|
|
+ pinctrl-0 = <&pp1800_mipibrdg_en>;
|
|
|
|
enable-active-high;
|
|
regulator-boot-on;
|
|
|
|
gpio = <&pio 36 GPIO_ACTIVE_HIGH>;
|
|
+ vin-supply = <&pp1800_alw>;
|
|
};
|
|
|
|
pp3300_panel: pp3300-panel {
|
|
@@ -44,18 +48,20 @@ pp3300_panel: pp3300-panel {
|
|
regulator-boot-on;
|
|
|
|
gpio = <&pio 35 GPIO_ACTIVE_HIGH>;
|
|
+ vin-supply = <&pp3300_alw>;
|
|
};
|
|
|
|
- vddio_mipibrdg: vddio-mipibrdg {
|
|
+ pp3300_mipibrdg: pp3300-mipibrdg {
|
|
compatible = "regulator-fixed";
|
|
- regulator-name = "vddio_mipibrdg";
|
|
+ regulator-name = "pp3300_mipibrdg";
|
|
pinctrl-names = "default";
|
|
- pinctrl-0 = <&vddio_mipibrdg_en>;
|
|
+ pinctrl-0 = <&pp3300_mipibrdg_en>;
|
|
|
|
enable-active-high;
|
|
regulator-boot-on;
|
|
|
|
gpio = <&pio 37 GPIO_ACTIVE_HIGH>;
|
|
+ vin-supply = <&pp3300_alw>;
|
|
};
|
|
|
|
volume_buttons: volume-buttons {
|
|
@@ -152,9 +158,9 @@ anx_bridge: anx7625@58 {
|
|
panel_flags = <1>;
|
|
enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>;
|
|
reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>;
|
|
- vdd10-supply = <&pp1200_mipibrdg>;
|
|
+ vdd10-supply = <&pp1000_mipibrdg>;
|
|
vdd18-supply = <&pp1800_mipibrdg>;
|
|
- vdd33-supply = <&vddio_mipibrdg>;
|
|
+ vdd33-supply = <&pp3300_mipibrdg>;
|
|
|
|
ports {
|
|
#address-cells = <1>;
|
|
@@ -397,14 +403,14 @@ &pio {
|
|
"",
|
|
"";
|
|
|
|
- pp1200_mipibrdg_en: pp1200-mipibrdg-en {
|
|
+ pp1000_mipibrdg_en: pp1000-mipibrdg-en {
|
|
pins1 {
|
|
pinmux = <PINMUX_GPIO54__FUNC_GPIO54>;
|
|
output-low;
|
|
};
|
|
};
|
|
|
|
- pp1800_lcd_en: pp1800-lcd-en {
|
|
+ pp1800_mipibrdg_en: pp1800-mipibrdg-en {
|
|
pins1 {
|
|
pinmux = <PINMUX_GPIO36__FUNC_GPIO36>;
|
|
output-low;
|
|
@@ -466,7 +472,7 @@ trackpad-int {
|
|
};
|
|
};
|
|
|
|
- vddio_mipibrdg_en: vddio-mipibrdg-en {
|
|
+ pp3300_mipibrdg_en: pp3300-mipibrdg-en {
|
|
pins1 {
|
|
pinmux = <PINMUX_GPIO37__FUNC_GPIO37>;
|
|
output-low;
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
|
|
index 0d3c7b8162ff0b..9eca1c80fe0107 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
|
|
@@ -105,9 +105,9 @@ &i2c4 {
|
|
clock-frequency = <400000>;
|
|
vbus-supply = <&mt6358_vcn18_reg>;
|
|
|
|
- eeprom@54 {
|
|
+ eeprom@50 {
|
|
compatible = "atmel,24c32";
|
|
- reg = <0x54>;
|
|
+ reg = <0x50>;
|
|
pagesize = <32>;
|
|
vcc-supply = <&mt6358_vcn18_reg>;
|
|
};
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
|
|
index e73113cb51f538..29216ebe4de845 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
|
|
@@ -80,9 +80,9 @@ &i2c4 {
|
|
clock-frequency = <400000>;
|
|
vbus-supply = <&mt6358_vcn18_reg>;
|
|
|
|
- eeprom@54 {
|
|
+ eeprom@50 {
|
|
compatible = "atmel,24c64";
|
|
- reg = <0x54>;
|
|
+ reg = <0x50>;
|
|
pagesize = <32>;
|
|
vcc-supply = <&mt6358_vcn18_reg>;
|
|
};
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
|
|
index 181da69d18f46a..b0469a95ddc430 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
|
|
@@ -89,9 +89,9 @@ &i2c4 {
|
|
clock-frequency = <400000>;
|
|
vbus-supply = <&mt6358_vcn18_reg>;
|
|
|
|
- eeprom@54 {
|
|
+ eeprom@50 {
|
|
compatible = "atmel,24c32";
|
|
- reg = <0x54>;
|
|
+ reg = <0x50>;
|
|
pagesize = <32>;
|
|
vcc-supply = <&mt6358_vcn18_reg>;
|
|
};
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
|
|
index 34e18eb5d7f450..b21663b46b5192 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
|
|
@@ -1296,6 +1296,7 @@ &xhci1 {
|
|
|
|
vusb33-supply = <&mt6359_vusb_ldo_reg>;
|
|
vbus-supply = <&usb_vbus>;
|
|
+ mediatek,u3p-dis-msk = <1>;
|
|
};
|
|
|
|
&xhci2 {
|
|
@@ -1312,7 +1313,6 @@ &xhci3 {
|
|
usb2-lpm-disable;
|
|
vusb33-supply = <&mt6359_vusb_ldo_reg>;
|
|
vbus-supply = <&usb_vbus>;
|
|
- mediatek,u3p-dis-msk = <1>;
|
|
};
|
|
|
|
#include <arm/cros-ec-keyboard.dtsi>
|
|
diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
|
|
index d21ba00a5bd5df..5a087404ccc2d9 100644
|
|
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
|
|
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
|
|
@@ -487,7 +487,7 @@ topckgen: syscon@10000000 {
|
|
};
|
|
|
|
infracfg_ao: syscon@10001000 {
|
|
- compatible = "mediatek,mt8195-infracfg_ao", "syscon", "simple-mfd";
|
|
+ compatible = "mediatek,mt8195-infracfg_ao", "syscon";
|
|
reg = <0 0x10001000 0 0x1000>;
|
|
#clock-cells = <1>;
|
|
#reset-cells = <1>;
|
|
@@ -2845,11 +2845,9 @@ &larb19 &larb21 &larb24 &larb25
|
|
mutex1: mutex@1c101000 {
|
|
compatible = "mediatek,mt8195-disp-mutex";
|
|
reg = <0 0x1c101000 0 0x1000>;
|
|
- reg-names = "vdo1_mutex";
|
|
interrupts = <GIC_SPI 494 IRQ_TYPE_LEVEL_HIGH 0>;
|
|
power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
|
|
clocks = <&vdosys1 CLK_VDO1_DISP_MUTEX>;
|
|
- clock-names = "vdo1_mutex";
|
|
mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x1000 0x1000>;
|
|
mediatek,gce-events = <CMDQ_EVENT_VDO1_STREAM_DONE_ENG_0>;
|
|
};
|
|
diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
|
|
index 92b85de7706d39..dfeeada91b7800 100644
|
|
--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi
|
|
+++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
|
|
@@ -3618,7 +3618,7 @@ lmh@18358800 {
|
|
};
|
|
|
|
cpufreq_hw: cpufreq@18323000 {
|
|
- compatible = "qcom,cpufreq-hw";
|
|
+ compatible = "qcom,sc8180x-cpufreq-hw", "qcom,cpufreq-hw";
|
|
reg = <0 0x18323000 0 0x1400>, <0 0x18325800 0 0x1400>;
|
|
reg-names = "freq-domain0", "freq-domain1";
|
|
|
|
diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi
|
|
index 2efceb49a3218e..f271b69485c5ce 100644
|
|
--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi
|
|
+++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi
|
|
@@ -1351,43 +1351,43 @@ gpu_opp_table: opp-table {
|
|
opp-850000000 {
|
|
opp-hz = /bits/ 64 <850000000>;
|
|
opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
|
|
- opp-supported-hw = <0x02>;
|
|
+ opp-supported-hw = <0x03>;
|
|
};
|
|
|
|
opp-800000000 {
|
|
opp-hz = /bits/ 64 <800000000>;
|
|
opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
|
|
- opp-supported-hw = <0x04>;
|
|
+ opp-supported-hw = <0x07>;
|
|
};
|
|
|
|
opp-650000000 {
|
|
opp-hz = /bits/ 64 <650000000>;
|
|
opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
|
|
- opp-supported-hw = <0x08>;
|
|
+ opp-supported-hw = <0x0f>;
|
|
};
|
|
|
|
opp-565000000 {
|
|
opp-hz = /bits/ 64 <565000000>;
|
|
opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
|
|
- opp-supported-hw = <0x10>;
|
|
+ opp-supported-hw = <0x1f>;
|
|
};
|
|
|
|
opp-430000000 {
|
|
opp-hz = /bits/ 64 <430000000>;
|
|
opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
|
|
- opp-supported-hw = <0xff>;
|
|
+ opp-supported-hw = <0x1f>;
|
|
};
|
|
|
|
opp-355000000 {
|
|
opp-hz = /bits/ 64 <355000000>;
|
|
opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
|
|
- opp-supported-hw = <0xff>;
|
|
+ opp-supported-hw = <0x1f>;
|
|
};
|
|
|
|
opp-253000000 {
|
|
opp-hz = /bits/ 64 <253000000>;
|
|
opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
|
|
- opp-supported-hw = <0xff>;
|
|
+ opp-supported-hw = <0x1f>;
|
|
};
|
|
};
|
|
};
|
|
diff --git a/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi b/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi
|
|
index 8e2db1d6ca81e2..25c55b32aafe5a 100644
|
|
--- a/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi
|
|
+++ b/arch/arm64/boot/dts/renesas/hihope-rev2.dtsi
|
|
@@ -69,9 +69,6 @@ &rcar_sound {
|
|
|
|
status = "okay";
|
|
|
|
- /* Single DAI */
|
|
- #sound-dai-cells = <0>;
|
|
-
|
|
rsnd_port: port {
|
|
rsnd_endpoint: endpoint {
|
|
remote-endpoint = <&dw_hdmi0_snd_in>;
|
|
diff --git a/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi b/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
|
|
index 7fc0339a3ac978..e59191562d06c1 100644
|
|
--- a/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
|
|
+++ b/arch/arm64/boot/dts/renesas/hihope-rev4.dtsi
|
|
@@ -84,9 +84,6 @@ &rcar_sound {
|
|
pinctrl-names = "default";
|
|
status = "okay";
|
|
|
|
- /* Single DAI */
|
|
- #sound-dai-cells = <0>;
|
|
-
|
|
/* audio_clkout0/1/2/3 */
|
|
#clock-cells = <1>;
|
|
clock-frequency = <12288000 11289600>;
|
|
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
|
|
index 9299fa7e3e2150..e813d426be1052 100644
|
|
--- a/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
|
|
+++ b/arch/arm64/boot/dts/rockchip/rk3588s-indiedroid-nova.dts
|
|
@@ -34,7 +34,7 @@ sdio_pwrseq: sdio-pwrseq {
|
|
|
|
sound {
|
|
compatible = "audio-graph-card";
|
|
- label = "rockchip,es8388-codec";
|
|
+ label = "rockchip,es8388";
|
|
widgets = "Microphone", "Mic Jack",
|
|
"Headphone", "Headphones";
|
|
routing = "LINPUT2", "Mic Jack",
|
|
diff --git a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
|
|
index 0a5634ca005dfb..e931c966b7f22b 100644
|
|
--- a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
|
|
+++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi
|
|
@@ -134,7 +134,7 @@ reg_sdhc1_vmmc: regulator-sdhci1 {
|
|
regulator-max-microvolt = <3300000>;
|
|
regulator-min-microvolt = <3300000>;
|
|
regulator-name = "+V3.3_SD";
|
|
- startup-delay-us = <2000>;
|
|
+ startup-delay-us = <20000>;
|
|
};
|
|
|
|
reg_sdhc1_vqmmc: regulator-sdhci1-vqmmc {
|
|
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
|
|
index 7a0c599f2b1c35..9b122117ef72dd 100644
|
|
--- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
|
|
+++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
|
|
@@ -192,7 +192,7 @@ J721E_IOPAD(0xd0, PIN_OUTPUT, 7) /* (T5) SPI0_D1.GPIO0_55 */
|
|
};
|
|
};
|
|
|
|
-&main_pmx1 {
|
|
+&main_pmx2 {
|
|
main_usbss0_pins_default: main-usbss0-default-pins {
|
|
pinctrl-single,pins = <
|
|
J721E_IOPAD(0x04, PIN_OUTPUT, 0) /* (T4) USB0_DRVVBUS */
|
|
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
|
|
index cdb1d6b2a98295..e5ff6f038a9aca 100644
|
|
--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
|
|
+++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
|
|
@@ -395,7 +395,7 @@ cpts@3d000 {
|
|
|
|
/* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */
|
|
main_timerio_input: pinctrl@104200 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
reg = <0x0 0x104200 0x0 0x50>;
|
|
#pinctrl-cells = <1>;
|
|
pinctrl-single,register-width = <32>;
|
|
@@ -404,7 +404,7 @@ main_timerio_input: pinctrl@104200 {
|
|
|
|
/* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */
|
|
main_timerio_output: pinctrl@104280 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
reg = <0x0 0x104280 0x0 0x20>;
|
|
#pinctrl-cells = <1>;
|
|
pinctrl-single,register-width = <32>;
|
|
@@ -412,7 +412,7 @@ main_timerio_output: pinctrl@104280 {
|
|
};
|
|
|
|
main_pmx0: pinctrl@11c000 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
/* Proxy 0 addressing */
|
|
reg = <0x00 0x11c000 0x00 0x10c>;
|
|
#pinctrl-cells = <1>;
|
|
@@ -420,10 +420,28 @@ main_pmx0: pinctrl@11c000 {
|
|
pinctrl-single,function-mask = <0xffffffff>;
|
|
};
|
|
|
|
- main_pmx1: pinctrl@11c11c {
|
|
- compatible = "pinctrl-single";
|
|
+ main_pmx1: pinctrl@11c110 {
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
/* Proxy 0 addressing */
|
|
- reg = <0x00 0x11c11c 0x00 0xc>;
|
|
+ reg = <0x00 0x11c110 0x00 0x004>;
|
|
+ #pinctrl-cells = <1>;
|
|
+ pinctrl-single,register-width = <32>;
|
|
+ pinctrl-single,function-mask = <0xffffffff>;
|
|
+ };
|
|
+
|
|
+ main_pmx2: pinctrl@11c11c {
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
+ /* Proxy 0 addressing */
|
|
+ reg = <0x00 0x11c11c 0x00 0x00c>;
|
|
+ #pinctrl-cells = <1>;
|
|
+ pinctrl-single,register-width = <32>;
|
|
+ pinctrl-single,function-mask = <0xffffffff>;
|
|
+ };
|
|
+
|
|
+ main_pmx3: pinctrl@11c164 {
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
+ /* Proxy 0 addressing */
|
|
+ reg = <0x00 0x11c164 0x00 0x008>;
|
|
#pinctrl-cells = <1>;
|
|
pinctrl-single,register-width = <32>;
|
|
pinctrl-single,function-mask = <0xffffffff>;
|
|
@@ -897,7 +915,7 @@ main_spi0: spi@2100000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 266 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 266 1>;
|
|
+ clocks = <&k3_clks 266 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -908,7 +926,7 @@ main_spi1: spi@2110000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 267 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 267 1>;
|
|
+ clocks = <&k3_clks 267 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -919,7 +937,7 @@ main_spi2: spi@2120000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 268 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 268 1>;
|
|
+ clocks = <&k3_clks 268 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -930,7 +948,7 @@ main_spi3: spi@2130000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 269 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 269 1>;
|
|
+ clocks = <&k3_clks 269 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -941,7 +959,7 @@ main_spi4: spi@2140000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 270 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 270 1>;
|
|
+ clocks = <&k3_clks 270 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -952,7 +970,7 @@ main_spi5: spi@2150000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 271 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 271 1>;
|
|
+ clocks = <&k3_clks 271 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -963,7 +981,7 @@ main_spi6: spi@2160000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 272 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 272 1>;
|
|
+ clocks = <&k3_clks 272 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -974,7 +992,7 @@ main_spi7: spi@2170000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 273 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 273 1>;
|
|
+ clocks = <&k3_clks 273 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
|
|
index 6ffaf85fa63f50..8e9d0a25e23667 100644
|
|
--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
|
|
+++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
|
|
@@ -185,7 +185,7 @@ chipid@43000014 {
|
|
|
|
/* MCU_TIMERIO pad input CTRLMMR_MCU_TIMER*_CTRL registers */
|
|
mcu_timerio_input: pinctrl@40f04200 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
reg = <0x0 0x40f04200 0x0 0x28>;
|
|
#pinctrl-cells = <1>;
|
|
pinctrl-single,register-width = <32>;
|
|
@@ -195,7 +195,7 @@ mcu_timerio_input: pinctrl@40f04200 {
|
|
|
|
/* MCU_TIMERIO pad output CTRLMMR_MCU_TIMERIO*_CTRL registers */
|
|
mcu_timerio_output: pinctrl@40f04280 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
reg = <0x0 0x40f04280 0x0 0x28>;
|
|
#pinctrl-cells = <1>;
|
|
pinctrl-single,register-width = <32>;
|
|
@@ -204,7 +204,7 @@ mcu_timerio_output: pinctrl@40f04280 {
|
|
};
|
|
|
|
wkup_pmx0: pinctrl@4301c000 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
/* Proxy 0 addressing */
|
|
reg = <0x00 0x4301c000 0x00 0x34>;
|
|
#pinctrl-cells = <1>;
|
|
@@ -213,7 +213,7 @@ wkup_pmx0: pinctrl@4301c000 {
|
|
};
|
|
|
|
wkup_pmx1: pinctrl@4301c038 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
/* Proxy 0 addressing */
|
|
reg = <0x00 0x4301c038 0x00 0x8>;
|
|
#pinctrl-cells = <1>;
|
|
@@ -222,7 +222,7 @@ wkup_pmx1: pinctrl@4301c038 {
|
|
};
|
|
|
|
wkup_pmx2: pinctrl@4301c068 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
/* Proxy 0 addressing */
|
|
reg = <0x00 0x4301c068 0x00 0xec>;
|
|
#pinctrl-cells = <1>;
|
|
@@ -231,7 +231,7 @@ wkup_pmx2: pinctrl@4301c068 {
|
|
};
|
|
|
|
wkup_pmx3: pinctrl@4301c174 {
|
|
- compatible = "pinctrl-single";
|
|
+ compatible = "ti,j7200-padconf", "pinctrl-single";
|
|
/* Proxy 0 addressing */
|
|
reg = <0x00 0x4301c174 0x00 0x20>;
|
|
#pinctrl-cells = <1>;
|
|
@@ -481,7 +481,7 @@ mcu_spi0: spi@40300000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 274 0>;
|
|
+ clocks = <&k3_clks 274 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -492,7 +492,7 @@ mcu_spi1: spi@40310000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 275 0>;
|
|
+ clocks = <&k3_clks 275 4>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -503,7 +503,7 @@ mcu_spi2: spi@40320000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 276 0>;
|
|
+ clocks = <&k3_clks 276 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
|
|
index 05d6ef127ba784..1893d611b17357 100644
|
|
--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
|
|
+++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
|
|
@@ -637,7 +637,7 @@ mcu_spi0: spi@40300000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 274 0>;
|
|
+ clocks = <&k3_clks 274 1>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -648,7 +648,7 @@ mcu_spi1: spi@40310000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 275 0>;
|
|
+ clocks = <&k3_clks 275 1>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -659,7 +659,7 @@ mcu_spi2: spi@40320000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 276 0>;
|
|
+ clocks = <&k3_clks 276 1>;
|
|
status = "disabled";
|
|
};
|
|
|
|
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
|
|
index 084f8f5b669931..9484347acba794 100644
|
|
--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
|
|
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
|
|
@@ -1569,7 +1569,7 @@ main_spi0: spi@2100000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 339 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 339 1>;
|
|
+ clocks = <&k3_clks 339 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -1580,7 +1580,7 @@ main_spi1: spi@2110000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 340 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 340 1>;
|
|
+ clocks = <&k3_clks 340 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -1591,7 +1591,7 @@ main_spi2: spi@2120000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 341 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 341 1>;
|
|
+ clocks = <&k3_clks 341 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -1602,7 +1602,7 @@ main_spi3: spi@2130000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 342 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 342 1>;
|
|
+ clocks = <&k3_clks 342 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -1613,7 +1613,7 @@ main_spi4: spi@2140000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 343 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 343 1>;
|
|
+ clocks = <&k3_clks 343 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -1624,7 +1624,7 @@ main_spi5: spi@2150000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 344 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 344 1>;
|
|
+ clocks = <&k3_clks 344 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -1635,7 +1635,7 @@ main_spi6: spi@2160000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 345 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 345 1>;
|
|
+ clocks = <&k3_clks 345 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -1646,7 +1646,7 @@ main_spi7: spi@2170000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 346 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 346 1>;
|
|
+ clocks = <&k3_clks 346 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
|
|
index 71324fec415ae2..6fc008fbfb003f 100644
|
|
--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
|
|
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
|
|
@@ -416,7 +416,7 @@ mcu_spi0: spi@40300000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 347 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 347 0>;
|
|
+ clocks = <&k3_clks 347 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -427,7 +427,7 @@ mcu_spi1: spi@40310000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 348 0>;
|
|
+ clocks = <&k3_clks 348 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
@@ -438,7 +438,7 @@ mcu_spi2: spi@40320000 {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>;
|
|
- clocks = <&k3_clks 349 0>;
|
|
+ clocks = <&k3_clks 349 2>;
|
|
status = "disabled";
|
|
};
|
|
|
|
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
|
|
index db1aeacd4cd99d..0ccf51afde31a6 100644
|
|
--- a/arch/arm64/include/asm/insn.h
|
|
+++ b/arch/arm64/include/asm/insn.h
|
|
@@ -347,6 +347,7 @@ __AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000)
|
|
__AARCH64_INSN_FUNCS(exclusive, 0x3F800000, 0x08000000)
|
|
__AARCH64_INSN_FUNCS(load_ex, 0x3F400000, 0x08400000)
|
|
__AARCH64_INSN_FUNCS(store_ex, 0x3F400000, 0x08000000)
|
|
+__AARCH64_INSN_FUNCS(mops, 0x3B200C00, 0x19000400)
|
|
__AARCH64_INSN_FUNCS(stp, 0x7FC00000, 0x29000000)
|
|
__AARCH64_INSN_FUNCS(ldp, 0x7FC00000, 0x29400000)
|
|
__AARCH64_INSN_FUNCS(stp_post, 0x7FC00000, 0x28800000)
|
|
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
|
|
index af06ccb7ee3433..b84ed3ad91a9eb 100644
|
|
--- a/arch/arm64/include/asm/kvm_host.h
|
|
+++ b/arch/arm64/include/asm/kvm_host.h
|
|
@@ -72,8 +72,6 @@ enum kvm_mode kvm_get_mode(void);
|
|
static inline enum kvm_mode kvm_get_mode(void) { return KVM_MODE_NONE; };
|
|
#endif
|
|
|
|
-DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
|
|
-
|
|
extern unsigned int __ro_after_init kvm_sve_max_vl;
|
|
int __init kvm_arm_init_sve(void);
|
|
|
|
diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c
|
|
index 3496d6169e59b2..42b69936cee34b 100644
|
|
--- a/arch/arm64/kernel/probes/decode-insn.c
|
|
+++ b/arch/arm64/kernel/probes/decode-insn.c
|
|
@@ -58,10 +58,13 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn)
|
|
* Instructions which load PC relative literals are not going to work
|
|
* when executed from an XOL slot. Instructions doing an exclusive
|
|
* load/store are not going to complete successfully when single-step
|
|
- * exception handling happens in the middle of the sequence.
|
|
+ * exception handling happens in the middle of the sequence. Memory
|
|
+ * copy/set instructions require that all three instructions be placed
|
|
+ * consecutively in memory.
|
|
*/
|
|
if (aarch64_insn_uses_literal(insn) ||
|
|
- aarch64_insn_is_exclusive(insn))
|
|
+ aarch64_insn_is_exclusive(insn) ||
|
|
+ aarch64_insn_is_mops(insn))
|
|
return false;
|
|
|
|
return true;
|
|
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
|
|
index 0fcc4eb1a7abcc..385fb78845d696 100644
|
|
--- a/arch/arm64/kernel/process.c
|
|
+++ b/arch/arm64/kernel/process.c
|
|
@@ -429,7 +429,7 @@ static void tls_thread_switch(struct task_struct *next)
|
|
|
|
if (is_compat_thread(task_thread_info(next)))
|
|
write_sysreg(next->thread.uw.tp_value, tpidrro_el0);
|
|
- else if (!arm64_kernel_unmapped_at_el0())
|
|
+ else
|
|
write_sysreg(0, tpidrro_el0);
|
|
|
|
write_sysreg(*task_user_tls(next), tpidr_el0);
|
|
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
|
|
index c583d1f335f8c7..040b0175334c05 100644
|
|
--- a/arch/arm64/kernel/setup.c
|
|
+++ b/arch/arm64/kernel/setup.c
|
|
@@ -190,7 +190,11 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
|
|
if (dt_virt)
|
|
memblock_reserve(dt_phys, size);
|
|
|
|
- if (!dt_virt || !early_init_dt_scan(dt_virt)) {
|
|
+ /*
|
|
+ * dt_virt is a fixmap address, hence __pa(dt_virt) can't be used.
|
|
+ * Pass dt_phys directly.
|
|
+ */
|
|
+ if (!early_init_dt_scan(dt_virt, dt_phys)) {
|
|
pr_crit("\n"
|
|
"Error: invalid device tree blob at physical address %pa (virtual address 0x%px)\n"
|
|
"The dtb must be 8-byte aligned and must not exceed 2 MB in size\n"
|
|
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
|
|
index 3cd7e76cc56266..a553dae9a0d482 100644
|
|
--- a/arch/arm64/kernel/vmlinux.lds.S
|
|
+++ b/arch/arm64/kernel/vmlinux.lds.S
|
|
@@ -285,6 +285,9 @@ SECTIONS
|
|
__initdata_end = .;
|
|
__init_end = .;
|
|
|
|
+ .data.rel.ro : { *(.data.rel.ro) }
|
|
+ ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!")
|
|
+
|
|
_data = .;
|
|
_sdata = .;
|
|
RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_ALIGN)
|
|
@@ -336,9 +339,6 @@ SECTIONS
|
|
*(.plt) *(.plt.*) *(.iplt) *(.igot .igot.plt)
|
|
}
|
|
ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")
|
|
-
|
|
- .data.rel.ro : { *(.data.rel.ro) }
|
|
- ASSERT(SIZEOF(.data.rel.ro) == 0, "Unexpected RELRO detected!")
|
|
}
|
|
|
|
#include "image-vars.h"
|
|
diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
|
|
index a1e24228aaaa76..d221829502f3e0 100644
|
|
--- a/arch/arm64/kvm/arch_timer.c
|
|
+++ b/arch/arm64/kvm/arch_timer.c
|
|
@@ -206,8 +206,7 @@ void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map)
|
|
|
|
static inline bool userspace_irqchip(struct kvm *kvm)
|
|
{
|
|
- return static_branch_unlikely(&userspace_irqchip_in_use) &&
|
|
- unlikely(!irqchip_in_kernel(kvm));
|
|
+ return unlikely(!irqchip_in_kernel(kvm));
|
|
}
|
|
|
|
static void soft_timer_start(struct hrtimer *hrt, u64 ns)
|
|
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
|
|
index 18413d869cca1a..4742e6c5ea7a00 100644
|
|
--- a/arch/arm64/kvm/arm.c
|
|
+++ b/arch/arm64/kvm/arm.c
|
|
@@ -57,7 +57,6 @@ DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
|
|
static bool vgic_present, kvm_arm_initialised;
|
|
|
|
static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized);
|
|
-DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
|
|
|
|
bool is_kvm_arm_initialised(void)
|
|
{
|
|
@@ -401,9 +400,6 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
|
|
|
|
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
|
|
{
|
|
- if (vcpu_has_run_once(vcpu) && unlikely(!irqchip_in_kernel(vcpu->kvm)))
|
|
- static_branch_dec(&userspace_irqchip_in_use);
|
|
-
|
|
kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
|
|
kvm_timer_vcpu_terminate(vcpu);
|
|
kvm_pmu_vcpu_destroy(vcpu);
|
|
@@ -627,14 +623,6 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
|
|
return ret;
|
|
}
|
|
|
|
- if (!irqchip_in_kernel(kvm)) {
|
|
- /*
|
|
- * Tell the rest of the code that there are userspace irqchip
|
|
- * VMs in the wild.
|
|
- */
|
|
- static_branch_inc(&userspace_irqchip_in_use);
|
|
- }
|
|
-
|
|
/*
|
|
* Initialize traps for protected VMs.
|
|
* NOTE: Move to run in EL2 directly, rather than via a hypercall, once
|
|
@@ -856,7 +844,7 @@ static bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu, int *ret)
|
|
* state gets updated in kvm_timer_update_run and
|
|
* kvm_pmu_update_run below).
|
|
*/
|
|
- if (static_branch_unlikely(&userspace_irqchip_in_use)) {
|
|
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm))) {
|
|
if (kvm_timer_should_notify_user(vcpu) ||
|
|
kvm_pmu_should_notify_user(vcpu)) {
|
|
*ret = -EINTR;
|
|
@@ -975,7 +963,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
|
vcpu->mode = OUTSIDE_GUEST_MODE;
|
|
isb(); /* Ensure work in x_flush_hwstate is committed */
|
|
kvm_pmu_sync_hwstate(vcpu);
|
|
- if (static_branch_unlikely(&userspace_irqchip_in_use))
|
|
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
|
|
kvm_timer_sync_user(vcpu);
|
|
kvm_vgic_sync_hwstate(vcpu);
|
|
local_irq_enable();
|
|
@@ -1021,7 +1009,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
|
* we don't want vtimer interrupts to race with syncing the
|
|
* timer virtual interrupt state.
|
|
*/
|
|
- if (static_branch_unlikely(&userspace_irqchip_in_use))
|
|
+ if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
|
|
kvm_timer_sync_user(vcpu);
|
|
|
|
kvm_arch_vcpu_ctxsync_fp(vcpu);
|
|
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
|
|
index 6b066e04dc5dfe..3867d6d1f5d1bd 100644
|
|
--- a/arch/arm64/kvm/pmu-emul.c
|
|
+++ b/arch/arm64/kvm/pmu-emul.c
|
|
@@ -326,7 +326,6 @@ static u64 kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
|
|
|
|
if ((__vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E)) {
|
|
reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
|
|
- reg &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
|
|
reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
|
|
}
|
|
|
|
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
|
|
index 4f9084ba7949c0..608c39859f4ec3 100644
|
|
--- a/arch/arm64/kvm/vgic/vgic-its.c
|
|
+++ b/arch/arm64/kvm/vgic/vgic-its.c
|
|
@@ -855,6 +855,9 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
|
|
|
|
ite = find_ite(its, device_id, event_id);
|
|
if (ite && its_is_collection_mapped(ite->collection)) {
|
|
+ struct its_device *device = find_its_device(its, device_id);
|
|
+ int ite_esz = vgic_its_get_abi(its)->ite_esz;
|
|
+ gpa_t gpa = device->itt_addr + ite->event_id * ite_esz;
|
|
/*
|
|
* Though the spec talks about removing the pending state, we
|
|
* don't bother here since we clear the ITTE anyway and the
|
|
@@ -863,7 +866,8 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
|
|
vgic_its_invalidate_cache(kvm);
|
|
|
|
its_free_ite(kvm, ite);
|
|
- return 0;
|
|
+
|
|
+ return vgic_its_write_entry_lock(its, gpa, 0, ite_esz);
|
|
}
|
|
|
|
return E_ITS_DISCARD_UNMAPPED_INTERRUPT;
|
|
@@ -1211,9 +1215,11 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
|
|
bool valid = its_cmd_get_validbit(its_cmd);
|
|
u8 num_eventid_bits = its_cmd_get_size(its_cmd);
|
|
gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd);
|
|
+ int dte_esz = vgic_its_get_abi(its)->dte_esz;
|
|
struct its_device *device;
|
|
+ gpa_t gpa;
|
|
|
|
- if (!vgic_its_check_id(its, its->baser_device_table, device_id, NULL))
|
|
+ if (!vgic_its_check_id(its, its->baser_device_table, device_id, &gpa))
|
|
return E_ITS_MAPD_DEVICE_OOR;
|
|
|
|
if (valid && num_eventid_bits > VITS_TYPER_IDBITS)
|
|
@@ -1234,7 +1240,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
|
|
* is an error, so we are done in any case.
|
|
*/
|
|
if (!valid)
|
|
- return 0;
|
|
+ return vgic_its_write_entry_lock(its, gpa, 0, dte_esz);
|
|
|
|
device = vgic_its_alloc_device(its, device_id, itt_addr,
|
|
num_eventid_bits);
|
|
@@ -2207,7 +2213,6 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz,
|
|
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
|
struct its_ite *ite, gpa_t gpa, int ite_esz)
|
|
{
|
|
- struct kvm *kvm = its->dev->kvm;
|
|
u32 next_offset;
|
|
u64 val;
|
|
|
|
@@ -2216,7 +2221,8 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
|
|
((u64)ite->irq->intid << KVM_ITS_ITE_PINTID_SHIFT) |
|
|
ite->collection->collection_id;
|
|
val = cpu_to_le64(val);
|
|
- return vgic_write_guest_lock(kvm, gpa, &val, ite_esz);
|
|
+
|
|
+ return vgic_its_write_entry_lock(its, gpa, val, ite_esz);
|
|
}
|
|
|
|
/**
|
|
@@ -2357,7 +2363,6 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
|
|
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
|
|
gpa_t ptr, int dte_esz)
|
|
{
|
|
- struct kvm *kvm = its->dev->kvm;
|
|
u64 val, itt_addr_field;
|
|
u32 next_offset;
|
|
|
|
@@ -2368,7 +2373,8 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
|
|
(itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
|
|
(dev->num_eventid_bits - 1));
|
|
val = cpu_to_le64(val);
|
|
- return vgic_write_guest_lock(kvm, ptr, &val, dte_esz);
|
|
+
|
|
+ return vgic_its_write_entry_lock(its, ptr, val, dte_esz);
|
|
}
|
|
|
|
/**
|
|
@@ -2555,7 +2561,8 @@ static int vgic_its_save_cte(struct vgic_its *its,
|
|
((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
|
|
collection->collection_id);
|
|
val = cpu_to_le64(val);
|
|
- return vgic_write_guest_lock(its->dev->kvm, gpa, &val, esz);
|
|
+
|
|
+ return vgic_its_write_entry_lock(its, gpa, val, esz);
|
|
}
|
|
|
|
/*
|
|
@@ -2571,8 +2578,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
|
|
u64 val;
|
|
int ret;
|
|
|
|
- BUG_ON(esz > sizeof(val));
|
|
- ret = kvm_read_guest_lock(kvm, gpa, &val, esz);
|
|
+ ret = vgic_its_read_entry_lock(its, gpa, &val, esz);
|
|
if (ret)
|
|
return ret;
|
|
val = le64_to_cpu(val);
|
|
@@ -2610,7 +2616,6 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
|
|
u64 baser = its->baser_coll_table;
|
|
gpa_t gpa = GITS_BASER_ADDR_48_to_52(baser);
|
|
struct its_collection *collection;
|
|
- u64 val;
|
|
size_t max_size, filled = 0;
|
|
int ret, cte_esz = abi->cte_esz;
|
|
|
|
@@ -2634,10 +2639,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
|
|
* table is not fully filled, add a last dummy element
|
|
* with valid bit unset
|
|
*/
|
|
- val = 0;
|
|
- BUG_ON(cte_esz > sizeof(val));
|
|
- ret = vgic_write_guest_lock(its->dev->kvm, gpa, &val, cte_esz);
|
|
- return ret;
|
|
+ return vgic_its_write_entry_lock(its, gpa, 0, cte_esz);
|
|
}
|
|
|
|
/**
|
|
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
|
|
index 48e8b60ff1e338..7c0b23415ad9b0 100644
|
|
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
|
|
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
|
|
@@ -555,6 +555,7 @@ static void vgic_mmio_write_invlpi(struct kvm_vcpu *vcpu,
|
|
unsigned long val)
|
|
{
|
|
struct vgic_irq *irq;
|
|
+ u32 intid;
|
|
|
|
/*
|
|
* If the guest wrote only to the upper 32bit part of the
|
|
@@ -566,9 +567,13 @@ static void vgic_mmio_write_invlpi(struct kvm_vcpu *vcpu,
|
|
if ((addr & 4) || !vgic_lpis_enabled(vcpu))
|
|
return;
|
|
|
|
+ intid = lower_32_bits(val);
|
|
+ if (intid < VGIC_MIN_LPI)
|
|
+ return;
|
|
+
|
|
vgic_set_rdist_busy(vcpu, true);
|
|
|
|
- irq = vgic_get_irq(vcpu->kvm, NULL, lower_32_bits(val));
|
|
+ irq = vgic_get_irq(vcpu->kvm, NULL, intid);
|
|
if (irq) {
|
|
vgic_its_inv_lpi(vcpu->kvm, irq);
|
|
vgic_put_irq(vcpu->kvm, irq);
|
|
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
|
|
index 07e48f8a4f23b3..3fa68827dc89fc 100644
|
|
--- a/arch/arm64/kvm/vgic/vgic.h
|
|
+++ b/arch/arm64/kvm/vgic/vgic.h
|
|
@@ -145,6 +145,29 @@ static inline int vgic_write_guest_lock(struct kvm *kvm, gpa_t gpa,
|
|
return ret;
|
|
}
|
|
|
|
+static inline int vgic_its_read_entry_lock(struct vgic_its *its, gpa_t eaddr,
|
|
+ u64 *eval, unsigned long esize)
|
|
+{
|
|
+ struct kvm *kvm = its->dev->kvm;
|
|
+
|
|
+ if (KVM_BUG_ON(esize != sizeof(*eval), kvm))
|
|
+ return -EINVAL;
|
|
+
|
|
+ return kvm_read_guest_lock(kvm, eaddr, eval, esize);
|
|
+
|
|
+}
|
|
+
|
|
+static inline int vgic_its_write_entry_lock(struct vgic_its *its, gpa_t eaddr,
|
|
+ u64 eval, unsigned long esize)
|
|
+{
|
|
+ struct kvm *kvm = its->dev->kvm;
|
|
+
|
|
+ if (KVM_BUG_ON(esize != sizeof(eval), kvm))
|
|
+ return -EINVAL;
|
|
+
|
|
+ return vgic_write_guest_lock(kvm, eaddr, &eval, esize);
|
|
+}
|
|
+
|
|
/*
|
|
* This struct provides an intermediate representation of the fields contained
|
|
* in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC
|
|
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
|
|
index 166619348b98e4..5074bd1d37b5f6 100644
|
|
--- a/arch/arm64/net/bpf_jit_comp.c
|
|
+++ b/arch/arm64/net/bpf_jit_comp.c
|
|
@@ -1816,6 +1816,12 @@ static void restore_args(struct jit_ctx *ctx, int args_off, int nregs)
|
|
}
|
|
}
|
|
|
|
+static bool is_struct_ops_tramp(const struct bpf_tramp_links *fentry_links)
|
|
+{
|
|
+ return fentry_links->nr_links == 1 &&
|
|
+ fentry_links->links[0]->link.type == BPF_LINK_TYPE_STRUCT_OPS;
|
|
+}
|
|
+
|
|
/* Based on the x86's implementation of arch_prepare_bpf_trampoline().
|
|
*
|
|
* bpf prog and function entry before bpf trampoline hooked:
|
|
@@ -1845,6 +1851,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
|
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
|
|
bool save_ret;
|
|
__le32 **branches = NULL;
|
|
+ bool is_struct_ops = is_struct_ops_tramp(fentry);
|
|
|
|
/* trampoline stack layout:
|
|
* [ parent ip ]
|
|
@@ -1913,11 +1920,14 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
|
*/
|
|
emit_bti(A64_BTI_JC, ctx);
|
|
|
|
- /* frame for parent function */
|
|
- emit(A64_PUSH(A64_FP, A64_R(9), A64_SP), ctx);
|
|
- emit(A64_MOV(1, A64_FP, A64_SP), ctx);
|
|
+ /* x9 is not set for struct_ops */
|
|
+ if (!is_struct_ops) {
|
|
+ /* frame for parent function */
|
|
+ emit(A64_PUSH(A64_FP, A64_R(9), A64_SP), ctx);
|
|
+ emit(A64_MOV(1, A64_FP, A64_SP), ctx);
|
|
+ }
|
|
|
|
- /* frame for patched function */
|
|
+ /* frame for patched function for tracing, or caller for struct_ops */
|
|
emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
|
|
emit(A64_MOV(1, A64_FP, A64_SP), ctx);
|
|
|
|
@@ -2003,19 +2013,24 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
|
|
/* reset SP */
|
|
emit(A64_MOV(1, A64_SP, A64_FP), ctx);
|
|
|
|
- /* pop frames */
|
|
- emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
|
|
- emit(A64_POP(A64_FP, A64_R(9), A64_SP), ctx);
|
|
-
|
|
- if (flags & BPF_TRAMP_F_SKIP_FRAME) {
|
|
- /* skip patched function, return to parent */
|
|
- emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
|
|
- emit(A64_RET(A64_R(9)), ctx);
|
|
+ if (is_struct_ops) {
|
|
+ emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
|
|
+ emit(A64_RET(A64_LR), ctx);
|
|
} else {
|
|
- /* return to patched function */
|
|
- emit(A64_MOV(1, A64_R(10), A64_LR), ctx);
|
|
- emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
|
|
- emit(A64_RET(A64_R(10)), ctx);
|
|
+ /* pop frames */
|
|
+ emit(A64_POP(A64_FP, A64_LR, A64_SP), ctx);
|
|
+ emit(A64_POP(A64_FP, A64_R(9), A64_SP), ctx);
|
|
+
|
|
+ if (flags & BPF_TRAMP_F_SKIP_FRAME) {
|
|
+ /* skip patched function, return to parent */
|
|
+ emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
|
|
+ emit(A64_RET(A64_R(9)), ctx);
|
|
+ } else {
|
|
+ /* return to patched function */
|
|
+ emit(A64_MOV(1, A64_R(10), A64_LR), ctx);
|
|
+ emit(A64_MOV(1, A64_LR, A64_R(9)), ctx);
|
|
+ emit(A64_RET(A64_R(10)), ctx);
|
|
+ }
|
|
}
|
|
|
|
if (ctx->image)
|
|
diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c
|
|
index 106fbf0b6f3b40..2d85484ae0e7ef 100644
|
|
--- a/arch/csky/kernel/setup.c
|
|
+++ b/arch/csky/kernel/setup.c
|
|
@@ -124,9 +124,9 @@ asmlinkage __visible void __init csky_start(unsigned int unused,
|
|
pre_trap_init();
|
|
|
|
if (dtb_start == NULL)
|
|
- early_init_dt_scan(__dtb_start);
|
|
+ early_init_dt_scan(__dtb_start, __pa(dtb_start));
|
|
else
|
|
- early_init_dt_scan(dtb_start);
|
|
+ early_init_dt_scan(dtb_start, __pa(dtb_start));
|
|
|
|
start_kernel();
|
|
|
|
diff --git a/arch/loongarch/include/asm/page.h b/arch/loongarch/include/asm/page.h
|
|
index 63f137ce82a41f..f49c2782c5c4db 100644
|
|
--- a/arch/loongarch/include/asm/page.h
|
|
+++ b/arch/loongarch/include/asm/page.h
|
|
@@ -94,10 +94,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
|
|
extern int __virt_addr_valid(volatile void *kaddr);
|
|
#define virt_addr_valid(kaddr) __virt_addr_valid((volatile void *)(kaddr))
|
|
|
|
-#define VM_DATA_DEFAULT_FLAGS \
|
|
- (VM_READ | VM_WRITE | \
|
|
- ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
|
|
- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
|
+#define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_TSK_EXEC
|
|
|
|
#include <asm-generic/memory_model.h>
|
|
#include <asm-generic/getorder.h>
|
|
diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c
|
|
index 065f2db57c0992..7ef1c1ff1fc44c 100644
|
|
--- a/arch/loongarch/kernel/setup.c
|
|
+++ b/arch/loongarch/kernel/setup.c
|
|
@@ -304,7 +304,7 @@ static void __init fdt_setup(void)
|
|
if (!fdt_pointer || fdt_check_header(fdt_pointer))
|
|
return;
|
|
|
|
- early_init_dt_scan(fdt_pointer);
|
|
+ early_init_dt_scan(fdt_pointer, __pa(fdt_pointer));
|
|
early_init_fdt_reserve_self();
|
|
|
|
max_low_pfn = PFN_PHYS(memblock_end_of_DRAM());
|
|
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
|
|
index 9eb7753d117dfb..497f8b0a5f1efb 100644
|
|
--- a/arch/loongarch/net/bpf_jit.c
|
|
+++ b/arch/loongarch/net/bpf_jit.c
|
|
@@ -179,7 +179,7 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
|
|
|
|
if (!is_tail_call) {
|
|
/* Set return value */
|
|
- move_reg(ctx, LOONGARCH_GPR_A0, regmap[BPF_REG_0]);
|
|
+ emit_insn(ctx, addiw, LOONGARCH_GPR_A0, regmap[BPF_REG_0], 0);
|
|
/* Return to the caller */
|
|
emit_insn(ctx, jirl, LOONGARCH_GPR_RA, LOONGARCH_GPR_ZERO, 0);
|
|
} else {
|
|
diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile
|
|
index f597cd08a96be0..1a0f6ca0247b4c 100644
|
|
--- a/arch/loongarch/vdso/Makefile
|
|
+++ b/arch/loongarch/vdso/Makefile
|
|
@@ -22,7 +22,7 @@ ccflags-vdso := \
|
|
cflags-vdso := $(ccflags-vdso) \
|
|
-isystem $(shell $(CC) -print-file-name=include) \
|
|
$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
|
|
- -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \
|
|
+ -std=gnu11 -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \
|
|
-fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \
|
|
$(call cc-option, -fno-asynchronous-unwind-tables) \
|
|
$(call cc-option, -fno-stack-protector)
|
|
diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c
|
|
index 7dab46728aedaf..b6958ec2a220cf 100644
|
|
--- a/arch/m68k/coldfire/device.c
|
|
+++ b/arch/m68k/coldfire/device.c
|
|
@@ -93,7 +93,7 @@ static struct platform_device mcf_uart = {
|
|
.dev.platform_data = mcf_uart_platform_data,
|
|
};
|
|
|
|
-#if IS_ENABLED(CONFIG_FEC)
|
|
+#ifdef MCFFEC_BASE0
|
|
|
|
#ifdef CONFIG_M5441x
|
|
#define FEC_NAME "enet-fec"
|
|
@@ -145,6 +145,7 @@ static struct platform_device mcf_fec0 = {
|
|
.platform_data = FEC_PDATA,
|
|
}
|
|
};
|
|
+#endif /* MCFFEC_BASE0 */
|
|
|
|
#ifdef MCFFEC_BASE1
|
|
static struct resource mcf_fec1_resources[] = {
|
|
@@ -182,7 +183,6 @@ static struct platform_device mcf_fec1 = {
|
|
}
|
|
};
|
|
#endif /* MCFFEC_BASE1 */
|
|
-#endif /* CONFIG_FEC */
|
|
|
|
#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
|
|
/*
|
|
@@ -624,12 +624,12 @@ static struct platform_device mcf_flexcan0 = {
|
|
|
|
static struct platform_device *mcf_devices[] __initdata = {
|
|
&mcf_uart,
|
|
-#if IS_ENABLED(CONFIG_FEC)
|
|
+#ifdef MCFFEC_BASE0
|
|
&mcf_fec0,
|
|
+#endif
|
|
#ifdef MCFFEC_BASE1
|
|
&mcf_fec1,
|
|
#endif
|
|
-#endif
|
|
#if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
|
|
&mcf_qspi,
|
|
#endif
|
|
diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h
|
|
index 7abd322c019fc1..295624d01d3dcd 100644
|
|
--- a/arch/m68k/include/asm/mcfgpio.h
|
|
+++ b/arch/m68k/include/asm/mcfgpio.h
|
|
@@ -136,7 +136,7 @@ static inline void gpio_free(unsigned gpio)
|
|
* read-modify-write as well as those controlled by the EPORT and GPIO modules.
|
|
*/
|
|
#define MCFGPIO_SCR_START 40
|
|
-#elif defined(CONFIGM5441x)
|
|
+#elif defined(CONFIG_M5441x)
|
|
/* The m5441x EPORT doesn't have its own GPIO port, uses PORT C */
|
|
#define MCFGPIO_SCR_START 0
|
|
#else
|
|
diff --git a/arch/m68k/include/asm/mvme147hw.h b/arch/m68k/include/asm/mvme147hw.h
|
|
index e28eb1c0e0bfb3..dbf88059e47a4d 100644
|
|
--- a/arch/m68k/include/asm/mvme147hw.h
|
|
+++ b/arch/m68k/include/asm/mvme147hw.h
|
|
@@ -93,8 +93,8 @@ struct pcc_regs {
|
|
#define M147_SCC_B_ADDR 0xfffe3000
|
|
#define M147_SCC_PCLK 5000000
|
|
|
|
-#define MVME147_IRQ_SCSI_PORT (IRQ_USER+0x45)
|
|
-#define MVME147_IRQ_SCSI_DMA (IRQ_USER+0x46)
|
|
+#define MVME147_IRQ_SCSI_PORT (IRQ_USER + 5)
|
|
+#define MVME147_IRQ_SCSI_DMA (IRQ_USER + 6)
|
|
|
|
/* SCC interrupts, for MVME147 */
|
|
|
|
diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c
|
|
index 7d3fe08a48eb03..f11ef9f1f56fcf 100644
|
|
--- a/arch/m68k/kernel/early_printk.c
|
|
+++ b/arch/m68k/kernel/early_printk.c
|
|
@@ -12,8 +12,9 @@
|
|
#include <linux/string.h>
|
|
#include <asm/setup.h>
|
|
|
|
-extern void mvme16x_cons_write(struct console *co,
|
|
- const char *str, unsigned count);
|
|
+
|
|
+#include "../mvme147/mvme147.h"
|
|
+#include "../mvme16x/mvme16x.h"
|
|
|
|
asmlinkage void __init debug_cons_nputs(const char *s, unsigned n);
|
|
|
|
@@ -22,7 +23,9 @@ static void __ref debug_cons_write(struct console *c,
|
|
{
|
|
#if !(defined(CONFIG_SUN3) || defined(CONFIG_M68000) || \
|
|
defined(CONFIG_COLDFIRE))
|
|
- if (MACH_IS_MVME16x)
|
|
+ if (MACH_IS_MVME147)
|
|
+ mvme147_scc_write(c, s, n);
|
|
+ else if (MACH_IS_MVME16x)
|
|
mvme16x_cons_write(c, s, n);
|
|
else
|
|
debug_cons_nputs(s, n);
|
|
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
|
|
index 4e6218115f43ce..95d4a7e13b33d5 100644
|
|
--- a/arch/m68k/mvme147/config.c
|
|
+++ b/arch/m68k/mvme147/config.c
|
|
@@ -35,6 +35,7 @@
|
|
#include <asm/mvme147hw.h>
|
|
#include <asm/config.h>
|
|
|
|
+#include "mvme147.h"
|
|
|
|
static void mvme147_get_model(char *model);
|
|
extern void mvme147_sched_init(void);
|
|
@@ -188,3 +189,32 @@ int mvme147_hwclk(int op, struct rtc_time *t)
|
|
}
|
|
return 0;
|
|
}
|
|
+
|
|
+static void scc_delay(void)
|
|
+{
|
|
+ __asm__ __volatile__ ("nop; nop;");
|
|
+}
|
|
+
|
|
+static void scc_write(char ch)
|
|
+{
|
|
+ do {
|
|
+ scc_delay();
|
|
+ } while (!(in_8(M147_SCC_A_ADDR) & BIT(2)));
|
|
+ scc_delay();
|
|
+ out_8(M147_SCC_A_ADDR, 8);
|
|
+ scc_delay();
|
|
+ out_8(M147_SCC_A_ADDR, ch);
|
|
+}
|
|
+
|
|
+void mvme147_scc_write(struct console *co, const char *str, unsigned int count)
|
|
+{
|
|
+ unsigned long flags;
|
|
+
|
|
+ local_irq_save(flags);
|
|
+ while (count--) {
|
|
+ if (*str == '\n')
|
|
+ scc_write('\r');
|
|
+ scc_write(*str++);
|
|
+ }
|
|
+ local_irq_restore(flags);
|
|
+}
|
|
diff --git a/arch/m68k/mvme147/mvme147.h b/arch/m68k/mvme147/mvme147.h
|
|
new file mode 100644
|
|
index 00000000000000..140bc98b0102aa
|
|
--- /dev/null
|
|
+++ b/arch/m68k/mvme147/mvme147.h
|
|
@@ -0,0 +1,6 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0-only */
|
|
+
|
|
+struct console;
|
|
+
|
|
+/* config.c */
|
|
+void mvme147_scc_write(struct console *co, const char *str, unsigned int count);
|
|
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
|
|
index f00c7aa058dec2..2b7eac224138e2 100644
|
|
--- a/arch/m68k/mvme16x/config.c
|
|
+++ b/arch/m68k/mvme16x/config.c
|
|
@@ -38,6 +38,8 @@
|
|
#include <asm/mvme16xhw.h>
|
|
#include <asm/config.h>
|
|
|
|
+#include "mvme16x.h"
|
|
+
|
|
extern t_bdid mvme_bdid;
|
|
|
|
static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
|
|
diff --git a/arch/m68k/mvme16x/mvme16x.h b/arch/m68k/mvme16x/mvme16x.h
|
|
new file mode 100644
|
|
index 00000000000000..159c34b7003941
|
|
--- /dev/null
|
|
+++ b/arch/m68k/mvme16x/mvme16x.h
|
|
@@ -0,0 +1,6 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0-only */
|
|
+
|
|
+struct console;
|
|
+
|
|
+/* config.c */
|
|
+void mvme16x_cons_write(struct console *co, const char *str, unsigned count);
|
|
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
|
|
index c892e173ec990b..a8553f54152b76 100644
|
|
--- a/arch/microblaze/kernel/microblaze_ksyms.c
|
|
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
|
|
@@ -16,6 +16,7 @@
|
|
#include <asm/page.h>
|
|
#include <linux/ftrace.h>
|
|
#include <linux/uaccess.h>
|
|
+#include <asm/xilinx_mb_manager.h>
|
|
|
|
#ifdef CONFIG_FUNCTION_TRACER
|
|
extern void _mcount(void);
|
|
@@ -46,3 +47,12 @@ extern void __udivsi3(void);
|
|
EXPORT_SYMBOL(__udivsi3);
|
|
extern void __umodsi3(void);
|
|
EXPORT_SYMBOL(__umodsi3);
|
|
+
|
|
+#ifdef CONFIG_MB_MANAGER
|
|
+extern void xmb_manager_register(uintptr_t phys_baseaddr, u32 cr_val,
|
|
+ void (*callback)(void *data),
|
|
+ void *priv, void (*reset_callback)(void *data));
|
|
+EXPORT_SYMBOL(xmb_manager_register);
|
|
+extern asmlinkage void xmb_inject_err(void);
|
|
+EXPORT_SYMBOL(xmb_inject_err);
|
|
+#endif
|
|
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
|
|
index e424c796e297c5..76ac4cfdfb42ce 100644
|
|
--- a/arch/microblaze/kernel/prom.c
|
|
+++ b/arch/microblaze/kernel/prom.c
|
|
@@ -18,7 +18,7 @@ void __init early_init_devtree(void *params)
|
|
{
|
|
pr_debug(" -> early_init_devtree(%p)\n", params);
|
|
|
|
- early_init_dt_scan(params);
|
|
+ early_init_dt_scan(params, __pa(params));
|
|
if (!strlen(boot_command_line))
|
|
strscpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
|
|
|
|
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
|
|
index a4374b4cb88fd8..d6ccd534402133 100644
|
|
--- a/arch/mips/include/asm/switch_to.h
|
|
+++ b/arch/mips/include/asm/switch_to.h
|
|
@@ -97,7 +97,7 @@ do { \
|
|
} \
|
|
} while (0)
|
|
#else
|
|
-# define __sanitize_fcr31(next)
|
|
+# define __sanitize_fcr31(next) do { (void) (next); } while (0)
|
|
#endif
|
|
|
|
/*
|
|
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
|
|
index f88ce78e13e3a2..474dc1eec3bb5d 100644
|
|
--- a/arch/mips/kernel/prom.c
|
|
+++ b/arch/mips/kernel/prom.c
|
|
@@ -39,7 +39,7 @@ char *mips_get_machine_name(void)
|
|
|
|
void __init __dt_setup_arch(void *bph)
|
|
{
|
|
- if (!early_init_dt_scan(bph))
|
|
+ if (!early_init_dt_scan(bph, __pa(bph)))
|
|
return;
|
|
|
|
mips_set_machine_name(of_flat_dt_get_machine_name());
|
|
diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c
|
|
index 58fc8d089402bd..6d35d4f7ebe196 100644
|
|
--- a/arch/mips/kernel/relocate.c
|
|
+++ b/arch/mips/kernel/relocate.c
|
|
@@ -337,7 +337,7 @@ void *__init relocate_kernel(void)
|
|
#if defined(CONFIG_USE_OF)
|
|
/* Deal with the device tree */
|
|
fdt = plat_get_fdt();
|
|
- early_init_dt_scan(fdt);
|
|
+ early_init_dt_scan(fdt, __pa(fdt));
|
|
if (boot_command_line[0]) {
|
|
/* Boot command line was passed in device tree */
|
|
strscpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
|
|
diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c
|
|
index 8d98af5c7201bb..15bbdd78e9bf20 100644
|
|
--- a/arch/nios2/kernel/prom.c
|
|
+++ b/arch/nios2/kernel/prom.c
|
|
@@ -26,12 +26,12 @@ void __init early_init_devtree(void *params)
|
|
if (be32_to_cpup((__be32 *)CONFIG_NIOS2_DTB_PHYS_ADDR) ==
|
|
OF_DT_HEADER) {
|
|
params = (void *)CONFIG_NIOS2_DTB_PHYS_ADDR;
|
|
- early_init_dt_scan(params);
|
|
+ early_init_dt_scan(params, __pa(params));
|
|
return;
|
|
}
|
|
#endif
|
|
if (be32_to_cpu((__be32) *dtb) == OF_DT_HEADER)
|
|
params = (void *)__dtb_start;
|
|
|
|
- early_init_dt_scan(params);
|
|
+ early_init_dt_scan(params, __pa(params));
|
|
}
|
|
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
|
|
index fd9bb76a610bf0..206a6da4f31b0c 100644
|
|
--- a/arch/openrisc/Kconfig
|
|
+++ b/arch/openrisc/Kconfig
|
|
@@ -64,6 +64,9 @@ config STACKTRACE_SUPPORT
|
|
config LOCKDEP_SUPPORT
|
|
def_bool y
|
|
|
|
+config FIX_EARLYCON_MEM
|
|
+ def_bool y
|
|
+
|
|
menu "Processor type and features"
|
|
|
|
choice
|
|
diff --git a/arch/openrisc/include/asm/fixmap.h b/arch/openrisc/include/asm/fixmap.h
|
|
index ad78e50b7ba327..aece6013fead1f 100644
|
|
--- a/arch/openrisc/include/asm/fixmap.h
|
|
+++ b/arch/openrisc/include/asm/fixmap.h
|
|
@@ -26,29 +26,18 @@
|
|
#include <linux/bug.h>
|
|
#include <asm/page.h>
|
|
|
|
-/*
|
|
- * On OpenRISC we use these special fixed_addresses for doing ioremap
|
|
- * early in the boot process before memory initialization is complete.
|
|
- * This is used, in particular, by the early serial console code.
|
|
- *
|
|
- * It's not really 'fixmap', per se, but fits loosely into the same
|
|
- * paradigm.
|
|
- */
|
|
enum fixed_addresses {
|
|
- /*
|
|
- * FIX_IOREMAP entries are useful for mapping physical address
|
|
- * space before ioremap() is useable, e.g. really early in boot
|
|
- * before kmalloc() is working.
|
|
- */
|
|
-#define FIX_N_IOREMAPS 32
|
|
- FIX_IOREMAP_BEGIN,
|
|
- FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1,
|
|
+ FIX_EARLYCON_MEM_BASE,
|
|
__end_of_fixed_addresses
|
|
};
|
|
|
|
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
|
|
/* FIXADDR_BOTTOM might be a better name here... */
|
|
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
|
|
+#define FIXMAP_PAGE_IO PAGE_KERNEL_NOCACHE
|
|
+
|
|
+extern void __set_fixmap(enum fixed_addresses idx,
|
|
+ phys_addr_t phys, pgprot_t flags);
|
|
|
|
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
|
|
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
|
|
diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c
|
|
index 19e6008bf114c6..e424e9bd12a793 100644
|
|
--- a/arch/openrisc/kernel/prom.c
|
|
+++ b/arch/openrisc/kernel/prom.c
|
|
@@ -22,6 +22,6 @@
|
|
|
|
void __init early_init_devtree(void *params)
|
|
{
|
|
- early_init_dt_scan(params);
|
|
+ early_init_dt_scan(params, __pa(params));
|
|
memblock_allow_resize();
|
|
}
|
|
diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c
|
|
index 1dcd78c8f0e99b..d0cb1a0126f95d 100644
|
|
--- a/arch/openrisc/mm/init.c
|
|
+++ b/arch/openrisc/mm/init.c
|
|
@@ -207,6 +207,43 @@ void __init mem_init(void)
|
|
return;
|
|
}
|
|
|
|
+static int __init map_page(unsigned long va, phys_addr_t pa, pgprot_t prot)
|
|
+{
|
|
+ p4d_t *p4d;
|
|
+ pud_t *pud;
|
|
+ pmd_t *pmd;
|
|
+ pte_t *pte;
|
|
+
|
|
+ p4d = p4d_offset(pgd_offset_k(va), va);
|
|
+ pud = pud_offset(p4d, va);
|
|
+ pmd = pmd_offset(pud, va);
|
|
+ pte = pte_alloc_kernel(pmd, va);
|
|
+
|
|
+ if (pte == NULL)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ if (pgprot_val(prot))
|
|
+ set_pte_at(&init_mm, va, pte, pfn_pte(pa >> PAGE_SHIFT, prot));
|
|
+ else
|
|
+ pte_clear(&init_mm, va, pte);
|
|
+
|
|
+ local_flush_tlb_page(NULL, va);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void __init __set_fixmap(enum fixed_addresses idx,
|
|
+ phys_addr_t phys, pgprot_t prot)
|
|
+{
|
|
+ unsigned long address = __fix_to_virt(idx);
|
|
+
|
|
+ if (idx >= __end_of_fixed_addresses) {
|
|
+ BUG();
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ map_page(address, phys, prot);
|
|
+}
|
|
+
|
|
static const pgprot_t protection_map[16] = {
|
|
[VM_NONE] = PAGE_NONE,
|
|
[VM_READ] = PAGE_READONLY_X,
|
|
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c
|
|
index c91f9c2e61ed25..f8d08eab7db8b0 100644
|
|
--- a/arch/parisc/kernel/ftrace.c
|
|
+++ b/arch/parisc/kernel/ftrace.c
|
|
@@ -87,7 +87,7 @@ int ftrace_enable_ftrace_graph_caller(void)
|
|
|
|
int ftrace_disable_ftrace_graph_caller(void)
|
|
{
|
|
- static_key_enable(&ftrace_graph_enable.key);
|
|
+ static_key_disable(&ftrace_graph_enable.key);
|
|
return 0;
|
|
}
|
|
#endif
|
|
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
|
|
index 2fe51e0ad63713..6baa8b85601aa2 100644
|
|
--- a/arch/powerpc/Kconfig
|
|
+++ b/arch/powerpc/Kconfig
|
|
@@ -271,8 +271,8 @@ config PPC
|
|
select HAVE_RSEQ
|
|
select HAVE_SETUP_PER_CPU_AREA if PPC64
|
|
select HAVE_SOFTIRQ_ON_OWN_STACK
|
|
- select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2)
|
|
- select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13)
|
|
+ select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,$(m32-flag) -mstack-protector-guard=tls -mstack-protector-guard-reg=r2 -mstack-protector-guard-offset=0)
|
|
+ select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,$(m64-flag) -mstack-protector-guard=tls -mstack-protector-guard-reg=r13 -mstack-protector-guard-offset=0)
|
|
select HAVE_STATIC_CALL if PPC32
|
|
select HAVE_SYSCALL_TRACEPOINTS
|
|
select HAVE_VIRT_CPU_ACCOUNTING
|
|
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
|
|
index f19dbaa1d54136..46cbc8ead07d9d 100644
|
|
--- a/arch/powerpc/Makefile
|
|
+++ b/arch/powerpc/Makefile
|
|
@@ -89,13 +89,6 @@ KBUILD_AFLAGS += -m$(BITS)
|
|
KBUILD_LDFLAGS += -m elf$(BITS)$(LDEMULATION)
|
|
endif
|
|
|
|
-cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard=tls
|
|
-ifdef CONFIG_PPC64
|
|
-cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r13
|
|
-else
|
|
-cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r2
|
|
-endif
|
|
-
|
|
LDFLAGS_vmlinux-y := -Bstatic
|
|
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
|
|
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) += -z notext
|
|
@@ -389,9 +382,11 @@ prepare: stack_protector_prepare
|
|
PHONY += stack_protector_prepare
|
|
stack_protector_prepare: prepare0
|
|
ifdef CONFIG_PPC64
|
|
- $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' include/generated/asm-offsets.h))
|
|
+ $(eval KBUILD_CFLAGS += -mstack-protector-guard=tls -mstack-protector-guard-reg=r13 \
|
|
+ -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' include/generated/asm-offsets.h))
|
|
else
|
|
- $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h))
|
|
+ $(eval KBUILD_CFLAGS += -mstack-protector-guard=tls -mstack-protector-guard-reg=r2 \
|
|
+ -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h))
|
|
endif
|
|
endif
|
|
|
|
diff --git a/arch/powerpc/include/asm/dtl.h b/arch/powerpc/include/asm/dtl.h
|
|
index d6f43d149f8dcb..a5c21bc623cb00 100644
|
|
--- a/arch/powerpc/include/asm/dtl.h
|
|
+++ b/arch/powerpc/include/asm/dtl.h
|
|
@@ -1,8 +1,8 @@
|
|
#ifndef _ASM_POWERPC_DTL_H
|
|
#define _ASM_POWERPC_DTL_H
|
|
|
|
+#include <linux/rwsem.h>
|
|
#include <asm/lppaca.h>
|
|
-#include <linux/spinlock_types.h>
|
|
|
|
/*
|
|
* Layout of entries in the hypervisor's dispatch trace log buffer.
|
|
@@ -35,7 +35,7 @@ struct dtl_entry {
|
|
#define DTL_LOG_ALL (DTL_LOG_CEDE | DTL_LOG_PREEMPT | DTL_LOG_FAULT)
|
|
|
|
extern struct kmem_cache *dtl_cache;
|
|
-extern rwlock_t dtl_access_lock;
|
|
+extern struct rw_semaphore dtl_access_lock;
|
|
|
|
extern void register_dtl_buffer(int cpu);
|
|
extern void alloc_dtl_buffers(unsigned long *time_limit);
|
|
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
|
|
index 526a6a6473128a..daa44b2ef35ad0 100644
|
|
--- a/arch/powerpc/include/asm/fadump.h
|
|
+++ b/arch/powerpc/include/asm/fadump.h
|
|
@@ -32,4 +32,11 @@ extern int early_init_dt_scan_fw_dump(unsigned long node, const char *uname,
|
|
int depth, void *data);
|
|
extern int fadump_reserve_mem(void);
|
|
#endif
|
|
+
|
|
+#if defined(CONFIG_FA_DUMP) && defined(CONFIG_CMA)
|
|
+void fadump_cma_init(void);
|
|
+#else
|
|
+static inline void fadump_cma_init(void) { }
|
|
+#endif
|
|
+
|
|
#endif /* _ASM_POWERPC_FADUMP_H */
|
|
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h
|
|
index 50950deedb8734..e3d0e714ff280e 100644
|
|
--- a/arch/powerpc/include/asm/sstep.h
|
|
+++ b/arch/powerpc/include/asm/sstep.h
|
|
@@ -173,9 +173,4 @@ int emulate_step(struct pt_regs *regs, ppc_inst_t instr);
|
|
*/
|
|
extern int emulate_loadstore(struct pt_regs *regs, struct instruction_op *op);
|
|
|
|
-extern void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
|
|
- const void *mem, bool cross_endian);
|
|
-extern void emulate_vsx_store(struct instruction_op *op,
|
|
- const union vsx_reg *reg, void *mem,
|
|
- bool cross_endian);
|
|
extern int emulate_dcbz(unsigned long ea, struct pt_regs *regs);
|
|
diff --git a/arch/powerpc/include/asm/vdso.h b/arch/powerpc/include/asm/vdso.h
|
|
index 7650b6ce14c85a..8d972bc98b55fe 100644
|
|
--- a/arch/powerpc/include/asm/vdso.h
|
|
+++ b/arch/powerpc/include/asm/vdso.h
|
|
@@ -25,6 +25,7 @@ int vdso_getcpu_init(void);
|
|
#ifdef __VDSO64__
|
|
#define V_FUNCTION_BEGIN(name) \
|
|
.globl name; \
|
|
+ .type name,@function; \
|
|
name: \
|
|
|
|
#define V_FUNCTION_END(name) \
|
|
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
|
|
index c3fb9fdf5bd782..a84e75fff1dfe1 100644
|
|
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
|
|
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
|
|
@@ -857,7 +857,7 @@ bool __init dt_cpu_ftrs_init(void *fdt)
|
|
using_dt_cpu_ftrs = false;
|
|
|
|
/* Setup and verify the FDT, if it fails we just bail */
|
|
- if (!early_init_dt_verify(fdt))
|
|
+ if (!early_init_dt_verify(fdt, __pa(fdt)))
|
|
return false;
|
|
|
|
if (!of_scan_flat_dt(fdt_find_cpu_features, NULL))
|
|
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
|
|
index 3ff2da7b120b50..1866bac2340007 100644
|
|
--- a/arch/powerpc/kernel/fadump.c
|
|
+++ b/arch/powerpc/kernel/fadump.c
|
|
@@ -80,27 +80,23 @@ static struct cma *fadump_cma;
|
|
* But for some reason even if it fails we still have the memory reservation
|
|
* with us and we can still continue doing fadump.
|
|
*/
|
|
-static int __init fadump_cma_init(void)
|
|
+void __init fadump_cma_init(void)
|
|
{
|
|
unsigned long long base, size;
|
|
int rc;
|
|
|
|
- if (!fw_dump.fadump_enabled)
|
|
- return 0;
|
|
-
|
|
+ if (!fw_dump.fadump_supported || !fw_dump.fadump_enabled ||
|
|
+ fw_dump.dump_active)
|
|
+ return;
|
|
/*
|
|
* Do not use CMA if user has provided fadump=nocma kernel parameter.
|
|
- * Return 1 to continue with fadump old behaviour.
|
|
*/
|
|
- if (fw_dump.nocma)
|
|
- return 1;
|
|
+ if (fw_dump.nocma || !fw_dump.boot_memory_size)
|
|
+ return;
|
|
|
|
base = fw_dump.reserve_dump_area_start;
|
|
size = fw_dump.boot_memory_size;
|
|
|
|
- if (!size)
|
|
- return 0;
|
|
-
|
|
rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma);
|
|
if (rc) {
|
|
pr_err("Failed to init cma area for firmware-assisted dump,%d\n", rc);
|
|
@@ -110,7 +106,7 @@ static int __init fadump_cma_init(void)
|
|
* blocked from production system usage. Hence return 1,
|
|
* so that we can continue with fadump.
|
|
*/
|
|
- return 1;
|
|
+ return;
|
|
}
|
|
|
|
/*
|
|
@@ -127,10 +123,7 @@ static int __init fadump_cma_init(void)
|
|
cma_get_size(fadump_cma),
|
|
(unsigned long)cma_get_base(fadump_cma) >> 20,
|
|
fw_dump.reserve_dump_area_size);
|
|
- return 1;
|
|
}
|
|
-#else
|
|
-static int __init fadump_cma_init(void) { return 1; }
|
|
#endif /* CONFIG_CMA */
|
|
|
|
/* Scan the Firmware Assisted dump configuration details. */
|
|
@@ -647,8 +640,6 @@ int __init fadump_reserve_mem(void)
|
|
|
|
pr_info("Reserved %lldMB of memory at %#016llx (System RAM: %lldMB)\n",
|
|
(size >> 20), base, (memblock_phys_mem_size() >> 20));
|
|
-
|
|
- ret = fadump_cma_init();
|
|
}
|
|
|
|
return ret;
|
|
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
|
|
index bf6d8ad3819e99..7d5eccf3f80d92 100644
|
|
--- a/arch/powerpc/kernel/prom.c
|
|
+++ b/arch/powerpc/kernel/prom.c
|
|
@@ -781,7 +781,7 @@ void __init early_init_devtree(void *params)
|
|
DBG(" -> early_init_devtree(%px)\n", params);
|
|
|
|
/* Too early to BUG_ON(), do it by hand */
|
|
- if (!early_init_dt_verify(params))
|
|
+ if (!early_init_dt_verify(params, __pa(params)))
|
|
panic("BUG: Failed verifying flat device tree, bad version?");
|
|
|
|
of_scan_flat_dt(early_init_dt_scan_model, NULL);
|
|
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
|
|
index 03eaad5949f141..d43db8150767be 100644
|
|
--- a/arch/powerpc/kernel/setup-common.c
|
|
+++ b/arch/powerpc/kernel/setup-common.c
|
|
@@ -988,9 +988,11 @@ void __init setup_arch(char **cmdline_p)
|
|
initmem_init();
|
|
|
|
/*
|
|
- * Reserve large chunks of memory for use by CMA for KVM and hugetlb. These must
|
|
- * be called after initmem_init(), so that pageblock_order is initialised.
|
|
+ * Reserve large chunks of memory for use by CMA for fadump, KVM and
|
|
+ * hugetlb. These must be called after initmem_init(), so that
|
|
+ * pageblock_order is initialised.
|
|
*/
|
|
+ fadump_cma_init();
|
|
kvm_cma_reserve();
|
|
gigantic_hugetlb_cma_reserve();
|
|
|
|
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
|
|
index 394f209536cee0..a70fe396996423 100644
|
|
--- a/arch/powerpc/kernel/setup_64.c
|
|
+++ b/arch/powerpc/kernel/setup_64.c
|
|
@@ -924,6 +924,7 @@ static int __init disable_hardlockup_detector(void)
|
|
hardlockup_detector_disable();
|
|
#else
|
|
if (firmware_has_feature(FW_FEATURE_LPAR)) {
|
|
+ check_kvm_guest();
|
|
if (is_kvm_guest())
|
|
hardlockup_detector_disable();
|
|
}
|
|
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
|
|
index f420df7888a75c..7ab4e2fb28b1e3 100644
|
|
--- a/arch/powerpc/kernel/vmlinux.lds.S
|
|
+++ b/arch/powerpc/kernel/vmlinux.lds.S
|
|
@@ -123,8 +123,6 @@ SECTIONS
|
|
*/
|
|
*(.sfpr);
|
|
*(.text.asan.* .text.tsan.*)
|
|
- MEM_KEEP(init.text)
|
|
- MEM_KEEP(exit.text)
|
|
} :text
|
|
|
|
. = ALIGN(PAGE_SIZE);
|
|
diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c
|
|
index a3de5369d22c23..7b71737ae24cc2 100644
|
|
--- a/arch/powerpc/kexec/file_load_64.c
|
|
+++ b/arch/powerpc/kexec/file_load_64.c
|
|
@@ -916,13 +916,18 @@ int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
|
|
if (dn) {
|
|
u64 val;
|
|
|
|
- of_property_read_u64(dn, "opal-base-address", &val);
|
|
+ ret = of_property_read_u64(dn, "opal-base-address", &val);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
ret = kexec_purgatory_get_set_symbol(image, "opal_base", &val,
|
|
sizeof(val), false);
|
|
if (ret)
|
|
goto out;
|
|
|
|
- of_property_read_u64(dn, "opal-entry-address", &val);
|
|
+ ret = of_property_read_u64(dn, "opal-entry-address", &val);
|
|
+ if (ret)
|
|
+ goto out;
|
|
ret = kexec_purgatory_get_set_symbol(image, "opal_entry", &val,
|
|
sizeof(val), false);
|
|
}
|
|
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
|
|
index 1bb00c72154407..924689fa5efa15 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv.c
|
|
+++ b/arch/powerpc/kvm/book3s_hv.c
|
|
@@ -4090,6 +4090,15 @@ static int kvmhv_vcpu_entry_p9_nested(struct kvm_vcpu *vcpu, u64 time_limit, uns
|
|
}
|
|
hvregs.hdec_expiry = time_limit;
|
|
|
|
+ /*
|
|
+ * hvregs has the doorbell status, so zero it here which
|
|
+ * enables us to receive doorbells when H_ENTER_NESTED is
|
|
+ * in progress for this vCPU
|
|
+ */
|
|
+
|
|
+ if (vcpu->arch.doorbell_request)
|
|
+ vcpu->arch.doorbell_request = 0;
|
|
+
|
|
/*
|
|
* When setting DEC, we must always deal with irq_work_raise
|
|
* via NMI vs setting DEC. The problem occurs right as we
|
|
@@ -4678,7 +4687,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
|
lpcr |= LPCR_MER;
|
|
}
|
|
} else if (vcpu->arch.pending_exceptions ||
|
|
- vcpu->arch.doorbell_request ||
|
|
xive_interrupt_pending(vcpu)) {
|
|
vcpu->arch.ret = RESUME_HOST;
|
|
goto out;
|
|
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
|
|
index 377d0b4a05eeb4..49144129da420e 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv_nested.c
|
|
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
|
|
@@ -32,7 +32,7 @@ void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
|
|
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
|
|
|
hr->pcr = vc->pcr | PCR_MASK;
|
|
- hr->dpdes = vc->dpdes;
|
|
+ hr->dpdes = vcpu->arch.doorbell_request;
|
|
hr->hfscr = vcpu->arch.hfscr;
|
|
hr->tb_offset = vc->tb_offset;
|
|
hr->dawr0 = vcpu->arch.dawr0;
|
|
@@ -105,7 +105,7 @@ static void save_hv_return_state(struct kvm_vcpu *vcpu,
|
|
{
|
|
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
|
|
|
- hr->dpdes = vc->dpdes;
|
|
+ hr->dpdes = vcpu->arch.doorbell_request;
|
|
hr->purr = vcpu->arch.purr;
|
|
hr->spurr = vcpu->arch.spurr;
|
|
hr->ic = vcpu->arch.ic;
|
|
@@ -143,7 +143,7 @@ static void restore_hv_regs(struct kvm_vcpu *vcpu, const struct hv_guest_state *
|
|
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
|
|
|
vc->pcr = hr->pcr | PCR_MASK;
|
|
- vc->dpdes = hr->dpdes;
|
|
+ vcpu->arch.doorbell_request = hr->dpdes;
|
|
vcpu->arch.hfscr = hr->hfscr;
|
|
vcpu->arch.dawr0 = hr->dawr0;
|
|
vcpu->arch.dawrx0 = hr->dawrx0;
|
|
@@ -170,7 +170,13 @@ void kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu,
|
|
{
|
|
struct kvmppc_vcore *vc = vcpu->arch.vcore;
|
|
|
|
- vc->dpdes = hr->dpdes;
|
|
+ /*
|
|
+ * This L2 vCPU might have received a doorbell while H_ENTER_NESTED was being handled.
|
|
+ * Make sure we preserve the doorbell if it was either:
|
|
+ * a) Sent after H_ENTER_NESTED was called on this vCPU (arch.doorbell_request would be 1)
|
|
+ * b) Doorbell was not handled and L2 exited for some other reason (hr->dpdes would be 1)
|
|
+ */
|
|
+ vcpu->arch.doorbell_request = vcpu->arch.doorbell_request | hr->dpdes;
|
|
vcpu->arch.hfscr = hr->hfscr;
|
|
vcpu->arch.purr = hr->purr;
|
|
vcpu->arch.spurr = hr->spurr;
|
|
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
|
|
index 6af97dc0f6d5a8..efbf1807887086 100644
|
|
--- a/arch/powerpc/lib/sstep.c
|
|
+++ b/arch/powerpc/lib/sstep.c
|
|
@@ -780,8 +780,8 @@ static nokprobe_inline int emulate_stq(struct pt_regs *regs, unsigned long ea,
|
|
#endif /* __powerpc64 */
|
|
|
|
#ifdef CONFIG_VSX
|
|
-void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
|
|
- const void *mem, bool rev)
|
|
+static nokprobe_inline void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
|
|
+ const void *mem, bool rev)
|
|
{
|
|
int size, read_size;
|
|
int i, j;
|
|
@@ -863,11 +863,9 @@ void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
|
|
break;
|
|
}
|
|
}
|
|
-EXPORT_SYMBOL_GPL(emulate_vsx_load);
|
|
-NOKPROBE_SYMBOL(emulate_vsx_load);
|
|
|
|
-void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
|
|
- void *mem, bool rev)
|
|
+static nokprobe_inline void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
|
|
+ void *mem, bool rev)
|
|
{
|
|
int size, write_size;
|
|
int i, j;
|
|
@@ -955,8 +953,6 @@ void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
|
|
break;
|
|
}
|
|
}
|
|
-EXPORT_SYMBOL_GPL(emulate_vsx_store);
|
|
-NOKPROBE_SYMBOL(emulate_vsx_store);
|
|
|
|
static nokprobe_inline int do_vsx_load(struct instruction_op *op,
|
|
unsigned long ea, struct pt_regs *regs,
|
|
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
|
|
index b1723094d464cf..d3e0f5b3ecc74d 100644
|
|
--- a/arch/powerpc/mm/fault.c
|
|
+++ b/arch/powerpc/mm/fault.c
|
|
@@ -431,10 +431,16 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address,
|
|
/*
|
|
* The kernel should never take an execute fault nor should it
|
|
* take a page fault to a kernel address or a page fault to a user
|
|
- * address outside of dedicated places
|
|
+ * address outside of dedicated places.
|
|
+ *
|
|
+ * Rather than kfence directly reporting false negatives, search whether
|
|
+ * the NIP belongs to the fixup table for cases where fault could come
|
|
+ * from functions like copy_from_kernel_nofault().
|
|
*/
|
|
if (unlikely(!is_user && bad_kernel_fault(regs, error_code, address, is_write))) {
|
|
- if (kfence_handle_page_fault(address, is_write, regs))
|
|
+ if (is_kfence_address((void *)address) &&
|
|
+ !search_exception_tables(instruction_pointer(regs)) &&
|
|
+ kfence_handle_page_fault(address, is_write, regs))
|
|
return 0;
|
|
|
|
return SIGSEGV;
|
|
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
|
|
index 3f1cdccebc9c15..ecc04ef8c53e31 100644
|
|
--- a/arch/powerpc/platforms/pseries/dtl.c
|
|
+++ b/arch/powerpc/platforms/pseries/dtl.c
|
|
@@ -191,7 +191,7 @@ static int dtl_enable(struct dtl *dtl)
|
|
return -EBUSY;
|
|
|
|
/* ensure there are no other conflicting dtl users */
|
|
- if (!read_trylock(&dtl_access_lock))
|
|
+ if (!down_read_trylock(&dtl_access_lock))
|
|
return -EBUSY;
|
|
|
|
n_entries = dtl_buf_entries;
|
|
@@ -199,7 +199,7 @@ static int dtl_enable(struct dtl *dtl)
|
|
if (!buf) {
|
|
printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
|
|
__func__, dtl->cpu);
|
|
- read_unlock(&dtl_access_lock);
|
|
+ up_read(&dtl_access_lock);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
@@ -217,7 +217,7 @@ static int dtl_enable(struct dtl *dtl)
|
|
spin_unlock(&dtl->lock);
|
|
|
|
if (rc) {
|
|
- read_unlock(&dtl_access_lock);
|
|
+ up_read(&dtl_access_lock);
|
|
kmem_cache_free(dtl_cache, buf);
|
|
}
|
|
|
|
@@ -232,7 +232,7 @@ static void dtl_disable(struct dtl *dtl)
|
|
dtl->buf = NULL;
|
|
dtl->buf_entries = 0;
|
|
spin_unlock(&dtl->lock);
|
|
- read_unlock(&dtl_access_lock);
|
|
+ up_read(&dtl_access_lock);
|
|
}
|
|
|
|
/* file interface */
|
|
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
|
|
index c3585e90c6db6b..cade33aef41477 100644
|
|
--- a/arch/powerpc/platforms/pseries/lpar.c
|
|
+++ b/arch/powerpc/platforms/pseries/lpar.c
|
|
@@ -169,7 +169,7 @@ struct vcpu_dispatch_data {
|
|
*/
|
|
#define NR_CPUS_H NR_CPUS
|
|
|
|
-DEFINE_RWLOCK(dtl_access_lock);
|
|
+DECLARE_RWSEM(dtl_access_lock);
|
|
static DEFINE_PER_CPU(struct vcpu_dispatch_data, vcpu_disp_data);
|
|
static DEFINE_PER_CPU(u64, dtl_entry_ridx);
|
|
static DEFINE_PER_CPU(struct dtl_worker, dtl_workers);
|
|
@@ -463,7 +463,7 @@ static int dtl_worker_enable(unsigned long *time_limit)
|
|
{
|
|
int rc = 0, state;
|
|
|
|
- if (!write_trylock(&dtl_access_lock)) {
|
|
+ if (!down_write_trylock(&dtl_access_lock)) {
|
|
rc = -EBUSY;
|
|
goto out;
|
|
}
|
|
@@ -479,7 +479,7 @@ static int dtl_worker_enable(unsigned long *time_limit)
|
|
pr_err("vcpudispatch_stats: unable to setup workqueue for DTL processing\n");
|
|
free_dtl_buffers(time_limit);
|
|
reset_global_dtl_mask();
|
|
- write_unlock(&dtl_access_lock);
|
|
+ up_write(&dtl_access_lock);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
@@ -494,7 +494,7 @@ static void dtl_worker_disable(unsigned long *time_limit)
|
|
cpuhp_remove_state(dtl_worker_state);
|
|
free_dtl_buffers(time_limit);
|
|
reset_global_dtl_mask();
|
|
- write_unlock(&dtl_access_lock);
|
|
+ up_write(&dtl_access_lock);
|
|
}
|
|
|
|
static ssize_t vcpudispatch_stats_write(struct file *file, const char __user *p,
|
|
diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c
|
|
index ed492d38f6ad6b..fe7a43a8a1f46d 100644
|
|
--- a/arch/powerpc/platforms/pseries/plpks.c
|
|
+++ b/arch/powerpc/platforms/pseries/plpks.c
|
|
@@ -683,7 +683,7 @@ void __init plpks_early_init_devtree(void)
|
|
out:
|
|
fdt_nop_property(fdt, chosen_node, "ibm,plpks-pw");
|
|
// Since we've cleared the password, we must update the FDT checksum
|
|
- early_init_dt_verify(fdt);
|
|
+ early_init_dt_verify(fdt, __pa(fdt));
|
|
}
|
|
|
|
static __init int pseries_plpks_init(void)
|
|
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
|
|
index ddadee6621f0da..1fa501b7d0c868 100644
|
|
--- a/arch/riscv/kernel/setup.c
|
|
+++ b/arch/riscv/kernel/setup.c
|
|
@@ -246,7 +246,7 @@ static void __init init_resources(void)
|
|
static void __init parse_dtb(void)
|
|
{
|
|
/* Early scan of device tree from init memory */
|
|
- if (early_init_dt_scan(dtb_early_va)) {
|
|
+ if (early_init_dt_scan(dtb_early_va, __pa(dtb_early_va))) {
|
|
const char *name = of_flat_dt_get_machine_name();
|
|
|
|
if (name) {
|
|
diff --git a/arch/riscv/kvm/aia_aplic.c b/arch/riscv/kvm/aia_aplic.c
|
|
index b467ba5ed91000..9d5b04c971c4d9 100644
|
|
--- a/arch/riscv/kvm/aia_aplic.c
|
|
+++ b/arch/riscv/kvm/aia_aplic.c
|
|
@@ -143,7 +143,7 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending)
|
|
if (sm == APLIC_SOURCECFG_SM_LEVEL_HIGH ||
|
|
sm == APLIC_SOURCECFG_SM_LEVEL_LOW) {
|
|
if (!pending)
|
|
- goto skip_write_pending;
|
|
+ goto noskip_write_pending;
|
|
if ((irqd->state & APLIC_IRQ_STATE_INPUT) &&
|
|
sm == APLIC_SOURCECFG_SM_LEVEL_LOW)
|
|
goto skip_write_pending;
|
|
@@ -152,6 +152,7 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending)
|
|
goto skip_write_pending;
|
|
}
|
|
|
|
+noskip_write_pending:
|
|
if (pending)
|
|
irqd->state |= APLIC_IRQ_STATE_PENDING;
|
|
else
|
|
diff --git a/arch/s390/include/asm/set_memory.h b/arch/s390/include/asm/set_memory.h
|
|
index 06fbabe2f66c98..cb4cc0f59012f7 100644
|
|
--- a/arch/s390/include/asm/set_memory.h
|
|
+++ b/arch/s390/include/asm/set_memory.h
|
|
@@ -62,5 +62,6 @@ __SET_MEMORY_FUNC(set_memory_4k, SET_MEMORY_4K)
|
|
|
|
int set_direct_map_invalid_noflush(struct page *page);
|
|
int set_direct_map_default_noflush(struct page *page);
|
|
+bool kernel_page_present(struct page *page);
|
|
|
|
#endif
|
|
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
|
|
index 26c08ee8774077..ebad8c8b8c57dd 100644
|
|
--- a/arch/s390/kernel/entry.S
|
|
+++ b/arch/s390/kernel/entry.S
|
|
@@ -458,9 +458,13 @@ SYM_CODE_START(\name)
|
|
SYM_CODE_END(\name)
|
|
.endm
|
|
|
|
+ .section .irqentry.text, "ax"
|
|
+
|
|
INT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,do_ext_irq
|
|
INT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq
|
|
|
|
+ .section .kprobes.text, "ax"
|
|
+
|
|
/*
|
|
* Load idle PSW.
|
|
*/
|
|
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
|
|
index d4b863ed0aa75d..cb149a64dba646 100644
|
|
--- a/arch/s390/kernel/kprobes.c
|
|
+++ b/arch/s390/kernel/kprobes.c
|
|
@@ -518,6 +518,12 @@ int __init arch_init_kprobes(void)
|
|
return 0;
|
|
}
|
|
|
|
+int __init arch_populate_kprobe_blacklist(void)
|
|
+{
|
|
+ return kprobe_add_area_blacklist((unsigned long)__irqentry_text_start,
|
|
+ (unsigned long)__irqentry_text_end);
|
|
+}
|
|
+
|
|
int arch_trampoline_kprobe(struct kprobe *p)
|
|
{
|
|
return 0;
|
|
diff --git a/arch/s390/kernel/syscalls/Makefile b/arch/s390/kernel/syscalls/Makefile
|
|
index fb85e797946db6..2bd7756288df61 100644
|
|
--- a/arch/s390/kernel/syscalls/Makefile
|
|
+++ b/arch/s390/kernel/syscalls/Makefile
|
|
@@ -12,7 +12,7 @@ kapi-hdrs-y := $(kapi)/unistd_nr.h
|
|
uapi-hdrs-y := $(uapi)/unistd_32.h
|
|
uapi-hdrs-y += $(uapi)/unistd_64.h
|
|
|
|
-targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y))
|
|
+targets += $(addprefix ../../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y))
|
|
|
|
PHONY += kapi uapi
|
|
|
|
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
|
|
index 441f654d048d20..44271835c97e7d 100644
|
|
--- a/arch/s390/mm/pageattr.c
|
|
+++ b/arch/s390/mm/pageattr.c
|
|
@@ -406,6 +406,21 @@ int set_direct_map_default_noflush(struct page *page)
|
|
return __set_memory((unsigned long)page_to_virt(page), 1, SET_MEMORY_DEF);
|
|
}
|
|
|
|
+bool kernel_page_present(struct page *page)
|
|
+{
|
|
+ unsigned long addr;
|
|
+ unsigned int cc;
|
|
+
|
|
+ addr = (unsigned long)page_address(page);
|
|
+ asm volatile(
|
|
+ " lra %[addr],0(%[addr])\n"
|
|
+ " ipm %[cc]\n"
|
|
+ : [cc] "=d" (cc), [addr] "+a" (addr)
|
|
+ :
|
|
+ : "cc");
|
|
+ return (cc >> 28) == 0;
|
|
+}
|
|
+
|
|
#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
|
|
|
|
static void ipte_range(pte_t *pte, unsigned long address, int nr)
|
|
diff --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c
|
|
index a306bcd6b34130..5f6d0e827baeb0 100644
|
|
--- a/arch/sh/kernel/cpu/proc.c
|
|
+++ b/arch/sh/kernel/cpu/proc.c
|
|
@@ -132,7 +132,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|
|
|
static void *c_start(struct seq_file *m, loff_t *pos)
|
|
{
|
|
- return *pos < NR_CPUS ? cpu_data + *pos : NULL;
|
|
+ return *pos < nr_cpu_ids ? cpu_data + *pos : NULL;
|
|
}
|
|
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
|
|
{
|
|
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
|
|
index b3da2757faaf31..1fb59c69b97c85 100644
|
|
--- a/arch/sh/kernel/setup.c
|
|
+++ b/arch/sh/kernel/setup.c
|
|
@@ -260,7 +260,7 @@ void __ref sh_fdt_init(phys_addr_t dt_phys)
|
|
dt_virt = phys_to_virt(dt_phys);
|
|
#endif
|
|
|
|
- if (!dt_virt || !early_init_dt_scan(dt_virt)) {
|
|
+ if (!dt_virt || !early_init_dt_scan(dt_virt, __pa(dt_virt))) {
|
|
pr_crit("Error: invalid device tree blob"
|
|
" at physical address %p\n", (void *)dt_phys);
|
|
|
|
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
|
|
index cabcc501b448a3..de187e58dc2b19 100644
|
|
--- a/arch/um/drivers/net_kern.c
|
|
+++ b/arch/um/drivers/net_kern.c
|
|
@@ -336,7 +336,7 @@ static struct platform_driver uml_net_driver = {
|
|
|
|
static void net_device_release(struct device *dev)
|
|
{
|
|
- struct uml_net *device = dev_get_drvdata(dev);
|
|
+ struct uml_net *device = container_of(dev, struct uml_net, pdev.dev);
|
|
struct net_device *netdev = device->dev;
|
|
struct uml_net_private *lp = netdev_priv(netdev);
|
|
|
|
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
|
|
index ef7b4b911a455a..7ddda2c0ae436f 100644
|
|
--- a/arch/um/drivers/ubd_kern.c
|
|
+++ b/arch/um/drivers/ubd_kern.c
|
|
@@ -799,7 +799,7 @@ static int ubd_open_dev(struct ubd *ubd_dev)
|
|
|
|
static void ubd_device_release(struct device *dev)
|
|
{
|
|
- struct ubd *ubd_dev = dev_get_drvdata(dev);
|
|
+ struct ubd *ubd_dev = container_of(dev, struct ubd, pdev.dev);
|
|
|
|
blk_mq_free_tag_set(&ubd_dev->tag_set);
|
|
*ubd_dev = ((struct ubd) DEFAULT_UBD);
|
|
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
|
|
index 94a4dfac6c2368..2baa8d4a33ed3d 100644
|
|
--- a/arch/um/drivers/vector_kern.c
|
|
+++ b/arch/um/drivers/vector_kern.c
|
|
@@ -823,7 +823,8 @@ static struct platform_driver uml_net_driver = {
|
|
|
|
static void vector_device_release(struct device *dev)
|
|
{
|
|
- struct vector_device *device = dev_get_drvdata(dev);
|
|
+ struct vector_device *device =
|
|
+ container_of(dev, struct vector_device, pdev.dev);
|
|
struct net_device *netdev = device->dev;
|
|
|
|
list_del(&device->list);
|
|
diff --git a/arch/um/kernel/dtb.c b/arch/um/kernel/dtb.c
|
|
index 484141b06938ff..8d78ced9e08f6d 100644
|
|
--- a/arch/um/kernel/dtb.c
|
|
+++ b/arch/um/kernel/dtb.c
|
|
@@ -16,16 +16,16 @@ void uml_dtb_init(void)
|
|
void *area;
|
|
|
|
area = uml_load_file(dtb, &size);
|
|
- if (!area)
|
|
- return;
|
|
-
|
|
- if (!early_init_dt_scan(area)) {
|
|
- pr_err("invalid DTB %s\n", dtb);
|
|
- memblock_free(area, size);
|
|
- return;
|
|
+ if (area) {
|
|
+ if (!early_init_dt_scan(area, __pa(area))) {
|
|
+ pr_err("invalid DTB %s\n", dtb);
|
|
+ memblock_free(area, size);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ early_init_fdt_scan_reserved_mem();
|
|
}
|
|
|
|
- early_init_fdt_scan_reserved_mem();
|
|
unflatten_device_tree();
|
|
}
|
|
|
|
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
|
|
index 91485119ae67a7..4339580f5a4f64 100644
|
|
--- a/arch/um/kernel/physmem.c
|
|
+++ b/arch/um/kernel/physmem.c
|
|
@@ -80,10 +80,10 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
|
|
unsigned long len, unsigned long long highmem)
|
|
{
|
|
unsigned long reserve = reserve_end - start;
|
|
- long map_size = len - reserve;
|
|
+ unsigned long map_size = len - reserve;
|
|
int err;
|
|
|
|
- if(map_size <= 0) {
|
|
+ if (len <= reserve) {
|
|
os_warn("Too few physical memory! Needed=%lu, given=%lu\n",
|
|
reserve, len);
|
|
exit(1);
|
|
@@ -94,7 +94,7 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
|
|
err = os_map_memory((void *) reserve_end, physmem_fd, reserve,
|
|
map_size, 1, 1, 1);
|
|
if (err < 0) {
|
|
- os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p "
|
|
+ os_warn("setup_physmem - mapping %lu bytes of memory at 0x%p "
|
|
"failed - errno = %d\n", map_size,
|
|
(void *) reserve_end, err);
|
|
exit(1);
|
|
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
|
|
index 6daffb9d8a8d74..afe67d81614676 100644
|
|
--- a/arch/um/kernel/process.c
|
|
+++ b/arch/um/kernel/process.c
|
|
@@ -397,6 +397,6 @@ int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
|
|
{
|
|
int cpu = current_thread_info()->cpu;
|
|
|
|
- return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu);
|
|
+ return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu) == 0;
|
|
}
|
|
|
|
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
|
|
index 746715379f12a8..7e897e44a03da2 100644
|
|
--- a/arch/um/kernel/sysrq.c
|
|
+++ b/arch/um/kernel/sysrq.c
|
|
@@ -53,5 +53,5 @@ void show_stack(struct task_struct *task, unsigned long *stack,
|
|
}
|
|
|
|
printk("%sCall Trace:\n", loglvl);
|
|
- dump_trace(current, &stackops, (void *)loglvl);
|
|
+ dump_trace(task ?: current, &stackops, (void *)loglvl);
|
|
}
|
|
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
|
|
index 3ff53a2d4ff084..c83582b5a010de 100644
|
|
--- a/arch/x86/Makefile
|
|
+++ b/arch/x86/Makefile
|
|
@@ -113,7 +113,8 @@ ifeq ($(CONFIG_X86_32),y)
|
|
|
|
ifeq ($(CONFIG_STACKPROTECTOR),y)
|
|
ifeq ($(CONFIG_SMP),y)
|
|
- KBUILD_CFLAGS += -mstack-protector-guard-reg=fs -mstack-protector-guard-symbol=__stack_chk_guard
|
|
+ KBUILD_CFLAGS += -mstack-protector-guard-reg=fs \
|
|
+ -mstack-protector-guard-symbol=__ref_stack_chk_guard
|
|
else
|
|
KBUILD_CFLAGS += -mstack-protector-guard=global
|
|
endif
|
|
diff --git a/arch/x86/coco/tdx/tdcall.S b/arch/x86/coco/tdx/tdcall.S
|
|
index 2eca5f43734feb..56b9cd32895e4b 100644
|
|
--- a/arch/x86/coco/tdx/tdcall.S
|
|
+++ b/arch/x86/coco/tdx/tdcall.S
|
|
@@ -40,49 +40,35 @@
|
|
.section .noinstr.text, "ax"
|
|
|
|
/*
|
|
- * __tdx_module_call() - Used by TDX guests to request services from
|
|
- * the TDX module (does not include VMM services) using TDCALL instruction.
|
|
+ * __tdcall() - Used by TDX guests to request services from the TDX
|
|
+ * module (does not include VMM services) using TDCALL instruction.
|
|
*
|
|
- * Transforms function call register arguments into the TDCALL register ABI.
|
|
- * After TDCALL operation, TDX module output is saved in @out (if it is
|
|
- * provided by the user).
|
|
+ * __tdcall() function ABI:
|
|
*
|
|
- *-------------------------------------------------------------------------
|
|
- * TDCALL ABI:
|
|
- *-------------------------------------------------------------------------
|
|
- * Input Registers:
|
|
- *
|
|
- * RAX - TDCALL Leaf number.
|
|
- * RCX,RDX,R8-R9 - TDCALL Leaf specific input registers.
|
|
- *
|
|
- * Output Registers:
|
|
- *
|
|
- * RAX - TDCALL instruction error code.
|
|
- * RCX,RDX,R8-R11 - TDCALL Leaf specific output registers.
|
|
- *
|
|
- *-------------------------------------------------------------------------
|
|
+ * @fn (RDI) - TDCALL Leaf ID, moved to RAX
|
|
+ * @args (RSI) - struct tdx_module_args for input
|
|
*
|
|
- * __tdx_module_call() function ABI:
|
|
+ * Return status of TDCALL via RAX.
|
|
+ */
|
|
+SYM_FUNC_START(__tdcall)
|
|
+ TDX_MODULE_CALL host=0
|
|
+SYM_FUNC_END(__tdcall)
|
|
+
|
|
+/*
|
|
+ * __tdcall_ret() - Used by TDX guests to request services from the TDX
|
|
+ * module (does not include VMM services) using TDCALL instruction, with
|
|
+ * saving output registers to the 'struct tdx_module_args' used as input.
|
|
*
|
|
- * @fn (RDI) - TDCALL Leaf ID, moved to RAX
|
|
- * @rcx (RSI) - Input parameter 1, moved to RCX
|
|
- * @rdx (RDX) - Input parameter 2, moved to RDX
|
|
- * @r8 (RCX) - Input parameter 3, moved to R8
|
|
- * @r9 (R8) - Input parameter 4, moved to R9
|
|
+ * __tdcall_ret() function ABI:
|
|
*
|
|
- * @out (R9) - struct tdx_module_output pointer
|
|
- * stored temporarily in R12 (not
|
|
- * shared with the TDX module). It
|
|
- * can be NULL.
|
|
+ * @fn (RDI) - TDCALL Leaf ID, moved to RAX
|
|
+ * @args (RSI) - struct tdx_module_args for input and output
|
|
*
|
|
* Return status of TDCALL via RAX.
|
|
*/
|
|
-SYM_FUNC_START(__tdx_module_call)
|
|
- FRAME_BEGIN
|
|
- TDX_MODULE_CALL host=0
|
|
- FRAME_END
|
|
- RET
|
|
-SYM_FUNC_END(__tdx_module_call)
|
|
+SYM_FUNC_START(__tdcall_ret)
|
|
+ TDX_MODULE_CALL host=0 ret=1
|
|
+SYM_FUNC_END(__tdcall_ret)
|
|
|
|
/*
|
|
* TDX_HYPERCALL - Make hypercalls to a TDX VMM using TDVMCALL leaf of TDCALL
|
|
diff --git a/arch/x86/coco/tdx/tdx-shared.c b/arch/x86/coco/tdx/tdx-shared.c
|
|
index ef20ddc37b58aa..a7396d0ddef9e6 100644
|
|
--- a/arch/x86/coco/tdx/tdx-shared.c
|
|
+++ b/arch/x86/coco/tdx/tdx-shared.c
|
|
@@ -5,7 +5,7 @@ static unsigned long try_accept_one(phys_addr_t start, unsigned long len,
|
|
enum pg_level pg_level)
|
|
{
|
|
unsigned long accept_size = page_level_size(pg_level);
|
|
- u64 tdcall_rcx;
|
|
+ struct tdx_module_args args = {};
|
|
u8 page_size;
|
|
|
|
if (!IS_ALIGNED(start, accept_size))
|
|
@@ -34,8 +34,8 @@ static unsigned long try_accept_one(phys_addr_t start, unsigned long len,
|
|
return 0;
|
|
}
|
|
|
|
- tdcall_rcx = start | page_size;
|
|
- if (__tdx_module_call(TDX_ACCEPT_PAGE, tdcall_rcx, 0, 0, 0, NULL))
|
|
+ args.rcx = start | page_size;
|
|
+ if (__tdcall(TDG_MEM_PAGE_ACCEPT, &args))
|
|
return 0;
|
|
|
|
return accept_size;
|
|
@@ -45,7 +45,7 @@ bool tdx_accept_memory(phys_addr_t start, phys_addr_t end)
|
|
{
|
|
/*
|
|
* For shared->private conversion, accept the page using
|
|
- * TDX_ACCEPT_PAGE TDX module call.
|
|
+ * TDG_MEM_PAGE_ACCEPT TDX module call.
|
|
*/
|
|
while (start < end) {
|
|
unsigned long len = end - start;
|
|
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
|
|
index 905ac8a3f7165c..2f67e196a2ead2 100644
|
|
--- a/arch/x86/coco/tdx/tdx.c
|
|
+++ b/arch/x86/coco/tdx/tdx.c
|
|
@@ -68,13 +68,38 @@ EXPORT_SYMBOL_GPL(tdx_kvm_hypercall);
|
|
* should only be used for calls that have no legitimate reason to fail
|
|
* or where the kernel can not survive the call failing.
|
|
*/
|
|
-static inline void tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
|
|
- struct tdx_module_output *out)
|
|
+static inline void tdcall(u64 fn, struct tdx_module_args *args)
|
|
{
|
|
- if (__tdx_module_call(fn, rcx, rdx, r8, r9, out))
|
|
+ if (__tdcall_ret(fn, args))
|
|
panic("TDCALL %lld failed (Buggy TDX module!)\n", fn);
|
|
}
|
|
|
|
+/* Read TD-scoped metadata */
|
|
+static inline u64 tdg_vm_rd(u64 field, u64 *value)
|
|
+{
|
|
+ struct tdx_module_args args = {
|
|
+ .rdx = field,
|
|
+ };
|
|
+ u64 ret;
|
|
+
|
|
+ ret = __tdcall_ret(TDG_VM_RD, &args);
|
|
+ *value = args.r8;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* Write TD-scoped metadata */
|
|
+static inline u64 tdg_vm_wr(u64 field, u64 value, u64 mask)
|
|
+{
|
|
+ struct tdx_module_args args = {
|
|
+ .rdx = field,
|
|
+ .r8 = value,
|
|
+ .r9 = mask,
|
|
+ };
|
|
+
|
|
+ return __tdcall(TDG_VM_WR, &args);
|
|
+}
|
|
+
|
|
/**
|
|
* tdx_mcall_get_report0() - Wrapper to get TDREPORT0 (a.k.a. TDREPORT
|
|
* subtype 0) using TDG.MR.REPORT TDCALL.
|
|
@@ -91,11 +116,14 @@ static inline void tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
|
|
*/
|
|
int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport)
|
|
{
|
|
+ struct tdx_module_args args = {
|
|
+ .rcx = virt_to_phys(tdreport),
|
|
+ .rdx = virt_to_phys(reportdata),
|
|
+ .r8 = TDREPORT_SUBTYPE_0,
|
|
+ };
|
|
u64 ret;
|
|
|
|
- ret = __tdx_module_call(TDX_GET_REPORT, virt_to_phys(tdreport),
|
|
- virt_to_phys(reportdata), TDREPORT_SUBTYPE_0,
|
|
- 0, NULL);
|
|
+ ret = __tdcall(TDG_MR_REPORT, &args);
|
|
if (ret) {
|
|
if (TDCALL_RETURN_CODE(ret) == TDCALL_INVALID_OPERAND)
|
|
return -EINVAL;
|
|
@@ -141,9 +169,63 @@ static void __noreturn tdx_panic(const char *msg)
|
|
__tdx_hypercall(&args);
|
|
}
|
|
|
|
-static void tdx_parse_tdinfo(u64 *cc_mask)
|
|
+/*
|
|
+ * The kernel cannot handle #VEs when accessing normal kernel memory. Ensure
|
|
+ * that no #VE will be delivered for accesses to TD-private memory.
|
|
+ *
|
|
+ * TDX 1.0 does not allow the guest to disable SEPT #VE on its own. The VMM
|
|
+ * controls if the guest will receive such #VE with TD attribute
|
|
+ * ATTR_SEPT_VE_DISABLE.
|
|
+ *
|
|
+ * Newer TDX modules allow the guest to control if it wants to receive SEPT
|
|
+ * violation #VEs.
|
|
+ *
|
|
+ * Check if the feature is available and disable SEPT #VE if possible.
|
|
+ *
|
|
+ * If the TD is allowed to disable/enable SEPT #VEs, the ATTR_SEPT_VE_DISABLE
|
|
+ * attribute is no longer reliable. It reflects the initial state of the
|
|
+ * control for the TD, but it will not be updated if someone (e.g. bootloader)
|
|
+ * changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit to
|
|
+ * determine if SEPT #VEs are enabled or disabled.
|
|
+ */
|
|
+static void disable_sept_ve(u64 td_attr)
|
|
+{
|
|
+ const char *msg = "TD misconfiguration: SEPT #VE has to be disabled";
|
|
+ bool debug = td_attr & ATTR_DEBUG;
|
|
+ u64 config, controls;
|
|
+
|
|
+ /* Is this TD allowed to disable SEPT #VE */
|
|
+ tdg_vm_rd(TDCS_CONFIG_FLAGS, &config);
|
|
+ if (!(config & TDCS_CONFIG_FLEXIBLE_PENDING_VE)) {
|
|
+ /* No SEPT #VE controls for the guest: check the attribute */
|
|
+ if (td_attr & ATTR_SEPT_VE_DISABLE)
|
|
+ return;
|
|
+
|
|
+ /* Relax SEPT_VE_DISABLE check for debug TD for backtraces */
|
|
+ if (debug)
|
|
+ pr_warn("%s\n", msg);
|
|
+ else
|
|
+ tdx_panic(msg);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* Check if SEPT #VE has been disabled before us */
|
|
+ tdg_vm_rd(TDCS_TD_CTLS, &controls);
|
|
+ if (controls & TD_CTLS_PENDING_VE_DISABLE)
|
|
+ return;
|
|
+
|
|
+ /* Keep #VEs enabled for splats in debugging environments */
|
|
+ if (debug)
|
|
+ return;
|
|
+
|
|
+ /* Disable SEPT #VEs */
|
|
+ tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_PENDING_VE_DISABLE,
|
|
+ TD_CTLS_PENDING_VE_DISABLE);
|
|
+}
|
|
+
|
|
+static void tdx_setup(u64 *cc_mask)
|
|
{
|
|
- struct tdx_module_output out;
|
|
+ struct tdx_module_args args = {};
|
|
unsigned int gpa_width;
|
|
u64 td_attr;
|
|
|
|
@@ -154,7 +236,7 @@ static void tdx_parse_tdinfo(u64 *cc_mask)
|
|
* Guest-Host-Communication Interface (GHCI), section 2.4.2 TDCALL
|
|
* [TDG.VP.INFO].
|
|
*/
|
|
- tdx_module_call(TDX_GET_INFO, 0, 0, 0, 0, &out);
|
|
+ tdcall(TDG_VP_INFO, &args);
|
|
|
|
/*
|
|
* The highest bit of a guest physical address is the "sharing" bit.
|
|
@@ -163,24 +245,15 @@ static void tdx_parse_tdinfo(u64 *cc_mask)
|
|
* The GPA width that comes out of this call is critical. TDX guests
|
|
* can not meaningfully run without it.
|
|
*/
|
|
- gpa_width = out.rcx & GENMASK(5, 0);
|
|
+ gpa_width = args.rcx & GENMASK(5, 0);
|
|
*cc_mask = BIT_ULL(gpa_width - 1);
|
|
|
|
- /*
|
|
- * The kernel can not handle #VE's when accessing normal kernel
|
|
- * memory. Ensure that no #VE will be delivered for accesses to
|
|
- * TD-private memory. Only VMM-shared memory (MMIO) will #VE.
|
|
- */
|
|
- td_attr = out.rdx;
|
|
- if (!(td_attr & ATTR_SEPT_VE_DISABLE)) {
|
|
- const char *msg = "TD misconfiguration: SEPT_VE_DISABLE attribute must be set.";
|
|
+ td_attr = args.rdx;
|
|
|
|
- /* Relax SEPT_VE_DISABLE check for debug TD. */
|
|
- if (td_attr & ATTR_DEBUG)
|
|
- pr_warn("%s\n", msg);
|
|
- else
|
|
- tdx_panic(msg);
|
|
- }
|
|
+ /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */
|
|
+ tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL);
|
|
+
|
|
+ disable_sept_ve(td_attr);
|
|
}
|
|
|
|
/*
|
|
@@ -583,7 +656,7 @@ __init bool tdx_early_handle_ve(struct pt_regs *regs)
|
|
|
|
void tdx_get_ve_info(struct ve_info *ve)
|
|
{
|
|
- struct tdx_module_output out;
|
|
+ struct tdx_module_args args = {};
|
|
|
|
/*
|
|
* Called during #VE handling to retrieve the #VE info from the
|
|
@@ -600,15 +673,15 @@ void tdx_get_ve_info(struct ve_info *ve)
|
|
* Note, the TDX module treats virtual NMIs as inhibited if the #VE
|
|
* valid flag is set. It means that NMI=>#VE will not result in a #DF.
|
|
*/
|
|
- tdx_module_call(TDX_GET_VEINFO, 0, 0, 0, 0, &out);
|
|
+ tdcall(TDG_VP_VEINFO_GET, &args);
|
|
|
|
/* Transfer the output parameters */
|
|
- ve->exit_reason = out.rcx;
|
|
- ve->exit_qual = out.rdx;
|
|
- ve->gla = out.r8;
|
|
- ve->gpa = out.r9;
|
|
- ve->instr_len = lower_32_bits(out.r10);
|
|
- ve->instr_info = upper_32_bits(out.r10);
|
|
+ ve->exit_reason = args.rcx;
|
|
+ ve->exit_qual = args.rdx;
|
|
+ ve->gla = args.r8;
|
|
+ ve->gpa = args.r9;
|
|
+ ve->instr_len = lower_32_bits(args.r10);
|
|
+ ve->instr_info = upper_32_bits(args.r10);
|
|
}
|
|
|
|
/*
|
|
@@ -776,11 +849,11 @@ void __init tdx_early_init(void)
|
|
setup_force_cpu_cap(X86_FEATURE_TDX_GUEST);
|
|
|
|
cc_vendor = CC_VENDOR_INTEL;
|
|
- tdx_parse_tdinfo(&cc_mask);
|
|
- cc_set_mask(cc_mask);
|
|
|
|
- /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */
|
|
- tdx_module_call(TDX_WR, 0, TDCS_NOTIFY_ENABLES, 0, -1ULL, NULL);
|
|
+ /* Configure the TD */
|
|
+ tdx_setup(&cc_mask);
|
|
+
|
|
+ cc_set_mask(cc_mask);
|
|
|
|
/*
|
|
* All bits above GPA width are reserved and kernel treats shared bit
|
|
diff --git a/arch/x86/crypto/aegis128-aesni-asm.S b/arch/x86/crypto/aegis128-aesni-asm.S
|
|
index ad7f4c89162568..2de859173940eb 100644
|
|
--- a/arch/x86/crypto/aegis128-aesni-asm.S
|
|
+++ b/arch/x86/crypto/aegis128-aesni-asm.S
|
|
@@ -21,7 +21,7 @@
|
|
#define T1 %xmm7
|
|
|
|
#define STATEP %rdi
|
|
-#define LEN %rsi
|
|
+#define LEN %esi
|
|
#define SRC %rdx
|
|
#define DST %rcx
|
|
|
|
@@ -76,32 +76,32 @@ SYM_FUNC_START_LOCAL(__load_partial)
|
|
xor %r9d, %r9d
|
|
pxor MSG, MSG
|
|
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
and $0x1, %r8
|
|
jz .Lld_partial_1
|
|
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
and $0x1E, %r8
|
|
add SRC, %r8
|
|
mov (%r8), %r9b
|
|
|
|
.Lld_partial_1:
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
and $0x2, %r8
|
|
jz .Lld_partial_2
|
|
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
and $0x1C, %r8
|
|
add SRC, %r8
|
|
shl $0x10, %r9
|
|
mov (%r8), %r9w
|
|
|
|
.Lld_partial_2:
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
and $0x4, %r8
|
|
jz .Lld_partial_4
|
|
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
and $0x18, %r8
|
|
add SRC, %r8
|
|
shl $32, %r9
|
|
@@ -111,11 +111,11 @@ SYM_FUNC_START_LOCAL(__load_partial)
|
|
.Lld_partial_4:
|
|
movq %r9, MSG
|
|
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
and $0x8, %r8
|
|
jz .Lld_partial_8
|
|
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
and $0x10, %r8
|
|
add SRC, %r8
|
|
pslldq $8, MSG
|
|
@@ -139,7 +139,7 @@ SYM_FUNC_END(__load_partial)
|
|
* %r10
|
|
*/
|
|
SYM_FUNC_START_LOCAL(__store_partial)
|
|
- mov LEN, %r8
|
|
+ mov LEN, %r8d
|
|
mov DST, %r9
|
|
|
|
movq T0, %r10
|
|
@@ -677,7 +677,7 @@ SYM_TYPED_FUNC_START(crypto_aegis128_aesni_dec_tail)
|
|
call __store_partial
|
|
|
|
/* mask with byte count: */
|
|
- movq LEN, T0
|
|
+ movd LEN, T0
|
|
punpcklbw T0, T0
|
|
punpcklbw T0, T0
|
|
punpcklbw T0, T0
|
|
@@ -702,7 +702,8 @@ SYM_FUNC_END(crypto_aegis128_aesni_dec_tail)
|
|
|
|
/*
|
|
* void crypto_aegis128_aesni_final(void *state, void *tag_xor,
|
|
- * u64 assoclen, u64 cryptlen);
|
|
+ * unsigned int assoclen,
|
|
+ * unsigned int cryptlen);
|
|
*/
|
|
SYM_FUNC_START(crypto_aegis128_aesni_final)
|
|
FRAME_BEGIN
|
|
@@ -715,8 +716,8 @@ SYM_FUNC_START(crypto_aegis128_aesni_final)
|
|
movdqu 0x40(STATEP), STATE4
|
|
|
|
/* prepare length block: */
|
|
- movq %rdx, MSG
|
|
- movq %rcx, T0
|
|
+ movd %edx, MSG
|
|
+ movd %ecx, T0
|
|
pslldq $8, T0
|
|
pxor T0, MSG
|
|
psllq $3, MSG /* multiply by 8 (to get bit count) */
|
|
diff --git a/arch/x86/entry/entry.S b/arch/x86/entry/entry.S
|
|
index 34eca8015b64bc..2143358d0c4c74 100644
|
|
--- a/arch/x86/entry/entry.S
|
|
+++ b/arch/x86/entry/entry.S
|
|
@@ -48,3 +48,18 @@ EXPORT_SYMBOL_GPL(mds_verw_sel);
|
|
|
|
.popsection
|
|
|
|
+#ifndef CONFIG_X86_64
|
|
+/*
|
|
+ * Clang's implementation of TLS stack cookies requires the variable in
|
|
+ * question to be a TLS variable. If the variable happens to be defined as an
|
|
+ * ordinary variable with external linkage in the same compilation unit (which
|
|
+ * amounts to the whole of vmlinux with LTO enabled), Clang will drop the
|
|
+ * segment register prefix from the references, resulting in broken code. Work
|
|
+ * around this by avoiding the symbol used in -mstack-protector-guard-symbol=
|
|
+ * entirely in the C code, and use an alias emitted by the linker script
|
|
+ * instead.
|
|
+ */
|
|
+#ifdef CONFIG_STACKPROTECTOR
|
|
+EXPORT_SYMBOL(__ref_stack_chk_guard);
|
|
+#endif
|
|
+#endif
|
|
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
|
|
index 688550e336ce17..37c8badd270155 100644
|
|
--- a/arch/x86/events/intel/core.c
|
|
+++ b/arch/x86/events/intel/core.c
|
|
@@ -5559,8 +5559,22 @@ default_is_visible(struct kobject *kobj, struct attribute *attr, int i)
|
|
return attr->mode;
|
|
}
|
|
|
|
+static umode_t
|
|
+td_is_visible(struct kobject *kobj, struct attribute *attr, int i)
|
|
+{
|
|
+ /*
|
|
+ * Hide the perf metrics topdown events
|
|
+ * if the feature is not enumerated.
|
|
+ */
|
|
+ if (x86_pmu.num_topdown_events)
|
|
+ return x86_pmu.intel_cap.perf_metrics ? attr->mode : 0;
|
|
+
|
|
+ return attr->mode;
|
|
+}
|
|
+
|
|
static struct attribute_group group_events_td = {
|
|
.name = "events",
|
|
+ .is_visible = td_is_visible,
|
|
};
|
|
|
|
static struct attribute_group group_events_mem = {
|
|
@@ -5762,9 +5776,27 @@ static umode_t hybrid_format_is_visible(struct kobject *kobj,
|
|
return (cpu >= 0) && (pmu->cpu_type & pmu_attr->pmu_type) ? attr->mode : 0;
|
|
}
|
|
|
|
+static umode_t hybrid_td_is_visible(struct kobject *kobj,
|
|
+ struct attribute *attr, int i)
|
|
+{
|
|
+ struct device *dev = kobj_to_dev(kobj);
|
|
+ struct x86_hybrid_pmu *pmu =
|
|
+ container_of(dev_get_drvdata(dev), struct x86_hybrid_pmu, pmu);
|
|
+
|
|
+ if (!is_attr_for_this_pmu(kobj, attr))
|
|
+ return 0;
|
|
+
|
|
+
|
|
+ /* Only the big core supports perf metrics */
|
|
+ if (pmu->cpu_type == hybrid_big)
|
|
+ return pmu->intel_cap.perf_metrics ? attr->mode : 0;
|
|
+
|
|
+ return attr->mode;
|
|
+}
|
|
+
|
|
static struct attribute_group hybrid_group_events_td = {
|
|
.name = "events",
|
|
- .is_visible = hybrid_events_is_visible,
|
|
+ .is_visible = hybrid_td_is_visible,
|
|
};
|
|
|
|
static struct attribute_group hybrid_group_events_mem = {
|
|
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
|
|
index 4110246aba12c3..7ee8dc80a35935 100644
|
|
--- a/arch/x86/events/intel/pt.c
|
|
+++ b/arch/x86/events/intel/pt.c
|
|
@@ -827,11 +827,13 @@ static void pt_buffer_advance(struct pt_buffer *buf)
|
|
buf->cur_idx++;
|
|
|
|
if (buf->cur_idx == buf->cur->last) {
|
|
- if (buf->cur == buf->last)
|
|
+ if (buf->cur == buf->last) {
|
|
buf->cur = buf->first;
|
|
- else
|
|
+ buf->wrapped = true;
|
|
+ } else {
|
|
buf->cur = list_entry(buf->cur->list.next, struct topa,
|
|
list);
|
|
+ }
|
|
buf->cur_idx = 0;
|
|
}
|
|
}
|
|
@@ -845,8 +847,11 @@ static void pt_buffer_advance(struct pt_buffer *buf)
|
|
static void pt_update_head(struct pt *pt)
|
|
{
|
|
struct pt_buffer *buf = perf_get_aux(&pt->handle);
|
|
+ bool wrapped = buf->wrapped;
|
|
u64 topa_idx, base, old;
|
|
|
|
+ buf->wrapped = false;
|
|
+
|
|
if (buf->single) {
|
|
local_set(&buf->data_size, buf->output_off);
|
|
return;
|
|
@@ -864,7 +869,7 @@ static void pt_update_head(struct pt *pt)
|
|
} else {
|
|
old = (local64_xchg(&buf->head, base) &
|
|
((buf->nr_pages << PAGE_SHIFT) - 1));
|
|
- if (base < old)
|
|
+ if (base < old || (base == old && wrapped))
|
|
base += buf->nr_pages << PAGE_SHIFT;
|
|
|
|
local_add(base - old, &buf->data_size);
|
|
diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h
|
|
index f5e46c04c145d0..a1b6c04b7f6848 100644
|
|
--- a/arch/x86/events/intel/pt.h
|
|
+++ b/arch/x86/events/intel/pt.h
|
|
@@ -65,6 +65,7 @@ struct pt_pmu {
|
|
* @head: logical write offset inside the buffer
|
|
* @snapshot: if this is for a snapshot/overwrite counter
|
|
* @single: use Single Range Output instead of ToPA
|
|
+ * @wrapped: buffer advance wrapped back to the first topa table
|
|
* @stop_pos: STOP topa entry index
|
|
* @intr_pos: INT topa entry index
|
|
* @stop_te: STOP topa entry pointer
|
|
@@ -82,6 +83,7 @@ struct pt_buffer {
|
|
local64_t head;
|
|
bool snapshot;
|
|
bool single;
|
|
+ bool wrapped;
|
|
long stop_pos, intr_pos;
|
|
struct topa_entry *stop_te, *intr_te;
|
|
void **data_pages;
|
|
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
|
|
index ed0eaf65c43721..c8cdc69aae098b 100644
|
|
--- a/arch/x86/include/asm/amd_nb.h
|
|
+++ b/arch/x86/include/asm/amd_nb.h
|
|
@@ -116,7 +116,10 @@ static inline bool amd_gart_present(void)
|
|
|
|
#define amd_nb_num(x) 0
|
|
#define amd_nb_has_feature(x) false
|
|
-#define node_to_amd_nb(x) NULL
|
|
+static inline struct amd_northbridge *node_to_amd_nb(int node)
|
|
+{
|
|
+ return NULL;
|
|
+}
|
|
#define amd_gart_present(x) false
|
|
|
|
#endif
|
|
diff --git a/arch/x86/include/asm/asm-prototypes.h b/arch/x86/include/asm/asm-prototypes.h
|
|
index 0e82074517f6b7..768076e6866844 100644
|
|
--- a/arch/x86/include/asm/asm-prototypes.h
|
|
+++ b/arch/x86/include/asm/asm-prototypes.h
|
|
@@ -19,3 +19,6 @@
|
|
extern void cmpxchg8b_emu(void);
|
|
#endif
|
|
|
|
+#if defined(__GENKSYMS__) && defined(CONFIG_STACKPROTECTOR)
|
|
+extern unsigned long __ref_stack_chk_guard;
|
|
+#endif
|
|
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
|
|
index 7513b3bb69b7e4..aed99fb099d9c5 100644
|
|
--- a/arch/x86/include/asm/shared/tdx.h
|
|
+++ b/arch/x86/include/asm/shared/tdx.h
|
|
@@ -11,15 +11,24 @@
|
|
#define TDX_IDENT "IntelTDX "
|
|
|
|
/* TDX module Call Leaf IDs */
|
|
-#define TDX_GET_INFO 1
|
|
-#define TDX_GET_VEINFO 3
|
|
-#define TDX_GET_REPORT 4
|
|
-#define TDX_ACCEPT_PAGE 6
|
|
-#define TDX_WR 8
|
|
-
|
|
-/* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */
|
|
+#define TDG_VP_INFO 1
|
|
+#define TDG_VP_VEINFO_GET 3
|
|
+#define TDG_MR_REPORT 4
|
|
+#define TDG_MEM_PAGE_ACCEPT 6
|
|
+#define TDG_VM_RD 7
|
|
+#define TDG_VM_WR 8
|
|
+
|
|
+/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */
|
|
+#define TDCS_CONFIG_FLAGS 0x1110000300000016
|
|
+#define TDCS_TD_CTLS 0x1110000300000017
|
|
#define TDCS_NOTIFY_ENABLES 0x9100000000000010
|
|
|
|
+/* TDCS_CONFIG_FLAGS bits */
|
|
+#define TDCS_CONFIG_FLEXIBLE_PENDING_VE BIT_ULL(1)
|
|
+
|
|
+/* TDCS_TD_CTLS bits */
|
|
+#define TD_CTLS_PENDING_VE_DISABLE BIT_ULL(0)
|
|
+
|
|
/* TDX hypercall Leaf IDs */
|
|
#define TDVMCALL_MAP_GPA 0x10001
|
|
#define TDVMCALL_REPORT_FATAL_ERROR 0x10003
|
|
@@ -74,11 +83,11 @@ static inline u64 _tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15)
|
|
void __tdx_hypercall_failed(void);
|
|
|
|
/*
|
|
- * Used in __tdx_module_call() to gather the output registers' values of the
|
|
+ * Used in __tdcall*() to gather the input/output registers' values of the
|
|
* TDCALL instruction when requesting services from the TDX module. This is a
|
|
* software only structure and not part of the TDX module/VMM ABI
|
|
*/
|
|
-struct tdx_module_output {
|
|
+struct tdx_module_args {
|
|
u64 rcx;
|
|
u64 rdx;
|
|
u64 r8;
|
|
@@ -88,8 +97,8 @@ struct tdx_module_output {
|
|
};
|
|
|
|
/* Used to communicate with the TDX module */
|
|
-u64 __tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
|
|
- struct tdx_module_output *out);
|
|
+u64 __tdcall(u64 fn, struct tdx_module_args *args);
|
|
+u64 __tdcall_ret(u64 fn, struct tdx_module_args *args);
|
|
|
|
bool tdx_accept_memory(phys_addr_t start, phys_addr_t end);
|
|
|
|
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
|
|
index dc3576303f1ade..50383bc46dd77d 100644
|
|
--- a/arch/x86/kernel/asm-offsets.c
|
|
+++ b/arch/x86/kernel/asm-offsets.c
|
|
@@ -68,12 +68,12 @@ static void __used common(void)
|
|
#endif
|
|
|
|
BLANK();
|
|
- OFFSET(TDX_MODULE_rcx, tdx_module_output, rcx);
|
|
- OFFSET(TDX_MODULE_rdx, tdx_module_output, rdx);
|
|
- OFFSET(TDX_MODULE_r8, tdx_module_output, r8);
|
|
- OFFSET(TDX_MODULE_r9, tdx_module_output, r9);
|
|
- OFFSET(TDX_MODULE_r10, tdx_module_output, r10);
|
|
- OFFSET(TDX_MODULE_r11, tdx_module_output, r11);
|
|
+ OFFSET(TDX_MODULE_rcx, tdx_module_args, rcx);
|
|
+ OFFSET(TDX_MODULE_rdx, tdx_module_args, rdx);
|
|
+ OFFSET(TDX_MODULE_r8, tdx_module_args, r8);
|
|
+ OFFSET(TDX_MODULE_r9, tdx_module_args, r9);
|
|
+ OFFSET(TDX_MODULE_r10, tdx_module_args, r10);
|
|
+ OFFSET(TDX_MODULE_r11, tdx_module_args, r11);
|
|
|
|
BLANK();
|
|
OFFSET(TDX_HYPERCALL_r8, tdx_hypercall_args, r8);
|
|
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
|
|
index 7a1e58fb43a033..852cc2ab4df946 100644
|
|
--- a/arch/x86/kernel/cpu/common.c
|
|
+++ b/arch/x86/kernel/cpu/common.c
|
|
@@ -2159,8 +2159,10 @@ void syscall_init(void)
|
|
|
|
#ifdef CONFIG_STACKPROTECTOR
|
|
DEFINE_PER_CPU(unsigned long, __stack_chk_guard);
|
|
+#ifndef CONFIG_SMP
|
|
EXPORT_PER_CPU_SYMBOL(__stack_chk_guard);
|
|
#endif
|
|
+#endif
|
|
|
|
#endif /* CONFIG_X86_64 */
|
|
|
|
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
|
|
index c13c9cb40b9b46..37ca25d82bbcdb 100644
|
|
--- a/arch/x86/kernel/devicetree.c
|
|
+++ b/arch/x86/kernel/devicetree.c
|
|
@@ -283,22 +283,24 @@ static void __init x86_flattree_get_config(void)
|
|
u32 size, map_len;
|
|
void *dt;
|
|
|
|
- if (!initial_dtb)
|
|
- return;
|
|
-
|
|
- map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
|
|
+ if (initial_dtb) {
|
|
+ map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
|
|
+
|
|
+ dt = early_memremap(initial_dtb, map_len);
|
|
+ size = fdt_totalsize(dt);
|
|
+ if (map_len < size) {
|
|
+ early_memunmap(dt, map_len);
|
|
+ dt = early_memremap(initial_dtb, size);
|
|
+ map_len = size;
|
|
+ }
|
|
|
|
- dt = early_memremap(initial_dtb, map_len);
|
|
- size = fdt_totalsize(dt);
|
|
- if (map_len < size) {
|
|
- early_memunmap(dt, map_len);
|
|
- dt = early_memremap(initial_dtb, size);
|
|
- map_len = size;
|
|
+ early_init_dt_verify(dt, __pa(dt));
|
|
}
|
|
|
|
- early_init_dt_verify(dt);
|
|
unflatten_and_copy_device_tree();
|
|
- early_memunmap(dt, map_len);
|
|
+
|
|
+ if (initial_dtb)
|
|
+ early_memunmap(dt, map_len);
|
|
}
|
|
#else
|
|
static inline void x86_flattree_get_config(void) { }
|
|
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
|
|
index 7e574cf3bf8a29..7784076819de58 100644
|
|
--- a/arch/x86/kernel/unwind_orc.c
|
|
+++ b/arch/x86/kernel/unwind_orc.c
|
|
@@ -723,7 +723,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
|
state->sp = task->thread.sp + sizeof(*frame);
|
|
state->bp = READ_ONCE_NOCHECK(frame->bp);
|
|
state->ip = READ_ONCE_NOCHECK(frame->ret_addr);
|
|
- state->signal = (void *)state->ip == ret_from_fork;
|
|
+ state->signal = (void *)state->ip == ret_from_fork_asm;
|
|
}
|
|
|
|
if (get_stack_info((unsigned long *)state->sp, state->task,
|
|
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
|
|
index 54a5596adaa61e..60eb8baa44d7b7 100644
|
|
--- a/arch/x86/kernel/vmlinux.lds.S
|
|
+++ b/arch/x86/kernel/vmlinux.lds.S
|
|
@@ -496,6 +496,9 @@ SECTIONS
|
|
ASSERT(SIZEOF(.rela.dyn) == 0, "Unexpected run-time relocations (.rela) detected!")
|
|
}
|
|
|
|
+/* needed for Clang - see arch/x86/entry/entry.S */
|
|
+PROVIDE(__ref_stack_chk_guard = __stack_chk_guard);
|
|
+
|
|
/*
|
|
* The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
|
|
*/
|
|
diff --git a/arch/x86/kvm/mmu/spte.c b/arch/x86/kvm/mmu/spte.c
|
|
index 4a599130e9c994..b4c1119cc48b69 100644
|
|
--- a/arch/x86/kvm/mmu/spte.c
|
|
+++ b/arch/x86/kvm/mmu/spte.c
|
|
@@ -206,12 +206,20 @@ bool make_spte(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
|
|
spte |= PT_WRITABLE_MASK | shadow_mmu_writable_mask;
|
|
|
|
/*
|
|
- * Optimization: for pte sync, if spte was writable the hash
|
|
- * lookup is unnecessary (and expensive). Write protection
|
|
- * is responsibility of kvm_mmu_get_page / kvm_mmu_sync_roots.
|
|
- * Same reasoning can be applied to dirty page accounting.
|
|
+ * When overwriting an existing leaf SPTE, and the old SPTE was
|
|
+ * writable, skip trying to unsync shadow pages as any relevant
|
|
+ * shadow pages must already be unsync, i.e. the hash lookup is
|
|
+ * unnecessary (and expensive).
|
|
+ *
|
|
+ * The same reasoning applies to dirty page/folio accounting;
|
|
+ * KVM will mark the folio dirty using the old SPTE, thus
|
|
+ * there's no need to immediately mark the new SPTE as dirty.
|
|
+ *
|
|
+ * Note, both cases rely on KVM not changing PFNs without first
|
|
+ * zapping the old SPTE, which is guaranteed by both the shadow
|
|
+ * MMU and the TDP MMU.
|
|
*/
|
|
- if (is_writable_pte(old_spte))
|
|
+ if (is_last_spte(old_spte, level) && is_writable_pte(old_spte))
|
|
goto out;
|
|
|
|
/*
|
|
diff --git a/arch/x86/platform/pvh/head.S b/arch/x86/platform/pvh/head.S
|
|
index c4365a05ab83b3..008a805522245f 100644
|
|
--- a/arch/x86/platform/pvh/head.S
|
|
+++ b/arch/x86/platform/pvh/head.S
|
|
@@ -100,7 +100,27 @@ SYM_CODE_START_LOCAL(pvh_start_xen)
|
|
xor %edx, %edx
|
|
wrmsr
|
|
|
|
- call xen_prepare_pvh
|
|
+ /*
|
|
+ * Calculate load offset and store in phys_base. __pa() needs
|
|
+ * phys_base set to calculate the hypercall page in xen_pvh_init().
|
|
+ */
|
|
+ movq %rbp, %rbx
|
|
+ subq $_pa(pvh_start_xen), %rbx
|
|
+ movq %rbx, phys_base(%rip)
|
|
+
|
|
+ /* Call xen_prepare_pvh() via the kernel virtual mapping */
|
|
+ leaq xen_prepare_pvh(%rip), %rax
|
|
+ subq phys_base(%rip), %rax
|
|
+ addq $__START_KERNEL_map, %rax
|
|
+ ANNOTATE_RETPOLINE_SAFE
|
|
+ call *%rax
|
|
+
|
|
+ /*
|
|
+ * Clear phys_base. __startup_64 will *add* to its value,
|
|
+ * so reset to 0.
|
|
+ */
|
|
+ xor %rbx, %rbx
|
|
+ movq %rbx, phys_base(%rip)
|
|
|
|
/* startup_64 expects boot_params in %rsi. */
|
|
mov $_pa(pvh_bootparams), %rsi
|
|
diff --git a/arch/x86/virt/vmx/tdx/tdxcall.S b/arch/x86/virt/vmx/tdx/tdxcall.S
|
|
index 49a54356ae9925..e9e19e7d77f818 100644
|
|
--- a/arch/x86/virt/vmx/tdx/tdxcall.S
|
|
+++ b/arch/x86/virt/vmx/tdx/tdxcall.S
|
|
@@ -1,5 +1,6 @@
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#include <asm/asm-offsets.h>
|
|
+#include <asm/frame.h>
|
|
#include <asm/tdx.h>
|
|
|
|
/*
|
|
@@ -16,35 +17,37 @@
|
|
* TDX module and hypercalls to the VMM.
|
|
* SEAMCALL - used by TDX hosts to make requests to the
|
|
* TDX module.
|
|
+ *
|
|
+ *-------------------------------------------------------------------------
|
|
+ * TDCALL/SEAMCALL ABI:
|
|
+ *-------------------------------------------------------------------------
|
|
+ * Input Registers:
|
|
+ *
|
|
+ * RAX - TDCALL/SEAMCALL Leaf number.
|
|
+ * RCX,RDX,R8-R11 - TDCALL/SEAMCALL Leaf specific input registers.
|
|
+ *
|
|
+ * Output Registers:
|
|
+ *
|
|
+ * RAX - TDCALL/SEAMCALL instruction error code.
|
|
+ * RCX,RDX,R8-R11 - TDCALL/SEAMCALL Leaf specific output registers.
|
|
+ *
|
|
+ *-------------------------------------------------------------------------
|
|
*/
|
|
-.macro TDX_MODULE_CALL host:req
|
|
- /*
|
|
- * R12 will be used as temporary storage for struct tdx_module_output
|
|
- * pointer. Since R12-R15 registers are not used by TDCALL/SEAMCALL
|
|
- * services supported by this function, it can be reused.
|
|
- */
|
|
-
|
|
- /* Callee saved, so preserve it */
|
|
- push %r12
|
|
-
|
|
- /*
|
|
- * Push output pointer to stack.
|
|
- * After the operation, it will be fetched into R12 register.
|
|
- */
|
|
- push %r9
|
|
+.macro TDX_MODULE_CALL host:req ret=0
|
|
+ FRAME_BEGIN
|
|
|
|
- /* Mangle function call ABI into TDCALL/SEAMCALL ABI: */
|
|
/* Move Leaf ID to RAX */
|
|
mov %rdi, %rax
|
|
- /* Move input 4 to R9 */
|
|
- mov %r8, %r9
|
|
- /* Move input 3 to R8 */
|
|
- mov %rcx, %r8
|
|
- /* Move input 1 to RCX */
|
|
- mov %rsi, %rcx
|
|
- /* Leave input param 2 in RDX */
|
|
|
|
- .if \host
|
|
+ /* Move other input regs from 'struct tdx_module_args' */
|
|
+ movq TDX_MODULE_rcx(%rsi), %rcx
|
|
+ movq TDX_MODULE_rdx(%rsi), %rdx
|
|
+ movq TDX_MODULE_r8(%rsi), %r8
|
|
+ movq TDX_MODULE_r9(%rsi), %r9
|
|
+ movq TDX_MODULE_r10(%rsi), %r10
|
|
+ movq TDX_MODULE_r11(%rsi), %r11
|
|
+
|
|
+.if \host
|
|
seamcall
|
|
/*
|
|
* SEAMCALL instruction is essentially a VMExit from VMX root
|
|
@@ -57,40 +60,31 @@
|
|
* This value will never be used as actual SEAMCALL error code as
|
|
* it is from the Reserved status code class.
|
|
*/
|
|
- jnc .Lno_vmfailinvalid
|
|
- mov $TDX_SEAMCALL_VMFAILINVALID, %rax
|
|
-.Lno_vmfailinvalid:
|
|
-
|
|
- .else
|
|
+ jc .Lseamcall_vmfailinvalid\@
|
|
+.else
|
|
tdcall
|
|
- .endif
|
|
+.endif
|
|
|
|
- /*
|
|
- * Fetch output pointer from stack to R12 (It is used
|
|
- * as temporary storage)
|
|
- */
|
|
- pop %r12
|
|
+.if \ret
|
|
+ /* Copy output registers to the structure */
|
|
+ movq %rcx, TDX_MODULE_rcx(%rsi)
|
|
+ movq %rdx, TDX_MODULE_rdx(%rsi)
|
|
+ movq %r8, TDX_MODULE_r8(%rsi)
|
|
+ movq %r9, TDX_MODULE_r9(%rsi)
|
|
+ movq %r10, TDX_MODULE_r10(%rsi)
|
|
+ movq %r11, TDX_MODULE_r11(%rsi)
|
|
+.endif
|
|
|
|
- /*
|
|
- * Since this macro can be invoked with NULL as an output pointer,
|
|
- * check if caller provided an output struct before storing output
|
|
- * registers.
|
|
- *
|
|
- * Update output registers, even if the call failed (RAX != 0).
|
|
- * Other registers may contain details of the failure.
|
|
- */
|
|
- test %r12, %r12
|
|
- jz .Lno_output_struct
|
|
+.if \host
|
|
+.Lout\@:
|
|
+.endif
|
|
+ FRAME_END
|
|
+ RET
|
|
|
|
- /* Copy result registers to output struct: */
|
|
- movq %rcx, TDX_MODULE_rcx(%r12)
|
|
- movq %rdx, TDX_MODULE_rdx(%r12)
|
|
- movq %r8, TDX_MODULE_r8(%r12)
|
|
- movq %r9, TDX_MODULE_r9(%r12)
|
|
- movq %r10, TDX_MODULE_r10(%r12)
|
|
- movq %r11, TDX_MODULE_r11(%r12)
|
|
+.if \host
|
|
+.Lseamcall_vmfailinvalid\@:
|
|
+ mov $TDX_SEAMCALL_VMFAILINVALID, %rax
|
|
+ jmp .Lout\@
|
|
+.endif /* \host */
|
|
|
|
-.Lno_output_struct:
|
|
- /* Restore the state of R12 register */
|
|
- pop %r12
|
|
.endm
|
|
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
|
|
index 52d6e4870a04c9..124e84fd9a2960 100644
|
|
--- a/arch/xtensa/kernel/setup.c
|
|
+++ b/arch/xtensa/kernel/setup.c
|
|
@@ -228,7 +228,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
|
|
|
|
void __init early_init_devtree(void *params)
|
|
{
|
|
- early_init_dt_scan(params);
|
|
+ early_init_dt_scan(params, __pa(params));
|
|
of_scan_flat_dt(xtensa_dt_io_area, NULL);
|
|
|
|
if (!command_line[0])
|
|
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
|
index 7e0dcded5713a0..dd8ca3f7ba60a1 100644
|
|
--- a/block/bfq-iosched.c
|
|
+++ b/block/bfq-iosched.c
|
|
@@ -582,23 +582,31 @@ static struct request *bfq_choose_req(struct bfq_data *bfqd,
|
|
#define BFQ_LIMIT_INLINE_DEPTH 16
|
|
|
|
#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
|
-static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
|
|
+static bool bfqq_request_over_limit(struct bfq_data *bfqd,
|
|
+ struct bfq_io_cq *bic, blk_opf_t opf,
|
|
+ unsigned int act_idx, int limit)
|
|
{
|
|
- struct bfq_data *bfqd = bfqq->bfqd;
|
|
- struct bfq_entity *entity = &bfqq->entity;
|
|
struct bfq_entity *inline_entities[BFQ_LIMIT_INLINE_DEPTH];
|
|
struct bfq_entity **entities = inline_entities;
|
|
- int depth, level, alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
|
|
- int class_idx = bfqq->ioprio_class - 1;
|
|
+ int alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
|
|
struct bfq_sched_data *sched_data;
|
|
+ struct bfq_entity *entity;
|
|
+ struct bfq_queue *bfqq;
|
|
unsigned long wsum;
|
|
bool ret = false;
|
|
-
|
|
- if (!entity->on_st_or_in_serv)
|
|
- return false;
|
|
+ int depth;
|
|
+ int level;
|
|
|
|
retry:
|
|
spin_lock_irq(&bfqd->lock);
|
|
+ bfqq = bic_to_bfqq(bic, op_is_sync(opf), act_idx);
|
|
+ if (!bfqq)
|
|
+ goto out;
|
|
+
|
|
+ entity = &bfqq->entity;
|
|
+ if (!entity->on_st_or_in_serv)
|
|
+ goto out;
|
|
+
|
|
/* +1 for bfqq entity, root cgroup not included */
|
|
depth = bfqg_to_blkg(bfqq_group(bfqq))->blkcg->css.cgroup->level + 1;
|
|
if (depth > alloc_depth) {
|
|
@@ -643,7 +651,7 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
|
|
* class.
|
|
*/
|
|
wsum = 0;
|
|
- for (i = 0; i <= class_idx; i++) {
|
|
+ for (i = 0; i <= bfqq->ioprio_class - 1; i++) {
|
|
wsum = wsum * IOPRIO_BE_NR +
|
|
sched_data->service_tree[i].wsum;
|
|
}
|
|
@@ -666,7 +674,9 @@ static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
|
|
return ret;
|
|
}
|
|
#else
|
|
-static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
|
|
+static bool bfqq_request_over_limit(struct bfq_data *bfqd,
|
|
+ struct bfq_io_cq *bic, blk_opf_t opf,
|
|
+ unsigned int act_idx, int limit)
|
|
{
|
|
return false;
|
|
}
|
|
@@ -704,8 +714,9 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
|
|
}
|
|
|
|
for (act_idx = 0; bic && act_idx < bfqd->num_actuators; act_idx++) {
|
|
- struct bfq_queue *bfqq =
|
|
- bic_to_bfqq(bic, op_is_sync(opf), act_idx);
|
|
+ /* Fast path to check if bfqq is already allocated. */
|
|
+ if (!bic_to_bfqq(bic, op_is_sync(opf), act_idx))
|
|
+ continue;
|
|
|
|
/*
|
|
* Does queue (or any parent entity) exceed number of
|
|
@@ -713,7 +724,7 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
|
|
* limit depth so that it cannot consume more
|
|
* available requests and thus starve other entities.
|
|
*/
|
|
- if (bfqq && bfqq_request_over_limit(bfqq, limit)) {
|
|
+ if (bfqq_request_over_limit(bfqd, bic, opf, act_idx, limit)) {
|
|
depth = 1;
|
|
break;
|
|
}
|
|
diff --git a/block/blk-merge.c b/block/blk-merge.c
|
|
index 07bf758c523a9c..889ac59759a26f 100644
|
|
--- a/block/blk-merge.c
|
|
+++ b/block/blk-merge.c
|
|
@@ -256,6 +256,14 @@ static bool bvec_split_segs(const struct queue_limits *lim,
|
|
return len > 0 || bv->bv_len > max_len;
|
|
}
|
|
|
|
+static unsigned int bio_split_alignment(struct bio *bio,
|
|
+ const struct queue_limits *lim)
|
|
+{
|
|
+ if (op_is_write(bio_op(bio)) && lim->zone_write_granularity)
|
|
+ return lim->zone_write_granularity;
|
|
+ return lim->logical_block_size;
|
|
+}
|
|
+
|
|
/**
|
|
* bio_split_rw - split a bio in two bios
|
|
* @bio: [in] bio to be split
|
|
@@ -326,7 +334,7 @@ struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
|
|
* split size so that each bio is properly block size aligned, even if
|
|
* we do not use the full hardware limits.
|
|
*/
|
|
- bytes = ALIGN_DOWN(bytes, lim->logical_block_size);
|
|
+ bytes = ALIGN_DOWN(bytes, bio_split_alignment(bio, lim));
|
|
|
|
/*
|
|
* Bio splitting may cause subtle trouble such as hang when doing sync
|
|
diff --git a/block/blk-mq.c b/block/blk-mq.c
|
|
index 733d72f4d1cc9d..6c71add013bfc2 100644
|
|
--- a/block/blk-mq.c
|
|
+++ b/block/blk-mq.c
|
|
@@ -283,8 +283,9 @@ void blk_mq_quiesce_tagset(struct blk_mq_tag_set *set)
|
|
if (!blk_queue_skip_tagset_quiesce(q))
|
|
blk_mq_quiesce_queue_nowait(q);
|
|
}
|
|
- blk_mq_wait_quiesce_done(set);
|
|
mutex_unlock(&set->tag_list_lock);
|
|
+
|
|
+ blk_mq_wait_quiesce_done(set);
|
|
}
|
|
EXPORT_SYMBOL_GPL(blk_mq_quiesce_tagset);
|
|
|
|
@@ -2252,6 +2253,24 @@ void blk_mq_delay_run_hw_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
|
|
}
|
|
EXPORT_SYMBOL(blk_mq_delay_run_hw_queue);
|
|
|
|
+static inline bool blk_mq_hw_queue_need_run(struct blk_mq_hw_ctx *hctx)
|
|
+{
|
|
+ bool need_run;
|
|
+
|
|
+ /*
|
|
+ * When queue is quiesced, we may be switching io scheduler, or
|
|
+ * updating nr_hw_queues, or other things, and we can't run queue
|
|
+ * any more, even blk_mq_hctx_has_pending() can't be called safely.
|
|
+ *
|
|
+ * And queue will be rerun in blk_mq_unquiesce_queue() if it is
|
|
+ * quiesced.
|
|
+ */
|
|
+ __blk_mq_run_dispatch_ops(hctx->queue, false,
|
|
+ need_run = !blk_queue_quiesced(hctx->queue) &&
|
|
+ blk_mq_hctx_has_pending(hctx));
|
|
+ return need_run;
|
|
+}
|
|
+
|
|
/**
|
|
* blk_mq_run_hw_queue - Start to run a hardware queue.
|
|
* @hctx: Pointer to the hardware queue to run.
|
|
@@ -2272,20 +2291,23 @@ void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
|
|
|
|
might_sleep_if(!async && hctx->flags & BLK_MQ_F_BLOCKING);
|
|
|
|
- /*
|
|
- * When queue is quiesced, we may be switching io scheduler, or
|
|
- * updating nr_hw_queues, or other things, and we can't run queue
|
|
- * any more, even __blk_mq_hctx_has_pending() can't be called safely.
|
|
- *
|
|
- * And queue will be rerun in blk_mq_unquiesce_queue() if it is
|
|
- * quiesced.
|
|
- */
|
|
- __blk_mq_run_dispatch_ops(hctx->queue, false,
|
|
- need_run = !blk_queue_quiesced(hctx->queue) &&
|
|
- blk_mq_hctx_has_pending(hctx));
|
|
+ need_run = blk_mq_hw_queue_need_run(hctx);
|
|
+ if (!need_run) {
|
|
+ unsigned long flags;
|
|
|
|
- if (!need_run)
|
|
- return;
|
|
+ /*
|
|
+ * Synchronize with blk_mq_unquiesce_queue(), because we check
|
|
+ * if hw queue is quiesced locklessly above, we need the use
|
|
+ * ->queue_lock to make sure we see the up-to-date status to
|
|
+ * not miss rerunning the hw queue.
|
|
+ */
|
|
+ spin_lock_irqsave(&hctx->queue->queue_lock, flags);
|
|
+ need_run = blk_mq_hw_queue_need_run(hctx);
|
|
+ spin_unlock_irqrestore(&hctx->queue->queue_lock, flags);
|
|
+
|
|
+ if (!need_run)
|
|
+ return;
|
|
+ }
|
|
|
|
if (async || !cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask)) {
|
|
blk_mq_delay_run_hw_queue(hctx, 0);
|
|
@@ -2442,6 +2464,12 @@ void blk_mq_start_stopped_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
|
|
return;
|
|
|
|
clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
|
|
+ /*
|
|
+ * Pairs with the smp_mb() in blk_mq_hctx_stopped() to order the
|
|
+ * clearing of BLK_MQ_S_STOPPED above and the checking of dispatch
|
|
+ * list in the subsequent routine.
|
|
+ */
|
|
+ smp_mb__after_atomic();
|
|
blk_mq_run_hw_queue(hctx, async);
|
|
}
|
|
EXPORT_SYMBOL_GPL(blk_mq_start_stopped_hw_queue);
|
|
@@ -2668,6 +2696,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
|
|
|
|
if (blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(rq->q)) {
|
|
blk_mq_insert_request(rq, 0);
|
|
+ blk_mq_run_hw_queue(hctx, false);
|
|
return;
|
|
}
|
|
|
|
@@ -2698,6 +2727,7 @@ static blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last)
|
|
|
|
if (blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(rq->q)) {
|
|
blk_mq_insert_request(rq, 0);
|
|
+ blk_mq_run_hw_queue(hctx, false);
|
|
return BLK_STS_OK;
|
|
}
|
|
|
|
diff --git a/block/blk-mq.h b/block/blk-mq.h
|
|
index 1743857e0b01d9..cf9f21772ddc8e 100644
|
|
--- a/block/blk-mq.h
|
|
+++ b/block/blk-mq.h
|
|
@@ -228,6 +228,19 @@ static inline struct blk_mq_tags *blk_mq_tags_from_data(struct blk_mq_alloc_data
|
|
|
|
static inline bool blk_mq_hctx_stopped(struct blk_mq_hw_ctx *hctx)
|
|
{
|
|
+ /* Fast path: hardware queue is not stopped most of the time. */
|
|
+ if (likely(!test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
|
|
+ return false;
|
|
+
|
|
+ /*
|
|
+ * This barrier is used to order adding of dispatch list before and
|
|
+ * the test of BLK_MQ_S_STOPPED below. Pairs with the memory barrier
|
|
+ * in blk_mq_start_stopped_hw_queue() so that dispatch code could
|
|
+ * either see BLK_MQ_S_STOPPED is cleared or dispatch list is not
|
|
+ * empty to avoid missing dispatching requests.
|
|
+ */
|
|
+ smp_mb();
|
|
+
|
|
return test_bit(BLK_MQ_S_STOPPED, &hctx->state);
|
|
}
|
|
|
|
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c
|
|
index d0d954fe9d54f3..7fc79e7dce44a9 100644
|
|
--- a/crypto/pcrypt.c
|
|
+++ b/crypto/pcrypt.c
|
|
@@ -117,8 +117,10 @@ static int pcrypt_aead_encrypt(struct aead_request *req)
|
|
err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu);
|
|
if (!err)
|
|
return -EINPROGRESS;
|
|
- if (err == -EBUSY)
|
|
- return -EAGAIN;
|
|
+ if (err == -EBUSY) {
|
|
+ /* try non-parallel mode */
|
|
+ return crypto_aead_encrypt(creq);
|
|
+ }
|
|
|
|
return err;
|
|
}
|
|
@@ -166,8 +168,10 @@ static int pcrypt_aead_decrypt(struct aead_request *req)
|
|
err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu);
|
|
if (!err)
|
|
return -EINPROGRESS;
|
|
- if (err == -EBUSY)
|
|
- return -EAGAIN;
|
|
+ if (err == -EBUSY) {
|
|
+ /* try non-parallel mode */
|
|
+ return crypto_aead_decrypt(creq);
|
|
+ }
|
|
|
|
return err;
|
|
}
|
|
diff --git a/drivers/acpi/arm64/gtdt.c b/drivers/acpi/arm64/gtdt.c
|
|
index c0e77c1c8e09d6..eb6c2d3603874a 100644
|
|
--- a/drivers/acpi/arm64/gtdt.c
|
|
+++ b/drivers/acpi/arm64/gtdt.c
|
|
@@ -283,7 +283,7 @@ static int __init gtdt_parse_timer_block(struct acpi_gtdt_timer_block *block,
|
|
if (frame->virt_irq > 0)
|
|
acpi_unregister_gsi(gtdt_frame->virtual_timer_interrupt);
|
|
frame->virt_irq = 0;
|
|
- } while (i-- >= 0 && gtdt_frame--);
|
|
+ } while (i-- > 0 && gtdt_frame--);
|
|
|
|
return -EINVAL;
|
|
}
|
|
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
|
|
index 26d1beec99137e..ed02a2a9970aa3 100644
|
|
--- a/drivers/acpi/cppc_acpi.c
|
|
+++ b/drivers/acpi/cppc_acpi.c
|
|
@@ -1142,7 +1142,6 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
|
|
return -EFAULT;
|
|
}
|
|
val = MASK_VAL_WRITE(reg, prev_val, val);
|
|
- val |= prev_val;
|
|
}
|
|
|
|
switch (size) {
|
|
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
|
|
index 0b18c6b46e65d8..f3133ba831c5e0 100644
|
|
--- a/drivers/base/firmware_loader/main.c
|
|
+++ b/drivers/base/firmware_loader/main.c
|
|
@@ -824,19 +824,18 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name, st
|
|
shash->tfm = alg;
|
|
|
|
if (crypto_shash_digest(shash, fw->data, fw->size, sha256buf) < 0)
|
|
- goto out_shash;
|
|
+ goto out_free;
|
|
|
|
for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
|
|
sprintf(&outbuf[i * 2], "%02x", sha256buf[i]);
|
|
outbuf[SHA256_BLOCK_SIZE] = 0;
|
|
dev_dbg(device, "Loaded FW: %s, sha256: %s\n", name, outbuf);
|
|
|
|
-out_shash:
|
|
- crypto_free_shash(alg);
|
|
out_free:
|
|
kfree(shash);
|
|
kfree(outbuf);
|
|
kfree(sha256buf);
|
|
+ crypto_free_shash(alg);
|
|
}
|
|
#else
|
|
static void fw_log_firmware_info(const struct firmware *fw, const char *name,
|
|
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
|
|
index 45fd13ef13fc64..dceab5d013dec9 100644
|
|
--- a/drivers/base/regmap/regmap-irq.c
|
|
+++ b/drivers/base/regmap/regmap-irq.c
|
|
@@ -514,12 +514,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
|
|
return IRQ_NONE;
|
|
}
|
|
|
|
+static struct lock_class_key regmap_irq_lock_class;
|
|
+static struct lock_class_key regmap_irq_request_class;
|
|
+
|
|
static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
|
|
irq_hw_number_t hw)
|
|
{
|
|
struct regmap_irq_chip_data *data = h->host_data;
|
|
|
|
irq_set_chip_data(virq, data);
|
|
+ irq_set_lockdep_class(virq, ®map_irq_lock_class, ®map_irq_request_class);
|
|
irq_set_chip(virq, &data->irq_chip);
|
|
irq_set_nested_thread(virq, 1);
|
|
irq_set_parent(virq, data->irq);
|
|
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
|
|
index 970bd6ff38c491..d816d1512531e4 100644
|
|
--- a/drivers/block/brd.c
|
|
+++ b/drivers/block/brd.c
|
|
@@ -310,8 +310,40 @@ __setup("ramdisk_size=", ramdisk_size);
|
|
* (should share code eventually).
|
|
*/
|
|
static LIST_HEAD(brd_devices);
|
|
+static DEFINE_MUTEX(brd_devices_mutex);
|
|
static struct dentry *brd_debugfs_dir;
|
|
|
|
+static struct brd_device *brd_find_or_alloc_device(int i)
|
|
+{
|
|
+ struct brd_device *brd;
|
|
+
|
|
+ mutex_lock(&brd_devices_mutex);
|
|
+ list_for_each_entry(brd, &brd_devices, brd_list) {
|
|
+ if (brd->brd_number == i) {
|
|
+ mutex_unlock(&brd_devices_mutex);
|
|
+ return ERR_PTR(-EEXIST);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ brd = kzalloc(sizeof(*brd), GFP_KERNEL);
|
|
+ if (!brd) {
|
|
+ mutex_unlock(&brd_devices_mutex);
|
|
+ return ERR_PTR(-ENOMEM);
|
|
+ }
|
|
+ brd->brd_number = i;
|
|
+ list_add_tail(&brd->brd_list, &brd_devices);
|
|
+ mutex_unlock(&brd_devices_mutex);
|
|
+ return brd;
|
|
+}
|
|
+
|
|
+static void brd_free_device(struct brd_device *brd)
|
|
+{
|
|
+ mutex_lock(&brd_devices_mutex);
|
|
+ list_del(&brd->brd_list);
|
|
+ mutex_unlock(&brd_devices_mutex);
|
|
+ kfree(brd);
|
|
+}
|
|
+
|
|
static int brd_alloc(int i)
|
|
{
|
|
struct brd_device *brd;
|
|
@@ -319,14 +351,9 @@ static int brd_alloc(int i)
|
|
char buf[DISK_NAME_LEN];
|
|
int err = -ENOMEM;
|
|
|
|
- list_for_each_entry(brd, &brd_devices, brd_list)
|
|
- if (brd->brd_number == i)
|
|
- return -EEXIST;
|
|
- brd = kzalloc(sizeof(*brd), GFP_KERNEL);
|
|
- if (!brd)
|
|
- return -ENOMEM;
|
|
- brd->brd_number = i;
|
|
- list_add_tail(&brd->brd_list, &brd_devices);
|
|
+ brd = brd_find_or_alloc_device(i);
|
|
+ if (IS_ERR(brd))
|
|
+ return PTR_ERR(brd);
|
|
|
|
xa_init(&brd->brd_pages);
|
|
|
|
@@ -369,8 +396,7 @@ static int brd_alloc(int i)
|
|
out_cleanup_disk:
|
|
put_disk(disk);
|
|
out_free_dev:
|
|
- list_del(&brd->brd_list);
|
|
- kfree(brd);
|
|
+ brd_free_device(brd);
|
|
return err;
|
|
}
|
|
|
|
@@ -389,8 +415,7 @@ static void brd_cleanup(void)
|
|
del_gendisk(brd->brd_disk);
|
|
put_disk(brd->brd_disk);
|
|
brd_free_pages(brd);
|
|
- list_del(&brd->brd_list);
|
|
- kfree(brd);
|
|
+ brd_free_device(brd);
|
|
}
|
|
}
|
|
|
|
@@ -417,16 +442,6 @@ static int __init brd_init(void)
|
|
{
|
|
int err, i;
|
|
|
|
- brd_check_and_reset_par();
|
|
-
|
|
- brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL);
|
|
-
|
|
- for (i = 0; i < rd_nr; i++) {
|
|
- err = brd_alloc(i);
|
|
- if (err)
|
|
- goto out_free;
|
|
- }
|
|
-
|
|
/*
|
|
* brd module now has a feature to instantiate underlying device
|
|
* structure on-demand, provided that there is an access dev node.
|
|
@@ -442,11 +457,18 @@ static int __init brd_init(void)
|
|
* dynamically.
|
|
*/
|
|
|
|
+ brd_check_and_reset_par();
|
|
+
|
|
+ brd_debugfs_dir = debugfs_create_dir("ramdisk_pages", NULL);
|
|
+
|
|
if (__register_blkdev(RAMDISK_MAJOR, "ramdisk", brd_probe)) {
|
|
err = -EIO;
|
|
goto out_free;
|
|
}
|
|
|
|
+ for (i = 0; i < rd_nr; i++)
|
|
+ brd_alloc(i);
|
|
+
|
|
pr_info("brd: module loaded\n");
|
|
return 0;
|
|
|
|
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
|
|
index f31607a24f5735..1105e8adf7f96f 100644
|
|
--- a/drivers/block/ublk_drv.c
|
|
+++ b/drivers/block/ublk_drv.c
|
|
@@ -713,12 +713,21 @@ static inline char *ublk_queue_cmd_buf(struct ublk_device *ub, int q_id)
|
|
return ublk_get_queue(ub, q_id)->io_cmd_buf;
|
|
}
|
|
|
|
+static inline int __ublk_queue_cmd_buf_size(int depth)
|
|
+{
|
|
+ return round_up(depth * sizeof(struct ublksrv_io_desc), PAGE_SIZE);
|
|
+}
|
|
+
|
|
static inline int ublk_queue_cmd_buf_size(struct ublk_device *ub, int q_id)
|
|
{
|
|
struct ublk_queue *ubq = ublk_get_queue(ub, q_id);
|
|
|
|
- return round_up(ubq->q_depth * sizeof(struct ublksrv_io_desc),
|
|
- PAGE_SIZE);
|
|
+ return __ublk_queue_cmd_buf_size(ubq->q_depth);
|
|
+}
|
|
+
|
|
+static int ublk_max_cmd_buf_size(void)
|
|
+{
|
|
+ return __ublk_queue_cmd_buf_size(UBLK_MAX_QUEUE_DEPTH);
|
|
}
|
|
|
|
static inline bool ublk_queue_can_use_recovery_reissue(
|
|
@@ -1387,7 +1396,7 @@ static int ublk_ch_mmap(struct file *filp, struct vm_area_struct *vma)
|
|
{
|
|
struct ublk_device *ub = filp->private_data;
|
|
size_t sz = vma->vm_end - vma->vm_start;
|
|
- unsigned max_sz = UBLK_MAX_QUEUE_DEPTH * sizeof(struct ublksrv_io_desc);
|
|
+ unsigned max_sz = ublk_max_cmd_buf_size();
|
|
unsigned long pfn, end, phys_off = vma->vm_pgoff << PAGE_SHIFT;
|
|
int q_id, ret = 0;
|
|
|
|
@@ -2904,7 +2913,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
|
|
ret = ublk_ctrl_end_recovery(ub, cmd);
|
|
break;
|
|
default:
|
|
- ret = -ENOTSUPP;
|
|
+ ret = -EOPNOTSUPP;
|
|
break;
|
|
}
|
|
|
|
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
|
|
index 41b2fd7e1b9e50..997106fe73e49f 100644
|
|
--- a/drivers/block/virtio_blk.c
|
|
+++ b/drivers/block/virtio_blk.c
|
|
@@ -475,18 +475,18 @@ static bool virtblk_prep_rq_batch(struct request *req)
|
|
return virtblk_prep_rq(req->mq_hctx, vblk, req, vbr) == BLK_STS_OK;
|
|
}
|
|
|
|
-static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
|
|
+static void virtblk_add_req_batch(struct virtio_blk_vq *vq,
|
|
struct request **rqlist)
|
|
{
|
|
+ struct request *req;
|
|
unsigned long flags;
|
|
- int err;
|
|
bool kick;
|
|
|
|
spin_lock_irqsave(&vq->lock, flags);
|
|
|
|
- while (!rq_list_empty(*rqlist)) {
|
|
- struct request *req = rq_list_pop(rqlist);
|
|
+ while ((req = rq_list_pop(rqlist))) {
|
|
struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
|
|
+ int err;
|
|
|
|
err = virtblk_add_req(vq->vq, vbr);
|
|
if (err) {
|
|
@@ -499,37 +499,33 @@ static bool virtblk_add_req_batch(struct virtio_blk_vq *vq,
|
|
kick = virtqueue_kick_prepare(vq->vq);
|
|
spin_unlock_irqrestore(&vq->lock, flags);
|
|
|
|
- return kick;
|
|
+ if (kick)
|
|
+ virtqueue_notify(vq->vq);
|
|
}
|
|
|
|
static void virtio_queue_rqs(struct request **rqlist)
|
|
{
|
|
- struct request *req, *next, *prev = NULL;
|
|
+ struct request *submit_list = NULL;
|
|
struct request *requeue_list = NULL;
|
|
+ struct request **requeue_lastp = &requeue_list;
|
|
+ struct virtio_blk_vq *vq = NULL;
|
|
+ struct request *req;
|
|
|
|
- rq_list_for_each_safe(rqlist, req, next) {
|
|
- struct virtio_blk_vq *vq = get_virtio_blk_vq(req->mq_hctx);
|
|
- bool kick;
|
|
-
|
|
- if (!virtblk_prep_rq_batch(req)) {
|
|
- rq_list_move(rqlist, &requeue_list, req, prev);
|
|
- req = prev;
|
|
- if (!req)
|
|
- continue;
|
|
- }
|
|
+ while ((req = rq_list_pop(rqlist))) {
|
|
+ struct virtio_blk_vq *this_vq = get_virtio_blk_vq(req->mq_hctx);
|
|
|
|
- if (!next || req->mq_hctx != next->mq_hctx) {
|
|
- req->rq_next = NULL;
|
|
- kick = virtblk_add_req_batch(vq, rqlist);
|
|
- if (kick)
|
|
- virtqueue_notify(vq->vq);
|
|
+ if (vq && vq != this_vq)
|
|
+ virtblk_add_req_batch(vq, &submit_list);
|
|
+ vq = this_vq;
|
|
|
|
- *rqlist = next;
|
|
- prev = NULL;
|
|
- } else
|
|
- prev = req;
|
|
+ if (virtblk_prep_rq_batch(req))
|
|
+ rq_list_add(&submit_list, req); /* reverse order */
|
|
+ else
|
|
+ rq_list_add_tail(&requeue_lastp, req);
|
|
}
|
|
|
|
+ if (vq)
|
|
+ virtblk_add_req_batch(vq, &submit_list);
|
|
*rqlist = requeue_list;
|
|
}
|
|
|
|
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
|
|
index 606f388c7a5716..c29c471b6a1826 100644
|
|
--- a/drivers/block/zram/zram_drv.c
|
|
+++ b/drivers/block/zram/zram_drv.c
|
|
@@ -1600,6 +1600,13 @@ static int zram_recompress(struct zram *zram, u32 index, struct page *page,
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ /*
|
|
+ * We touched this entry so mark it as non-IDLE. This makes sure that
|
|
+ * we don't preserve IDLE flag and don't incorrectly pick this entry
|
|
+ * for different post-processing type (e.g. writeback).
|
|
+ */
|
|
+ zram_clear_flag(zram, index, ZRAM_IDLE);
|
|
+
|
|
class_index_old = zs_lookup_class_index(zram->mem_pool, comp_len_old);
|
|
/*
|
|
* Iterate the secondary comp algorithms list (in order of priority)
|
|
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
|
|
index 42b1062e33cd5d..78999f7f248cb2 100644
|
|
--- a/drivers/char/tpm/tpm-chip.c
|
|
+++ b/drivers/char/tpm/tpm-chip.c
|
|
@@ -519,10 +519,6 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
|
|
{
|
|
struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
|
|
|
|
- /* Give back zero bytes, as TPM chip has not yet fully resumed: */
|
|
- if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
|
|
- return 0;
|
|
-
|
|
return tpm_get_random(chip, data, max);
|
|
}
|
|
|
|
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
|
|
index 66b16d26eecc78..c8ea52dfa55678 100644
|
|
--- a/drivers/char/tpm/tpm-interface.c
|
|
+++ b/drivers/char/tpm/tpm-interface.c
|
|
@@ -394,6 +394,13 @@ int tpm_pm_suspend(struct device *dev)
|
|
if (!chip)
|
|
return -ENODEV;
|
|
|
|
+ rc = tpm_try_get_ops(chip);
|
|
+ if (rc) {
|
|
+ /* Can be safely set out of locks, as no action cannot race: */
|
|
+ chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
|
|
goto suspended;
|
|
|
|
@@ -401,19 +408,18 @@ int tpm_pm_suspend(struct device *dev)
|
|
!pm_suspend_via_firmware())
|
|
goto suspended;
|
|
|
|
- rc = tpm_try_get_ops(chip);
|
|
- if (!rc) {
|
|
- if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
|
- tpm2_shutdown(chip, TPM2_SU_STATE);
|
|
- else
|
|
- rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
|
|
-
|
|
- tpm_put_ops(chip);
|
|
+ if (chip->flags & TPM_CHIP_FLAG_TPM2) {
|
|
+ tpm2_shutdown(chip, TPM2_SU_STATE);
|
|
+ goto suspended;
|
|
}
|
|
|
|
+ rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
|
|
+
|
|
suspended:
|
|
chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
|
|
+ tpm_put_ops(chip);
|
|
|
|
+out:
|
|
if (rc)
|
|
dev_err(dev, "Ignoring error %d while suspending\n", rc);
|
|
return 0;
|
|
@@ -462,11 +468,18 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
|
|
if (!chip)
|
|
return -ENODEV;
|
|
|
|
+ /* Give back zero bytes, as TPM chip has not yet fully resumed: */
|
|
+ if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) {
|
|
+ rc = 0;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
|
rc = tpm2_get_random(chip, out, max);
|
|
else
|
|
rc = tpm1_get_random(chip, out, max);
|
|
|
|
+out:
|
|
tpm_put_ops(chip);
|
|
return rc;
|
|
}
|
|
diff --git a/drivers/clk/clk-apple-nco.c b/drivers/clk/clk-apple-nco.c
|
|
index 39472a51530a34..457a48d4894128 100644
|
|
--- a/drivers/clk/clk-apple-nco.c
|
|
+++ b/drivers/clk/clk-apple-nco.c
|
|
@@ -297,6 +297,9 @@ static int applnco_probe(struct platform_device *pdev)
|
|
memset(&init, 0, sizeof(init));
|
|
init.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
|
"%s-%d", np->name, i);
|
|
+ if (!init.name)
|
|
+ return -ENOMEM;
|
|
+
|
|
init.ops = &applnco_ops;
|
|
init.parent_data = &pdata;
|
|
init.num_parents = 1;
|
|
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
|
|
index bf4d8ddc93aea1..934e53a96dddac 100644
|
|
--- a/drivers/clk/clk-axi-clkgen.c
|
|
+++ b/drivers/clk/clk-axi-clkgen.c
|
|
@@ -7,6 +7,7 @@
|
|
*/
|
|
|
|
#include <linux/platform_device.h>
|
|
+#include <linux/clk.h>
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/io.h>
|
|
@@ -512,6 +513,7 @@ static int axi_clkgen_probe(struct platform_device *pdev)
|
|
struct clk_init_data init;
|
|
const char *parent_names[2];
|
|
const char *clk_name;
|
|
+ struct clk *axi_clk;
|
|
unsigned int i;
|
|
int ret;
|
|
|
|
@@ -528,8 +530,24 @@ static int axi_clkgen_probe(struct platform_device *pdev)
|
|
return PTR_ERR(axi_clkgen->base);
|
|
|
|
init.num_parents = of_clk_get_parent_count(pdev->dev.of_node);
|
|
- if (init.num_parents < 1 || init.num_parents > 2)
|
|
- return -EINVAL;
|
|
+
|
|
+ axi_clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
|
|
+ if (!IS_ERR(axi_clk)) {
|
|
+ if (init.num_parents < 2 || init.num_parents > 3)
|
|
+ return -EINVAL;
|
|
+
|
|
+ init.num_parents -= 1;
|
|
+ } else {
|
|
+ /*
|
|
+ * Legacy... So that old DTs which do not have clock-names still
|
|
+ * work. In this case we don't explicitly enable the AXI bus
|
|
+ * clock.
|
|
+ */
|
|
+ if (PTR_ERR(axi_clk) != -ENOENT)
|
|
+ return PTR_ERR(axi_clk);
|
|
+ if (init.num_parents < 1 || init.num_parents > 2)
|
|
+ return -EINVAL;
|
|
+ }
|
|
|
|
for (i = 0; i < init.num_parents; i++) {
|
|
parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i);
|
|
diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c
|
|
index 1becba2b62d0be..b12b00a2f07fab 100644
|
|
--- a/drivers/clk/imx/clk-fracn-gppll.c
|
|
+++ b/drivers/clk/imx/clk-fracn-gppll.c
|
|
@@ -252,9 +252,11 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
|
|
pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv |
|
|
FIELD_PREP(PLL_MFI_MASK, rate->mfi);
|
|
writel_relaxed(pll_div, pll->base + PLL_DIV);
|
|
+ readl(pll->base + PLL_DIV);
|
|
if (pll->flags & CLK_FRACN_GPPLL_FRACN) {
|
|
writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR);
|
|
writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR);
|
|
+ readl(pll->base + PLL_NUMERATOR);
|
|
}
|
|
|
|
/* Wait for 5us according to fracn mode pll doc */
|
|
@@ -263,6 +265,7 @@ static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
|
|
/* Enable Powerup */
|
|
tmp |= POWERUP_MASK;
|
|
writel_relaxed(tmp, pll->base + PLL_CTRL);
|
|
+ readl(pll->base + PLL_CTRL);
|
|
|
|
/* Wait Lock */
|
|
ret = clk_fracn_gppll_wait_lock(pll);
|
|
@@ -300,14 +303,15 @@ static int clk_fracn_gppll_prepare(struct clk_hw *hw)
|
|
|
|
val |= POWERUP_MASK;
|
|
writel_relaxed(val, pll->base + PLL_CTRL);
|
|
-
|
|
- val |= CLKMUX_EN;
|
|
- writel_relaxed(val, pll->base + PLL_CTRL);
|
|
+ readl(pll->base + PLL_CTRL);
|
|
|
|
ret = clk_fracn_gppll_wait_lock(pll);
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ val |= CLKMUX_EN;
|
|
+ writel_relaxed(val, pll->base + PLL_CTRL);
|
|
+
|
|
val &= ~CLKMUX_BYPASS;
|
|
writel_relaxed(val, pll->base + PLL_CTRL);
|
|
|
|
diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c
|
|
index 1c95ae905eec82..b9ddb74b86f7a3 100644
|
|
--- a/drivers/clk/imx/clk-imx8-acm.c
|
|
+++ b/drivers/clk/imx/clk-imx8-acm.c
|
|
@@ -289,9 +289,9 @@ static int clk_imx_acm_attach_pm_domains(struct device *dev,
|
|
DL_FLAG_STATELESS |
|
|
DL_FLAG_PM_RUNTIME |
|
|
DL_FLAG_RPM_ACTIVE);
|
|
- if (IS_ERR(dev_pm->pd_dev_link[i])) {
|
|
+ if (!dev_pm->pd_dev_link[i]) {
|
|
dev_pm_domain_detach(dev_pm->pd_dev[i], false);
|
|
- ret = PTR_ERR(dev_pm->pd_dev_link[i]);
|
|
+ ret = -EINVAL;
|
|
goto detach_pm;
|
|
}
|
|
}
|
|
diff --git a/drivers/clk/imx/clk-lpcg-scu.c b/drivers/clk/imx/clk-lpcg-scu.c
|
|
index dd5abd09f3e206..620afdf8dc03e9 100644
|
|
--- a/drivers/clk/imx/clk-lpcg-scu.c
|
|
+++ b/drivers/clk/imx/clk-lpcg-scu.c
|
|
@@ -6,10 +6,12 @@
|
|
|
|
#include <linux/bits.h>
|
|
#include <linux/clk-provider.h>
|
|
+#include <linux/delay.h>
|
|
#include <linux/err.h>
|
|
#include <linux/io.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/spinlock.h>
|
|
+#include <linux/units.h>
|
|
|
|
#include "clk-scu.h"
|
|
|
|
@@ -41,6 +43,29 @@ struct clk_lpcg_scu {
|
|
|
|
#define to_clk_lpcg_scu(_hw) container_of(_hw, struct clk_lpcg_scu, hw)
|
|
|
|
+/* e10858 -LPCG clock gating register synchronization errata */
|
|
+static void lpcg_e10858_writel(unsigned long rate, void __iomem *reg, u32 val)
|
|
+{
|
|
+ writel(val, reg);
|
|
+
|
|
+ if (rate >= 24 * HZ_PER_MHZ || rate == 0) {
|
|
+ /*
|
|
+ * The time taken to access the LPCG registers from the AP core
|
|
+ * through the interconnect is longer than the minimum delay
|
|
+ * of 4 clock cycles required by the errata.
|
|
+ * Adding a readl will provide sufficient delay to prevent
|
|
+ * back-to-back writes.
|
|
+ */
|
|
+ readl(reg);
|
|
+ } else {
|
|
+ /*
|
|
+ * For clocks running below 24MHz, wait a minimum of
|
|
+ * 4 clock cycles.
|
|
+ */
|
|
+ ndelay(4 * (DIV_ROUND_UP(1000 * HZ_PER_MHZ, rate)));
|
|
+ }
|
|
+}
|
|
+
|
|
static int clk_lpcg_scu_enable(struct clk_hw *hw)
|
|
{
|
|
struct clk_lpcg_scu *clk = to_clk_lpcg_scu(hw);
|
|
@@ -57,7 +82,8 @@ static int clk_lpcg_scu_enable(struct clk_hw *hw)
|
|
val |= CLK_GATE_SCU_LPCG_HW_SEL;
|
|
|
|
reg |= val << clk->bit_idx;
|
|
- writel(reg, clk->reg);
|
|
+
|
|
+ lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg);
|
|
|
|
spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
|
|
|
|
@@ -74,7 +100,7 @@ static void clk_lpcg_scu_disable(struct clk_hw *hw)
|
|
|
|
reg = readl_relaxed(clk->reg);
|
|
reg &= ~(CLK_GATE_SCU_LPCG_MASK << clk->bit_idx);
|
|
- writel(reg, clk->reg);
|
|
+ lpcg_e10858_writel(clk_hw_get_rate(hw), clk->reg, reg);
|
|
|
|
spin_unlock_irqrestore(&imx_lpcg_scu_lock, flags);
|
|
}
|
|
@@ -145,13 +171,8 @@ static int __maybe_unused imx_clk_lpcg_scu_resume(struct device *dev)
|
|
{
|
|
struct clk_lpcg_scu *clk = dev_get_drvdata(dev);
|
|
|
|
- /*
|
|
- * FIXME: Sometimes writes don't work unless the CPU issues
|
|
- * them twice
|
|
- */
|
|
-
|
|
- writel(clk->state, clk->reg);
|
|
writel(clk->state, clk->reg);
|
|
+ lpcg_e10858_writel(0, clk->reg, clk->state);
|
|
dev_dbg(dev, "restore lpcg state 0x%x\n", clk->state);
|
|
|
|
return 0;
|
|
diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c
|
|
index cd83c52e9952ab..564f549ec204f4 100644
|
|
--- a/drivers/clk/imx/clk-scu.c
|
|
+++ b/drivers/clk/imx/clk-scu.c
|
|
@@ -594,7 +594,7 @@ static int __maybe_unused imx_clk_scu_suspend(struct device *dev)
|
|
clk->rate = clk_scu_recalc_rate(&clk->hw, 0);
|
|
else
|
|
clk->rate = clk_hw_get_rate(&clk->hw);
|
|
- clk->is_enabled = clk_hw_is_enabled(&clk->hw);
|
|
+ clk->is_enabled = clk_hw_is_prepared(&clk->hw);
|
|
|
|
if (clk->parent)
|
|
dev_dbg(dev, "save parent %s idx %u\n", clk_hw_get_name(clk->parent),
|
|
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
|
|
index 48b42d11111cde..8ad02c1f035b30 100644
|
|
--- a/drivers/clk/mediatek/Kconfig
|
|
+++ b/drivers/clk/mediatek/Kconfig
|
|
@@ -878,13 +878,6 @@ config COMMON_CLK_MT8195_APUSYS
|
|
help
|
|
This driver supports MediaTek MT8195 AI Processor Unit System clocks.
|
|
|
|
-config COMMON_CLK_MT8195_AUDSYS
|
|
- tristate "Clock driver for MediaTek MT8195 audsys"
|
|
- depends on COMMON_CLK_MT8195
|
|
- default COMMON_CLK_MT8195
|
|
- help
|
|
- This driver supports MediaTek MT8195 audsys clocks.
|
|
-
|
|
config COMMON_CLK_MT8195_IMP_IIC_WRAP
|
|
tristate "Clock driver for MediaTek MT8195 imp_iic_wrap"
|
|
depends on COMMON_CLK_MT8195
|
|
@@ -899,14 +892,6 @@ config COMMON_CLK_MT8195_MFGCFG
|
|
help
|
|
This driver supports MediaTek MT8195 mfgcfg clocks.
|
|
|
|
-config COMMON_CLK_MT8195_MSDC
|
|
- tristate "Clock driver for MediaTek MT8195 msdc"
|
|
- depends on COMMON_CLK_MT8195
|
|
- default COMMON_CLK_MT8195
|
|
- help
|
|
- This driver supports MediaTek MT8195 MMC and SD Controller's
|
|
- msdc and msdc_top clocks.
|
|
-
|
|
config COMMON_CLK_MT8195_SCP_ADSP
|
|
tristate "Clock driver for MediaTek MT8195 scp_adsp"
|
|
depends on COMMON_CLK_MT8195
|
|
diff --git a/drivers/clk/qcom/gcc-qcs404.c b/drivers/clk/qcom/gcc-qcs404.c
|
|
index a39c4990b29dbf..7977b981b8e5fe 100644
|
|
--- a/drivers/clk/qcom/gcc-qcs404.c
|
|
+++ b/drivers/clk/qcom/gcc-qcs404.c
|
|
@@ -131,6 +131,7 @@ static struct clk_alpha_pll gpll1_out_main = {
|
|
/* 930MHz configuration */
|
|
static const struct alpha_pll_config gpll3_config = {
|
|
.l = 48,
|
|
+ .alpha_hi = 0x70,
|
|
.alpha = 0x0,
|
|
.alpha_en_mask = BIT(24),
|
|
.post_div_mask = 0xf << 8,
|
|
diff --git a/drivers/clk/ralink/clk-mtmips.c b/drivers/clk/ralink/clk-mtmips.c
|
|
index 50a443bf79ecd3..76285fbbdeaa2d 100644
|
|
--- a/drivers/clk/ralink/clk-mtmips.c
|
|
+++ b/drivers/clk/ralink/clk-mtmips.c
|
|
@@ -263,8 +263,9 @@ static int mtmips_register_pherip_clocks(struct device_node *np,
|
|
.rate = _rate \
|
|
}
|
|
|
|
-static struct mtmips_clk_fixed rt305x_fixed_clocks[] = {
|
|
- CLK_FIXED("xtal", NULL, 40000000)
|
|
+static struct mtmips_clk_fixed rt3883_fixed_clocks[] = {
|
|
+ CLK_FIXED("xtal", NULL, 40000000),
|
|
+ CLK_FIXED("periph", "xtal", 40000000)
|
|
};
|
|
|
|
static struct mtmips_clk_fixed rt3352_fixed_clocks[] = {
|
|
@@ -366,6 +367,12 @@ static inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw)
|
|
return container_of(hw, struct mtmips_clk, hw);
|
|
}
|
|
|
|
+static unsigned long rt2880_xtal_recalc_rate(struct clk_hw *hw,
|
|
+ unsigned long parent_rate)
|
|
+{
|
|
+ return 40000000;
|
|
+}
|
|
+
|
|
static unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw,
|
|
unsigned long parent_rate)
|
|
{
|
|
@@ -677,10 +684,12 @@ static unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw,
|
|
}
|
|
|
|
static struct mtmips_clk rt2880_clks_base[] = {
|
|
+ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) },
|
|
{ CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) }
|
|
};
|
|
|
|
static struct mtmips_clk rt305x_clks_base[] = {
|
|
+ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) },
|
|
{ CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) }
|
|
};
|
|
|
|
@@ -690,6 +699,7 @@ static struct mtmips_clk rt3352_clks_base[] = {
|
|
};
|
|
|
|
static struct mtmips_clk rt3883_clks_base[] = {
|
|
+ { CLK_BASE("xtal", NULL, rt2880_xtal_recalc_rate) },
|
|
{ CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) },
|
|
{ CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) }
|
|
};
|
|
@@ -746,8 +756,8 @@ static int mtmips_register_clocks(struct device_node *np,
|
|
static const struct mtmips_clk_data rt2880_clk_data = {
|
|
.clk_base = rt2880_clks_base,
|
|
.num_clk_base = ARRAY_SIZE(rt2880_clks_base),
|
|
- .clk_fixed = rt305x_fixed_clocks,
|
|
- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
|
|
+ .clk_fixed = NULL,
|
|
+ .num_clk_fixed = 0,
|
|
.clk_factor = rt2880_factor_clocks,
|
|
.num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks),
|
|
.clk_periph = rt2880_pherip_clks,
|
|
@@ -757,8 +767,8 @@ static const struct mtmips_clk_data rt2880_clk_data = {
|
|
static const struct mtmips_clk_data rt305x_clk_data = {
|
|
.clk_base = rt305x_clks_base,
|
|
.num_clk_base = ARRAY_SIZE(rt305x_clks_base),
|
|
- .clk_fixed = rt305x_fixed_clocks,
|
|
- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
|
|
+ .clk_fixed = NULL,
|
|
+ .num_clk_fixed = 0,
|
|
.clk_factor = rt305x_factor_clocks,
|
|
.num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks),
|
|
.clk_periph = rt305x_pherip_clks,
|
|
@@ -779,8 +789,8 @@ static const struct mtmips_clk_data rt3352_clk_data = {
|
|
static const struct mtmips_clk_data rt3883_clk_data = {
|
|
.clk_base = rt3883_clks_base,
|
|
.num_clk_base = ARRAY_SIZE(rt3883_clks_base),
|
|
- .clk_fixed = rt305x_fixed_clocks,
|
|
- .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks),
|
|
+ .clk_fixed = rt3883_fixed_clocks,
|
|
+ .num_clk_fixed = ARRAY_SIZE(rt3883_fixed_clocks),
|
|
.clk_factor = NULL,
|
|
.num_clk_factor = 0,
|
|
.clk_periph = rt5350_pherip_clks,
|
|
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
|
|
index 75f9eca020ce57..f8dbb092b9f1b2 100644
|
|
--- a/drivers/clk/renesas/rzg2l-cpg.c
|
|
+++ b/drivers/clk/renesas/rzg2l-cpg.c
|
|
@@ -285,7 +285,7 @@ static unsigned long
|
|
rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
|
|
unsigned long rate)
|
|
{
|
|
- unsigned long foutpostdiv_rate;
|
|
+ unsigned long foutpostdiv_rate, foutvco_rate;
|
|
|
|
params->pl5_intin = rate / MEGA;
|
|
params->pl5_fracin = div_u64(((u64)rate % MEGA) << 24, MEGA);
|
|
@@ -294,10 +294,11 @@ rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_pll5_param *params,
|
|
params->pl5_postdiv2 = 1;
|
|
params->pl5_spread = 0x16;
|
|
|
|
- foutpostdiv_rate =
|
|
- EXTAL_FREQ_IN_MEGA_HZ * MEGA / params->pl5_refdiv *
|
|
- ((((params->pl5_intin << 24) + params->pl5_fracin)) >> 24) /
|
|
- (params->pl5_postdiv1 * params->pl5_postdiv2);
|
|
+ foutvco_rate = div_u64(mul_u32_u32(EXTAL_FREQ_IN_MEGA_HZ * MEGA,
|
|
+ (params->pl5_intin << 24) + params->pl5_fracin),
|
|
+ params->pl5_refdiv) >> 24;
|
|
+ foutpostdiv_rate = DIV_ROUND_CLOSEST_ULL(foutvco_rate,
|
|
+ params->pl5_postdiv1 * params->pl5_postdiv2);
|
|
|
|
return foutpostdiv_rate;
|
|
}
|
|
diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
|
|
index 48a8fb2c43b746..f95c3615ca7727 100644
|
|
--- a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
|
|
+++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
|
|
@@ -1371,7 +1371,7 @@ static int sun20i_d1_ccu_probe(struct platform_device *pdev)
|
|
|
|
/* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */
|
|
val = readl(reg + SUN20I_D1_PLL_AUDIO0_REG);
|
|
- val &= ~BIT(1) | BIT(0);
|
|
+ val &= ~(BIT(1) | BIT(0));
|
|
writel(val, reg + SUN20I_D1_PLL_AUDIO0_REG);
|
|
|
|
/* Force fanout-27M factor N to 0. */
|
|
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
|
|
index 0ba0dc4ecf0620..8208a3d895634b 100644
|
|
--- a/drivers/clocksource/Kconfig
|
|
+++ b/drivers/clocksource/Kconfig
|
|
@@ -390,7 +390,8 @@ config ARM_GT_INITIAL_PRESCALER_VAL
|
|
This affects CPU_FREQ max delta from the initial frequency.
|
|
|
|
config ARM_TIMER_SP804
|
|
- bool "Support for Dual Timer SP804 module" if COMPILE_TEST
|
|
+ bool "Support for Dual Timer SP804 module"
|
|
+ depends on ARM || ARM64 || COMPILE_TEST
|
|
depends on GENERIC_SCHED_CLOCK && HAVE_CLK
|
|
select CLKSRC_MMIO
|
|
select TIMER_OF if OF
|
|
diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c
|
|
index c2dcd8d68e4587..d1c144d6f328cf 100644
|
|
--- a/drivers/clocksource/timer-ti-dm-systimer.c
|
|
+++ b/drivers/clocksource/timer-ti-dm-systimer.c
|
|
@@ -686,9 +686,9 @@ subsys_initcall(dmtimer_percpu_timer_startup);
|
|
|
|
static int __init dmtimer_percpu_quirk_init(struct device_node *np, u32 pa)
|
|
{
|
|
- struct device_node *arm_timer;
|
|
+ struct device_node *arm_timer __free(device_node) =
|
|
+ of_find_compatible_node(NULL, NULL, "arm,armv7-timer");
|
|
|
|
- arm_timer = of_find_compatible_node(NULL, NULL, "arm,armv7-timer");
|
|
if (of_device_is_available(arm_timer)) {
|
|
pr_warn_once("ARM architected timer wrap issue i940 detected\n");
|
|
return 0;
|
|
diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
|
|
index 1548dea15df140..81763e3f948467 100644
|
|
--- a/drivers/comedi/comedi_fops.c
|
|
+++ b/drivers/comedi/comedi_fops.c
|
|
@@ -2407,6 +2407,18 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
|
|
|
|
start += PAGE_SIZE;
|
|
}
|
|
+
|
|
+#ifdef CONFIG_MMU
|
|
+ /*
|
|
+ * Leaving behind a partial mapping of a buffer we're about to
|
|
+ * drop is unsafe, see remap_pfn_range_notrack().
|
|
+ * We need to zap the range here ourselves instead of relying
|
|
+ * on the automatic zapping in remap_pfn_range() because we call
|
|
+ * remap_pfn_range() in a loop.
|
|
+ */
|
|
+ if (retval)
|
|
+ zap_vma_ptes(vma, vma->vm_start, size);
|
|
+#endif
|
|
}
|
|
|
|
if (retval == 0) {
|
|
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
|
|
index 6206d2dc3d4709..36d7f0d05b5f2f 100644
|
|
--- a/drivers/counter/stm32-timer-cnt.c
|
|
+++ b/drivers/counter/stm32-timer-cnt.c
|
|
@@ -195,11 +195,17 @@ static int stm32_count_enable_write(struct counter_device *counter,
|
|
{
|
|
struct stm32_timer_cnt *const priv = counter_priv(counter);
|
|
u32 cr1;
|
|
+ int ret;
|
|
|
|
if (enable) {
|
|
regmap_read(priv->regmap, TIM_CR1, &cr1);
|
|
- if (!(cr1 & TIM_CR1_CEN))
|
|
- clk_enable(priv->clk);
|
|
+ if (!(cr1 & TIM_CR1_CEN)) {
|
|
+ ret = clk_enable(priv->clk);
|
|
+ if (ret) {
|
|
+ dev_err(counter->parent, "Cannot enable clock %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
|
|
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
|
|
TIM_CR1_CEN);
|
|
@@ -383,7 +389,11 @@ static int __maybe_unused stm32_timer_cnt_resume(struct device *dev)
|
|
return ret;
|
|
|
|
if (priv->enabled) {
|
|
- clk_enable(priv->clk);
|
|
+ ret = clk_enable(priv->clk);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "Cannot enable clock %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
|
|
/* Restore registers that may have been lost */
|
|
regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr);
|
|
diff --git a/drivers/counter/ti-ecap-capture.c b/drivers/counter/ti-ecap-capture.c
|
|
index fb1cb1774674a5..b84e368a413f58 100644
|
|
--- a/drivers/counter/ti-ecap-capture.c
|
|
+++ b/drivers/counter/ti-ecap-capture.c
|
|
@@ -576,8 +576,13 @@ static int ecap_cnt_resume(struct device *dev)
|
|
{
|
|
struct counter_device *counter_dev = dev_get_drvdata(dev);
|
|
struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev);
|
|
+ int ret;
|
|
|
|
- clk_enable(ecap_dev->clk);
|
|
+ ret = clk_enable(ecap_dev->clk);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "Cannot enable clock %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
|
|
ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode);
|
|
|
|
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
|
|
index 8c16d67b98bfe4..cdead37d0823ad 100644
|
|
--- a/drivers/cpufreq/amd-pstate.c
|
|
+++ b/drivers/cpufreq/amd-pstate.c
|
|
@@ -1383,7 +1383,7 @@ static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
|
|
value = READ_ONCE(cpudata->cppc_req_cached);
|
|
|
|
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
|
- min_perf = max_perf;
|
|
+ min_perf = min(cpudata->nominal_perf, max_perf);
|
|
|
|
/* Initial min/max values for CPPC Performance Controls Register */
|
|
value &= ~AMD_CPPC_MIN_PERF(~0L);
|
|
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
|
|
index 15f1d41920a339..c8447ecad797e7 100644
|
|
--- a/drivers/cpufreq/cppc_cpufreq.c
|
|
+++ b/drivers/cpufreq/cppc_cpufreq.c
|
|
@@ -118,6 +118,9 @@ static void cppc_scale_freq_workfn(struct kthread_work *work)
|
|
|
|
perf = cppc_perf_from_fbctrs(cpu_data, &cppc_fi->prev_perf_fb_ctrs,
|
|
&fb_ctrs);
|
|
+ if (!perf)
|
|
+ return;
|
|
+
|
|
cppc_fi->prev_perf_fb_ctrs = fb_ctrs;
|
|
|
|
perf <<= SCHED_CAPACITY_SHIFT;
|
|
@@ -425,6 +428,9 @@ static int cppc_get_cpu_power(struct device *cpu_dev,
|
|
struct cppc_cpudata *cpu_data;
|
|
|
|
policy = cpufreq_cpu_get_raw(cpu_dev->id);
|
|
+ if (!policy)
|
|
+ return -EINVAL;
|
|
+
|
|
cpu_data = policy->driver_data;
|
|
perf_caps = &cpu_data->perf_caps;
|
|
max_cap = arch_scale_cpu_capacity(cpu_dev->id);
|
|
@@ -492,6 +498,9 @@ static int cppc_get_cpu_cost(struct device *cpu_dev, unsigned long KHz,
|
|
int step;
|
|
|
|
policy = cpufreq_cpu_get_raw(cpu_dev->id);
|
|
+ if (!policy)
|
|
+ return -EINVAL;
|
|
+
|
|
cpu_data = policy->driver_data;
|
|
perf_caps = &cpu_data->perf_caps;
|
|
max_cap = arch_scale_cpu_capacity(cpu_dev->id);
|
|
@@ -730,13 +739,31 @@ static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
|
|
delta_delivered = get_delta(fb_ctrs_t1->delivered,
|
|
fb_ctrs_t0->delivered);
|
|
|
|
- /* Check to avoid divide-by zero and invalid delivered_perf */
|
|
+ /*
|
|
+ * Avoid divide-by zero and unchanged feedback counters.
|
|
+ * Leave it for callers to handle.
|
|
+ */
|
|
if (!delta_reference || !delta_delivered)
|
|
- return cpu_data->perf_ctrls.desired_perf;
|
|
+ return 0;
|
|
|
|
return (reference_perf * delta_delivered) / delta_reference;
|
|
}
|
|
|
|
+static int cppc_get_perf_ctrs_sample(int cpu,
|
|
+ struct cppc_perf_fb_ctrs *fb_ctrs_t0,
|
|
+ struct cppc_perf_fb_ctrs *fb_ctrs_t1)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = cppc_get_perf_ctrs(cpu, fb_ctrs_t0);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ udelay(2); /* 2usec delay between sampling */
|
|
+
|
|
+ return cppc_get_perf_ctrs(cpu, fb_ctrs_t1);
|
|
+}
|
|
+
|
|
static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
|
|
{
|
|
struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
|
|
@@ -752,18 +779,32 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
|
|
|
|
cpufreq_cpu_put(policy);
|
|
|
|
- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0);
|
|
- if (ret)
|
|
- return 0;
|
|
-
|
|
- udelay(2); /* 2usec delay between sampling */
|
|
-
|
|
- ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1);
|
|
- if (ret)
|
|
- return 0;
|
|
+ ret = cppc_get_perf_ctrs_sample(cpu, &fb_ctrs_t0, &fb_ctrs_t1);
|
|
+ if (ret) {
|
|
+ if (ret == -EFAULT)
|
|
+ /* Any of the associated CPPC regs is 0. */
|
|
+ goto out_invalid_counters;
|
|
+ else
|
|
+ return 0;
|
|
+ }
|
|
|
|
delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0,
|
|
&fb_ctrs_t1);
|
|
+ if (!delivered_perf)
|
|
+ goto out_invalid_counters;
|
|
+
|
|
+ return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf);
|
|
+
|
|
+out_invalid_counters:
|
|
+ /*
|
|
+ * Feedback counters could be unchanged or 0 when a cpu enters a
|
|
+ * low-power idle state, e.g. clock-gated or power-gated.
|
|
+ * Use desired perf for reflecting frequency. Get the latest register
|
|
+ * value first as some platforms may update the actual delivered perf
|
|
+ * there; if failed, resort to the cached desired perf.
|
|
+ */
|
|
+ if (cppc_get_desired_perf(cpu, &delivered_perf))
|
|
+ delivered_perf = cpu_data->perf_ctrls.desired_perf;
|
|
|
|
return cppc_perf_to_khz(&cpu_data->perf_caps, delivered_perf);
|
|
}
|
|
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
|
|
index afc59b292153d3..63cae4037deb13 100644
|
|
--- a/drivers/cpufreq/loongson2_cpufreq.c
|
|
+++ b/drivers/cpufreq/loongson2_cpufreq.c
|
|
@@ -154,7 +154,9 @@ static int __init cpufreq_init(void)
|
|
|
|
ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
|
|
|
|
- if (!ret && !nowait) {
|
|
+ if (ret) {
|
|
+ platform_driver_unregister(&platform_driver);
|
|
+ } else if (!nowait) {
|
|
saved_cpu_wait = cpu_wait;
|
|
cpu_wait = loongson2_cpu_wait;
|
|
}
|
|
diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c
|
|
index 8d097dcddda47d..55353fe7b9e744 100644
|
|
--- a/drivers/cpufreq/mediatek-cpufreq-hw.c
|
|
+++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
|
|
@@ -62,7 +62,7 @@ mtk_cpufreq_get_cpu_power(struct device *cpu_dev, unsigned long *uW,
|
|
|
|
policy = cpufreq_cpu_get_raw(cpu_dev->id);
|
|
if (!policy)
|
|
- return 0;
|
|
+ return -EINVAL;
|
|
|
|
data = policy->driver_data;
|
|
|
|
diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c
|
|
index 689be70d69c18b..1d1ff3b1b0d5a7 100644
|
|
--- a/drivers/crypto/bcm/cipher.c
|
|
+++ b/drivers/crypto/bcm/cipher.c
|
|
@@ -2415,6 +2415,7 @@ static int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key,
|
|
|
|
static int ahash_hmac_init(struct ahash_request *req)
|
|
{
|
|
+ int ret;
|
|
struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
|
|
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
|
|
struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
|
|
@@ -2424,7 +2425,9 @@ static int ahash_hmac_init(struct ahash_request *req)
|
|
flow_log("ahash_hmac_init()\n");
|
|
|
|
/* init the context as a hash */
|
|
- ahash_init(req);
|
|
+ ret = ahash_init(req);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
if (!spu_no_incr_hash(ctx)) {
|
|
/* SPU-M can do incr hashing but needs sw for outer HMAC */
|
|
diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c
|
|
index 887a5f2fb9279b..cb001aa1de6618 100644
|
|
--- a/drivers/crypto/caam/caampkc.c
|
|
+++ b/drivers/crypto/caam/caampkc.c
|
|
@@ -984,7 +984,7 @@ static int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
|
|
return -ENOMEM;
|
|
}
|
|
|
|
-static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
|
|
+static int caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
|
|
struct rsa_key *raw_key)
|
|
{
|
|
struct caam_rsa_key *rsa_key = &ctx->key;
|
|
@@ -994,7 +994,7 @@ static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
|
|
|
|
rsa_key->p = caam_read_raw_data(raw_key->p, &p_sz);
|
|
if (!rsa_key->p)
|
|
- return;
|
|
+ return -ENOMEM;
|
|
rsa_key->p_sz = p_sz;
|
|
|
|
rsa_key->q = caam_read_raw_data(raw_key->q, &q_sz);
|
|
@@ -1029,7 +1029,7 @@ static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
|
|
|
|
rsa_key->priv_form = FORM3;
|
|
|
|
- return;
|
|
+ return 0;
|
|
|
|
free_dq:
|
|
kfree_sensitive(rsa_key->dq);
|
|
@@ -1043,6 +1043,7 @@ static void caam_rsa_set_priv_key_form(struct caam_rsa_ctx *ctx,
|
|
kfree_sensitive(rsa_key->q);
|
|
free_p:
|
|
kfree_sensitive(rsa_key->p);
|
|
+ return -ENOMEM;
|
|
}
|
|
|
|
static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
|
|
@@ -1088,7 +1089,9 @@ static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
|
|
rsa_key->e_sz = raw_key.e_sz;
|
|
rsa_key->n_sz = raw_key.n_sz;
|
|
|
|
- caam_rsa_set_priv_key_form(ctx, &raw_key);
|
|
+ ret = caam_rsa_set_priv_key_form(ctx, &raw_key);
|
|
+ if (ret)
|
|
+ goto err;
|
|
|
|
return 0;
|
|
|
|
diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c
|
|
index 46a083849a8ee6..7a3a104557f035 100644
|
|
--- a/drivers/crypto/caam/qi.c
|
|
+++ b/drivers/crypto/caam/qi.c
|
|
@@ -772,7 +772,7 @@ int caam_qi_init(struct platform_device *caam_pdev)
|
|
|
|
caam_debugfs_qi_init(ctrlpriv);
|
|
|
|
- err = devm_add_action_or_reset(qidev, caam_qi_shutdown, ctrlpriv);
|
|
+ err = devm_add_action_or_reset(qidev, caam_qi_shutdown, qidev);
|
|
if (err)
|
|
return err;
|
|
|
|
diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c
|
|
index 6872ac3440010f..54de869e5374c2 100644
|
|
--- a/drivers/crypto/cavium/cpt/cptpf_main.c
|
|
+++ b/drivers/crypto/cavium/cpt/cptpf_main.c
|
|
@@ -44,7 +44,7 @@ static void cpt_disable_cores(struct cpt_device *cpt, u64 coremask,
|
|
dev_err(dev, "Cores still busy %llx", coremask);
|
|
grp = cpt_read_csr64(cpt->reg_base,
|
|
CPTX_PF_EXEC_BUSY(0));
|
|
- if (timeout--)
|
|
+ if (!timeout--)
|
|
break;
|
|
|
|
udelay(CSR_DELAY);
|
|
@@ -302,6 +302,8 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae)
|
|
|
|
ret = do_cpt_init(cpt, mcode);
|
|
if (ret) {
|
|
+ dma_free_coherent(&cpt->pdev->dev, mcode->code_size,
|
|
+ mcode->code, mcode->phys_base);
|
|
dev_err(dev, "do_cpt_init failed with ret: %d\n", ret);
|
|
goto fw_release;
|
|
}
|
|
@@ -394,7 +396,7 @@ static void cpt_disable_all_cores(struct cpt_device *cpt)
|
|
dev_err(dev, "Cores still busy");
|
|
grp = cpt_read_csr64(cpt->reg_base,
|
|
CPTX_PF_EXEC_BUSY(0));
|
|
- if (timeout--)
|
|
+ if (!timeout--)
|
|
break;
|
|
|
|
udelay(CSR_DELAY);
|
|
diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
|
|
index 3463f5ee83c0df..762a2a54ca8219 100644
|
|
--- a/drivers/crypto/hisilicon/hpre/hpre_main.c
|
|
+++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
|
|
@@ -1280,11 +1280,15 @@ static u32 hpre_get_hw_err_status(struct hisi_qm *qm)
|
|
|
|
static void hpre_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts)
|
|
{
|
|
- u32 nfe;
|
|
-
|
|
writel(err_sts, qm->io_base + HPRE_HAC_SOURCE_INT);
|
|
- nfe = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver);
|
|
- writel(nfe, qm->io_base + HPRE_RAS_NFE_ENB);
|
|
+}
|
|
+
|
|
+static void hpre_disable_error_report(struct hisi_qm *qm, u32 err_type)
|
|
+{
|
|
+ u32 nfe_mask;
|
|
+
|
|
+ nfe_mask = hisi_qm_get_hw_info(qm, hpre_basic_info, HPRE_NFE_MASK_CAP, qm->cap_ver);
|
|
+ writel(nfe_mask & (~err_type), qm->io_base + HPRE_RAS_NFE_ENB);
|
|
}
|
|
|
|
static void hpre_open_axi_master_ooo(struct hisi_qm *qm)
|
|
@@ -1298,6 +1302,27 @@ static void hpre_open_axi_master_ooo(struct hisi_qm *qm)
|
|
qm->io_base + HPRE_AM_OOO_SHUTDOWN_ENB);
|
|
}
|
|
|
|
+static enum acc_err_result hpre_get_err_result(struct hisi_qm *qm)
|
|
+{
|
|
+ u32 err_status;
|
|
+
|
|
+ err_status = hpre_get_hw_err_status(qm);
|
|
+ if (err_status) {
|
|
+ if (err_status & qm->err_info.ecc_2bits_mask)
|
|
+ qm->err_status.is_dev_ecc_mbit = true;
|
|
+ hpre_log_hw_error(qm, err_status);
|
|
+
|
|
+ if (err_status & qm->err_info.dev_reset_mask) {
|
|
+ /* Disable the same error reporting until device is recovered. */
|
|
+ hpre_disable_error_report(qm, err_status);
|
|
+ return ACC_ERR_NEED_RESET;
|
|
+ }
|
|
+ hpre_clear_hw_err_status(qm, err_status);
|
|
+ }
|
|
+
|
|
+ return ACC_ERR_RECOVERED;
|
|
+}
|
|
+
|
|
static void hpre_err_info_init(struct hisi_qm *qm)
|
|
{
|
|
struct hisi_qm_err_info *err_info = &qm->err_info;
|
|
@@ -1324,12 +1349,12 @@ static const struct hisi_qm_err_ini hpre_err_ini = {
|
|
.hw_err_disable = hpre_hw_error_disable,
|
|
.get_dev_hw_err_status = hpre_get_hw_err_status,
|
|
.clear_dev_hw_err_status = hpre_clear_hw_err_status,
|
|
- .log_dev_hw_err = hpre_log_hw_error,
|
|
.open_axi_master_ooo = hpre_open_axi_master_ooo,
|
|
.open_sva_prefetch = hpre_open_sva_prefetch,
|
|
.close_sva_prefetch = hpre_close_sva_prefetch,
|
|
.show_last_dfx_regs = hpre_show_last_dfx_regs,
|
|
.err_info_init = hpre_err_info_init,
|
|
+ .get_err_result = hpre_get_err_result,
|
|
};
|
|
|
|
static int hpre_pf_probe_init(struct hpre *hpre)
|
|
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
|
|
index 1b00edbbfe26a9..7921409791fb03 100644
|
|
--- a/drivers/crypto/hisilicon/qm.c
|
|
+++ b/drivers/crypto/hisilicon/qm.c
|
|
@@ -272,12 +272,6 @@ enum vft_type {
|
|
SHAPER_VFT,
|
|
};
|
|
|
|
-enum acc_err_result {
|
|
- ACC_ERR_NONE,
|
|
- ACC_ERR_NEED_RESET,
|
|
- ACC_ERR_RECOVERED,
|
|
-};
|
|
-
|
|
enum qm_alg_type {
|
|
ALG_TYPE_0,
|
|
ALG_TYPE_1,
|
|
@@ -1489,22 +1483,25 @@ static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status)
|
|
|
|
static enum acc_err_result qm_hw_error_handle_v2(struct hisi_qm *qm)
|
|
{
|
|
- u32 error_status, tmp;
|
|
-
|
|
- /* read err sts */
|
|
- tmp = readl(qm->io_base + QM_ABNORMAL_INT_STATUS);
|
|
- error_status = qm->error_mask & tmp;
|
|
+ u32 error_status;
|
|
|
|
- if (error_status) {
|
|
+ error_status = qm_get_hw_error_status(qm);
|
|
+ if (error_status & qm->error_mask) {
|
|
if (error_status & QM_ECC_MBIT)
|
|
qm->err_status.is_qm_ecc_mbit = true;
|
|
|
|
qm_log_hw_error(qm, error_status);
|
|
- if (error_status & qm->err_info.qm_reset_mask)
|
|
+ if (error_status & qm->err_info.qm_reset_mask) {
|
|
+ /* Disable the same error reporting until device is recovered. */
|
|
+ writel(qm->err_info.nfe & (~error_status),
|
|
+ qm->io_base + QM_RAS_NFE_ENABLE);
|
|
return ACC_ERR_NEED_RESET;
|
|
+ }
|
|
|
|
+ /* Clear error source if not need reset. */
|
|
writel(error_status, qm->io_base + QM_ABNORMAL_INT_SOURCE);
|
|
writel(qm->err_info.nfe, qm->io_base + QM_RAS_NFE_ENABLE);
|
|
+ writel(qm->err_info.ce, qm->io_base + QM_RAS_CE_ENABLE);
|
|
}
|
|
|
|
return ACC_ERR_RECOVERED;
|
|
@@ -3957,30 +3954,12 @@ EXPORT_SYMBOL_GPL(hisi_qm_sriov_configure);
|
|
|
|
static enum acc_err_result qm_dev_err_handle(struct hisi_qm *qm)
|
|
{
|
|
- u32 err_sts;
|
|
-
|
|
- if (!qm->err_ini->get_dev_hw_err_status) {
|
|
- dev_err(&qm->pdev->dev, "Device doesn't support get hw error status!\n");
|
|
+ if (!qm->err_ini->get_err_result) {
|
|
+ dev_err(&qm->pdev->dev, "Device doesn't support reset!\n");
|
|
return ACC_ERR_NONE;
|
|
}
|
|
|
|
- /* get device hardware error status */
|
|
- err_sts = qm->err_ini->get_dev_hw_err_status(qm);
|
|
- if (err_sts) {
|
|
- if (err_sts & qm->err_info.ecc_2bits_mask)
|
|
- qm->err_status.is_dev_ecc_mbit = true;
|
|
-
|
|
- if (qm->err_ini->log_dev_hw_err)
|
|
- qm->err_ini->log_dev_hw_err(qm, err_sts);
|
|
-
|
|
- if (err_sts & qm->err_info.dev_reset_mask)
|
|
- return ACC_ERR_NEED_RESET;
|
|
-
|
|
- if (qm->err_ini->clear_dev_hw_err_status)
|
|
- qm->err_ini->clear_dev_hw_err_status(qm, err_sts);
|
|
- }
|
|
-
|
|
- return ACC_ERR_RECOVERED;
|
|
+ return qm->err_ini->get_err_result(qm);
|
|
}
|
|
|
|
static enum acc_err_result qm_process_dev_error(struct hisi_qm *qm)
|
|
diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c
|
|
index cf7b6a37e7df7a..6aaaaf784ddc03 100644
|
|
--- a/drivers/crypto/hisilicon/sec2/sec_main.c
|
|
+++ b/drivers/crypto/hisilicon/sec2/sec_main.c
|
|
@@ -1006,11 +1006,15 @@ static u32 sec_get_hw_err_status(struct hisi_qm *qm)
|
|
|
|
static void sec_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts)
|
|
{
|
|
- u32 nfe;
|
|
-
|
|
writel(err_sts, qm->io_base + SEC_CORE_INT_SOURCE);
|
|
- nfe = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver);
|
|
- writel(nfe, qm->io_base + SEC_RAS_NFE_REG);
|
|
+}
|
|
+
|
|
+static void sec_disable_error_report(struct hisi_qm *qm, u32 err_type)
|
|
+{
|
|
+ u32 nfe_mask;
|
|
+
|
|
+ nfe_mask = hisi_qm_get_hw_info(qm, sec_basic_info, SEC_NFE_MASK_CAP, qm->cap_ver);
|
|
+ writel(nfe_mask & (~err_type), qm->io_base + SEC_RAS_NFE_REG);
|
|
}
|
|
|
|
static void sec_open_axi_master_ooo(struct hisi_qm *qm)
|
|
@@ -1022,6 +1026,27 @@ static void sec_open_axi_master_ooo(struct hisi_qm *qm)
|
|
writel(val | SEC_AXI_SHUTDOWN_ENABLE, qm->io_base + SEC_CONTROL_REG);
|
|
}
|
|
|
|
+static enum acc_err_result sec_get_err_result(struct hisi_qm *qm)
|
|
+{
|
|
+ u32 err_status;
|
|
+
|
|
+ err_status = sec_get_hw_err_status(qm);
|
|
+ if (err_status) {
|
|
+ if (err_status & qm->err_info.ecc_2bits_mask)
|
|
+ qm->err_status.is_dev_ecc_mbit = true;
|
|
+ sec_log_hw_error(qm, err_status);
|
|
+
|
|
+ if (err_status & qm->err_info.dev_reset_mask) {
|
|
+ /* Disable the same error reporting until device is recovered. */
|
|
+ sec_disable_error_report(qm, err_status);
|
|
+ return ACC_ERR_NEED_RESET;
|
|
+ }
|
|
+ sec_clear_hw_err_status(qm, err_status);
|
|
+ }
|
|
+
|
|
+ return ACC_ERR_RECOVERED;
|
|
+}
|
|
+
|
|
static void sec_err_info_init(struct hisi_qm *qm)
|
|
{
|
|
struct hisi_qm_err_info *err_info = &qm->err_info;
|
|
@@ -1048,12 +1073,12 @@ static const struct hisi_qm_err_ini sec_err_ini = {
|
|
.hw_err_disable = sec_hw_error_disable,
|
|
.get_dev_hw_err_status = sec_get_hw_err_status,
|
|
.clear_dev_hw_err_status = sec_clear_hw_err_status,
|
|
- .log_dev_hw_err = sec_log_hw_error,
|
|
.open_axi_master_ooo = sec_open_axi_master_ooo,
|
|
.open_sva_prefetch = sec_open_sva_prefetch,
|
|
.close_sva_prefetch = sec_close_sva_prefetch,
|
|
.show_last_dfx_regs = sec_show_last_dfx_regs,
|
|
.err_info_init = sec_err_info_init,
|
|
+ .get_err_result = sec_get_err_result,
|
|
};
|
|
|
|
static int sec_pf_probe_init(struct sec_dev *sec)
|
|
diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c
|
|
index 9d47b3675da7d4..66e553115adfd5 100644
|
|
--- a/drivers/crypto/hisilicon/zip/zip_main.c
|
|
+++ b/drivers/crypto/hisilicon/zip/zip_main.c
|
|
@@ -1068,11 +1068,15 @@ static u32 hisi_zip_get_hw_err_status(struct hisi_qm *qm)
|
|
|
|
static void hisi_zip_clear_hw_err_status(struct hisi_qm *qm, u32 err_sts)
|
|
{
|
|
- u32 nfe;
|
|
-
|
|
writel(err_sts, qm->io_base + HZIP_CORE_INT_SOURCE);
|
|
- nfe = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver);
|
|
- writel(nfe, qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB);
|
|
+}
|
|
+
|
|
+static void hisi_zip_disable_error_report(struct hisi_qm *qm, u32 err_type)
|
|
+{
|
|
+ u32 nfe_mask;
|
|
+
|
|
+ nfe_mask = hisi_qm_get_hw_info(qm, zip_basic_cap_info, ZIP_NFE_MASK_CAP, qm->cap_ver);
|
|
+ writel(nfe_mask & (~err_type), qm->io_base + HZIP_CORE_INT_RAS_NFE_ENB);
|
|
}
|
|
|
|
static void hisi_zip_open_axi_master_ooo(struct hisi_qm *qm)
|
|
@@ -1102,6 +1106,27 @@ static void hisi_zip_close_axi_master_ooo(struct hisi_qm *qm)
|
|
qm->io_base + HZIP_CORE_INT_SET);
|
|
}
|
|
|
|
+static enum acc_err_result hisi_zip_get_err_result(struct hisi_qm *qm)
|
|
+{
|
|
+ u32 err_status;
|
|
+
|
|
+ err_status = hisi_zip_get_hw_err_status(qm);
|
|
+ if (err_status) {
|
|
+ if (err_status & qm->err_info.ecc_2bits_mask)
|
|
+ qm->err_status.is_dev_ecc_mbit = true;
|
|
+ hisi_zip_log_hw_error(qm, err_status);
|
|
+
|
|
+ if (err_status & qm->err_info.dev_reset_mask) {
|
|
+ /* Disable the same error reporting until device is recovered. */
|
|
+ hisi_zip_disable_error_report(qm, err_status);
|
|
+ return ACC_ERR_NEED_RESET;
|
|
+ }
|
|
+ hisi_zip_clear_hw_err_status(qm, err_status);
|
|
+ }
|
|
+
|
|
+ return ACC_ERR_RECOVERED;
|
|
+}
|
|
+
|
|
static void hisi_zip_err_info_init(struct hisi_qm *qm)
|
|
{
|
|
struct hisi_qm_err_info *err_info = &qm->err_info;
|
|
@@ -1129,13 +1154,13 @@ static const struct hisi_qm_err_ini hisi_zip_err_ini = {
|
|
.hw_err_disable = hisi_zip_hw_error_disable,
|
|
.get_dev_hw_err_status = hisi_zip_get_hw_err_status,
|
|
.clear_dev_hw_err_status = hisi_zip_clear_hw_err_status,
|
|
- .log_dev_hw_err = hisi_zip_log_hw_error,
|
|
.open_axi_master_ooo = hisi_zip_open_axi_master_ooo,
|
|
.close_axi_master_ooo = hisi_zip_close_axi_master_ooo,
|
|
.open_sva_prefetch = hisi_zip_open_sva_prefetch,
|
|
.close_sva_prefetch = hisi_zip_close_sva_prefetch,
|
|
.show_last_dfx_regs = hisi_zip_show_last_dfx_regs,
|
|
.err_info_init = hisi_zip_err_info_init,
|
|
+ .get_err_result = hisi_zip_get_err_result,
|
|
};
|
|
|
|
static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip)
|
|
diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c
|
|
index e17577b785c33a..f44c08f5f5ec4a 100644
|
|
--- a/drivers/crypto/inside-secure/safexcel_hash.c
|
|
+++ b/drivers/crypto/inside-secure/safexcel_hash.c
|
|
@@ -2093,7 +2093,7 @@ static int safexcel_xcbcmac_cra_init(struct crypto_tfm *tfm)
|
|
|
|
safexcel_ahash_cra_init(tfm);
|
|
ctx->aes = kmalloc(sizeof(*ctx->aes), GFP_KERNEL);
|
|
- return PTR_ERR_OR_ZERO(ctx->aes);
|
|
+ return ctx->aes == NULL ? -ENOMEM : 0;
|
|
}
|
|
|
|
static void safexcel_xcbcmac_cra_exit(struct crypto_tfm *tfm)
|
|
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
|
|
index 615af08832076a..403f0737144507 100644
|
|
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
|
|
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
|
|
@@ -473,7 +473,7 @@ static const char *uof_get_name(struct adf_accel_dev *accel_dev, u32 obj_num,
|
|
else
|
|
id = -EINVAL;
|
|
|
|
- if (id < 0 || id > num_objs)
|
|
+ if (id < 0 || id >= num_objs)
|
|
return NULL;
|
|
|
|
return fw_objs[id];
|
|
diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
|
|
index 04845f8d72be6f..056fc59b5ae61d 100644
|
|
--- a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
|
|
+++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c
|
|
@@ -19,18 +19,13 @@
|
|
void adf_dbgfs_init(struct adf_accel_dev *accel_dev)
|
|
{
|
|
char name[ADF_DEVICE_NAME_LENGTH];
|
|
- void *ret;
|
|
|
|
/* Create dev top level debugfs entry */
|
|
snprintf(name, sizeof(name), "%s%s_%s", ADF_DEVICE_NAME_PREFIX,
|
|
accel_dev->hw_device->dev_class->name,
|
|
pci_name(accel_dev->accel_pci_dev.pci_dev));
|
|
|
|
- ret = debugfs_create_dir(name, NULL);
|
|
- if (IS_ERR_OR_NULL(ret))
|
|
- return;
|
|
-
|
|
- accel_dev->debugfs_dir = ret;
|
|
+ accel_dev->debugfs_dir = debugfs_create_dir(name, NULL);
|
|
|
|
adf_cfg_dev_dbgfs_add(accel_dev);
|
|
}
|
|
@@ -56,9 +51,6 @@ EXPORT_SYMBOL_GPL(adf_dbgfs_exit);
|
|
*/
|
|
void adf_dbgfs_add(struct adf_accel_dev *accel_dev)
|
|
{
|
|
- if (!accel_dev->debugfs_dir)
|
|
- return;
|
|
-
|
|
if (!accel_dev->is_vf) {
|
|
adf_fw_counters_dbgfs_add(accel_dev);
|
|
adf_heartbeat_dbgfs_add(accel_dev);
|
|
@@ -71,9 +63,6 @@ void adf_dbgfs_add(struct adf_accel_dev *accel_dev)
|
|
*/
|
|
void adf_dbgfs_rm(struct adf_accel_dev *accel_dev)
|
|
{
|
|
- if (!accel_dev->debugfs_dir)
|
|
- return;
|
|
-
|
|
if (!accel_dev->is_vf) {
|
|
adf_heartbeat_dbgfs_rm(accel_dev);
|
|
adf_fw_counters_dbgfs_rm(accel_dev);
|
|
diff --git a/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c b/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c
|
|
index da695669924674..dd9a31c20bc9c9 100644
|
|
--- a/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c
|
|
+++ b/drivers/crypto/intel/qat/qat_common/adf_hw_arbiter.c
|
|
@@ -90,10 +90,6 @@ void adf_exit_arb(struct adf_accel_dev *accel_dev)
|
|
|
|
hw_data->get_arb_info(&info);
|
|
|
|
- /* Reset arbiter configuration */
|
|
- for (i = 0; i < ADF_ARB_NUM; i++)
|
|
- WRITE_CSR_ARB_SARCONFIG(csr, arb_off, i, 0);
|
|
-
|
|
/* Unmap worker threads to service arbiters */
|
|
for (i = 0; i < hw_data->num_engines; i++)
|
|
WRITE_CSR_ARB_WT2SAM(csr, arb_off, wt_off, i, 0);
|
|
diff --git a/drivers/dax/pmem/Makefile b/drivers/dax/pmem/Makefile
|
|
deleted file mode 100644
|
|
index 191c31f0d4f008..00000000000000
|
|
--- a/drivers/dax/pmem/Makefile
|
|
+++ /dev/null
|
|
@@ -1,7 +0,0 @@
|
|
-# SPDX-License-Identifier: GPL-2.0-only
|
|
-obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
|
|
-obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem_core.o
|
|
-
|
|
-dax_pmem-y := pmem.o
|
|
-dax_pmem_core-y := core.o
|
|
-dax_pmem_compat-y := compat.o
|
|
diff --git a/drivers/dax/pmem/pmem.c b/drivers/dax/pmem/pmem.c
|
|
deleted file mode 100644
|
|
index dfe91a2990fec4..00000000000000
|
|
--- a/drivers/dax/pmem/pmem.c
|
|
+++ /dev/null
|
|
@@ -1,10 +0,0 @@
|
|
-// SPDX-License-Identifier: GPL-2.0
|
|
-/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
|
|
-#include <linux/percpu-refcount.h>
|
|
-#include <linux/memremap.h>
|
|
-#include <linux/module.h>
|
|
-#include <linux/pfn_t.h>
|
|
-#include <linux/nd.h>
|
|
-#include "../bus.h"
|
|
-
|
|
-
|
|
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
|
|
index c406459996489c..820c993c86592a 100644
|
|
--- a/drivers/dma-buf/udmabuf.c
|
|
+++ b/drivers/dma-buf/udmabuf.c
|
|
@@ -35,12 +35,13 @@ static vm_fault_t udmabuf_vm_fault(struct vm_fault *vmf)
|
|
struct vm_area_struct *vma = vmf->vma;
|
|
struct udmabuf *ubuf = vma->vm_private_data;
|
|
pgoff_t pgoff = vmf->pgoff;
|
|
+ unsigned long pfn;
|
|
|
|
if (pgoff >= ubuf->pagecount)
|
|
return VM_FAULT_SIGBUS;
|
|
- vmf->page = ubuf->pages[pgoff];
|
|
- get_page(vmf->page);
|
|
- return 0;
|
|
+
|
|
+ pfn = page_to_pfn(ubuf->pages[pgoff]);
|
|
+ return vmf_insert_pfn(vma, vmf->address, pfn);
|
|
}
|
|
|
|
static const struct vm_operations_struct udmabuf_vm_ops = {
|
|
@@ -56,6 +57,7 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
|
|
|
|
vma->vm_ops = &udmabuf_vm_ops;
|
|
vma->vm_private_data = ubuf;
|
|
+ vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c
|
|
index e4736eb37bfb33..0ef04898276824 100644
|
|
--- a/drivers/edac/bluefield_edac.c
|
|
+++ b/drivers/edac/bluefield_edac.c
|
|
@@ -180,7 +180,7 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
|
|
static void bluefield_edac_init_dimms(struct mem_ctl_info *mci)
|
|
{
|
|
struct bluefield_edac_priv *priv = mci->pvt_info;
|
|
- int mem_ctrl_idx = mci->mc_idx;
|
|
+ u64 mem_ctrl_idx = mci->mc_idx;
|
|
struct dimm_info *dimm;
|
|
u64 smc_info, smc_arg;
|
|
int is_empty = 1, i;
|
|
diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
|
|
index b81757555a8a96..7809427c2dbeb1 100644
|
|
--- a/drivers/edac/fsl_ddr_edac.c
|
|
+++ b/drivers/edac/fsl_ddr_edac.c
|
|
@@ -328,21 +328,25 @@ static void fsl_mc_check(struct mem_ctl_info *mci)
|
|
* TODO: Add support for 32-bit wide buses
|
|
*/
|
|
if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) {
|
|
+ u64 cap = (u64)cap_high << 32 | cap_low;
|
|
+ u32 s = syndrome;
|
|
+
|
|
sbe_ecc_decode(cap_high, cap_low, syndrome,
|
|
&bad_data_bit, &bad_ecc_bit);
|
|
|
|
- if (bad_data_bit != -1)
|
|
- fsl_mc_printk(mci, KERN_ERR,
|
|
- "Faulty Data bit: %d\n", bad_data_bit);
|
|
- if (bad_ecc_bit != -1)
|
|
- fsl_mc_printk(mci, KERN_ERR,
|
|
- "Faulty ECC bit: %d\n", bad_ecc_bit);
|
|
+ if (bad_data_bit >= 0) {
|
|
+ fsl_mc_printk(mci, KERN_ERR, "Faulty Data bit: %d\n", bad_data_bit);
|
|
+ cap ^= 1ULL << bad_data_bit;
|
|
+ }
|
|
+
|
|
+ if (bad_ecc_bit >= 0) {
|
|
+ fsl_mc_printk(mci, KERN_ERR, "Faulty ECC bit: %d\n", bad_ecc_bit);
|
|
+ s ^= 1 << bad_ecc_bit;
|
|
+ }
|
|
|
|
fsl_mc_printk(mci, KERN_ERR,
|
|
"Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
|
|
- cap_high ^ (1 << (bad_data_bit - 32)),
|
|
- cap_low ^ (1 << bad_data_bit),
|
|
- syndrome ^ (1 << bad_ecc_bit));
|
|
+ upper_32_bits(cap), lower_32_bits(cap), s);
|
|
}
|
|
|
|
fsl_mc_printk(mci, KERN_ERR,
|
|
diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
|
|
index 2b83d6de9352be..535f058b48eef5 100644
|
|
--- a/drivers/edac/i10nm_base.c
|
|
+++ b/drivers/edac/i10nm_base.c
|
|
@@ -1088,6 +1088,7 @@ static int __init i10nm_init(void)
|
|
return -ENODEV;
|
|
|
|
cfg = (struct res_config *)id->driver_data;
|
|
+ skx_set_res_cfg(cfg);
|
|
res_cfg = cfg;
|
|
|
|
rc = skx_get_hi_lo(0x09a2, off, &tolm, &tohm);
|
|
diff --git a/drivers/edac/igen6_edac.c b/drivers/edac/igen6_edac.c
|
|
index a0edb61a5a01ac..0b408299699a8e 100644
|
|
--- a/drivers/edac/igen6_edac.c
|
|
+++ b/drivers/edac/igen6_edac.c
|
|
@@ -1075,6 +1075,7 @@ static int igen6_register_mci(int mc, u64 mchbar, struct pci_dev *pdev)
|
|
imc->mci = mci;
|
|
return 0;
|
|
fail3:
|
|
+ mci->pvt_info = NULL;
|
|
kfree(mci->ctl_name);
|
|
fail2:
|
|
edac_mc_free(mci);
|
|
@@ -1099,6 +1100,7 @@ static void igen6_unregister_mcis(void)
|
|
|
|
edac_mc_del_mc(mci->pdev);
|
|
kfree(mci->ctl_name);
|
|
+ mci->pvt_info = NULL;
|
|
edac_mc_free(mci);
|
|
iounmap(imc->window);
|
|
}
|
|
diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c
|
|
index 8d18099fd528cf..0b8aaf5f77d9f6 100644
|
|
--- a/drivers/edac/skx_common.c
|
|
+++ b/drivers/edac/skx_common.c
|
|
@@ -47,6 +47,7 @@ static skx_show_retry_log_f skx_show_retry_rd_err_log;
|
|
static u64 skx_tolm, skx_tohm;
|
|
static LIST_HEAD(dev_edac_list);
|
|
static bool skx_mem_cfg_2lm;
|
|
+static struct res_config *skx_res_cfg;
|
|
|
|
int skx_adxl_get(void)
|
|
{
|
|
@@ -119,7 +120,7 @@ void skx_adxl_put(void)
|
|
}
|
|
EXPORT_SYMBOL_GPL(skx_adxl_put);
|
|
|
|
-static bool skx_adxl_decode(struct decoded_addr *res, bool error_in_1st_level_mem)
|
|
+static bool skx_adxl_decode(struct decoded_addr *res, enum error_source err_src)
|
|
{
|
|
struct skx_dev *d;
|
|
int i, len = 0;
|
|
@@ -135,8 +136,24 @@ static bool skx_adxl_decode(struct decoded_addr *res, bool error_in_1st_level_me
|
|
return false;
|
|
}
|
|
|
|
+ /*
|
|
+ * GNR with a Flat2LM memory configuration may mistakenly classify
|
|
+ * a near-memory error(DDR5) as a far-memory error(CXL), resulting
|
|
+ * in the incorrect selection of decoded ADXL components.
|
|
+ * To address this, prefetch the decoded far-memory controller ID
|
|
+ * and adjust the error source to near-memory if the far-memory
|
|
+ * controller ID is invalid.
|
|
+ */
|
|
+ if (skx_res_cfg && skx_res_cfg->type == GNR && err_src == ERR_SRC_2LM_FM) {
|
|
+ res->imc = (int)adxl_values[component_indices[INDEX_MEMCTRL]];
|
|
+ if (res->imc == -1) {
|
|
+ err_src = ERR_SRC_2LM_NM;
|
|
+ edac_dbg(0, "Adjust the error source to near-memory.\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
res->socket = (int)adxl_values[component_indices[INDEX_SOCKET]];
|
|
- if (error_in_1st_level_mem) {
|
|
+ if (err_src == ERR_SRC_2LM_NM) {
|
|
res->imc = (adxl_nm_bitmap & BIT_NM_MEMCTRL) ?
|
|
(int)adxl_values[component_indices[INDEX_NM_MEMCTRL]] : -1;
|
|
res->channel = (adxl_nm_bitmap & BIT_NM_CHANNEL) ?
|
|
@@ -191,6 +208,12 @@ void skx_set_mem_cfg(bool mem_cfg_2lm)
|
|
}
|
|
EXPORT_SYMBOL_GPL(skx_set_mem_cfg);
|
|
|
|
+void skx_set_res_cfg(struct res_config *cfg)
|
|
+{
|
|
+ skx_res_cfg = cfg;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(skx_set_res_cfg);
|
|
+
|
|
void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log)
|
|
{
|
|
driver_decode = decode;
|
|
@@ -620,31 +643,27 @@ static void skx_mce_output_error(struct mem_ctl_info *mci,
|
|
optype, skx_msg);
|
|
}
|
|
|
|
-static bool skx_error_in_1st_level_mem(const struct mce *m)
|
|
+static enum error_source skx_error_source(const struct mce *m)
|
|
{
|
|
- u32 errcode;
|
|
+ u32 errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK;
|
|
|
|
- if (!skx_mem_cfg_2lm)
|
|
- return false;
|
|
-
|
|
- errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK;
|
|
-
|
|
- return errcode == MCACOD_EXT_MEM_ERR;
|
|
-}
|
|
+ if (errcode != MCACOD_MEM_CTL_ERR && errcode != MCACOD_EXT_MEM_ERR)
|
|
+ return ERR_SRC_NOT_MEMORY;
|
|
|
|
-static bool skx_error_in_mem(const struct mce *m)
|
|
-{
|
|
- u32 errcode;
|
|
+ if (!skx_mem_cfg_2lm)
|
|
+ return ERR_SRC_1LM;
|
|
|
|
- errcode = GET_BITFIELD(m->status, 0, 15) & MCACOD_MEM_ERR_MASK;
|
|
+ if (errcode == MCACOD_EXT_MEM_ERR)
|
|
+ return ERR_SRC_2LM_NM;
|
|
|
|
- return (errcode == MCACOD_MEM_CTL_ERR || errcode == MCACOD_EXT_MEM_ERR);
|
|
+ return ERR_SRC_2LM_FM;
|
|
}
|
|
|
|
int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
|
|
void *data)
|
|
{
|
|
struct mce *mce = (struct mce *)data;
|
|
+ enum error_source err_src;
|
|
struct decoded_addr res;
|
|
struct mem_ctl_info *mci;
|
|
char *type;
|
|
@@ -652,8 +671,10 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
|
|
if (mce->kflags & MCE_HANDLED_CEC)
|
|
return NOTIFY_DONE;
|
|
|
|
+ err_src = skx_error_source(mce);
|
|
+
|
|
/* Ignore unless this is memory related with an address */
|
|
- if (!skx_error_in_mem(mce) || !(mce->status & MCI_STATUS_ADDRV))
|
|
+ if (err_src == ERR_SRC_NOT_MEMORY || !(mce->status & MCI_STATUS_ADDRV))
|
|
return NOTIFY_DONE;
|
|
|
|
memset(&res, 0, sizeof(res));
|
|
@@ -667,7 +688,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
|
|
/* Try driver decoder first */
|
|
if (!(driver_decode && driver_decode(&res))) {
|
|
/* Then try firmware decoder (ACPI DSM methods) */
|
|
- if (!(adxl_component_count && skx_adxl_decode(&res, skx_error_in_1st_level_mem(mce))))
|
|
+ if (!(adxl_component_count && skx_adxl_decode(&res, err_src)))
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h
|
|
index 11faf1db4fa482..e7f18ada166814 100644
|
|
--- a/drivers/edac/skx_common.h
|
|
+++ b/drivers/edac/skx_common.h
|
|
@@ -147,6 +147,13 @@ enum {
|
|
INDEX_MAX
|
|
};
|
|
|
|
+enum error_source {
|
|
+ ERR_SRC_1LM,
|
|
+ ERR_SRC_2LM_NM,
|
|
+ ERR_SRC_2LM_FM,
|
|
+ ERR_SRC_NOT_MEMORY,
|
|
+};
|
|
+
|
|
#define BIT_NM_MEMCTRL BIT_ULL(INDEX_NM_MEMCTRL)
|
|
#define BIT_NM_CHANNEL BIT_ULL(INDEX_NM_CHANNEL)
|
|
#define BIT_NM_DIMM BIT_ULL(INDEX_NM_DIMM)
|
|
@@ -235,6 +242,7 @@ int skx_adxl_get(void);
|
|
void skx_adxl_put(void);
|
|
void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log);
|
|
void skx_set_mem_cfg(bool mem_cfg_2lm);
|
|
+void skx_set_res_cfg(struct res_config *cfg);
|
|
|
|
int skx_get_src_id(struct skx_dev *d, int off, u8 *id);
|
|
int skx_get_node_id(struct skx_dev *d, u8 *id);
|
|
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
|
|
index 00b165d1f502df..039f686f4580d1 100644
|
|
--- a/drivers/firmware/arm_scmi/common.h
|
|
+++ b/drivers/firmware/arm_scmi/common.h
|
|
@@ -163,6 +163,7 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);
|
|
* used to initialize this channel
|
|
* @dev: Reference to device in the SCMI hierarchy corresponding to this
|
|
* channel
|
|
+ * @is_p2a: A flag to identify a channel as P2A (RX)
|
|
* @rx_timeout_ms: The configured RX timeout in milliseconds.
|
|
* @handle: Pointer to SCMI entity handle
|
|
* @no_completion_irq: Flag to indicate that this channel has no completion
|
|
@@ -174,6 +175,7 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);
|
|
struct scmi_chan_info {
|
|
int id;
|
|
struct device *dev;
|
|
+ bool is_p2a;
|
|
unsigned int rx_timeout_ms;
|
|
struct scmi_handle *handle;
|
|
bool no_completion_irq;
|
|
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
|
|
index 3962683e2af9d4..efa9698c876a09 100644
|
|
--- a/drivers/firmware/arm_scmi/driver.c
|
|
+++ b/drivers/firmware/arm_scmi/driver.c
|
|
@@ -855,6 +855,11 @@ static inline void scmi_xfer_command_release(struct scmi_info *info,
|
|
static inline void scmi_clear_channel(struct scmi_info *info,
|
|
struct scmi_chan_info *cinfo)
|
|
{
|
|
+ if (!cinfo->is_p2a) {
|
|
+ dev_warn(cinfo->dev, "Invalid clear on A2P channel !\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (info->desc->ops->clear_channel)
|
|
info->desc->ops->clear_channel(cinfo);
|
|
}
|
|
@@ -2319,6 +2324,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
|
|
if (!cinfo)
|
|
return -ENOMEM;
|
|
|
|
+ cinfo->is_p2a = !tx;
|
|
cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms;
|
|
|
|
/* Create a unique name for this transport device */
|
|
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
|
|
index 435d0e2658a42e..3de25e9d18ef84 100644
|
|
--- a/drivers/firmware/arm_scpi.c
|
|
+++ b/drivers/firmware/arm_scpi.c
|
|
@@ -627,6 +627,9 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
|
|
if (ret)
|
|
return ERR_PTR(ret);
|
|
|
|
+ if (!buf.opp_count)
|
|
+ return ERR_PTR(-ENOENT);
|
|
+
|
|
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
|
if (!info)
|
|
return ERR_PTR(-ENOMEM);
|
|
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
|
|
index f9c1e8a2bd1d3e..ec01b7d3b6d4d5 100644
|
|
--- a/drivers/firmware/efi/libstub/efi-stub.c
|
|
+++ b/drivers/firmware/efi/libstub/efi-stub.c
|
|
@@ -129,7 +129,7 @@ efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
|
|
|
|
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
|
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
|
|
- cmdline_size == 0) {
|
|
+ cmdline[0] == 0) {
|
|
status = efi_parse_options(CONFIG_CMDLINE);
|
|
if (status != EFI_SUCCESS) {
|
|
efi_err("Failed to parse options\n");
|
|
@@ -149,7 +149,7 @@ efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
|
|
return EFI_SUCCESS;
|
|
|
|
fail_free_cmdline:
|
|
- efi_bs_call(free_pool, cmdline_ptr);
|
|
+ efi_bs_call(free_pool, cmdline);
|
|
return status;
|
|
}
|
|
|
|
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
|
|
index e8d69bd548f3fe..9c3613e6af158f 100644
|
|
--- a/drivers/firmware/efi/tpm.c
|
|
+++ b/drivers/firmware/efi/tpm.c
|
|
@@ -40,7 +40,8 @@ int __init efi_tpm_eventlog_init(void)
|
|
{
|
|
struct linux_efi_tpm_eventlog *log_tbl;
|
|
struct efi_tcg2_final_events_table *final_tbl;
|
|
- int tbl_size;
|
|
+ unsigned int tbl_size;
|
|
+ int final_tbl_size;
|
|
int ret = 0;
|
|
|
|
if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
|
|
@@ -80,26 +81,26 @@ int __init efi_tpm_eventlog_init(void)
|
|
goto out;
|
|
}
|
|
|
|
- tbl_size = 0;
|
|
+ final_tbl_size = 0;
|
|
if (final_tbl->nr_events != 0) {
|
|
void *events = (void *)efi.tpm_final_log
|
|
+ sizeof(final_tbl->version)
|
|
+ sizeof(final_tbl->nr_events);
|
|
|
|
- tbl_size = tpm2_calc_event_log_size(events,
|
|
- final_tbl->nr_events,
|
|
- log_tbl->log);
|
|
+ final_tbl_size = tpm2_calc_event_log_size(events,
|
|
+ final_tbl->nr_events,
|
|
+ log_tbl->log);
|
|
}
|
|
|
|
- if (tbl_size < 0) {
|
|
+ if (final_tbl_size < 0) {
|
|
pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n");
|
|
ret = -EINVAL;
|
|
goto out_calc;
|
|
}
|
|
|
|
memblock_reserve(efi.tpm_final_log,
|
|
- tbl_size + sizeof(*final_tbl));
|
|
- efi_tpm_final_log_size = tbl_size;
|
|
+ final_tbl_size + sizeof(*final_tbl));
|
|
+ efi_tpm_final_log_size = final_tbl_size;
|
|
|
|
out_calc:
|
|
early_memunmap(final_tbl, sizeof(*final_tbl));
|
|
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c
|
|
index 96ea1fa76d351f..854d488e025e96 100644
|
|
--- a/drivers/firmware/google/gsmi.c
|
|
+++ b/drivers/firmware/google/gsmi.c
|
|
@@ -918,7 +918,8 @@ static __init int gsmi_init(void)
|
|
gsmi_dev.pdev = platform_device_register_full(&gsmi_dev_info);
|
|
if (IS_ERR(gsmi_dev.pdev)) {
|
|
printk(KERN_ERR "gsmi: unable to register platform device\n");
|
|
- return PTR_ERR(gsmi_dev.pdev);
|
|
+ ret = PTR_ERR(gsmi_dev.pdev);
|
|
+ goto out_unregister;
|
|
}
|
|
|
|
/* SMI access needs to be serialized */
|
|
@@ -1056,10 +1057,11 @@ static __init int gsmi_init(void)
|
|
gsmi_buf_free(gsmi_dev.name_buf);
|
|
kmem_cache_destroy(gsmi_dev.mem_pool);
|
|
platform_device_unregister(gsmi_dev.pdev);
|
|
- pr_info("gsmi: failed to load: %d\n", ret);
|
|
+out_unregister:
|
|
#ifdef CONFIG_PM
|
|
platform_driver_unregister(&gsmi_driver_info);
|
|
#endif
|
|
+ pr_info("gsmi: failed to load: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c
|
|
index 5170fe7599cdf8..d5909a4f0433c1 100644
|
|
--- a/drivers/gpio/gpio-exar.c
|
|
+++ b/drivers/gpio/gpio-exar.c
|
|
@@ -99,11 +99,13 @@ static void exar_set_value(struct gpio_chip *chip, unsigned int offset,
|
|
struct exar_gpio_chip *exar_gpio = gpiochip_get_data(chip);
|
|
unsigned int addr = exar_offset_to_lvl_addr(exar_gpio, offset);
|
|
unsigned int bit = exar_offset_to_bit(exar_gpio, offset);
|
|
+ unsigned int bit_value = value ? BIT(bit) : 0;
|
|
|
|
- if (value)
|
|
- regmap_set_bits(exar_gpio->regmap, addr, BIT(bit));
|
|
- else
|
|
- regmap_clear_bits(exar_gpio->regmap, addr, BIT(bit));
|
|
+ /*
|
|
+ * regmap_write_bits() forces value to be written when an external
|
|
+ * pull up/down might otherwise indicate value was already set.
|
|
+ */
|
|
+ regmap_write_bits(exar_gpio->regmap, addr, BIT(bit), bit_value);
|
|
}
|
|
|
|
static int exar_direction_output(struct gpio_chip *chip, unsigned int offset,
|
|
diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c
|
|
index 2de61337ad3b54..d7230fd83f5d68 100644
|
|
--- a/drivers/gpio/gpio-zevio.c
|
|
+++ b/drivers/gpio/gpio-zevio.c
|
|
@@ -11,6 +11,7 @@
|
|
#include <linux/io.h>
|
|
#include <linux/mod_devicetable.h>
|
|
#include <linux/platform_device.h>
|
|
+#include <linux/property.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/spinlock.h>
|
|
|
|
@@ -169,6 +170,7 @@ static const struct gpio_chip zevio_gpio_chip = {
|
|
/* Initialization */
|
|
static int zevio_gpio_probe(struct platform_device *pdev)
|
|
{
|
|
+ struct device *dev = &pdev->dev;
|
|
struct zevio_gpio *controller;
|
|
int status, i;
|
|
|
|
@@ -180,6 +182,10 @@ static int zevio_gpio_probe(struct platform_device *pdev)
|
|
controller->chip = zevio_gpio_chip;
|
|
controller->chip.parent = &pdev->dev;
|
|
|
|
+ controller->chip.label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", dev_fwnode(dev));
|
|
+ if (!controller->chip.label)
|
|
+ return -ENOMEM;
|
|
+
|
|
controller->regs = devm_platform_ioremap_resource(pdev, 0);
|
|
if (IS_ERR(controller->regs))
|
|
return dev_err_probe(&pdev->dev, PTR_ERR(controller->regs),
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
index 9c99d69b4b083e..cd2d99e00b5d9d 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
@@ -4020,8 +4020,8 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
|
|
int idx;
|
|
bool px;
|
|
|
|
- amdgpu_fence_driver_sw_fini(adev);
|
|
amdgpu_device_ip_fini(adev);
|
|
+ amdgpu_fence_driver_sw_fini(adev);
|
|
amdgpu_ucode_release(&adev->firmware.gpu_info_fw);
|
|
adev->accel_working = false;
|
|
dma_fence_put(rcu_dereference_protected(adev->gang_submit, true));
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
|
|
index 88a3aa36b41d77..8e91355ad42cc5 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
|
|
@@ -214,15 +214,15 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
|
|
|
|
drm_sched_entity_destroy(&adev->vce.entity);
|
|
|
|
- amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
|
|
- (void **)&adev->vce.cpu_addr);
|
|
-
|
|
for (i = 0; i < adev->vce.num_rings; i++)
|
|
amdgpu_ring_fini(&adev->vce.ring[i]);
|
|
|
|
amdgpu_ucode_release(&adev->vce.fw);
|
|
mutex_destroy(&adev->vce.idle_mutex);
|
|
|
|
+ amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
|
|
+ (void **)&adev->vce.cpu_addr);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
|
|
index 1bea629c49ca02..68d13c4fac8f4f 100644
|
|
--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
|
|
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
|
|
@@ -123,7 +123,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
|
|
|
|
memset(kq->pq_kernel_addr, 0, queue_size);
|
|
memset(kq->rptr_kernel, 0, sizeof(*kq->rptr_kernel));
|
|
- memset(kq->wptr_kernel, 0, sizeof(*kq->wptr_kernel));
|
|
+ memset(kq->wptr_kernel, 0, dev->kfd->device_info.doorbell_size);
|
|
|
|
prop.queue_size = queue_size;
|
|
prop.is_interop = false;
|
|
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
|
|
index 6c90231e0aec2b..fd640a061c96a8 100644
|
|
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
|
|
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
|
|
@@ -312,8 +312,8 @@ static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr,
|
|
attr_sdma);
|
|
struct kfd_sdma_activity_handler_workarea sdma_activity_work_handler;
|
|
|
|
- INIT_WORK(&sdma_activity_work_handler.sdma_activity_work,
|
|
- kfd_sdma_activity_worker);
|
|
+ INIT_WORK_ONSTACK(&sdma_activity_work_handler.sdma_activity_work,
|
|
+ kfd_sdma_activity_worker);
|
|
|
|
sdma_activity_work_handler.pdd = pdd;
|
|
sdma_activity_work_handler.sdma_activity_counter = 0;
|
|
@@ -321,6 +321,7 @@ static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr,
|
|
schedule_work(&sdma_activity_work_handler.sdma_activity_work);
|
|
|
|
flush_work(&sdma_activity_work_handler.sdma_activity_work);
|
|
+ destroy_work_on_stack(&sdma_activity_work_handler.sdma_activity_work);
|
|
|
|
return snprintf(buffer, PAGE_SIZE, "%llu\n",
|
|
(sdma_activity_work_handler.sdma_activity_counter)/
|
|
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 d390e3d62e56e3..9ec9792f115a8a 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
|
|
@@ -179,6 +179,8 @@ amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
|
|
dc_sink_release(dc_sink);
|
|
aconnector->dc_sink = NULL;
|
|
aconnector->edid = NULL;
|
|
+ aconnector->dsc_aux = NULL;
|
|
+ port->passthrough_aux = NULL;
|
|
}
|
|
|
|
aconnector->mst_status = MST_STATUS_DEFAULT;
|
|
@@ -487,6 +489,8 @@ dm_dp_mst_detect(struct drm_connector *connector,
|
|
dc_sink_release(aconnector->dc_sink);
|
|
aconnector->dc_sink = NULL;
|
|
aconnector->edid = NULL;
|
|
+ aconnector->dsc_aux = NULL;
|
|
+ port->passthrough_aux = NULL;
|
|
|
|
amdgpu_dm_set_mst_status(&aconnector->mst_status,
|
|
MST_REMOTE_EDID | MST_ALLOCATE_NEW_PAYLOAD | MST_CLEAR_ALLOCATED_PAYLOAD,
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
|
|
index 3271c8c7905ddc..4e036356b6a89a 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
|
|
@@ -560,11 +560,19 @@ void dcn3_clk_mgr_construct(
|
|
dce_clock_read_ss_info(clk_mgr);
|
|
|
|
clk_mgr->base.bw_params = kzalloc(sizeof(*clk_mgr->base.bw_params), GFP_KERNEL);
|
|
+ if (!clk_mgr->base.bw_params) {
|
|
+ BREAK_TO_DEBUGGER();
|
|
+ return;
|
|
+ }
|
|
|
|
/* need physical address of table to give to PMFW */
|
|
clk_mgr->wm_range_table = dm_helpers_allocate_gpu_mem(clk_mgr->base.ctx,
|
|
DC_MEM_ALLOC_TYPE_GART, sizeof(WatermarksExternal_t),
|
|
&clk_mgr->wm_range_table_addr);
|
|
+ if (!clk_mgr->wm_range_table) {
|
|
+ BREAK_TO_DEBUGGER();
|
|
+ return;
|
|
+ }
|
|
}
|
|
|
|
void dcn3_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr)
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
|
|
index 2428a4763b85f6..1c5ae4d62e37b7 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
|
|
@@ -1022,11 +1022,19 @@ void dcn32_clk_mgr_construct(
|
|
clk_mgr->smu_present = false;
|
|
|
|
clk_mgr->base.bw_params = kzalloc(sizeof(*clk_mgr->base.bw_params), GFP_KERNEL);
|
|
+ if (!clk_mgr->base.bw_params) {
|
|
+ BREAK_TO_DEBUGGER();
|
|
+ return;
|
|
+ }
|
|
|
|
/* need physical address of table to give to PMFW */
|
|
clk_mgr->wm_range_table = dm_helpers_allocate_gpu_mem(clk_mgr->base.ctx,
|
|
DC_MEM_ALLOC_TYPE_GART, sizeof(WatermarksExternal_t),
|
|
&clk_mgr->wm_range_table_addr);
|
|
+ if (!clk_mgr->wm_range_table) {
|
|
+ BREAK_TO_DEBUGGER();
|
|
+ return;
|
|
+ }
|
|
}
|
|
|
|
void dcn32_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr)
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
|
|
index f99ec1b0efaffb..2eae1fd95fd06b 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
|
|
@@ -727,6 +727,9 @@ void hwss_setup_dpp(union block_sequence_params *params)
|
|
struct dpp *dpp = pipe_ctx->plane_res.dpp;
|
|
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
|
|
|
|
+ if (!plane_state)
|
|
+ return;
|
|
+
|
|
if (dpp && dpp->funcs->dpp_setup) {
|
|
// program the input csc
|
|
dpp->funcs->dpp_setup(dpp,
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
|
|
index 12af2859002f72..a825fd6c7fa666 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
|
|
@@ -880,7 +880,8 @@ bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
|
|
/*
|
|
* if above if is not executed then 'params' equal to 0 and set in bypass
|
|
*/
|
|
- mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
|
|
+ if (mpc->funcs->set_output_gamma)
|
|
+ mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
|
|
|
|
return true;
|
|
}
|
|
@@ -1732,17 +1733,26 @@ static void dcn20_program_pipe(
|
|
dc->res_pool->hubbub->funcs->program_det_size(
|
|
dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb);
|
|
|
|
- if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw)
|
|
+ if (pipe_ctx->update_flags.raw ||
|
|
+ (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) ||
|
|
+ pipe_ctx->stream->update_flags.raw)
|
|
dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
|
|
|
|
- if (pipe_ctx->update_flags.bits.enable
|
|
- || pipe_ctx->plane_state->update_flags.bits.hdr_mult)
|
|
+ if (pipe_ctx->update_flags.bits.enable ||
|
|
+ (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.bits.hdr_mult))
|
|
hws->funcs.set_hdr_multiplier(pipe_ctx);
|
|
|
|
- if (pipe_ctx->update_flags.bits.enable ||
|
|
- pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
|
|
- pipe_ctx->plane_state->update_flags.bits.gamma_change ||
|
|
- pipe_ctx->plane_state->update_flags.bits.lut_3d)
|
|
+ if ((pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.bits.hdr_mult) ||
|
|
+ pipe_ctx->update_flags.bits.enable)
|
|
+ hws->funcs.set_hdr_multiplier(pipe_ctx);
|
|
+
|
|
+ if ((pipe_ctx->plane_state &&
|
|
+ pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change) ||
|
|
+ (pipe_ctx->plane_state &&
|
|
+ pipe_ctx->plane_state->update_flags.bits.gamma_change) ||
|
|
+ (pipe_ctx->plane_state &&
|
|
+ pipe_ctx->plane_state->update_flags.bits.lut_3d) ||
|
|
+ pipe_ctx->update_flags.bits.enable)
|
|
hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
|
|
|
|
/* dcn10_translate_regamma_to_hw_format takes 750us to finish
|
|
@@ -1752,7 +1762,8 @@ static void dcn20_program_pipe(
|
|
if (pipe_ctx->update_flags.bits.enable ||
|
|
pipe_ctx->update_flags.bits.plane_changed ||
|
|
pipe_ctx->stream->update_flags.bits.out_tf ||
|
|
- pipe_ctx->plane_state->update_flags.bits.output_tf_change)
|
|
+ (pipe_ctx->plane_state &&
|
|
+ pipe_ctx->plane_state->update_flags.bits.output_tf_change))
|
|
hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
|
|
|
|
/* If the pipe has been enabled or has a different opp, we
|
|
@@ -1776,7 +1787,7 @@ static void dcn20_program_pipe(
|
|
}
|
|
|
|
/* Set ABM pipe after other pipe configurations done */
|
|
- if (pipe_ctx->plane_state->visible) {
|
|
+ if ((pipe_ctx->plane_state && pipe_ctx->plane_state->visible)) {
|
|
if (pipe_ctx->stream_res.abm) {
|
|
dc->hwss.set_pipe(pipe_ctx);
|
|
pipe_ctx->stream_res.abm->funcs->set_abm_level(pipe_ctx->stream_res.abm,
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
|
|
index ba4a1e7f196d10..b8653bdfc40fbd 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
|
|
@@ -440,7 +440,7 @@ void dcn30_init_hw(struct dc *dc)
|
|
int edp_num;
|
|
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
|
|
|
|
- if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
|
|
+ if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks)
|
|
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
|
|
|
|
// Initialize the dccg
|
|
@@ -599,11 +599,12 @@ void dcn30_init_hw(struct dc *dc)
|
|
if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
|
|
dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
|
|
|
|
- if (dc->clk_mgr->funcs->notify_wm_ranges)
|
|
+ if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
|
|
dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
|
|
|
|
//if softmax is enabled then hardmax will be set by a different call
|
|
- if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
|
|
+ if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->set_hard_max_memclk &&
|
|
+ !dc->clk_mgr->dc_mode_softmax_enabled)
|
|
dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
|
|
|
|
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
|
|
index 88c0b24a32497d..de83acd12250d8 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
|
|
@@ -2045,6 +2045,9 @@ bool dcn30_validate_bandwidth(struct dc *dc,
|
|
|
|
BW_VAL_TRACE_COUNT();
|
|
|
|
+ if (!pipes)
|
|
+ goto validate_fail;
|
|
+
|
|
DC_FP_START();
|
|
out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true);
|
|
DC_FP_END();
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
|
|
index 82de4fe2637fc1..84e3df49be2f8c 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
|
|
@@ -1308,6 +1308,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create(
|
|
|
|
/* allocate HPO link encoder */
|
|
hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
|
|
+ if (!hpo_dp_enc31)
|
|
+ return NULL; /* out of memory */
|
|
|
|
hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst,
|
|
&hpo_dp_link_enc_regs[inst],
|
|
@@ -1764,6 +1766,9 @@ bool dcn31_validate_bandwidth(struct dc *dc,
|
|
|
|
BW_VAL_TRACE_COUNT();
|
|
|
|
+ if (!pipes)
|
|
+ goto validate_fail;
|
|
+
|
|
DC_FP_START();
|
|
out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true);
|
|
DC_FP_END();
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
|
|
index 3e65e683db0acf..6e52851bc0316b 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
|
|
@@ -1381,6 +1381,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create(
|
|
|
|
/* allocate HPO link encoder */
|
|
hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
|
|
+ if (!hpo_dp_enc31)
|
|
+ return NULL; /* out of memory */
|
|
|
|
hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst,
|
|
&hpo_dp_link_enc_regs[inst],
|
|
@@ -1741,6 +1743,9 @@ bool dcn314_validate_bandwidth(struct dc *dc,
|
|
|
|
BW_VAL_TRACE_COUNT();
|
|
|
|
+ if (!pipes)
|
|
+ goto validate_fail;
|
|
+
|
|
if (filter_modes_for_single_channel_workaround(dc, context))
|
|
goto validate_fail;
|
|
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
|
|
index 127487ea3d7dc3..3f3b555b4523a2 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
|
|
@@ -1308,6 +1308,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create(
|
|
|
|
/* allocate HPO link encoder */
|
|
hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
|
|
+ if (!hpo_dp_enc31)
|
|
+ return NULL; /* out of memory */
|
|
|
|
hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst,
|
|
&hpo_dp_link_enc_regs[inst],
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
|
|
index 5fe2c61527dfad..37b7973fc9494a 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
|
|
@@ -1305,6 +1305,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create(
|
|
|
|
/* allocate HPO link encoder */
|
|
hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
|
|
+ if (!hpo_dp_enc31)
|
|
+ return NULL; /* out of memory */
|
|
|
|
hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst,
|
|
&hpo_dp_link_enc_regs[inst],
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
|
|
index 650e1598bddcb1..1a24fc8b536740 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
|
|
@@ -587,7 +587,9 @@ bool dcn32_set_output_transfer_func(struct dc *dc,
|
|
}
|
|
}
|
|
|
|
- mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
|
|
+ if (mpc->funcs->set_output_gamma)
|
|
+ mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -771,7 +773,7 @@ void dcn32_init_hw(struct dc *dc)
|
|
int edp_num;
|
|
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
|
|
|
|
- if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
|
|
+ if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks)
|
|
dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
|
|
|
|
// Initialize the dccg
|
|
@@ -948,10 +950,11 @@ void dcn32_init_hw(struct dc *dc)
|
|
if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
|
|
dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
|
|
|
|
- if (dc->clk_mgr->funcs->notify_wm_ranges)
|
|
+ if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
|
|
dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
|
|
|
|
- if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
|
|
+ if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->set_hard_max_memclk &&
|
|
+ !dc->clk_mgr->dc_mode_softmax_enabled)
|
|
dc->clk_mgr->funcs->set_hard_max_memclk(dc->clk_mgr);
|
|
|
|
if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
|
|
index f9d601c8c72176..f98f35ac68c01a 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
|
|
@@ -1299,6 +1299,8 @@ static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create(
|
|
|
|
/* allocate HPO link encoder */
|
|
hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
|
|
+ if (!hpo_dp_enc31)
|
|
+ return NULL; /* out of memory */
|
|
|
|
#undef REG_STRUCT
|
|
#define REG_STRUCT hpo_dp_link_enc_regs
|
|
@@ -1786,6 +1788,9 @@ void dcn32_add_phantom_pipes(struct dc *dc, struct dc_state *context,
|
|
// be a valid candidate for SubVP (i.e. has a plane, stream, doesn't
|
|
// already have phantom pipe assigned, etc.) by previous checks.
|
|
phantom_stream = dcn32_enable_phantom_stream(dc, context, pipes, pipe_cnt, index);
|
|
+ if (!phantom_stream)
|
|
+ return;
|
|
+
|
|
dcn32_enable_phantom_plane(dc, context, phantom_stream, index);
|
|
|
|
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
|
@@ -1842,6 +1847,9 @@ bool dcn32_validate_bandwidth(struct dc *dc,
|
|
|
|
BW_VAL_TRACE_COUNT();
|
|
|
|
+ if (!pipes)
|
|
+ goto validate_fail;
|
|
+
|
|
DC_FP_START();
|
|
out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);
|
|
DC_FP_END();
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
|
|
index aa4c64eec7b3d6..4289cd1643ece6 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
|
|
@@ -1285,6 +1285,8 @@ static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create(
|
|
|
|
/* allocate HPO link encoder */
|
|
hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
|
|
+ if (!hpo_dp_enc31)
|
|
+ return NULL; /* out of memory */
|
|
|
|
#undef REG_STRUCT
|
|
#define REG_STRUCT hpo_dp_link_enc_regs
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
|
|
index 548cdef8a8ade2..543ce9a08cfd31 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
|
|
@@ -78,7 +78,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
|
|
|
|
static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
|
|
{
|
|
- unsigned int ret_val = 0;
|
|
+ unsigned int ret_val = 1;
|
|
|
|
if (source_format == dm_444_16) {
|
|
if (!is_chroma)
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
|
|
index 3d82cbef12740c..ac6357c089e701 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
|
|
@@ -932,8 +932,9 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context)
|
|
* for VBLANK: (VACTIVE region of the SubVP pipe can fit the MALL prefetch, VBLANK frame time,
|
|
* and the max of (VBLANK blanking time, MALL region)).
|
|
*/
|
|
- if (stretched_drr_us < (1 / (double)drr_timing->min_refresh_in_uhz) * 1000000 * 1000000 &&
|
|
- subvp_active_us - prefetch_us - stretched_drr_us - max_vblank_mallregion > 0)
|
|
+ if (drr_timing &&
|
|
+ stretched_drr_us < (1 / (double)drr_timing->min_refresh_in_uhz) * 1000000 * 1000000 &&
|
|
+ subvp_active_us - prefetch_us - stretched_drr_us - max_vblank_mallregion > 0)
|
|
schedulable = true;
|
|
|
|
return schedulable;
|
|
@@ -995,7 +996,7 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
|
|
if (!subvp_pipe && pipe->stream->mall_stream_config.type == SUBVP_MAIN)
|
|
subvp_pipe = pipe;
|
|
}
|
|
- if (found) {
|
|
+ if (found && subvp_pipe) {
|
|
main_timing = &subvp_pipe->stream->timing;
|
|
phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
|
|
vblank_timing = &context->res_ctx.pipe_ctx[vblank_index].stream->timing;
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
|
|
index 3df559c591f890..70df992f859d7b 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
|
|
@@ -39,7 +39,7 @@
|
|
|
|
static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
|
|
{
|
|
- unsigned int ret_val = 0;
|
|
+ unsigned int ret_val = 1;
|
|
|
|
if (source_format == dm_444_16) {
|
|
if (!is_chroma)
|
|
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
|
|
index 51ae41cb43ea0e..e1521d3a5e0ca1 100644
|
|
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
|
|
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
|
|
@@ -1725,6 +1725,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
|
|
gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
|
|
|
|
gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
|
|
+ gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
|
|
+ gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
|
|
gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
|
|
gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
|
|
gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
|
|
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
|
|
index c1191ef5e8e679..412c6575e87b74 100644
|
|
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
|
|
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
|
|
@@ -2573,6 +2573,8 @@ static int __maybe_unused anx7625_runtime_pm_suspend(struct device *dev)
|
|
mutex_lock(&ctx->lock);
|
|
|
|
anx7625_stop_dp_work(ctx);
|
|
+ if (!ctx->pdata.panel_bridge)
|
|
+ anx7625_remove_edid(ctx);
|
|
anx7625_power_standby(ctx);
|
|
|
|
mutex_unlock(&ctx->lock);
|
|
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
|
|
index 4ad527fe04f27e..93eb8fba23d428 100644
|
|
--- a/drivers/gpu/drm/bridge/ite-it6505.c
|
|
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
|
|
@@ -3104,6 +3104,8 @@ static __maybe_unused int it6505_bridge_suspend(struct device *dev)
|
|
{
|
|
struct it6505 *it6505 = dev_get_drvdata(dev);
|
|
|
|
+ it6505_remove_edid(it6505);
|
|
+
|
|
return it6505_poweroff(it6505);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
|
|
index 7fd4a5fe03edf6..6a3f29390313b4 100644
|
|
--- a/drivers/gpu/drm/bridge/tc358767.c
|
|
+++ b/drivers/gpu/drm/bridge/tc358767.c
|
|
@@ -1579,6 +1579,13 @@ static struct edid *tc_get_edid(struct drm_bridge *bridge,
|
|
struct drm_connector *connector)
|
|
{
|
|
struct tc_data *tc = bridge_to_tc(bridge);
|
|
+ int ret;
|
|
+
|
|
+ ret = tc_get_display_props(tc);
|
|
+ if (ret < 0) {
|
|
+ dev_err(tc->dev, "failed to read display props: %d\n", ret);
|
|
+ return 0;
|
|
+ }
|
|
|
|
return drm_get_edid(connector, &tc->aux.ddc);
|
|
}
|
|
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
|
|
index 48af0e2960a226..1d22dba69b2753 100644
|
|
--- a/drivers/gpu/drm/drm_file.c
|
|
+++ b/drivers/gpu/drm/drm_file.c
|
|
@@ -149,7 +149,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev)
|
|
*/
|
|
struct drm_file *drm_file_alloc(struct drm_minor *minor)
|
|
{
|
|
- static atomic64_t ident = ATOMIC_INIT(0);
|
|
+ static atomic64_t ident = ATOMIC64_INIT(0);
|
|
struct drm_device *dev = minor->dev;
|
|
struct drm_file *file;
|
|
int ret;
|
|
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
|
|
index 8257f9d4f6190d..22a373eaffefd1 100644
|
|
--- a/drivers/gpu/drm/drm_mm.c
|
|
+++ b/drivers/gpu/drm/drm_mm.c
|
|
@@ -151,7 +151,7 @@ static void show_leaks(struct drm_mm *mm) { }
|
|
|
|
INTERVAL_TREE_DEFINE(struct drm_mm_node, rb,
|
|
u64, __subtree_last,
|
|
- START, LAST, static inline, drm_mm_interval_tree)
|
|
+ START, LAST, static inline __maybe_unused, drm_mm_interval_tree)
|
|
|
|
struct drm_mm_node *
|
|
__drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last)
|
|
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
|
|
index 5b2506c65e9520..259a0c765bafbf 100644
|
|
--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
|
|
+++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
|
|
@@ -403,7 +403,6 @@ static const struct dmi_system_id orientation_data[] = {
|
|
}, { /* Lenovo Yoga Tab 3 X90F */
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
|
|
DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
|
|
},
|
|
.driver_data = (void *)&lcd1600x2560_rightside_up,
|
|
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
|
|
index 384df1659be60d..b13a17276d07cd 100644
|
|
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
|
|
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
|
|
@@ -482,7 +482,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
|
|
} else {
|
|
CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
|
|
VIVS_GL_FLUSH_CACHE_DEPTH |
|
|
- VIVS_GL_FLUSH_CACHE_COLOR);
|
|
+ VIVS_GL_FLUSH_CACHE_COLOR |
|
|
+ VIVS_GL_FLUSH_CACHE_SHADER_L1);
|
|
if (has_blt) {
|
|
CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
|
|
CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
|
|
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
|
|
index f9bc837e22bddc..85d0695e94a5f8 100644
|
|
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
|
|
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
|
|
@@ -527,6 +527,16 @@ static int etnaviv_bind(struct device *dev)
|
|
priv->num_gpus = 0;
|
|
priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN;
|
|
|
|
+ /*
|
|
+ * If the GPU is part of a system with DMA addressing limitations,
|
|
+ * request pages for our SHM backend buffers from the DMA32 zone to
|
|
+ * hopefully avoid performance killing SWIOTLB bounce buffering.
|
|
+ */
|
|
+ if (dma_addressing_limited(dev)) {
|
|
+ priv->shm_gfp_mask |= GFP_DMA32;
|
|
+ priv->shm_gfp_mask &= ~__GFP_HIGHMEM;
|
|
+ }
|
|
+
|
|
priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev);
|
|
if (IS_ERR(priv->cmdbuf_suballoc)) {
|
|
dev_err(drm->dev, "Failed to create cmdbuf suballocator\n");
|
|
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
|
|
index 371e1f2733f6fb..ad543a7cbf073e 100644
|
|
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
|
|
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
|
|
@@ -820,14 +820,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
|
|
if (ret)
|
|
goto fail;
|
|
|
|
- /*
|
|
- * If the GPU is part of a system with DMA addressing limitations,
|
|
- * request pages for our SHM backend buffers from the DMA32 zone to
|
|
- * hopefully avoid performance killing SWIOTLB bounce buffering.
|
|
- */
|
|
- if (dma_addressing_limited(gpu->dev))
|
|
- priv->shm_gfp_mask |= GFP_DMA32;
|
|
-
|
|
/* Create buffer: */
|
|
ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer,
|
|
PAGE_SIZE);
|
|
@@ -1308,6 +1300,8 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
|
|
{
|
|
u32 val;
|
|
|
|
+ mutex_lock(&gpu->lock);
|
|
+
|
|
/* disable clock gating */
|
|
val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
|
|
val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
|
|
@@ -1319,6 +1313,8 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
|
|
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);
|
|
|
|
sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE);
|
|
+
|
|
+ mutex_unlock(&gpu->lock);
|
|
}
|
|
|
|
static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
|
|
@@ -1328,13 +1324,9 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
|
|
unsigned int i;
|
|
u32 val;
|
|
|
|
- sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST);
|
|
-
|
|
- for (i = 0; i < submit->nr_pmrs; i++) {
|
|
- const struct etnaviv_perfmon_request *pmr = submit->pmrs + i;
|
|
+ mutex_lock(&gpu->lock);
|
|
|
|
- *pmr->bo_vma = pmr->sequence;
|
|
- }
|
|
+ sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST);
|
|
|
|
/* disable debug register */
|
|
val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
|
|
@@ -1345,6 +1337,14 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
|
|
val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
|
|
val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
|
|
gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
|
|
+
|
|
+ mutex_unlock(&gpu->lock);
|
|
+
|
|
+ for (i = 0; i < submit->nr_pmrs; i++) {
|
|
+ const struct etnaviv_perfmon_request *pmr = submit->pmrs + i;
|
|
+
|
|
+ *pmr->bo_vma = pmr->sequence;
|
|
+ }
|
|
}
|
|
|
|
|
|
diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig
|
|
index 5ca71ef8732590..c9ee98693b48a4 100644
|
|
--- a/drivers/gpu/drm/fsl-dcu/Kconfig
|
|
+++ b/drivers/gpu/drm/fsl-dcu/Kconfig
|
|
@@ -8,6 +8,7 @@ config DRM_FSL_DCU
|
|
select DRM_PANEL
|
|
select REGMAP_MMIO
|
|
select VIDEOMODE_HELPERS
|
|
+ select MFD_SYSCON if SOC_LS1021A
|
|
help
|
|
Choose this option if you have an Freescale DCU chipset.
|
|
If M is selected the module will be called fsl-dcu-drm.
|
|
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
|
|
index a395f93449f368..a23f3f5c5530b9 100644
|
|
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
|
|
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
|
|
@@ -100,6 +100,7 @@ static void fsl_dcu_irq_uninstall(struct drm_device *dev)
|
|
static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
|
|
{
|
|
struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
|
|
+ struct regmap *scfg;
|
|
int ret;
|
|
|
|
ret = fsl_dcu_drm_modeset_init(fsl_dev);
|
|
@@ -108,6 +109,20 @@ static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
|
|
return ret;
|
|
}
|
|
|
|
+ scfg = syscon_regmap_lookup_by_compatible("fsl,ls1021a-scfg");
|
|
+ if (PTR_ERR(scfg) != -ENODEV) {
|
|
+ /*
|
|
+ * For simplicity, enable the PIXCLK unconditionally,
|
|
+ * resulting in increased power consumption. Disabling
|
|
+ * the clock in PM or on unload could be implemented as
|
|
+ * a future improvement.
|
|
+ */
|
|
+ ret = regmap_update_bits(scfg, SCFG_PIXCLKCR, SCFG_PIXCLKCR_PXCEN,
|
|
+ SCFG_PIXCLKCR_PXCEN);
|
|
+ if (ret < 0)
|
|
+ return dev_err_probe(dev->dev, ret, "failed to enable pixclk\n");
|
|
+ }
|
|
+
|
|
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
|
|
if (ret < 0) {
|
|
dev_err(dev->dev, "failed to initialize vblank\n");
|
|
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
|
|
index e2049a0e8a92a5..566396013c04a5 100644
|
|
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
|
|
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
|
|
@@ -160,6 +160,9 @@
|
|
#define FSL_DCU_ARGB4444 12
|
|
#define FSL_DCU_YUV422 14
|
|
|
|
+#define SCFG_PIXCLKCR 0x28
|
|
+#define SCFG_PIXCLKCR_PXCEN BIT(31)
|
|
+
|
|
#define VF610_LAYER_REG_NUM 9
|
|
#define LS1021A_LAYER_REG_NUM 10
|
|
|
|
diff --git a/drivers/gpu/drm/imx/dcss/dcss-crtc.c b/drivers/gpu/drm/imx/dcss/dcss-crtc.c
|
|
index 31267c00782fc1..af91e45b5d13b7 100644
|
|
--- a/drivers/gpu/drm/imx/dcss/dcss-crtc.c
|
|
+++ b/drivers/gpu/drm/imx/dcss/dcss-crtc.c
|
|
@@ -206,15 +206,13 @@ int dcss_crtc_init(struct dcss_crtc *crtc, struct drm_device *drm)
|
|
if (crtc->irq < 0)
|
|
return crtc->irq;
|
|
|
|
- ret = request_irq(crtc->irq, dcss_crtc_irq_handler,
|
|
- 0, "dcss_drm", crtc);
|
|
+ ret = request_irq(crtc->irq, dcss_crtc_irq_handler, IRQF_NO_AUTOEN,
|
|
+ "dcss_drm", crtc);
|
|
if (ret) {
|
|
dev_err(dcss->dev, "irq request failed with %d.\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
- disable_irq(crtc->irq);
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
|
|
index 89585b31b985e1..5f423a2e0ede36 100644
|
|
--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
|
|
+++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
|
|
@@ -410,14 +410,12 @@ static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
|
|
}
|
|
|
|
ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
|
|
- ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
|
|
- "imx_drm", ipu_crtc);
|
|
+ ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler,
|
|
+ IRQF_NO_AUTOEN, "imx_drm", ipu_crtc);
|
|
if (ret < 0) {
|
|
dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
|
|
return ret;
|
|
}
|
|
- /* Only enable IRQ when we actually need it to trigger work. */
|
|
- disable_irq(ipu_crtc->irq);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
|
|
index ffe016d6cbcfe0..600f4ccc90d378 100644
|
|
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
|
|
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
|
|
@@ -378,8 +378,10 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev)
|
|
if (all_drm_priv[cnt] && all_drm_priv[cnt]->mtk_drm_bound)
|
|
cnt++;
|
|
|
|
- if (cnt == MAX_CRTC)
|
|
+ if (cnt == MAX_CRTC) {
|
|
+ of_node_put(node);
|
|
break;
|
|
+ }
|
|
}
|
|
|
|
if (drm_priv->data->mmsys_dev_num == cnt) {
|
|
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
|
|
index 7923129363b0ae..c9edaa6d763697 100644
|
|
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
|
|
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
|
|
@@ -1432,15 +1432,13 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
|
|
|
|
irq = platform_get_irq_byname(pdev, name);
|
|
|
|
- ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH, name, gmu);
|
|
+ ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, name, gmu);
|
|
if (ret) {
|
|
DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s %d\n",
|
|
name, ret);
|
|
return ret;
|
|
}
|
|
|
|
- disable_irq(irq);
|
|
-
|
|
return irq;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
|
|
index 43c47a19cd94f5..a857ce8e385fc0 100644
|
|
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
|
|
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h
|
|
@@ -157,18 +157,6 @@ static const struct dpu_lm_cfg msm8998_lm[] = {
|
|
.sblk = &msm8998_lm_sblk,
|
|
.lm_pair = LM_5,
|
|
.pingpong = PINGPONG_2,
|
|
- }, {
|
|
- .name = "lm_3", .id = LM_3,
|
|
- .base = 0x47000, .len = 0x320,
|
|
- .features = MIXER_MSM8998_MASK,
|
|
- .sblk = &msm8998_lm_sblk,
|
|
- .pingpong = PINGPONG_NONE,
|
|
- }, {
|
|
- .name = "lm_4", .id = LM_4,
|
|
- .base = 0x48000, .len = 0x320,
|
|
- .features = MIXER_MSM8998_MASK,
|
|
- .sblk = &msm8998_lm_sblk,
|
|
- .pingpong = PINGPONG_NONE,
|
|
}, {
|
|
.name = "lm_5", .id = LM_5,
|
|
.base = 0x49000, .len = 0x320,
|
|
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
|
|
index 88a5177dfdb73e..3749c014870d36 100644
|
|
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
|
|
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_4_0_sdm845.h
|
|
@@ -156,19 +156,6 @@ static const struct dpu_lm_cfg sdm845_lm[] = {
|
|
.lm_pair = LM_5,
|
|
.pingpong = PINGPONG_2,
|
|
.dspp = DSPP_2,
|
|
- }, {
|
|
- .name = "lm_3", .id = LM_3,
|
|
- .base = 0x0, .len = 0x320,
|
|
- .features = MIXER_SDM845_MASK,
|
|
- .sblk = &sdm845_lm_sblk,
|
|
- .pingpong = PINGPONG_NONE,
|
|
- .dspp = DSPP_3,
|
|
- }, {
|
|
- .name = "lm_4", .id = LM_4,
|
|
- .base = 0x0, .len = 0x320,
|
|
- .features = MIXER_SDM845_MASK,
|
|
- .sblk = &sdm845_lm_sblk,
|
|
- .pingpong = PINGPONG_NONE,
|
|
}, {
|
|
.name = "lm_5", .id = LM_5,
|
|
.base = 0x49000, .len = 0x320,
|
|
@@ -176,6 +163,7 @@ static const struct dpu_lm_cfg sdm845_lm[] = {
|
|
.sblk = &sdm845_lm_sblk,
|
|
.lm_pair = LM_2,
|
|
.pingpong = PINGPONG_3,
|
|
+ .dspp = DSPP_3,
|
|
},
|
|
};
|
|
|
|
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
|
|
index 68fae048a9a837..260accc151d4b4 100644
|
|
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
|
|
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
|
|
@@ -80,7 +80,7 @@ static u64 _dpu_core_perf_calc_clk(const struct dpu_perf_cfg *perf_cfg,
|
|
|
|
mode = &state->adjusted_mode;
|
|
|
|
- crtc_clk = mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode);
|
|
+ crtc_clk = (u64)mode->vtotal * mode->hdisplay * drm_mode_vrefresh(mode);
|
|
|
|
drm_atomic_crtc_for_each_plane(plane, crtc) {
|
|
pstate = to_dpu_plane_state(plane->state);
|
|
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
|
|
index ea70c1c32d9401..6970b0f7f457c8 100644
|
|
--- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c
|
|
+++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c
|
|
@@ -140,6 +140,7 @@ void msm_devfreq_init(struct msm_gpu *gpu)
|
|
{
|
|
struct msm_gpu_devfreq *df = &gpu->devfreq;
|
|
struct msm_drm_private *priv = gpu->dev->dev_private;
|
|
+ int ret;
|
|
|
|
/* We need target support to do devfreq */
|
|
if (!gpu->funcs->gpu_busy)
|
|
@@ -156,8 +157,12 @@ void msm_devfreq_init(struct msm_gpu *gpu)
|
|
|
|
mutex_init(&df->lock);
|
|
|
|
- dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq,
|
|
- DEV_PM_QOS_MIN_FREQUENCY, 0);
|
|
+ ret = dev_pm_qos_add_request(&gpu->pdev->dev, &df->boost_freq,
|
|
+ DEV_PM_QOS_MIN_FREQUENCY, 0);
|
|
+ if (ret < 0) {
|
|
+ DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize QoS\n");
|
|
+ return;
|
|
+ }
|
|
|
|
msm_devfreq_profile.initial_freq = gpu->fast_rate;
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
|
|
index 3648868bb9fc51..cd533d16b96639 100644
|
|
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
|
|
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
|
|
@@ -443,6 +443,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch,
|
|
ret = gf100_grctx_generate(gr, chan, fifoch->inst);
|
|
if (ret) {
|
|
nvkm_error(&base->engine.subdev, "failed to construct context\n");
|
|
+ mutex_unlock(&gr->fecs.mutex);
|
|
return ret;
|
|
}
|
|
}
|
|
diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c
|
|
index 050ca7eafac586..556e0f9026bedd 100644
|
|
--- a/drivers/gpu/drm/omapdrm/dss/base.c
|
|
+++ b/drivers/gpu/drm/omapdrm/dss/base.c
|
|
@@ -139,21 +139,13 @@ static bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
|
|
}
|
|
|
|
int omapdss_device_connect(struct dss_device *dss,
|
|
- struct omap_dss_device *src,
|
|
struct omap_dss_device *dst)
|
|
{
|
|
- dev_dbg(&dss->pdev->dev, "connect(%s, %s)\n",
|
|
- src ? dev_name(src->dev) : "NULL",
|
|
+ dev_dbg(&dss->pdev->dev, "connect(%s)\n",
|
|
dst ? dev_name(dst->dev) : "NULL");
|
|
|
|
- if (!dst) {
|
|
- /*
|
|
- * The destination is NULL when the source is connected to a
|
|
- * bridge instead of a DSS device. Stop here, we will attach
|
|
- * the bridge later when we will have a DRM encoder.
|
|
- */
|
|
- return src && src->bridge ? 0 : -EINVAL;
|
|
- }
|
|
+ if (!dst)
|
|
+ return -EINVAL;
|
|
|
|
if (omapdss_device_is_connected(dst))
|
|
return -EBUSY;
|
|
@@ -163,19 +155,14 @@ int omapdss_device_connect(struct dss_device *dss,
|
|
return 0;
|
|
}
|
|
|
|
-void omapdss_device_disconnect(struct omap_dss_device *src,
|
|
+void omapdss_device_disconnect(struct dss_device *dss,
|
|
struct omap_dss_device *dst)
|
|
{
|
|
- struct dss_device *dss = src ? src->dss : dst->dss;
|
|
-
|
|
- dev_dbg(&dss->pdev->dev, "disconnect(%s, %s)\n",
|
|
- src ? dev_name(src->dev) : "NULL",
|
|
+ dev_dbg(&dss->pdev->dev, "disconnect(%s)\n",
|
|
dst ? dev_name(dst->dev) : "NULL");
|
|
|
|
- if (!dst) {
|
|
- WARN_ON(!src->bridge);
|
|
+ if (WARN_ON(!dst))
|
|
return;
|
|
- }
|
|
|
|
if (!dst->id && !omapdss_device_is_connected(dst)) {
|
|
WARN_ON(1);
|
|
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
|
|
index 040d5a3e33d680..4c22c09c93d523 100644
|
|
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
|
|
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
|
|
@@ -242,9 +242,8 @@ struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev);
|
|
void omapdss_device_put(struct omap_dss_device *dssdev);
|
|
struct omap_dss_device *omapdss_find_device_by_node(struct device_node *node);
|
|
int omapdss_device_connect(struct dss_device *dss,
|
|
- struct omap_dss_device *src,
|
|
struct omap_dss_device *dst);
|
|
-void omapdss_device_disconnect(struct omap_dss_device *src,
|
|
+void omapdss_device_disconnect(struct dss_device *dss,
|
|
struct omap_dss_device *dst);
|
|
|
|
int omap_dss_get_num_overlay_managers(void);
|
|
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
|
|
index 21996b713d1c3a..13790d3ac3b6a5 100644
|
|
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
|
|
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
|
|
@@ -307,7 +307,7 @@ static void omap_disconnect_pipelines(struct drm_device *ddev)
|
|
for (i = 0; i < priv->num_pipes; i++) {
|
|
struct omap_drm_pipeline *pipe = &priv->pipes[i];
|
|
|
|
- omapdss_device_disconnect(NULL, pipe->output);
|
|
+ omapdss_device_disconnect(priv->dss, pipe->output);
|
|
|
|
omapdss_device_put(pipe->output);
|
|
pipe->output = NULL;
|
|
@@ -325,7 +325,7 @@ static int omap_connect_pipelines(struct drm_device *ddev)
|
|
int r;
|
|
|
|
for_each_dss_output(output) {
|
|
- r = omapdss_device_connect(priv->dss, NULL, output);
|
|
+ r = omapdss_device_connect(priv->dss, output);
|
|
if (r == -EPROBE_DEFER) {
|
|
omapdss_device_put(output);
|
|
return r;
|
|
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
|
|
index c48fa531ca321c..68117eed702bef 100644
|
|
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
|
|
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
|
|
@@ -1395,8 +1395,6 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size,
|
|
|
|
omap_obj = to_omap_bo(obj);
|
|
|
|
- mutex_lock(&omap_obj->lock);
|
|
-
|
|
omap_obj->sgt = sgt;
|
|
|
|
if (sgt->orig_nents == 1) {
|
|
@@ -1411,21 +1409,17 @@ struct drm_gem_object *omap_gem_new_dmabuf(struct drm_device *dev, size_t size,
|
|
pages = kcalloc(npages, sizeof(*pages), GFP_KERNEL);
|
|
if (!pages) {
|
|
omap_gem_free_object(obj);
|
|
- obj = ERR_PTR(-ENOMEM);
|
|
- goto done;
|
|
+ return ERR_PTR(-ENOMEM);
|
|
}
|
|
|
|
omap_obj->pages = pages;
|
|
ret = drm_prime_sg_to_page_array(sgt, pages, npages);
|
|
if (ret) {
|
|
omap_gem_free_object(obj);
|
|
- obj = ERR_PTR(-ENOMEM);
|
|
- goto done;
|
|
+ return ERR_PTR(-ENOMEM);
|
|
}
|
|
}
|
|
|
|
-done:
|
|
- mutex_unlock(&omap_obj->lock);
|
|
return obj;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
index c067ff550692ad..164c4690cacaf9 100644
|
|
--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
+++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c
|
|
@@ -157,7 +157,6 @@ static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev)
|
|
struct panfrost_model {
|
|
const char *name;
|
|
u32 id;
|
|
- u32 id_mask;
|
|
u64 features;
|
|
u64 issues;
|
|
struct {
|
|
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
|
|
index 4aca09cab4b8cd..7ea76fdd714a9d 100644
|
|
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
|
|
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
|
|
@@ -2178,7 +2178,7 @@ int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
|
|
void
|
|
radeon_atom_encoder_init(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_encoder *encoder;
|
|
|
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
|
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
|
|
index 10be30366c2bf8..341441b241835f 100644
|
|
--- a/drivers/gpu/drm/radeon/cik.c
|
|
+++ b/drivers/gpu/drm/radeon/cik.c
|
|
@@ -7585,7 +7585,7 @@ int cik_irq_process(struct radeon_device *rdev)
|
|
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
|
|
|
|
if (rdev->irq.crtc_vblank_int[0]) {
|
|
- drm_handle_vblank(rdev->ddev, 0);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 0);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -7615,7 +7615,7 @@ int cik_irq_process(struct radeon_device *rdev)
|
|
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
|
|
|
|
if (rdev->irq.crtc_vblank_int[1]) {
|
|
- drm_handle_vblank(rdev->ddev, 1);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 1);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -7645,7 +7645,7 @@ int cik_irq_process(struct radeon_device *rdev)
|
|
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
|
|
|
|
if (rdev->irq.crtc_vblank_int[2]) {
|
|
- drm_handle_vblank(rdev->ddev, 2);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 2);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -7675,7 +7675,7 @@ int cik_irq_process(struct radeon_device *rdev)
|
|
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
|
|
|
|
if (rdev->irq.crtc_vblank_int[3]) {
|
|
- drm_handle_vblank(rdev->ddev, 3);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 3);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -7705,7 +7705,7 @@ int cik_irq_process(struct radeon_device *rdev)
|
|
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
|
|
|
|
if (rdev->irq.crtc_vblank_int[4]) {
|
|
- drm_handle_vblank(rdev->ddev, 4);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 4);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -7735,7 +7735,7 @@ int cik_irq_process(struct radeon_device *rdev)
|
|
DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
|
|
|
|
if (rdev->irq.crtc_vblank_int[5]) {
|
|
- drm_handle_vblank(rdev->ddev, 5);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 5);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -8581,7 +8581,7 @@ int cik_init(struct radeon_device *rdev)
|
|
/* Initialize surface registers */
|
|
radeon_surface_init(rdev);
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
|
|
/* Fence driver */
|
|
radeon_fence_driver_init(rdev);
|
|
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
|
|
index 4a1d5447eac17b..4419a0e85f69bf 100644
|
|
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
|
|
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
|
|
@@ -90,7 +90,7 @@ struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev)
|
|
pin = &rdev->audio.pin[i];
|
|
pin_count = 0;
|
|
|
|
- list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
|
|
+ list_for_each_entry(encoder, &rdev_to_drm(rdev)->mode_config.encoder_list, head) {
|
|
if (radeon_encoder_is_digital(encoder)) {
|
|
radeon_encoder = to_radeon_encoder(encoder);
|
|
dig = radeon_encoder->enc_priv;
|
|
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
|
|
index f0ae087be914ee..a7f9fc2b523999 100644
|
|
--- a/drivers/gpu/drm/radeon/evergreen.c
|
|
+++ b/drivers/gpu/drm/radeon/evergreen.c
|
|
@@ -1672,7 +1672,7 @@ void evergreen_pm_misc(struct radeon_device *rdev)
|
|
*/
|
|
void evergreen_pm_prepare(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
u32 tmp;
|
|
@@ -1697,7 +1697,7 @@ void evergreen_pm_prepare(struct radeon_device *rdev)
|
|
*/
|
|
void evergreen_pm_finish(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
u32 tmp;
|
|
@@ -1762,7 +1762,7 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
|
|
*/
|
|
void evergreen_hpd_init(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_connector *connector;
|
|
unsigned enabled = 0;
|
|
u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) |
|
|
@@ -1803,7 +1803,7 @@ void evergreen_hpd_init(struct radeon_device *rdev)
|
|
*/
|
|
void evergreen_hpd_fini(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_connector *connector;
|
|
unsigned disabled = 0;
|
|
|
|
@@ -4756,7 +4756,7 @@ int evergreen_irq_process(struct radeon_device *rdev)
|
|
event_name = "vblank";
|
|
|
|
if (rdev->irq.crtc_vblank_int[crtc_idx]) {
|
|
- drm_handle_vblank(rdev->ddev, crtc_idx);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), crtc_idx);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -5214,7 +5214,7 @@ int evergreen_init(struct radeon_device *rdev)
|
|
/* Initialize surface registers */
|
|
radeon_surface_init(rdev);
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* Fence driver */
|
|
radeon_fence_driver_init(rdev);
|
|
/* initialize AGP */
|
|
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
|
|
index 3e48cbb522a1ca..4cd89fd6e9a220 100644
|
|
--- a/drivers/gpu/drm/radeon/ni.c
|
|
+++ b/drivers/gpu/drm/radeon/ni.c
|
|
@@ -2373,7 +2373,7 @@ int cayman_init(struct radeon_device *rdev)
|
|
/* Initialize surface registers */
|
|
radeon_surface_init(rdev);
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* Fence driver */
|
|
radeon_fence_driver_init(rdev);
|
|
/* initialize memory controller */
|
|
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
|
|
index b63b6b4e9b2818..54cbfac3605fb3 100644
|
|
--- a/drivers/gpu/drm/radeon/r100.c
|
|
+++ b/drivers/gpu/drm/radeon/r100.c
|
|
@@ -458,7 +458,7 @@ void r100_pm_misc(struct radeon_device *rdev)
|
|
*/
|
|
void r100_pm_prepare(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
u32 tmp;
|
|
@@ -489,7 +489,7 @@ void r100_pm_prepare(struct radeon_device *rdev)
|
|
*/
|
|
void r100_pm_finish(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
u32 tmp;
|
|
@@ -602,7 +602,7 @@ void r100_hpd_set_polarity(struct radeon_device *rdev,
|
|
*/
|
|
void r100_hpd_init(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_connector *connector;
|
|
unsigned enable = 0;
|
|
|
|
@@ -625,7 +625,7 @@ void r100_hpd_init(struct radeon_device *rdev)
|
|
*/
|
|
void r100_hpd_fini(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_connector *connector;
|
|
unsigned disable = 0;
|
|
|
|
@@ -797,7 +797,7 @@ int r100_irq_process(struct radeon_device *rdev)
|
|
/* Vertical blank interrupts */
|
|
if (status & RADEON_CRTC_VBLANK_STAT) {
|
|
if (rdev->irq.crtc_vblank_int[0]) {
|
|
- drm_handle_vblank(rdev->ddev, 0);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 0);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -806,7 +806,7 @@ int r100_irq_process(struct radeon_device *rdev)
|
|
}
|
|
if (status & RADEON_CRTC2_VBLANK_STAT) {
|
|
if (rdev->irq.crtc_vblank_int[1]) {
|
|
- drm_handle_vblank(rdev->ddev, 1);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 1);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -1490,7 +1490,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
|
|
header = radeon_get_ib_value(p, h_idx);
|
|
crtc_id = radeon_get_ib_value(p, h_idx + 5);
|
|
reg = R100_CP_PACKET0_GET_REG(header);
|
|
- crtc = drm_crtc_find(p->rdev->ddev, p->filp, crtc_id);
|
|
+ crtc = drm_crtc_find(rdev_to_drm(p->rdev), p->filp, crtc_id);
|
|
if (!crtc) {
|
|
DRM_ERROR("cannot find crtc %d\n", crtc_id);
|
|
return -ENOENT;
|
|
@@ -3078,7 +3078,7 @@ DEFINE_SHOW_ATTRIBUTE(r100_debugfs_mc_info);
|
|
void r100_debugfs_rbbm_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("r100_rbbm_info", 0444, root, rdev,
|
|
&r100_debugfs_rbbm_info_fops);
|
|
@@ -3088,7 +3088,7 @@ void r100_debugfs_rbbm_init(struct radeon_device *rdev)
|
|
void r100_debugfs_cp_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("r100_cp_ring_info", 0444, root, rdev,
|
|
&r100_debugfs_cp_ring_info_fops);
|
|
@@ -3100,7 +3100,7 @@ void r100_debugfs_cp_init(struct radeon_device *rdev)
|
|
void r100_debugfs_mc_info_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("r100_mc_info", 0444, root, rdev,
|
|
&r100_debugfs_mc_info_fops);
|
|
@@ -3966,7 +3966,7 @@ int r100_resume(struct radeon_device *rdev)
|
|
RREG32(R_0007C0_CP_STAT));
|
|
}
|
|
/* post */
|
|
- radeon_combios_asic_init(rdev->ddev);
|
|
+ radeon_combios_asic_init(rdev_to_drm(rdev));
|
|
/* Resume clock after posting */
|
|
r100_clock_startup(rdev);
|
|
/* Initialize surface registers */
|
|
@@ -4075,7 +4075,7 @@ int r100_init(struct radeon_device *rdev)
|
|
/* Set asic errata */
|
|
r100_errata(rdev);
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* initialize AGP */
|
|
if (rdev->flags & RADEON_IS_AGP) {
|
|
r = radeon_agp_init(rdev);
|
|
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
|
|
index 25201b9a5aae7d..430a4263ccf7a8 100644
|
|
--- a/drivers/gpu/drm/radeon/r300.c
|
|
+++ b/drivers/gpu/drm/radeon/r300.c
|
|
@@ -615,7 +615,7 @@ DEFINE_SHOW_ATTRIBUTE(rv370_debugfs_pcie_gart_info);
|
|
static void rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("rv370_pcie_gart_info", 0444, root, rdev,
|
|
&rv370_debugfs_pcie_gart_info_fops);
|
|
@@ -1451,7 +1451,7 @@ int r300_resume(struct radeon_device *rdev)
|
|
RREG32(R_0007C0_CP_STAT));
|
|
}
|
|
/* post */
|
|
- radeon_combios_asic_init(rdev->ddev);
|
|
+ radeon_combios_asic_init(rdev_to_drm(rdev));
|
|
/* Resume clock after posting */
|
|
r300_clock_startup(rdev);
|
|
/* Initialize surface registers */
|
|
@@ -1537,7 +1537,7 @@ int r300_init(struct radeon_device *rdev)
|
|
/* Set asic errata */
|
|
r300_errata(rdev);
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* initialize AGP */
|
|
if (rdev->flags & RADEON_IS_AGP) {
|
|
r = radeon_agp_init(rdev);
|
|
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
|
|
index eae8a6389f5ea2..b3a747a8f17d55 100644
|
|
--- a/drivers/gpu/drm/radeon/r420.c
|
|
+++ b/drivers/gpu/drm/radeon/r420.c
|
|
@@ -321,7 +321,7 @@ int r420_resume(struct radeon_device *rdev)
|
|
if (rdev->is_atom_bios) {
|
|
atom_asic_init(rdev->mode_info.atom_context);
|
|
} else {
|
|
- radeon_combios_asic_init(rdev->ddev);
|
|
+ radeon_combios_asic_init(rdev_to_drm(rdev));
|
|
}
|
|
/* Resume clock after posting */
|
|
r420_clock_resume(rdev);
|
|
@@ -413,7 +413,7 @@ int r420_init(struct radeon_device *rdev)
|
|
return -EINVAL;
|
|
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* initialize AGP */
|
|
if (rdev->flags & RADEON_IS_AGP) {
|
|
r = radeon_agp_init(rdev);
|
|
@@ -492,7 +492,7 @@ DEFINE_SHOW_ATTRIBUTE(r420_debugfs_pipes_info);
|
|
void r420_debugfs_pipes_info_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("r420_pipes_info", 0444, root, rdev,
|
|
&r420_debugfs_pipes_info_fops);
|
|
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c
|
|
index 6cbcaa8451924c..08e127b3249a22 100644
|
|
--- a/drivers/gpu/drm/radeon/r520.c
|
|
+++ b/drivers/gpu/drm/radeon/r520.c
|
|
@@ -287,7 +287,7 @@ int r520_init(struct radeon_device *rdev)
|
|
atom_asic_init(rdev->mode_info.atom_context);
|
|
}
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* initialize AGP */
|
|
if (rdev->flags & RADEON_IS_AGP) {
|
|
r = radeon_agp_init(rdev);
|
|
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
|
|
index a17b95eec65fb8..98d075c540e5e5 100644
|
|
--- a/drivers/gpu/drm/radeon/r600.c
|
|
+++ b/drivers/gpu/drm/radeon/r600.c
|
|
@@ -950,7 +950,7 @@ void r600_hpd_set_polarity(struct radeon_device *rdev,
|
|
|
|
void r600_hpd_init(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_connector *connector;
|
|
unsigned enable = 0;
|
|
|
|
@@ -1017,7 +1017,7 @@ void r600_hpd_init(struct radeon_device *rdev)
|
|
|
|
void r600_hpd_fini(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_connector *connector;
|
|
unsigned disable = 0;
|
|
|
|
@@ -3280,7 +3280,7 @@ int r600_init(struct radeon_device *rdev)
|
|
/* Initialize surface registers */
|
|
radeon_surface_init(rdev);
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* Fence driver */
|
|
radeon_fence_driver_init(rdev);
|
|
if (rdev->flags & RADEON_IS_AGP) {
|
|
@@ -4136,7 +4136,7 @@ int r600_irq_process(struct radeon_device *rdev)
|
|
DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n");
|
|
|
|
if (rdev->irq.crtc_vblank_int[0]) {
|
|
- drm_handle_vblank(rdev->ddev, 0);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 0);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -4166,7 +4166,7 @@ int r600_irq_process(struct radeon_device *rdev)
|
|
DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n");
|
|
|
|
if (rdev->irq.crtc_vblank_int[1]) {
|
|
- drm_handle_vblank(rdev->ddev, 1);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 1);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -4358,7 +4358,7 @@ DEFINE_SHOW_ATTRIBUTE(r600_debugfs_mc_info);
|
|
static void r600_debugfs_mc_info_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("r600_mc_info", 0444, root, rdev,
|
|
&r600_debugfs_mc_info_fops);
|
|
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
|
|
index 6cf54a747749d3..1b2d31c4d77caa 100644
|
|
--- a/drivers/gpu/drm/radeon/r600_cs.c
|
|
+++ b/drivers/gpu/drm/radeon/r600_cs.c
|
|
@@ -884,7 +884,7 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
|
|
crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
|
|
reg = R600_CP_PACKET0_GET_REG(header);
|
|
|
|
- crtc = drm_crtc_find(p->rdev->ddev, p->filp, crtc_id);
|
|
+ crtc = drm_crtc_find(rdev_to_drm(p->rdev), p->filp, crtc_id);
|
|
if (!crtc) {
|
|
DRM_ERROR("cannot find crtc %d\n", crtc_id);
|
|
return -ENOENT;
|
|
diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c
|
|
index 9d2bcb9551e612..157107cf1bfb0d 100644
|
|
--- a/drivers/gpu/drm/radeon/r600_dpm.c
|
|
+++ b/drivers/gpu/drm/radeon/r600_dpm.c
|
|
@@ -155,7 +155,7 @@ void r600_dpm_print_ps_status(struct radeon_device *rdev,
|
|
|
|
u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
u32 vblank_in_pixels;
|
|
@@ -182,7 +182,7 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
|
|
|
|
u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
u32 vrefresh = 0;
|
|
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
|
|
index f3551ebaa2f08a..661f374f5f27a7 100644
|
|
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
|
|
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
|
|
@@ -116,7 +116,7 @@ void r600_audio_update_hdmi(struct work_struct *work)
|
|
{
|
|
struct radeon_device *rdev = container_of(work, struct radeon_device,
|
|
audio_work);
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct r600_audio_pin audio_status = r600_audio_status(rdev);
|
|
struct drm_encoder *encoder;
|
|
bool changed = false;
|
|
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
|
|
index 426a49851e3497..e0a02b357ce723 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon.h
|
|
+++ b/drivers/gpu/drm/radeon/radeon.h
|
|
@@ -2478,6 +2478,11 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
|
u32 cik_mm_rdoorbell(struct radeon_device *rdev, u32 index);
|
|
void cik_mm_wdoorbell(struct radeon_device *rdev, u32 index, u32 v);
|
|
|
|
+static inline struct drm_device *rdev_to_drm(struct radeon_device *rdev)
|
|
+{
|
|
+ return rdev->ddev;
|
|
+}
|
|
+
|
|
/*
|
|
* Cast helper
|
|
*/
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c
|
|
index 603a78e41ba55c..22ce61bdfc0603 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_acpi.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_acpi.c
|
|
@@ -405,11 +405,11 @@ static int radeon_atif_handler(struct radeon_device *rdev,
|
|
if (req.pending & ATIF_DGPU_DISPLAY_EVENT) {
|
|
if ((rdev->flags & RADEON_IS_PX) &&
|
|
radeon_atpx_dgpu_req_power_for_displays()) {
|
|
- pm_runtime_get_sync(rdev->ddev->dev);
|
|
+ pm_runtime_get_sync(rdev_to_drm(rdev)->dev);
|
|
/* Just fire off a uevent and let userspace tell us what to do */
|
|
- drm_helper_hpd_irq_event(rdev->ddev);
|
|
- pm_runtime_mark_last_busy(rdev->ddev->dev);
|
|
- pm_runtime_put_autosuspend(rdev->ddev->dev);
|
|
+ drm_helper_hpd_irq_event(rdev_to_drm(rdev));
|
|
+ pm_runtime_mark_last_busy(rdev_to_drm(rdev)->dev);
|
|
+ pm_runtime_put_autosuspend(rdev_to_drm(rdev)->dev);
|
|
}
|
|
}
|
|
/* TODO: check other events */
|
|
@@ -736,7 +736,7 @@ int radeon_acpi_init(struct radeon_device *rdev)
|
|
struct radeon_encoder *target = NULL;
|
|
|
|
/* Find the encoder controlling the brightness */
|
|
- list_for_each_entry(tmp, &rdev->ddev->mode_config.encoder_list,
|
|
+ list_for_each_entry(tmp, &rdev_to_drm(rdev)->mode_config.encoder_list,
|
|
head) {
|
|
struct radeon_encoder *enc = to_radeon_encoder(tmp);
|
|
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c
|
|
index a3d749e350f9c2..89d7b0e9e79f82 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_agp.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_agp.c
|
|
@@ -161,7 +161,7 @@ struct radeon_agp_head *radeon_agp_head_init(struct drm_device *dev)
|
|
|
|
static int radeon_agp_head_acquire(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
|
|
|
if (!rdev->agp)
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
index 53c7273eb6a5cf..c025ce6eb31672 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
@@ -186,7 +186,7 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
|
|
|
|
if (i2c.valid) {
|
|
sprintf(stmp, "0x%x", i2c.i2c_id);
|
|
- rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
|
|
+ rdev->i2c_bus[i] = radeon_i2c_create(rdev_to_drm(rdev), &i2c, stmp);
|
|
}
|
|
gpio = (ATOM_GPIO_I2C_ASSIGMENT *)
|
|
((u8 *)gpio + sizeof(ATOM_GPIO_I2C_ASSIGMENT));
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
|
|
index d6ccaf24ee0c70..fc22fe709b9c1b 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_audio.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
|
|
@@ -195,7 +195,7 @@ static void radeon_audio_enable(struct radeon_device *rdev,
|
|
return;
|
|
|
|
if (rdev->mode_info.mode_config_initialized) {
|
|
- list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
|
|
+ list_for_each_entry(encoder, &rdev_to_drm(rdev)->mode_config.encoder_list, head) {
|
|
if (radeon_encoder_is_digital(encoder)) {
|
|
radeon_encoder = to_radeon_encoder(encoder);
|
|
dig = radeon_encoder->enc_priv;
|
|
@@ -758,16 +758,20 @@ static int radeon_audio_component_get_eld(struct device *kdev, int port,
|
|
if (!rdev->audio.enabled || !rdev->mode_info.mode_config_initialized)
|
|
return 0;
|
|
|
|
- list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
|
|
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
+ const struct drm_connector_helper_funcs *connector_funcs =
|
|
+ connector->helper_private;
|
|
+ encoder = connector_funcs->best_encoder(connector);
|
|
+
|
|
+ if (!encoder)
|
|
+ continue;
|
|
+
|
|
if (!radeon_encoder_is_digital(encoder))
|
|
continue;
|
|
radeon_encoder = to_radeon_encoder(encoder);
|
|
dig = radeon_encoder->enc_priv;
|
|
if (!dig->pin || dig->pin->id != port)
|
|
continue;
|
|
- connector = radeon_get_connector_for_encoder(encoder);
|
|
- if (!connector)
|
|
- continue;
|
|
*enabled = true;
|
|
ret = drm_eld_size(connector->eld);
|
|
memcpy(buf, connector->eld, min(max_bytes, ret));
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
|
|
index 2620efc7c675bf..a30f36d098a8d1 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_combios.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
|
|
@@ -371,7 +371,7 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
|
|
int edid_info, size;
|
|
struct edid *edid;
|
|
unsigned char *raw;
|
|
- edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
|
|
+ edid_info = combios_get_table_offset(rdev_to_drm(rdev), COMBIOS_HARDCODED_EDID_TABLE);
|
|
if (!edid_info)
|
|
return false;
|
|
|
|
@@ -641,7 +641,7 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde
|
|
|
|
static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct radeon_i2c_bus_rec i2c;
|
|
u16 offset;
|
|
u8 id, blocks, clk, data;
|
|
@@ -669,7 +669,7 @@ static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct r
|
|
|
|
void radeon_combios_i2c_init(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct radeon_i2c_bus_rec i2c;
|
|
|
|
/* actual hw pads
|
|
@@ -811,7 +811,7 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
|
|
|
|
bool radeon_combios_sideport_present(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
u16 igp_info;
|
|
|
|
/* sideport is AMD only */
|
|
@@ -914,7 +914,7 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct
|
|
enum radeon_tv_std
|
|
radeon_combios_get_tv_info(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
uint16_t tv_info;
|
|
enum radeon_tv_std tv_std = TV_STD_NTSC;
|
|
|
|
@@ -2636,7 +2636,7 @@ static const char *thermal_controller_names[] = {
|
|
|
|
void radeon_combios_get_power_modes(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
u16 offset, misc, misc2 = 0;
|
|
u8 rev, tmp;
|
|
int state_index = 0;
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
|
|
index afbb3a80c0c6b5..32851632643db9 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_device.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_device.c
|
|
@@ -760,7 +760,7 @@ bool radeon_boot_test_post_card(struct radeon_device *rdev)
|
|
if (rdev->is_atom_bios)
|
|
atom_asic_init(rdev->mode_info.atom_context);
|
|
else
|
|
- radeon_combios_asic_init(rdev->ddev);
|
|
+ radeon_combios_asic_init(rdev_to_drm(rdev));
|
|
return true;
|
|
} else {
|
|
dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
|
|
@@ -980,7 +980,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
|
|
return -ENOMEM;
|
|
|
|
rdev->mode_info.atom_card_info = atom_card_info;
|
|
- atom_card_info->dev = rdev->ddev;
|
|
+ atom_card_info->dev = rdev_to_drm(rdev);
|
|
atom_card_info->reg_read = cail_reg_read;
|
|
atom_card_info->reg_write = cail_reg_write;
|
|
/* needed for iio ops */
|
|
@@ -1005,7 +1005,7 @@ int radeon_atombios_init(struct radeon_device *rdev)
|
|
|
|
mutex_init(&rdev->mode_info.atom_context->mutex);
|
|
mutex_init(&rdev->mode_info.atom_context->scratch_mutex);
|
|
- radeon_atom_initialize_bios_scratch_regs(rdev->ddev);
|
|
+ radeon_atom_initialize_bios_scratch_regs(rdev_to_drm(rdev));
|
|
atom_allocate_fb_scratch(rdev->mode_info.atom_context);
|
|
return 0;
|
|
}
|
|
@@ -1049,7 +1049,7 @@ void radeon_atombios_fini(struct radeon_device *rdev)
|
|
*/
|
|
int radeon_combios_init(struct radeon_device *rdev)
|
|
{
|
|
- radeon_combios_initialize_bios_scratch_regs(rdev->ddev);
|
|
+ radeon_combios_initialize_bios_scratch_regs(rdev_to_drm(rdev));
|
|
return 0;
|
|
}
|
|
|
|
@@ -1847,7 +1847,7 @@ int radeon_gpu_reset(struct radeon_device *rdev)
|
|
|
|
downgrade_write(&rdev->exclusive_lock);
|
|
|
|
- drm_helper_resume_force_mode(rdev->ddev);
|
|
+ drm_helper_resume_force_mode(rdev_to_drm(rdev));
|
|
|
|
/* set the power state here in case we are a PX system or headless */
|
|
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
|
|
index 5f1d24d3120c4a..8a8ffc5fc8040b 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_display.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_display.c
|
|
@@ -302,13 +302,13 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
|
|
if ((radeon_use_pflipirq == 2) && ASIC_IS_DCE4(rdev))
|
|
return;
|
|
|
|
- spin_lock_irqsave(&rdev->ddev->event_lock, flags);
|
|
+ spin_lock_irqsave(&rdev_to_drm(rdev)->event_lock, flags);
|
|
if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
|
|
DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
|
|
"RADEON_FLIP_SUBMITTED(%d)\n",
|
|
radeon_crtc->flip_status,
|
|
RADEON_FLIP_SUBMITTED);
|
|
- spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
|
|
+ spin_unlock_irqrestore(&rdev_to_drm(rdev)->event_lock, flags);
|
|
return;
|
|
}
|
|
|
|
@@ -334,7 +334,7 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
|
|
*/
|
|
if (update_pending &&
|
|
(DRM_SCANOUTPOS_VALID &
|
|
- radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id,
|
|
+ radeon_get_crtc_scanoutpos(rdev_to_drm(rdev), crtc_id,
|
|
GET_DISTANCE_TO_VBLANKSTART,
|
|
&vpos, &hpos, NULL, NULL,
|
|
&rdev->mode_info.crtcs[crtc_id]->base.hwmode)) &&
|
|
@@ -347,7 +347,7 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
|
|
*/
|
|
update_pending = 0;
|
|
}
|
|
- spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
|
|
+ spin_unlock_irqrestore(&rdev_to_drm(rdev)->event_lock, flags);
|
|
if (!update_pending)
|
|
radeon_crtc_handle_flip(rdev, crtc_id);
|
|
}
|
|
@@ -370,14 +370,14 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
|
|
if (radeon_crtc == NULL)
|
|
return;
|
|
|
|
- spin_lock_irqsave(&rdev->ddev->event_lock, flags);
|
|
+ spin_lock_irqsave(&rdev_to_drm(rdev)->event_lock, flags);
|
|
work = radeon_crtc->flip_work;
|
|
if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) {
|
|
DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != "
|
|
"RADEON_FLIP_SUBMITTED(%d)\n",
|
|
radeon_crtc->flip_status,
|
|
RADEON_FLIP_SUBMITTED);
|
|
- spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
|
|
+ spin_unlock_irqrestore(&rdev_to_drm(rdev)->event_lock, flags);
|
|
return;
|
|
}
|
|
|
|
@@ -389,7 +389,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
|
|
if (work->event)
|
|
drm_crtc_send_vblank_event(&radeon_crtc->base, work->event);
|
|
|
|
- spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
|
|
+ spin_unlock_irqrestore(&rdev_to_drm(rdev)->event_lock, flags);
|
|
|
|
drm_crtc_vblank_put(&radeon_crtc->base);
|
|
radeon_irq_kms_pflip_irq_put(rdev, work->crtc_id);
|
|
@@ -408,7 +408,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
|
|
struct radeon_flip_work *work =
|
|
container_of(__work, struct radeon_flip_work, flip_work);
|
|
struct radeon_device *rdev = work->rdev;
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id];
|
|
|
|
struct drm_crtc *crtc = &radeon_crtc->base;
|
|
@@ -1401,7 +1401,7 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
|
|
|
|
if (rdev->is_atom_bios) {
|
|
rdev->mode_info.coherent_mode_property =
|
|
- drm_property_create_range(rdev->ddev, 0 , "coherent", 0, 1);
|
|
+ drm_property_create_range(rdev_to_drm(rdev), 0, "coherent", 0, 1);
|
|
if (!rdev->mode_info.coherent_mode_property)
|
|
return -ENOMEM;
|
|
}
|
|
@@ -1409,57 +1409,57 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
|
|
if (!ASIC_IS_AVIVO(rdev)) {
|
|
sz = ARRAY_SIZE(radeon_tmds_pll_enum_list);
|
|
rdev->mode_info.tmds_pll_property =
|
|
- drm_property_create_enum(rdev->ddev, 0,
|
|
+ drm_property_create_enum(rdev_to_drm(rdev), 0,
|
|
"tmds_pll",
|
|
radeon_tmds_pll_enum_list, sz);
|
|
}
|
|
|
|
rdev->mode_info.load_detect_property =
|
|
- drm_property_create_range(rdev->ddev, 0, "load detection", 0, 1);
|
|
+ drm_property_create_range(rdev_to_drm(rdev), 0, "load detection", 0, 1);
|
|
if (!rdev->mode_info.load_detect_property)
|
|
return -ENOMEM;
|
|
|
|
- drm_mode_create_scaling_mode_property(rdev->ddev);
|
|
+ drm_mode_create_scaling_mode_property(rdev_to_drm(rdev));
|
|
|
|
sz = ARRAY_SIZE(radeon_tv_std_enum_list);
|
|
rdev->mode_info.tv_std_property =
|
|
- drm_property_create_enum(rdev->ddev, 0,
|
|
+ drm_property_create_enum(rdev_to_drm(rdev), 0,
|
|
"tv standard",
|
|
radeon_tv_std_enum_list, sz);
|
|
|
|
sz = ARRAY_SIZE(radeon_underscan_enum_list);
|
|
rdev->mode_info.underscan_property =
|
|
- drm_property_create_enum(rdev->ddev, 0,
|
|
+ drm_property_create_enum(rdev_to_drm(rdev), 0,
|
|
"underscan",
|
|
radeon_underscan_enum_list, sz);
|
|
|
|
rdev->mode_info.underscan_hborder_property =
|
|
- drm_property_create_range(rdev->ddev, 0,
|
|
+ drm_property_create_range(rdev_to_drm(rdev), 0,
|
|
"underscan hborder", 0, 128);
|
|
if (!rdev->mode_info.underscan_hborder_property)
|
|
return -ENOMEM;
|
|
|
|
rdev->mode_info.underscan_vborder_property =
|
|
- drm_property_create_range(rdev->ddev, 0,
|
|
+ drm_property_create_range(rdev_to_drm(rdev), 0,
|
|
"underscan vborder", 0, 128);
|
|
if (!rdev->mode_info.underscan_vborder_property)
|
|
return -ENOMEM;
|
|
|
|
sz = ARRAY_SIZE(radeon_audio_enum_list);
|
|
rdev->mode_info.audio_property =
|
|
- drm_property_create_enum(rdev->ddev, 0,
|
|
+ drm_property_create_enum(rdev_to_drm(rdev), 0,
|
|
"audio",
|
|
radeon_audio_enum_list, sz);
|
|
|
|
sz = ARRAY_SIZE(radeon_dither_enum_list);
|
|
rdev->mode_info.dither_property =
|
|
- drm_property_create_enum(rdev->ddev, 0,
|
|
+ drm_property_create_enum(rdev_to_drm(rdev), 0,
|
|
"dither",
|
|
radeon_dither_enum_list, sz);
|
|
|
|
sz = ARRAY_SIZE(radeon_output_csc_enum_list);
|
|
rdev->mode_info.output_csc_property =
|
|
- drm_property_create_enum(rdev->ddev, 0,
|
|
+ drm_property_create_enum(rdev_to_drm(rdev), 0,
|
|
"output_csc",
|
|
radeon_output_csc_enum_list, sz);
|
|
|
|
@@ -1578,29 +1578,29 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
|
int i;
|
|
int ret;
|
|
|
|
- drm_mode_config_init(rdev->ddev);
|
|
+ drm_mode_config_init(rdev_to_drm(rdev));
|
|
rdev->mode_info.mode_config_initialized = true;
|
|
|
|
- rdev->ddev->mode_config.funcs = &radeon_mode_funcs;
|
|
+ rdev_to_drm(rdev)->mode_config.funcs = &radeon_mode_funcs;
|
|
|
|
if (radeon_use_pflipirq == 2 && rdev->family >= CHIP_R600)
|
|
- rdev->ddev->mode_config.async_page_flip = true;
|
|
+ rdev_to_drm(rdev)->mode_config.async_page_flip = true;
|
|
|
|
if (ASIC_IS_DCE5(rdev)) {
|
|
- rdev->ddev->mode_config.max_width = 16384;
|
|
- rdev->ddev->mode_config.max_height = 16384;
|
|
+ rdev_to_drm(rdev)->mode_config.max_width = 16384;
|
|
+ rdev_to_drm(rdev)->mode_config.max_height = 16384;
|
|
} else if (ASIC_IS_AVIVO(rdev)) {
|
|
- rdev->ddev->mode_config.max_width = 8192;
|
|
- rdev->ddev->mode_config.max_height = 8192;
|
|
+ rdev_to_drm(rdev)->mode_config.max_width = 8192;
|
|
+ rdev_to_drm(rdev)->mode_config.max_height = 8192;
|
|
} else {
|
|
- rdev->ddev->mode_config.max_width = 4096;
|
|
- rdev->ddev->mode_config.max_height = 4096;
|
|
+ rdev_to_drm(rdev)->mode_config.max_width = 4096;
|
|
+ rdev_to_drm(rdev)->mode_config.max_height = 4096;
|
|
}
|
|
|
|
- rdev->ddev->mode_config.preferred_depth = 24;
|
|
- rdev->ddev->mode_config.prefer_shadow = 1;
|
|
+ rdev_to_drm(rdev)->mode_config.preferred_depth = 24;
|
|
+ rdev_to_drm(rdev)->mode_config.prefer_shadow = 1;
|
|
|
|
- rdev->ddev->mode_config.fb_modifiers_not_supported = true;
|
|
+ rdev_to_drm(rdev)->mode_config.fb_modifiers_not_supported = true;
|
|
|
|
ret = radeon_modeset_create_props(rdev);
|
|
if (ret) {
|
|
@@ -1618,11 +1618,11 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
|
|
|
/* allocate crtcs */
|
|
for (i = 0; i < rdev->num_crtc; i++) {
|
|
- radeon_crtc_init(rdev->ddev, i);
|
|
+ radeon_crtc_init(rdev_to_drm(rdev), i);
|
|
}
|
|
|
|
/* okay we should have all the bios connectors */
|
|
- ret = radeon_setup_enc_conn(rdev->ddev);
|
|
+ ret = radeon_setup_enc_conn(rdev_to_drm(rdev));
|
|
if (!ret) {
|
|
return ret;
|
|
}
|
|
@@ -1639,7 +1639,7 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
|
/* setup afmt */
|
|
radeon_afmt_init(rdev);
|
|
|
|
- drm_kms_helper_poll_init(rdev->ddev);
|
|
+ drm_kms_helper_poll_init(rdev_to_drm(rdev));
|
|
|
|
/* do pm late init */
|
|
ret = radeon_pm_late_init(rdev);
|
|
@@ -1650,11 +1650,11 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
|
void radeon_modeset_fini(struct radeon_device *rdev)
|
|
{
|
|
if (rdev->mode_info.mode_config_initialized) {
|
|
- drm_kms_helper_poll_fini(rdev->ddev);
|
|
+ drm_kms_helper_poll_fini(rdev_to_drm(rdev));
|
|
radeon_hpd_fini(rdev);
|
|
- drm_helper_force_disable_all(rdev->ddev);
|
|
+ drm_helper_force_disable_all(rdev_to_drm(rdev));
|
|
radeon_afmt_fini(rdev);
|
|
- drm_mode_config_cleanup(rdev->ddev);
|
|
+ drm_mode_config_cleanup(rdev_to_drm(rdev));
|
|
rdev->mode_info.mode_config_initialized = false;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_fbdev.c b/drivers/gpu/drm/radeon/radeon_fbdev.c
|
|
index 02bf25759059a7..fb70de29545c6f 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_fbdev.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_fbdev.c
|
|
@@ -67,7 +67,7 @@ static int radeon_fbdev_create_pinned_object(struct drm_fb_helper *fb_helper,
|
|
int height = mode_cmd->height;
|
|
u32 cpp;
|
|
|
|
- info = drm_get_format_info(rdev->ddev, mode_cmd);
|
|
+ info = drm_get_format_info(rdev_to_drm(rdev), mode_cmd);
|
|
cpp = info->cpp[0];
|
|
|
|
/* need to align pitch with crtc limits */
|
|
@@ -148,15 +148,15 @@ static int radeon_fbdev_fb_open(struct fb_info *info, int user)
|
|
struct radeon_device *rdev = fb_helper->dev->dev_private;
|
|
int ret;
|
|
|
|
- ret = pm_runtime_get_sync(rdev->ddev->dev);
|
|
+ ret = pm_runtime_get_sync(rdev_to_drm(rdev)->dev);
|
|
if (ret < 0 && ret != -EACCES)
|
|
goto err_pm_runtime_mark_last_busy;
|
|
|
|
return 0;
|
|
|
|
err_pm_runtime_mark_last_busy:
|
|
- pm_runtime_mark_last_busy(rdev->ddev->dev);
|
|
- pm_runtime_put_autosuspend(rdev->ddev->dev);
|
|
+ pm_runtime_mark_last_busy(rdev_to_drm(rdev)->dev);
|
|
+ pm_runtime_put_autosuspend(rdev_to_drm(rdev)->dev);
|
|
return ret;
|
|
}
|
|
|
|
@@ -165,8 +165,8 @@ static int radeon_fbdev_fb_release(struct fb_info *info, int user)
|
|
struct drm_fb_helper *fb_helper = info->par;
|
|
struct radeon_device *rdev = fb_helper->dev->dev_private;
|
|
|
|
- pm_runtime_mark_last_busy(rdev->ddev->dev);
|
|
- pm_runtime_put_autosuspend(rdev->ddev->dev);
|
|
+ pm_runtime_mark_last_busy(rdev_to_drm(rdev)->dev);
|
|
+ pm_runtime_put_autosuspend(rdev_to_drm(rdev)->dev);
|
|
|
|
return 0;
|
|
}
|
|
@@ -236,7 +236,7 @@ static int radeon_fbdev_fb_helper_fb_probe(struct drm_fb_helper *fb_helper,
|
|
ret = -ENOMEM;
|
|
goto err_radeon_fbdev_destroy_pinned_object;
|
|
}
|
|
- ret = radeon_framebuffer_init(rdev->ddev, fb, &mode_cmd, gobj);
|
|
+ ret = radeon_framebuffer_init(rdev_to_drm(rdev), fb, &mode_cmd, gobj);
|
|
if (ret) {
|
|
DRM_ERROR("failed to initialize framebuffer %d\n", ret);
|
|
goto err_kfree;
|
|
@@ -374,12 +374,12 @@ void radeon_fbdev_setup(struct radeon_device *rdev)
|
|
fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
|
|
if (!fb_helper)
|
|
return;
|
|
- drm_fb_helper_prepare(rdev->ddev, fb_helper, bpp_sel, &radeon_fbdev_fb_helper_funcs);
|
|
+ drm_fb_helper_prepare(rdev_to_drm(rdev), fb_helper, bpp_sel, &radeon_fbdev_fb_helper_funcs);
|
|
|
|
- ret = drm_client_init(rdev->ddev, &fb_helper->client, "radeon-fbdev",
|
|
+ ret = drm_client_init(rdev_to_drm(rdev), &fb_helper->client, "radeon-fbdev",
|
|
&radeon_fbdev_client_funcs);
|
|
if (ret) {
|
|
- drm_err(rdev->ddev, "Failed to register client: %d\n", ret);
|
|
+ drm_err(rdev_to_drm(rdev), "Failed to register client: %d\n", ret);
|
|
goto err_drm_client_init;
|
|
}
|
|
|
|
@@ -394,13 +394,13 @@ void radeon_fbdev_setup(struct radeon_device *rdev)
|
|
|
|
void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state)
|
|
{
|
|
- if (rdev->ddev->fb_helper)
|
|
- drm_fb_helper_set_suspend(rdev->ddev->fb_helper, state);
|
|
+ if (rdev_to_drm(rdev)->fb_helper)
|
|
+ drm_fb_helper_set_suspend(rdev_to_drm(rdev)->fb_helper, state);
|
|
}
|
|
|
|
bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
|
|
{
|
|
- struct drm_fb_helper *fb_helper = rdev->ddev->fb_helper;
|
|
+ struct drm_fb_helper *fb_helper = rdev_to_drm(rdev)->fb_helper;
|
|
struct drm_gem_object *gobj;
|
|
|
|
if (!fb_helper)
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
|
|
index 2749dde5838f1c..6d5e828fa39e3d 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_fence.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
|
|
@@ -151,7 +151,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
|
|
rdev->fence_context + ring,
|
|
seq);
|
|
radeon_fence_ring_emit(rdev, ring, *fence);
|
|
- trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq);
|
|
+ trace_radeon_fence_emit(rdev_to_drm(rdev), ring, (*fence)->seq);
|
|
radeon_fence_schedule_check(rdev, ring);
|
|
return 0;
|
|
}
|
|
@@ -492,7 +492,7 @@ static long radeon_fence_wait_seq_timeout(struct radeon_device *rdev,
|
|
if (!target_seq[i])
|
|
continue;
|
|
|
|
- trace_radeon_fence_wait_begin(rdev->ddev, i, target_seq[i]);
|
|
+ trace_radeon_fence_wait_begin(rdev_to_drm(rdev), i, target_seq[i]);
|
|
radeon_irq_kms_sw_irq_get(rdev, i);
|
|
}
|
|
|
|
@@ -514,7 +514,7 @@ static long radeon_fence_wait_seq_timeout(struct radeon_device *rdev,
|
|
continue;
|
|
|
|
radeon_irq_kms_sw_irq_put(rdev, i);
|
|
- trace_radeon_fence_wait_end(rdev->ddev, i, target_seq[i]);
|
|
+ trace_radeon_fence_wait_end(rdev_to_drm(rdev), i, target_seq[i]);
|
|
}
|
|
|
|
return r;
|
|
@@ -1004,7 +1004,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(radeon_debugfs_gpu_reset_fops,
|
|
void radeon_debugfs_fence_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("radeon_gpu_reset", 0444, root, rdev,
|
|
&radeon_debugfs_gpu_reset_fops);
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
|
|
index 27225d1fe8d2e7..96934fee7e9432 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_gem.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
|
|
@@ -898,7 +898,7 @@ DEFINE_SHOW_ATTRIBUTE(radeon_debugfs_gem_info);
|
|
void radeon_gem_debugfs_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("radeon_gem_info", 0444, root, rdev,
|
|
&radeon_debugfs_gem_info_fops);
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
|
|
index 314d066e68e9d0..e7b2e937072942 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
|
|
@@ -1012,7 +1012,7 @@ void radeon_i2c_add(struct radeon_device *rdev,
|
|
struct radeon_i2c_bus_rec *rec,
|
|
const char *name)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
int i;
|
|
|
|
for (i = 0; i < RADEON_MAX_I2C_BUS; i++) {
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_ib.c b/drivers/gpu/drm/radeon/radeon_ib.c
|
|
index fb9ecf5dbe2b7a..560ce90f4eb16a 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_ib.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_ib.c
|
|
@@ -307,7 +307,7 @@ DEFINE_SHOW_ATTRIBUTE(radeon_debugfs_sa_info);
|
|
static void radeon_debugfs_sa_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("radeon_sa_info", 0444, root, rdev,
|
|
&radeon_debugfs_sa_info_fops);
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
|
|
index c4dda908666cfc..9961251b44ba06 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
|
|
@@ -80,7 +80,7 @@ static void radeon_hotplug_work_func(struct work_struct *work)
|
|
{
|
|
struct radeon_device *rdev = container_of(work, struct radeon_device,
|
|
hotplug_work.work);
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
struct drm_connector *connector;
|
|
|
|
@@ -101,7 +101,7 @@ static void radeon_dp_work_func(struct work_struct *work)
|
|
{
|
|
struct radeon_device *rdev = container_of(work, struct radeon_device,
|
|
dp_work);
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
struct drm_connector *connector;
|
|
|
|
@@ -197,7 +197,7 @@ static void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
|
|
|
|
static int radeon_irq_install(struct radeon_device *rdev, int irq)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
int ret;
|
|
|
|
if (irq == IRQ_NOTCONNECTED)
|
|
@@ -218,7 +218,7 @@ static int radeon_irq_install(struct radeon_device *rdev, int irq)
|
|
|
|
static void radeon_irq_uninstall(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
|
|
|
radeon_driver_irq_uninstall_kms(dev);
|
|
@@ -322,9 +322,9 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
|
|
spin_lock_init(&rdev->irq.lock);
|
|
|
|
/* Disable vblank irqs aggressively for power-saving */
|
|
- rdev->ddev->vblank_disable_immediate = true;
|
|
+ rdev_to_drm(rdev)->vblank_disable_immediate = true;
|
|
|
|
- r = drm_vblank_init(rdev->ddev, rdev->num_crtc);
|
|
+ r = drm_vblank_init(rdev_to_drm(rdev), rdev->num_crtc);
|
|
if (r) {
|
|
return r;
|
|
}
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
|
|
index 10c0fbd9d2b441..6f3c9a20a2de58 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_object.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_object.c
|
|
@@ -152,7 +152,7 @@ int radeon_bo_create(struct radeon_device *rdev,
|
|
bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
|
|
if (bo == NULL)
|
|
return -ENOMEM;
|
|
- drm_gem_private_object_init(rdev->ddev, &bo->tbo.base, size);
|
|
+ drm_gem_private_object_init(rdev_to_drm(rdev), &bo->tbo.base, size);
|
|
bo->rdev = rdev;
|
|
bo->surface_reg = -1;
|
|
INIT_LIST_HEAD(&bo->list);
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
|
|
index b73fd9ab02522a..66fe9fb920452a 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_pm.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
|
|
@@ -281,7 +281,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
|
|
|
|
if (rdev->irq.installed) {
|
|
i = 0;
|
|
- drm_for_each_crtc(crtc, rdev->ddev) {
|
|
+ drm_for_each_crtc(crtc, rdev_to_drm(rdev)) {
|
|
if (rdev->pm.active_crtcs & (1 << i)) {
|
|
/* This can fail if a modeset is in progress */
|
|
if (drm_crtc_vblank_get(crtc) == 0)
|
|
@@ -298,7 +298,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
|
|
|
|
if (rdev->irq.installed) {
|
|
i = 0;
|
|
- drm_for_each_crtc(crtc, rdev->ddev) {
|
|
+ drm_for_each_crtc(crtc, rdev_to_drm(rdev)) {
|
|
if (rdev->pm.req_vblank & (1 << i)) {
|
|
rdev->pm.req_vblank &= ~(1 << i);
|
|
drm_crtc_vblank_put(crtc);
|
|
@@ -670,7 +670,7 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
|
|
char *buf)
|
|
{
|
|
struct radeon_device *rdev = dev_get_drvdata(dev);
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
int temp;
|
|
|
|
/* Can't get temperature when the card is off */
|
|
@@ -714,7 +714,7 @@ static ssize_t radeon_hwmon_show_sclk(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct radeon_device *rdev = dev_get_drvdata(dev);
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
u32 sclk = 0;
|
|
|
|
/* Can't get clock frequency when the card is off */
|
|
@@ -739,7 +739,7 @@ static ssize_t radeon_hwmon_show_vddc(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct radeon_device *rdev = dev_get_drvdata(dev);
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
u16 vddc = 0;
|
|
|
|
/* Can't get vddc when the card is off */
|
|
@@ -1691,7 +1691,7 @@ void radeon_pm_fini(struct radeon_device *rdev)
|
|
|
|
static void radeon_pm_compute_clocks_old(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
|
|
@@ -1764,7 +1764,7 @@ static void radeon_pm_compute_clocks_old(struct radeon_device *rdev)
|
|
|
|
static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
struct radeon_connector *radeon_connector;
|
|
@@ -1825,7 +1825,7 @@ static bool radeon_pm_in_vbl(struct radeon_device *rdev)
|
|
*/
|
|
for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) {
|
|
if (rdev->pm.active_crtcs & (1 << crtc)) {
|
|
- vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev,
|
|
+ vbl_status = radeon_get_crtc_scanoutpos(rdev_to_drm(rdev),
|
|
crtc,
|
|
USE_REAL_VBLANKSTART,
|
|
&vpos, &hpos, NULL, NULL,
|
|
@@ -1917,7 +1917,7 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work)
|
|
static int radeon_debugfs_pm_info_show(struct seq_file *m, void *unused)
|
|
{
|
|
struct radeon_device *rdev = m->private;
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
|
|
if ((rdev->flags & RADEON_IS_PX) &&
|
|
(ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
|
|
@@ -1954,7 +1954,7 @@ DEFINE_SHOW_ATTRIBUTE(radeon_debugfs_pm_info);
|
|
static void radeon_debugfs_pm_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("radeon_pm_info", 0444, root, rdev,
|
|
&radeon_debugfs_pm_info_fops);
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
|
|
index e6534fa9f1fb54..8626171e9a6db2 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_ring.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
|
|
@@ -548,7 +548,7 @@ static void radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_r
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
const char *ring_name = radeon_debugfs_ring_idx_to_name(ring->idx);
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
if (ring_name)
|
|
debugfs_create_file(ring_name, 0444, root, ring,
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
|
|
index 4eb83ccc4906ad..065a09e7997cdb 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
|
|
@@ -689,8 +689,8 @@ int radeon_ttm_init(struct radeon_device *rdev)
|
|
|
|
/* No others user of address space so set it to 0 */
|
|
r = ttm_device_init(&rdev->mman.bdev, &radeon_bo_driver, rdev->dev,
|
|
- rdev->ddev->anon_inode->i_mapping,
|
|
- rdev->ddev->vma_offset_manager,
|
|
+ rdev_to_drm(rdev)->anon_inode->i_mapping,
|
|
+ rdev_to_drm(rdev)->vma_offset_manager,
|
|
rdev->need_swiotlb,
|
|
dma_addressing_limited(&rdev->pdev->dev));
|
|
if (r) {
|
|
@@ -897,7 +897,7 @@ static const struct file_operations radeon_ttm_gtt_fops = {
|
|
static void radeon_ttm_debugfs_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct drm_minor *minor = rdev->ddev->primary;
|
|
+ struct drm_minor *minor = rdev_to_drm(rdev)->primary;
|
|
struct dentry *root = minor->debugfs_root;
|
|
|
|
debugfs_create_file("radeon_vram", 0444, root, rdev,
|
|
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
|
|
index 922a29e5888027..4f93fe468ec7f9 100644
|
|
--- a/drivers/gpu/drm/radeon/rs400.c
|
|
+++ b/drivers/gpu/drm/radeon/rs400.c
|
|
@@ -378,7 +378,7 @@ DEFINE_SHOW_ATTRIBUTE(rs400_debugfs_gart_info);
|
|
static void rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("rs400_gart_info", 0444, root, rdev,
|
|
&rs400_debugfs_gart_info_fops);
|
|
@@ -473,7 +473,7 @@ int rs400_resume(struct radeon_device *rdev)
|
|
RREG32(R_0007C0_CP_STAT));
|
|
}
|
|
/* post */
|
|
- radeon_combios_asic_init(rdev->ddev);
|
|
+ radeon_combios_asic_init(rdev_to_drm(rdev));
|
|
/* Resume clock after posting */
|
|
r300_clock_startup(rdev);
|
|
/* Initialize surface registers */
|
|
@@ -551,7 +551,7 @@ int rs400_init(struct radeon_device *rdev)
|
|
return -EINVAL;
|
|
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* initialize memory controller */
|
|
rs400_mc_init(rdev);
|
|
/* Fence driver */
|
|
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
|
|
index 8cf87a0a2b2a00..fa4cc2a185dd02 100644
|
|
--- a/drivers/gpu/drm/radeon/rs600.c
|
|
+++ b/drivers/gpu/drm/radeon/rs600.c
|
|
@@ -322,7 +322,7 @@ void rs600_pm_misc(struct radeon_device *rdev)
|
|
|
|
void rs600_pm_prepare(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
u32 tmp;
|
|
@@ -340,7 +340,7 @@ void rs600_pm_prepare(struct radeon_device *rdev)
|
|
|
|
void rs600_pm_finish(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *ddev = rdev->ddev;
|
|
+ struct drm_device *ddev = rdev_to_drm(rdev);
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
u32 tmp;
|
|
@@ -409,7 +409,7 @@ void rs600_hpd_set_polarity(struct radeon_device *rdev,
|
|
|
|
void rs600_hpd_init(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_connector *connector;
|
|
unsigned enable = 0;
|
|
|
|
@@ -436,7 +436,7 @@ void rs600_hpd_init(struct radeon_device *rdev)
|
|
|
|
void rs600_hpd_fini(struct radeon_device *rdev)
|
|
{
|
|
- struct drm_device *dev = rdev->ddev;
|
|
+ struct drm_device *dev = rdev_to_drm(rdev);
|
|
struct drm_connector *connector;
|
|
unsigned disable = 0;
|
|
|
|
@@ -798,7 +798,7 @@ int rs600_irq_process(struct radeon_device *rdev)
|
|
/* Vertical blank interrupts */
|
|
if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
|
|
if (rdev->irq.crtc_vblank_int[0]) {
|
|
- drm_handle_vblank(rdev->ddev, 0);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 0);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -807,7 +807,7 @@ int rs600_irq_process(struct radeon_device *rdev)
|
|
}
|
|
if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) {
|
|
if (rdev->irq.crtc_vblank_int[1]) {
|
|
- drm_handle_vblank(rdev->ddev, 1);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), 1);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -1134,7 +1134,7 @@ int rs600_init(struct radeon_device *rdev)
|
|
return -EINVAL;
|
|
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* initialize memory controller */
|
|
rs600_mc_init(rdev);
|
|
r100_debugfs_rbbm_init(rdev);
|
|
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
|
|
index 14fb0819b8c19c..016eb4992803dc 100644
|
|
--- a/drivers/gpu/drm/radeon/rs690.c
|
|
+++ b/drivers/gpu/drm/radeon/rs690.c
|
|
@@ -845,7 +845,7 @@ int rs690_init(struct radeon_device *rdev)
|
|
return -EINVAL;
|
|
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* initialize memory controller */
|
|
rs690_mc_init(rdev);
|
|
rv515_debugfs(rdev);
|
|
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
|
|
index 76260fdfbaa725..19a26d85e029c2 100644
|
|
--- a/drivers/gpu/drm/radeon/rv515.c
|
|
+++ b/drivers/gpu/drm/radeon/rv515.c
|
|
@@ -255,7 +255,7 @@ DEFINE_SHOW_ATTRIBUTE(rv515_debugfs_ga_info);
|
|
void rv515_debugfs(struct radeon_device *rdev)
|
|
{
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
- struct dentry *root = rdev->ddev->primary->debugfs_root;
|
|
+ struct dentry *root = rdev_to_drm(rdev)->primary->debugfs_root;
|
|
|
|
debugfs_create_file("rv515_pipes_info", 0444, root, rdev,
|
|
&rv515_debugfs_pipes_info_fops);
|
|
@@ -636,7 +636,7 @@ int rv515_init(struct radeon_device *rdev)
|
|
if (radeon_boot_test_post_card(rdev) == false)
|
|
return -EINVAL;
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* initialize AGP */
|
|
if (rdev->flags & RADEON_IS_AGP) {
|
|
r = radeon_agp_init(rdev);
|
|
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
|
|
index 9ce12fa3c35683..7d4b0bf591090a 100644
|
|
--- a/drivers/gpu/drm/radeon/rv770.c
|
|
+++ b/drivers/gpu/drm/radeon/rv770.c
|
|
@@ -1935,7 +1935,7 @@ int rv770_init(struct radeon_device *rdev)
|
|
/* Initialize surface registers */
|
|
radeon_surface_init(rdev);
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
/* Fence driver */
|
|
radeon_fence_driver_init(rdev);
|
|
/* initialize AGP */
|
|
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
|
|
index 85e9cba49cecb2..312fe76944a943 100644
|
|
--- a/drivers/gpu/drm/radeon/si.c
|
|
+++ b/drivers/gpu/drm/radeon/si.c
|
|
@@ -6296,7 +6296,7 @@ int si_irq_process(struct radeon_device *rdev)
|
|
event_name = "vblank";
|
|
|
|
if (rdev->irq.crtc_vblank_int[crtc_idx]) {
|
|
- drm_handle_vblank(rdev->ddev, crtc_idx);
|
|
+ drm_handle_vblank(rdev_to_drm(rdev), crtc_idx);
|
|
rdev->pm.vblank_sync = true;
|
|
wake_up(&rdev->irq.vblank_queue);
|
|
}
|
|
@@ -6858,7 +6858,7 @@ int si_init(struct radeon_device *rdev)
|
|
/* Initialize surface registers */
|
|
radeon_surface_init(rdev);
|
|
/* Initialize clocks */
|
|
- radeon_get_clock_info(rdev->ddev);
|
|
+ radeon_get_clock_info(rdev_to_drm(rdev));
|
|
|
|
/* Fence driver */
|
|
radeon_fence_driver_init(rdev);
|
|
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
|
|
index db0a1eb535328f..c59fcb4dca3249 100644
|
|
--- a/drivers/gpu/drm/sti/sti_cursor.c
|
|
+++ b/drivers/gpu/drm/sti/sti_cursor.c
|
|
@@ -200,6 +200,9 @@ static int sti_cursor_atomic_check(struct drm_plane *drm_plane,
|
|
return 0;
|
|
|
|
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
|
+ if (IS_ERR(crtc_state))
|
|
+ return PTR_ERR(crtc_state);
|
|
+
|
|
mode = &crtc_state->mode;
|
|
dst_x = new_plane_state->crtc_x;
|
|
dst_y = new_plane_state->crtc_y;
|
|
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
|
|
index 43c72c2604a0cd..f046f5f7ad259d 100644
|
|
--- a/drivers/gpu/drm/sti/sti_gdp.c
|
|
+++ b/drivers/gpu/drm/sti/sti_gdp.c
|
|
@@ -638,6 +638,9 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
|
|
|
|
mixer = to_sti_mixer(crtc);
|
|
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
|
+ if (IS_ERR(crtc_state))
|
|
+ return PTR_ERR(crtc_state);
|
|
+
|
|
mode = &crtc_state->mode;
|
|
dst_x = new_plane_state->crtc_x;
|
|
dst_y = new_plane_state->crtc_y;
|
|
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
|
|
index 0fb48ac044d8a0..abab92df78bd24 100644
|
|
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
|
|
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
|
|
@@ -1037,6 +1037,9 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane,
|
|
return 0;
|
|
|
|
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
|
+ if (IS_ERR(crtc_state))
|
|
+ return PTR_ERR(crtc_state);
|
|
+
|
|
mode = &crtc_state->mode;
|
|
dst_x = new_plane_state->crtc_x;
|
|
dst_y = new_plane_state->crtc_y;
|
|
diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c b/drivers/gpu/drm/v3d/v3d_mmu.c
|
|
index 5a453532901f15..166d4a88daee5b 100644
|
|
--- a/drivers/gpu/drm/v3d/v3d_mmu.c
|
|
+++ b/drivers/gpu/drm/v3d/v3d_mmu.c
|
|
@@ -34,32 +34,23 @@ static int v3d_mmu_flush_all(struct v3d_dev *v3d)
|
|
{
|
|
int ret;
|
|
|
|
- /* Make sure that another flush isn't already running when we
|
|
- * start this one.
|
|
- */
|
|
- ret = wait_for(!(V3D_READ(V3D_MMU_CTL) &
|
|
- V3D_MMU_CTL_TLB_CLEARING), 100);
|
|
- if (ret)
|
|
- dev_err(v3d->drm.dev, "TLB clear wait idle pre-wait failed\n");
|
|
-
|
|
- V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL) |
|
|
- V3D_MMU_CTL_TLB_CLEAR);
|
|
-
|
|
- V3D_WRITE(V3D_MMUC_CONTROL,
|
|
- V3D_MMUC_CONTROL_FLUSH |
|
|
+ V3D_WRITE(V3D_MMUC_CONTROL, V3D_MMUC_CONTROL_FLUSH |
|
|
V3D_MMUC_CONTROL_ENABLE);
|
|
|
|
- ret = wait_for(!(V3D_READ(V3D_MMU_CTL) &
|
|
- V3D_MMU_CTL_TLB_CLEARING), 100);
|
|
+ ret = wait_for(!(V3D_READ(V3D_MMUC_CONTROL) &
|
|
+ V3D_MMUC_CONTROL_FLUSHING), 100);
|
|
if (ret) {
|
|
- dev_err(v3d->drm.dev, "TLB clear wait idle failed\n");
|
|
+ dev_err(v3d->drm.dev, "MMUC flush wait idle failed\n");
|
|
return ret;
|
|
}
|
|
|
|
- ret = wait_for(!(V3D_READ(V3D_MMUC_CONTROL) &
|
|
- V3D_MMUC_CONTROL_FLUSHING), 100);
|
|
+ V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL) |
|
|
+ V3D_MMU_CTL_TLB_CLEAR);
|
|
+
|
|
+ ret = wait_for(!(V3D_READ(V3D_MMU_CTL) &
|
|
+ V3D_MMU_CTL_TLB_CLEARING), 100);
|
|
if (ret)
|
|
- dev_err(v3d->drm.dev, "MMUC flush wait idle failed\n");
|
|
+ dev_err(v3d->drm.dev, "MMU TLB clear wait idle failed\n");
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
|
|
index bf66499765fbb8..ac4ad95b364382 100644
|
|
--- a/drivers/gpu/drm/vc4/vc4_drv.h
|
|
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
|
|
@@ -314,6 +314,7 @@ struct vc4_hvs {
|
|
struct platform_device *pdev;
|
|
void __iomem *regs;
|
|
u32 __iomem *dlist;
|
|
+ unsigned int dlist_mem_size;
|
|
|
|
struct clk *core_clk;
|
|
|
|
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
index c6e986f71a26f8..d4487f4cb3034d 100644
|
|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
|
|
@@ -179,6 +179,8 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
|
|
if (!drm_dev_enter(drm, &idx))
|
|
return -ENODEV;
|
|
|
|
+ WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev));
|
|
+
|
|
drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
|
|
drm_print_regset32(&p, &vc4_hdmi->hd_regset);
|
|
drm_print_regset32(&p, &vc4_hdmi->cec_regset);
|
|
@@ -188,6 +190,8 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
|
|
drm_print_regset32(&p, &vc4_hdmi->ram_regset);
|
|
drm_print_regset32(&p, &vc4_hdmi->rm_regset);
|
|
|
|
+ pm_runtime_put(&vc4_hdmi->pdev->dev);
|
|
+
|
|
drm_dev_exit(idx);
|
|
|
|
return 0;
|
|
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
|
|
index 04af672caacb1b..008352166579ec 100644
|
|
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
|
|
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
|
|
@@ -110,7 +110,8 @@ static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data)
|
|
struct vc4_dev *vc4 = to_vc4_dev(dev);
|
|
struct vc4_hvs *hvs = vc4->hvs;
|
|
struct drm_printer p = drm_seq_file_printer(m);
|
|
- unsigned int next_entry_start = 0;
|
|
+ unsigned int dlist_mem_size = hvs->dlist_mem_size;
|
|
+ unsigned int next_entry_start;
|
|
unsigned int i, j;
|
|
u32 dlist_word, dispstat;
|
|
|
|
@@ -124,8 +125,9 @@ static int vc4_hvs_debugfs_dlist(struct seq_file *m, void *data)
|
|
}
|
|
|
|
drm_printf(&p, "HVS chan %u:\n", i);
|
|
+ next_entry_start = 0;
|
|
|
|
- for (j = HVS_READ(SCALER_DISPLISTX(i)); j < 256; j++) {
|
|
+ for (j = HVS_READ(SCALER_DISPLISTX(i)); j < dlist_mem_size; j++) {
|
|
dlist_word = readl((u32 __iomem *)vc4->hvs->dlist + j);
|
|
drm_printf(&p, "dlist: %02d: 0x%08x\n", j,
|
|
dlist_word);
|
|
@@ -222,6 +224,9 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs,
|
|
if (!drm_dev_enter(drm, &idx))
|
|
return;
|
|
|
|
+ if (hvs->vc4->is_vc5)
|
|
+ return;
|
|
+
|
|
/* The LUT memory is laid out with each HVS channel in order,
|
|
* each of which takes 256 writes for R, 256 for G, then 256
|
|
* for B.
|
|
@@ -415,13 +420,11 @@ void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan)
|
|
if (!drm_dev_enter(drm, &idx))
|
|
return;
|
|
|
|
- if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
|
|
+ if (!(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE))
|
|
goto out;
|
|
|
|
- HVS_WRITE(SCALER_DISPCTRLX(chan),
|
|
- HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
|
|
- HVS_WRITE(SCALER_DISPCTRLX(chan),
|
|
- HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE);
|
|
+ HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
|
|
+ HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
|
|
|
|
/* Once we leave, the scaler should be disabled and its fifo empty. */
|
|
WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
|
|
@@ -580,7 +583,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
|
|
}
|
|
|
|
if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED)
|
|
- return;
|
|
+ goto exit;
|
|
|
|
if (debug_dump_regs) {
|
|
DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
|
|
@@ -663,6 +666,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
|
|
vc4_hvs_dump_state(hvs);
|
|
}
|
|
|
|
+exit:
|
|
drm_dev_exit(idx);
|
|
}
|
|
|
|
@@ -800,9 +804,10 @@ struct vc4_hvs *__vc4_hvs_alloc(struct vc4_dev *vc4, struct platform_device *pde
|
|
* our 16K), since we don't want to scramble the screen when
|
|
* transitioning from the firmware's boot setup to runtime.
|
|
*/
|
|
+ hvs->dlist_mem_size = (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END;
|
|
drm_mm_init(&hvs->dlist_mm,
|
|
HVS_BOOTLOADER_DLIST_END,
|
|
- (SCALER_DLIST_SIZE >> 2) - HVS_BOOTLOADER_DLIST_END);
|
|
+ hvs->dlist_mem_size);
|
|
|
|
/* Set up the HVS LBM memory manager. We could have some more
|
|
* complicated data structure that allowed reuse of LBM areas
|
|
diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c
|
|
index 5ce70dd946aa63..24589b947dea3d 100644
|
|
--- a/drivers/gpu/drm/vkms/vkms_output.c
|
|
+++ b/drivers/gpu/drm/vkms/vkms_output.c
|
|
@@ -84,7 +84,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
|
|
DRM_MODE_CONNECTOR_VIRTUAL);
|
|
if (ret) {
|
|
DRM_ERROR("Failed to init connector\n");
|
|
- goto err_connector;
|
|
+ return ret;
|
|
}
|
|
|
|
drm_connector_helper_add(connector, &vkms_conn_helper_funcs);
|
|
@@ -119,8 +119,5 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
|
|
err_encoder:
|
|
drm_connector_cleanup(connector);
|
|
|
|
-err_connector:
|
|
- drm_crtc_cleanup(crtc);
|
|
-
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c
|
|
index 44d4a510ad7d68..079bd97da4fa67 100644
|
|
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.c
|
|
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
|
|
@@ -506,12 +506,12 @@ int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
|
|
if (ret)
|
|
return ret;
|
|
|
|
- drm_kms_helper_poll_init(drm);
|
|
-
|
|
ret = zynqmp_dpsub_kms_init(dpsub);
|
|
if (ret < 0)
|
|
goto err_poll_fini;
|
|
|
|
+ drm_kms_helper_poll_init(drm);
|
|
+
|
|
/* Reset all components and register the DRM device. */
|
|
drm_mode_config_reset(drm);
|
|
|
|
@@ -533,7 +533,7 @@ void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub)
|
|
{
|
|
struct drm_device *drm = &dpsub->drm->dev;
|
|
|
|
- drm_dev_unregister(drm);
|
|
+ drm_dev_unplug(drm);
|
|
drm_atomic_helper_shutdown(drm);
|
|
drm_encoder_cleanup(&dpsub->drm->encoder);
|
|
drm_kms_helper_poll_fini(drm);
|
|
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
|
|
index f33485d83d24ff..0fb210e40a4127 100644
|
|
--- a/drivers/hid/hid-hyperv.c
|
|
+++ b/drivers/hid/hid-hyperv.c
|
|
@@ -422,6 +422,25 @@ static int mousevsc_hid_raw_request(struct hid_device *hid,
|
|
return 0;
|
|
}
|
|
|
|
+static int mousevsc_hid_probe(struct hid_device *hid_dev, const struct hid_device_id *id)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = hid_parse(hid_dev);
|
|
+ if (ret) {
|
|
+ hid_err(hid_dev, "parse failed\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
|
|
+ if (ret) {
|
|
+ hid_err(hid_dev, "hw start failed\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static const struct hid_ll_driver mousevsc_ll_driver = {
|
|
.parse = mousevsc_hid_parse,
|
|
.open = mousevsc_hid_open,
|
|
@@ -431,7 +450,16 @@ static const struct hid_ll_driver mousevsc_ll_driver = {
|
|
.raw_request = mousevsc_hid_raw_request,
|
|
};
|
|
|
|
-static struct hid_driver mousevsc_hid_driver;
|
|
+static const struct hid_device_id mousevsc_devices[] = {
|
|
+ { HID_DEVICE(BUS_VIRTUAL, HID_GROUP_ANY, 0x045E, 0x0621) },
|
|
+ { }
|
|
+};
|
|
+
|
|
+static struct hid_driver mousevsc_hid_driver = {
|
|
+ .name = "hid-hyperv",
|
|
+ .id_table = mousevsc_devices,
|
|
+ .probe = mousevsc_hid_probe,
|
|
+};
|
|
|
|
static int mousevsc_probe(struct hv_device *device,
|
|
const struct hv_vmbus_device_id *dev_id)
|
|
@@ -473,7 +501,6 @@ static int mousevsc_probe(struct hv_device *device,
|
|
}
|
|
|
|
hid_dev->ll_driver = &mousevsc_ll_driver;
|
|
- hid_dev->driver = &mousevsc_hid_driver;
|
|
hid_dev->bus = BUS_VIRTUAL;
|
|
hid_dev->vendor = input_dev->hid_dev_info.vendor;
|
|
hid_dev->product = input_dev->hid_dev_info.product;
|
|
@@ -488,20 +515,6 @@ static int mousevsc_probe(struct hv_device *device,
|
|
if (ret)
|
|
goto probe_err2;
|
|
|
|
-
|
|
- ret = hid_parse(hid_dev);
|
|
- if (ret) {
|
|
- hid_err(hid_dev, "parse failed\n");
|
|
- goto probe_err2;
|
|
- }
|
|
-
|
|
- ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
|
|
-
|
|
- if (ret) {
|
|
- hid_err(hid_dev, "hw start failed\n");
|
|
- goto probe_err2;
|
|
- }
|
|
-
|
|
device_init_wakeup(&device->device, true);
|
|
|
|
input_dev->connected = true;
|
|
@@ -579,12 +592,23 @@ static struct hv_driver mousevsc_drv = {
|
|
|
|
static int __init mousevsc_init(void)
|
|
{
|
|
- return vmbus_driver_register(&mousevsc_drv);
|
|
+ int ret;
|
|
+
|
|
+ ret = hid_register_driver(&mousevsc_hid_driver);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = vmbus_driver_register(&mousevsc_drv);
|
|
+ if (ret)
|
|
+ hid_unregister_driver(&mousevsc_hid_driver);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static void __exit mousevsc_exit(void)
|
|
{
|
|
vmbus_driver_unregister(&mousevsc_drv);
|
|
+ hid_unregister_driver(&mousevsc_hid_driver);
|
|
}
|
|
|
|
MODULE_LICENSE("GPL");
|
|
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
|
|
index 18b5cd0234d213..33466c71c9da78 100644
|
|
--- a/drivers/hid/wacom_wac.c
|
|
+++ b/drivers/hid/wacom_wac.c
|
|
@@ -1399,9 +1399,9 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
|
|
rotation -= 1800;
|
|
|
|
input_report_abs(pen_input, ABS_TILT_X,
|
|
- (char)frame[7]);
|
|
+ (signed char)frame[7]);
|
|
input_report_abs(pen_input, ABS_TILT_Y,
|
|
- (char)frame[8]);
|
|
+ (signed char)frame[8]);
|
|
input_report_abs(pen_input, ABS_Z, rotation);
|
|
input_report_abs(pen_input, ABS_WHEEL,
|
|
get_unaligned_le16(&frame[11]));
|
|
diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c
|
|
index 8da7aa1614d7d1..16f6b7ba2a5def 100644
|
|
--- a/drivers/hwmon/nct6775-core.c
|
|
+++ b/drivers/hwmon/nct6775-core.c
|
|
@@ -2878,8 +2878,7 @@ store_target_temp(struct device *dev, struct device_attribute *attr,
|
|
if (err < 0)
|
|
return err;
|
|
|
|
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
|
|
- data->target_temp_mask);
|
|
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, data->target_temp_mask * 1000), 1000);
|
|
|
|
mutex_lock(&data->update_lock);
|
|
data->target_temp[nr] = val;
|
|
@@ -2959,7 +2958,7 @@ store_temp_tolerance(struct device *dev, struct device_attribute *attr,
|
|
return err;
|
|
|
|
/* Limit tolerance as needed */
|
|
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
|
|
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, data->tolerance_mask * 1000), 1000);
|
|
|
|
mutex_lock(&data->update_lock);
|
|
data->temp_tolerance[index][nr] = val;
|
|
@@ -3085,7 +3084,7 @@ store_weight_temp(struct device *dev, struct device_attribute *attr,
|
|
if (err < 0)
|
|
return err;
|
|
|
|
- val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
|
|
+ val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 255000), 1000);
|
|
|
|
mutex_lock(&data->update_lock);
|
|
data->weight_temp[index][nr] = val;
|
|
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
|
|
index 728c07c42651ce..019c5982ba564b 100644
|
|
--- a/drivers/hwmon/pmbus/pmbus_core.c
|
|
+++ b/drivers/hwmon/pmbus/pmbus_core.c
|
|
@@ -3199,7 +3199,17 @@ static int pmbus_regulator_notify(struct pmbus_data *data, int page, int event)
|
|
|
|
static int pmbus_write_smbalert_mask(struct i2c_client *client, u8 page, u8 reg, u8 val)
|
|
{
|
|
- return pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
|
|
+ int ret;
|
|
+
|
|
+ ret = _pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
|
|
+
|
|
+ /*
|
|
+ * Clear fault systematically in case writing PMBUS_SMBALERT_MASK
|
|
+ * is not supported by the chip.
|
|
+ */
|
|
+ pmbus_clear_fault_page(client, page);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
|
|
diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c
|
|
index d33ecbac00d6d9..cea34fb9ba5829 100644
|
|
--- a/drivers/hwmon/tps23861.c
|
|
+++ b/drivers/hwmon/tps23861.c
|
|
@@ -132,7 +132,7 @@ static int tps23861_read_temp(struct tps23861_data *data, long *val)
|
|
if (err < 0)
|
|
return err;
|
|
|
|
- *val = (regval * TEMPERATURE_LSB) - 20000;
|
|
+ *val = ((long)regval * TEMPERATURE_LSB) - 20000;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
|
|
index 678b30e90492ad..5d4f04a3c6d322 100644
|
|
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
|
|
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
|
|
@@ -99,6 +99,7 @@ struct lpi2c_imx_struct {
|
|
__u8 *rx_buf;
|
|
__u8 *tx_buf;
|
|
struct completion complete;
|
|
+ unsigned long rate_per;
|
|
unsigned int msglen;
|
|
unsigned int delivered;
|
|
unsigned int block_data;
|
|
@@ -207,9 +208,7 @@ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
|
|
|
|
lpi2c_imx_set_mode(lpi2c_imx);
|
|
|
|
- clk_rate = clk_get_rate(lpi2c_imx->clks[0].clk);
|
|
- if (!clk_rate)
|
|
- return -EINVAL;
|
|
+ clk_rate = lpi2c_imx->rate_per;
|
|
|
|
if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
|
|
filt = 0;
|
|
@@ -590,6 +589,11 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
|
|
if (ret)
|
|
return ret;
|
|
|
|
+ lpi2c_imx->rate_per = clk_get_rate(lpi2c_imx->clks[0].clk);
|
|
+ if (!lpi2c_imx->rate_per)
|
|
+ return dev_err_probe(&pdev->dev, -EINVAL,
|
|
+ "can't get I2C peripheral clock rate\n");
|
|
+
|
|
pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
|
|
pm_runtime_use_autosuspend(&pdev->dev);
|
|
pm_runtime_get_noresume(&pdev->dev);
|
|
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
|
|
index 0e9ff5500a7771..70d120dfb0908f 100644
|
|
--- a/drivers/i3c/master.c
|
|
+++ b/drivers/i3c/master.c
|
|
@@ -1293,7 +1293,7 @@ static void i3c_master_put_i3c_addrs(struct i3c_dev_desc *dev)
|
|
I3C_ADDR_SLOT_FREE);
|
|
|
|
if (dev->boardinfo && dev->boardinfo->init_dyn_addr)
|
|
- i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr,
|
|
+ i3c_bus_set_addr_slot_status(&master->bus, dev->boardinfo->init_dyn_addr,
|
|
I3C_ADDR_SLOT_FREE);
|
|
}
|
|
|
|
diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
|
|
index f344f8733f8324..dca266d9dd1220 100644
|
|
--- a/drivers/i3c/master/svc-i3c-master.c
|
|
+++ b/drivers/i3c/master/svc-i3c-master.c
|
|
@@ -1684,8 +1684,8 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
|
|
rpm_disable:
|
|
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
|
pm_runtime_put_noidle(&pdev->dev);
|
|
- pm_runtime_set_suspended(&pdev->dev);
|
|
pm_runtime_disable(&pdev->dev);
|
|
+ pm_runtime_set_suspended(&pdev->dev);
|
|
|
|
err_disable_clks:
|
|
svc_i3c_master_unprepare_clks(master);
|
|
diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c
|
|
index 971fc60efef01b..220465d9c713fe 100644
|
|
--- a/drivers/iio/accel/kionix-kx022a.c
|
|
+++ b/drivers/iio/accel/kionix-kx022a.c
|
|
@@ -475,7 +475,7 @@ static int kx022a_get_axis(struct kx022a_data *data,
|
|
if (ret)
|
|
return ret;
|
|
|
|
- *val = le16_to_cpu(data->buffer[0]);
|
|
+ *val = (s16)le16_to_cpu(data->buffer[0]);
|
|
|
|
return IIO_VAL_INT;
|
|
}
|
|
diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c
|
|
index a813fe04787c60..97b6774e7f5856 100644
|
|
--- a/drivers/iio/adc/ad7780.c
|
|
+++ b/drivers/iio/adc/ad7780.c
|
|
@@ -152,7 +152,7 @@ static int ad7780_write_raw(struct iio_dev *indio_dev,
|
|
|
|
switch (m) {
|
|
case IIO_CHAN_INFO_SCALE:
|
|
- if (val != 0)
|
|
+ if (val != 0 || val2 == 0)
|
|
return -EINVAL;
|
|
|
|
vref = st->int_vref_mv * 1000000LL;
|
|
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
|
|
index 9d6bf6d0927a4b..709ce2a5009779 100644
|
|
--- a/drivers/iio/adc/ad7923.c
|
|
+++ b/drivers/iio/adc/ad7923.c
|
|
@@ -48,7 +48,7 @@
|
|
|
|
struct ad7923_state {
|
|
struct spi_device *spi;
|
|
- struct spi_transfer ring_xfer[5];
|
|
+ struct spi_transfer ring_xfer[9];
|
|
struct spi_transfer scan_single_xfer[2];
|
|
struct spi_message ring_msg;
|
|
struct spi_message scan_single_msg;
|
|
@@ -64,7 +64,7 @@ struct ad7923_state {
|
|
* Length = 8 channels + 4 extra for 8 byte timestamp
|
|
*/
|
|
__be16 rx_buf[12] __aligned(IIO_DMA_MINALIGN);
|
|
- __be16 tx_buf[4];
|
|
+ __be16 tx_buf[8];
|
|
};
|
|
|
|
struct ad7923_chip_info {
|
|
diff --git a/drivers/iio/industrialio-gts-helper.c b/drivers/iio/industrialio-gts-helper.c
|
|
index 5f131bc1a01e97..291c0fc332c978 100644
|
|
--- a/drivers/iio/industrialio-gts-helper.c
|
|
+++ b/drivers/iio/industrialio-gts-helper.c
|
|
@@ -167,7 +167,7 @@ static int iio_gts_gain_cmp(const void *a, const void *b)
|
|
|
|
static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
|
|
{
|
|
- int ret, i, j, new_idx, time_idx;
|
|
+ int i, j, new_idx, time_idx, ret = 0;
|
|
int *all_gains;
|
|
size_t gain_bytes;
|
|
|
|
@@ -205,7 +205,7 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
|
|
memcpy(all_gains, gains[time_idx], gain_bytes);
|
|
new_idx = gts->num_hwgain;
|
|
|
|
- while (time_idx--) {
|
|
+ while (time_idx-- > 0) {
|
|
for (j = 0; j < gts->num_hwgain; j++) {
|
|
int candidate = gains[time_idx][j];
|
|
int chk;
|
|
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
|
|
index 80e1c45485c9b0..079e30c522bbd0 100644
|
|
--- a/drivers/iio/inkern.c
|
|
+++ b/drivers/iio/inkern.c
|
|
@@ -277,7 +277,7 @@ struct iio_channel *fwnode_iio_channel_get_by_name(struct fwnode_handle *fwnode,
|
|
return ERR_PTR(-ENODEV);
|
|
}
|
|
|
|
- chan = __fwnode_iio_channel_get_by_name(fwnode, name);
|
|
+ chan = __fwnode_iio_channel_get_by_name(parent, name);
|
|
if (!IS_ERR(chan) || PTR_ERR(chan) != -ENODEV) {
|
|
fwnode_handle_put(parent);
|
|
return chan;
|
|
diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c
|
|
index 8f0119f392b705..7d4053bfceea2f 100644
|
|
--- a/drivers/iio/light/al3010.c
|
|
+++ b/drivers/iio/light/al3010.c
|
|
@@ -87,7 +87,12 @@ static int al3010_init(struct al3010_data *data)
|
|
int ret;
|
|
|
|
ret = al3010_set_pwr(data->client, true);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
+ ret = devm_add_action_or_reset(&data->client->dev,
|
|
+ al3010_set_pwr_off,
|
|
+ data);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
@@ -190,12 +195,6 @@ static int al3010_probe(struct i2c_client *client)
|
|
return ret;
|
|
}
|
|
|
|
- ret = devm_add_action_or_reset(&client->dev,
|
|
- al3010_set_pwr_off,
|
|
- data);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
return devm_iio_device_register(&client->dev, indio_dev);
|
|
}
|
|
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
|
|
index f20da108fb2978..df589726060144 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
|
|
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
|
|
@@ -3559,7 +3559,7 @@ static void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *gsi_sqp,
|
|
wc->byte_len = orig_cqe->length;
|
|
wc->qp = &gsi_qp->ib_qp;
|
|
|
|
- wc->ex.imm_data = cpu_to_be32(le32_to_cpu(orig_cqe->immdata));
|
|
+ wc->ex.imm_data = cpu_to_be32(orig_cqe->immdata);
|
|
wc->src_qp = orig_cqe->src_qp;
|
|
memcpy(wc->smac, orig_cqe->smac, ETH_ALEN);
|
|
if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) {
|
|
@@ -3704,7 +3704,10 @@ int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
|
|
(unsigned long)(cqe->qp_handle),
|
|
struct bnxt_re_qp, qplib_qp);
|
|
wc->qp = &qp->ib_qp;
|
|
- wc->ex.imm_data = cpu_to_be32(le32_to_cpu(cqe->immdata));
|
|
+ if (cqe->flags & CQ_RES_RC_FLAGS_IMM)
|
|
+ wc->ex.imm_data = cpu_to_be32(cqe->immdata);
|
|
+ else
|
|
+ wc->ex.invalidate_rkey = cqe->invrkey;
|
|
wc->src_qp = cqe->src_qp;
|
|
memcpy(wc->smac, cqe->smac, ETH_ALEN);
|
|
wc->port_num = 1;
|
|
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
|
|
index 56ddff96b5083b..5d4c49089a20f4 100644
|
|
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
|
|
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
|
|
@@ -389,7 +389,7 @@ struct bnxt_qplib_cqe {
|
|
u16 cfa_meta;
|
|
u64 wr_id;
|
|
union {
|
|
- __le32 immdata;
|
|
+ u32 immdata;
|
|
u32 invrkey;
|
|
};
|
|
u64 qp_handle;
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c
|
|
index ff177466de9b49..9b91731a620795 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_cq.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_cq.c
|
|
@@ -180,8 +180,8 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
|
|
ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_CQC,
|
|
hr_cq->cqn);
|
|
if (ret)
|
|
- dev_err(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ret,
|
|
- hr_cq->cqn);
|
|
+ dev_err_ratelimited(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n",
|
|
+ ret, hr_cq->cqn);
|
|
|
|
xa_erase_irq(&cq_table->array, hr_cq->cqn);
|
|
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
|
|
index cd593d651e4caf..21ef00fdb65631 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
|
|
@@ -1236,6 +1236,7 @@ void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn);
|
|
void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type);
|
|
void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp);
|
|
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type);
|
|
+void hns_roce_flush_cqe(struct hns_roce_dev *hr_dev, u32 qpn);
|
|
void hns_roce_srq_event(struct hns_roce_dev *hr_dev, u32 srqn, int event_type);
|
|
void hns_roce_handle_device_err(struct hns_roce_dev *hr_dev);
|
|
int hns_roce_init(struct hns_roce_dev *hr_dev);
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c
|
|
index 7ebf80504fd125..0ab514c49d5e6e 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_hem.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_hem.c
|
|
@@ -337,7 +337,7 @@ static int calc_hem_config(struct hns_roce_dev *hr_dev,
|
|
struct hns_roce_hem_mhop *mhop,
|
|
struct hns_roce_hem_index *index)
|
|
{
|
|
- struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
+ struct device *dev = hr_dev->dev;
|
|
unsigned long mhop_obj = obj;
|
|
u32 l0_idx, l1_idx, l2_idx;
|
|
u32 chunk_ba_num;
|
|
@@ -368,14 +368,14 @@ static int calc_hem_config(struct hns_roce_dev *hr_dev,
|
|
index->buf = l0_idx;
|
|
break;
|
|
default:
|
|
- ibdev_err(ibdev, "table %u not support mhop.hop_num = %u!\n",
|
|
- table->type, mhop->hop_num);
|
|
+ dev_err(dev, "table %u not support mhop.hop_num = %u!\n",
|
|
+ table->type, mhop->hop_num);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (unlikely(index->buf >= table->num_hem)) {
|
|
- ibdev_err(ibdev, "table %u exceed hem limt idx %llu, max %lu!\n",
|
|
- table->type, index->buf, table->num_hem);
|
|
+ dev_err(dev, "table %u exceed hem limt idx %llu, max %lu!\n",
|
|
+ table->type, index->buf, table->num_hem);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -487,14 +487,14 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev,
|
|
struct hns_roce_hem_mhop *mhop,
|
|
struct hns_roce_hem_index *index)
|
|
{
|
|
- struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
+ struct device *dev = hr_dev->dev;
|
|
u32 step_idx;
|
|
int ret = 0;
|
|
|
|
if (index->inited & HEM_INDEX_L0) {
|
|
ret = hr_dev->hw->set_hem(hr_dev, table, obj, 0);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "set HEM step 0 failed!\n");
|
|
+ dev_err(dev, "set HEM step 0 failed!\n");
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -502,7 +502,7 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev,
|
|
if (index->inited & HEM_INDEX_L1) {
|
|
ret = hr_dev->hw->set_hem(hr_dev, table, obj, 1);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "set HEM step 1 failed!\n");
|
|
+ dev_err(dev, "set HEM step 1 failed!\n");
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -514,7 +514,7 @@ static int set_mhop_hem(struct hns_roce_dev *hr_dev,
|
|
step_idx = mhop->hop_num;
|
|
ret = hr_dev->hw->set_hem(hr_dev, table, obj, step_idx);
|
|
if (ret)
|
|
- ibdev_err(ibdev, "set HEM step last failed!\n");
|
|
+ dev_err(dev, "set HEM step last failed!\n");
|
|
}
|
|
out:
|
|
return ret;
|
|
@@ -524,14 +524,14 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
|
|
struct hns_roce_hem_table *table,
|
|
unsigned long obj)
|
|
{
|
|
- struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
struct hns_roce_hem_index index = {};
|
|
struct hns_roce_hem_mhop mhop = {};
|
|
+ struct device *dev = hr_dev->dev;
|
|
int ret;
|
|
|
|
ret = calc_hem_config(hr_dev, table, obj, &mhop, &index);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "calc hem config failed!\n");
|
|
+ dev_err(dev, "calc hem config failed!\n");
|
|
return ret;
|
|
}
|
|
|
|
@@ -543,7 +543,7 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
|
|
|
|
ret = alloc_mhop_hem(hr_dev, table, &mhop, &index);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "alloc mhop hem failed!\n");
|
|
+ dev_err(dev, "alloc mhop hem failed!\n");
|
|
goto out;
|
|
}
|
|
|
|
@@ -551,7 +551,7 @@ static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
|
|
if (table->type < HEM_TYPE_MTT) {
|
|
ret = set_mhop_hem(hr_dev, table, obj, &mhop, &index);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "set HEM address to HW failed!\n");
|
|
+ dev_err(dev, "set HEM address to HW failed!\n");
|
|
goto err_alloc;
|
|
}
|
|
}
|
|
@@ -615,7 +615,7 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev,
|
|
struct hns_roce_hem_mhop *mhop,
|
|
struct hns_roce_hem_index *index)
|
|
{
|
|
- struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
+ struct device *dev = hr_dev->dev;
|
|
u32 hop_num = mhop->hop_num;
|
|
u32 chunk_ba_num;
|
|
u32 step_idx;
|
|
@@ -645,21 +645,21 @@ static void clear_mhop_hem(struct hns_roce_dev *hr_dev,
|
|
|
|
ret = hr_dev->hw->clear_hem(hr_dev, table, obj, step_idx);
|
|
if (ret)
|
|
- ibdev_warn(ibdev, "failed to clear hop%u HEM, ret = %d.\n",
|
|
- hop_num, ret);
|
|
+ dev_warn(dev, "failed to clear hop%u HEM, ret = %d.\n",
|
|
+ hop_num, ret);
|
|
|
|
if (index->inited & HEM_INDEX_L1) {
|
|
ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 1);
|
|
if (ret)
|
|
- ibdev_warn(ibdev, "failed to clear HEM step 1, ret = %d.\n",
|
|
- ret);
|
|
+ dev_warn(dev, "failed to clear HEM step 1, ret = %d.\n",
|
|
+ ret);
|
|
}
|
|
|
|
if (index->inited & HEM_INDEX_L0) {
|
|
ret = hr_dev->hw->clear_hem(hr_dev, table, obj, 0);
|
|
if (ret)
|
|
- ibdev_warn(ibdev, "failed to clear HEM step 0, ret = %d.\n",
|
|
- ret);
|
|
+ dev_warn(dev, "failed to clear HEM step 0, ret = %d.\n",
|
|
+ ret);
|
|
}
|
|
}
|
|
}
|
|
@@ -669,14 +669,14 @@ static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev,
|
|
unsigned long obj,
|
|
int check_refcount)
|
|
{
|
|
- struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
struct hns_roce_hem_index index = {};
|
|
struct hns_roce_hem_mhop mhop = {};
|
|
+ struct device *dev = hr_dev->dev;
|
|
int ret;
|
|
|
|
ret = calc_hem_config(hr_dev, table, obj, &mhop, &index);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "calc hem config failed!\n");
|
|
+ dev_err(dev, "calc hem config failed!\n");
|
|
return;
|
|
}
|
|
|
|
@@ -712,8 +712,8 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev,
|
|
|
|
ret = hr_dev->hw->clear_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT);
|
|
if (ret)
|
|
- dev_warn(dev, "failed to clear HEM base address, ret = %d.\n",
|
|
- ret);
|
|
+ dev_warn_ratelimited(dev, "failed to clear HEM base address, ret = %d.\n",
|
|
+ ret);
|
|
|
|
hns_roce_free_hem(hr_dev, table->hem[i]);
|
|
table->hem[i] = NULL;
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
|
|
index 8066750afab908..2824d390ec3161 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
|
|
@@ -372,19 +372,12 @@ static int set_rwqe_data_seg(struct ib_qp *ibqp, const struct ib_send_wr *wr,
|
|
static int check_send_valid(struct hns_roce_dev *hr_dev,
|
|
struct hns_roce_qp *hr_qp)
|
|
{
|
|
- struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
-
|
|
if (unlikely(hr_qp->state == IB_QPS_RESET ||
|
|
hr_qp->state == IB_QPS_INIT ||
|
|
- hr_qp->state == IB_QPS_RTR)) {
|
|
- ibdev_err(ibdev, "failed to post WQE, QP state %u!\n",
|
|
- hr_qp->state);
|
|
+ hr_qp->state == IB_QPS_RTR))
|
|
return -EINVAL;
|
|
- } else if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)) {
|
|
- ibdev_err(ibdev, "failed to post WQE, dev state %d!\n",
|
|
- hr_dev->state);
|
|
+ else if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN))
|
|
return -EIO;
|
|
- }
|
|
|
|
return 0;
|
|
}
|
|
@@ -585,7 +578,7 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp,
|
|
if (WARN_ON(ret))
|
|
return ret;
|
|
|
|
- hr_reg_write(rc_sq_wqe, RC_SEND_WQE_FENCE,
|
|
+ hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SO,
|
|
(wr->send_flags & IB_SEND_FENCE) ? 1 : 0);
|
|
|
|
hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SE,
|
|
@@ -2737,8 +2730,8 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev,
|
|
ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_INIT,
|
|
IB_QPS_INIT, NULL);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "failed to modify qp to init, ret = %d.\n",
|
|
- ret);
|
|
+ ibdev_err_ratelimited(ibdev, "failed to modify qp to init, ret = %d.\n",
|
|
+ ret);
|
|
return ret;
|
|
}
|
|
|
|
@@ -3384,8 +3377,8 @@ static int free_mr_post_send_lp_wqe(struct hns_roce_qp *hr_qp)
|
|
|
|
ret = hns_roce_v2_post_send(&hr_qp->ibqp, send_wr, &bad_wr);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "failed to post wqe for free mr, ret = %d.\n",
|
|
- ret);
|
|
+ ibdev_err_ratelimited(ibdev, "failed to post wqe for free mr, ret = %d.\n",
|
|
+ ret);
|
|
return ret;
|
|
}
|
|
|
|
@@ -3424,9 +3417,9 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev)
|
|
|
|
ret = free_mr_post_send_lp_wqe(hr_qp);
|
|
if (ret) {
|
|
- ibdev_err(ibdev,
|
|
- "failed to send wqe (qp:0x%lx) for free mr, ret = %d.\n",
|
|
- hr_qp->qpn, ret);
|
|
+ ibdev_err_ratelimited(ibdev,
|
|
+ "failed to send wqe (qp:0x%lx) for free mr, ret = %d.\n",
|
|
+ hr_qp->qpn, ret);
|
|
break;
|
|
}
|
|
|
|
@@ -3437,16 +3430,16 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev)
|
|
while (cqe_cnt) {
|
|
npolled = hns_roce_v2_poll_cq(&free_mr->rsv_cq->ib_cq, cqe_cnt, wc);
|
|
if (npolled < 0) {
|
|
- ibdev_err(ibdev,
|
|
- "failed to poll cqe for free mr, remain %d cqe.\n",
|
|
- cqe_cnt);
|
|
+ ibdev_err_ratelimited(ibdev,
|
|
+ "failed to poll cqe for free mr, remain %d cqe.\n",
|
|
+ cqe_cnt);
|
|
goto out;
|
|
}
|
|
|
|
if (time_after(jiffies, end)) {
|
|
- ibdev_err(ibdev,
|
|
- "failed to poll cqe for free mr and timeout, remain %d cqe.\n",
|
|
- cqe_cnt);
|
|
+ ibdev_err_ratelimited(ibdev,
|
|
+ "failed to poll cqe for free mr and timeout, remain %d cqe.\n",
|
|
+ cqe_cnt);
|
|
goto out;
|
|
}
|
|
cqe_cnt -= npolled;
|
|
@@ -4986,10 +4979,8 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp,
|
|
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
|
|
int ret = 0;
|
|
|
|
- if (!check_qp_state(cur_state, new_state)) {
|
|
- ibdev_err(&hr_dev->ib_dev, "Illegal state for QP!\n");
|
|
+ if (!check_qp_state(cur_state, new_state))
|
|
return -EINVAL;
|
|
- }
|
|
|
|
if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
|
|
memset(qpc_mask, 0, hr_dev->caps.qpc_sz);
|
|
@@ -5251,7 +5242,7 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
|
|
/* SW pass context to HW */
|
|
ret = hns_roce_v2_qp_modify(hr_dev, context, qpc_mask, hr_qp);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "failed to modify QP, ret = %d.\n", ret);
|
|
+ ibdev_err_ratelimited(ibdev, "failed to modify QP, ret = %d.\n", ret);
|
|
goto out;
|
|
}
|
|
|
|
@@ -5341,7 +5332,9 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
|
|
|
ret = hns_roce_v2_query_qpc(hr_dev, hr_qp->qpn, &context);
|
|
if (ret) {
|
|
- ibdev_err(ibdev, "failed to query QPC, ret = %d.\n", ret);
|
|
+ ibdev_err_ratelimited(ibdev,
|
|
+ "failed to query QPC, ret = %d.\n",
|
|
+ ret);
|
|
ret = -EINVAL;
|
|
goto out;
|
|
}
|
|
@@ -5349,7 +5342,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
|
|
state = hr_reg_read(&context, QPC_QP_ST);
|
|
tmp_qp_state = to_ib_qp_st((enum hns_roce_v2_qp_state)state);
|
|
if (tmp_qp_state == -1) {
|
|
- ibdev_err(ibdev, "Illegal ib_qp_state\n");
|
|
+ ibdev_err_ratelimited(ibdev, "Illegal ib_qp_state\n");
|
|
ret = -EINVAL;
|
|
goto out;
|
|
}
|
|
@@ -5442,9 +5435,9 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev,
|
|
ret = hns_roce_v2_modify_qp(&hr_qp->ibqp, NULL, 0,
|
|
hr_qp->state, IB_QPS_RESET, udata);
|
|
if (ret)
|
|
- ibdev_err(ibdev,
|
|
- "failed to modify QP to RST, ret = %d.\n",
|
|
- ret);
|
|
+ ibdev_err_ratelimited(ibdev,
|
|
+ "failed to modify QP to RST, ret = %d.\n",
|
|
+ ret);
|
|
}
|
|
|
|
send_cq = hr_qp->ibqp.send_cq ? to_hr_cq(hr_qp->ibqp.send_cq) : NULL;
|
|
@@ -5480,9 +5473,9 @@ int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
|
|
|
|
ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata);
|
|
if (ret)
|
|
- ibdev_err(&hr_dev->ib_dev,
|
|
- "failed to destroy QP, QPN = 0x%06lx, ret = %d.\n",
|
|
- hr_qp->qpn, ret);
|
|
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
|
|
+ "failed to destroy QP, QPN = 0x%06lx, ret = %d.\n",
|
|
+ hr_qp->qpn, ret);
|
|
|
|
hns_roce_qp_destroy(hr_dev, hr_qp, udata);
|
|
|
|
@@ -5755,9 +5748,9 @@ static int hns_roce_v2_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
|
|
HNS_ROCE_CMD_MODIFY_CQC, hr_cq->cqn);
|
|
hns_roce_free_cmd_mailbox(hr_dev, mailbox);
|
|
if (ret)
|
|
- ibdev_err(&hr_dev->ib_dev,
|
|
- "failed to process cmd when modifying CQ, ret = %d.\n",
|
|
- ret);
|
|
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
|
|
+ "failed to process cmd when modifying CQ, ret = %d.\n",
|
|
+ ret);
|
|
|
|
return ret;
|
|
}
|
|
@@ -5777,9 +5770,9 @@ static int hns_roce_v2_query_cqc(struct hns_roce_dev *hr_dev, u32 cqn,
|
|
ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma,
|
|
HNS_ROCE_CMD_QUERY_CQC, cqn);
|
|
if (ret) {
|
|
- ibdev_err(&hr_dev->ib_dev,
|
|
- "failed to process cmd when querying CQ, ret = %d.\n",
|
|
- ret);
|
|
+ ibdev_err_ratelimited(&hr_dev->ib_dev,
|
|
+ "failed to process cmd when querying CQ, ret = %d.\n",
|
|
+ ret);
|
|
goto err_mailbox;
|
|
}
|
|
|
|
@@ -5820,11 +5813,10 @@ static int hns_roce_v2_query_mpt(struct hns_roce_dev *hr_dev, u32 key,
|
|
return ret;
|
|
}
|
|
|
|
-static void hns_roce_irq_work_handle(struct work_struct *work)
|
|
+static void dump_aeqe_log(struct hns_roce_work *irq_work)
|
|
{
|
|
- struct hns_roce_work *irq_work =
|
|
- container_of(work, struct hns_roce_work, work);
|
|
- struct ib_device *ibdev = &irq_work->hr_dev->ib_dev;
|
|
+ struct hns_roce_dev *hr_dev = irq_work->hr_dev;
|
|
+ struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
|
|
switch (irq_work->event_type) {
|
|
case HNS_ROCE_EVENT_TYPE_PATH_MIG:
|
|
@@ -5868,6 +5860,8 @@ static void hns_roce_irq_work_handle(struct work_struct *work)
|
|
case HNS_ROCE_EVENT_TYPE_DB_OVERFLOW:
|
|
ibdev_warn(ibdev, "DB overflow.\n");
|
|
break;
|
|
+ case HNS_ROCE_EVENT_TYPE_MB:
|
|
+ break;
|
|
case HNS_ROCE_EVENT_TYPE_FLR:
|
|
ibdev_warn(ibdev, "function level reset.\n");
|
|
break;
|
|
@@ -5877,10 +5871,48 @@ static void hns_roce_irq_work_handle(struct work_struct *work)
|
|
case HNS_ROCE_EVENT_TYPE_INVALID_XRCETH:
|
|
ibdev_err(ibdev, "invalid xrceth error.\n");
|
|
break;
|
|
+ default:
|
|
+ ibdev_info(ibdev, "Undefined event %d.\n",
|
|
+ irq_work->event_type);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void hns_roce_irq_work_handle(struct work_struct *work)
|
|
+{
|
|
+ struct hns_roce_work *irq_work =
|
|
+ container_of(work, struct hns_roce_work, work);
|
|
+ struct hns_roce_dev *hr_dev = irq_work->hr_dev;
|
|
+ int event_type = irq_work->event_type;
|
|
+ u32 queue_num = irq_work->queue_num;
|
|
+
|
|
+ switch (event_type) {
|
|
+ case HNS_ROCE_EVENT_TYPE_PATH_MIG:
|
|
+ case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED:
|
|
+ case HNS_ROCE_EVENT_TYPE_COMM_EST:
|
|
+ case HNS_ROCE_EVENT_TYPE_SQ_DRAINED:
|
|
+ case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR:
|
|
+ case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH:
|
|
+ case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR:
|
|
+ case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR:
|
|
+ case HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION:
|
|
+ case HNS_ROCE_EVENT_TYPE_INVALID_XRCETH:
|
|
+ hns_roce_qp_event(hr_dev, queue_num, event_type);
|
|
+ break;
|
|
+ case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH:
|
|
+ case HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR:
|
|
+ hns_roce_srq_event(hr_dev, queue_num, event_type);
|
|
+ break;
|
|
+ case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR:
|
|
+ case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW:
|
|
+ hns_roce_cq_event(hr_dev, queue_num, event_type);
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
+ dump_aeqe_log(irq_work);
|
|
+
|
|
kfree(irq_work);
|
|
}
|
|
|
|
@@ -5940,14 +5972,14 @@ static struct hns_roce_aeqe *next_aeqe_sw_v2(struct hns_roce_eq *eq)
|
|
static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev,
|
|
struct hns_roce_eq *eq)
|
|
{
|
|
- struct device *dev = hr_dev->dev;
|
|
struct hns_roce_aeqe *aeqe = next_aeqe_sw_v2(eq);
|
|
irqreturn_t aeqe_found = IRQ_NONE;
|
|
+ int num_aeqes = 0;
|
|
int event_type;
|
|
u32 queue_num;
|
|
int sub_type;
|
|
|
|
- while (aeqe) {
|
|
+ while (aeqe && num_aeqes < HNS_AEQ_POLLING_BUDGET) {
|
|
/* Make sure we read AEQ entry after we have checked the
|
|
* ownership bit
|
|
*/
|
|
@@ -5958,25 +5990,12 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev,
|
|
queue_num = hr_reg_read(aeqe, AEQE_EVENT_QUEUE_NUM);
|
|
|
|
switch (event_type) {
|
|
- case HNS_ROCE_EVENT_TYPE_PATH_MIG:
|
|
- case HNS_ROCE_EVENT_TYPE_PATH_MIG_FAILED:
|
|
- case HNS_ROCE_EVENT_TYPE_COMM_EST:
|
|
- case HNS_ROCE_EVENT_TYPE_SQ_DRAINED:
|
|
case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR:
|
|
- case HNS_ROCE_EVENT_TYPE_SRQ_LAST_WQE_REACH:
|
|
case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR:
|
|
case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR:
|
|
case HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION:
|
|
case HNS_ROCE_EVENT_TYPE_INVALID_XRCETH:
|
|
- hns_roce_qp_event(hr_dev, queue_num, event_type);
|
|
- break;
|
|
- case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH:
|
|
- case HNS_ROCE_EVENT_TYPE_SRQ_CATAS_ERROR:
|
|
- hns_roce_srq_event(hr_dev, queue_num, event_type);
|
|
- break;
|
|
- case HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR:
|
|
- case HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW:
|
|
- hns_roce_cq_event(hr_dev, queue_num, event_type);
|
|
+ hns_roce_flush_cqe(hr_dev, queue_num);
|
|
break;
|
|
case HNS_ROCE_EVENT_TYPE_MB:
|
|
hns_roce_cmd_event(hr_dev,
|
|
@@ -5984,12 +6003,7 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev,
|
|
aeqe->event.cmd.status,
|
|
le64_to_cpu(aeqe->event.cmd.out_param));
|
|
break;
|
|
- case HNS_ROCE_EVENT_TYPE_DB_OVERFLOW:
|
|
- case HNS_ROCE_EVENT_TYPE_FLR:
|
|
- break;
|
|
default:
|
|
- dev_err(dev, "unhandled event %d on EQ %d at idx %u.\n",
|
|
- event_type, eq->eqn, eq->cons_index);
|
|
break;
|
|
}
|
|
|
|
@@ -6001,6 +6015,7 @@ static irqreturn_t hns_roce_v2_aeq_int(struct hns_roce_dev *hr_dev,
|
|
hns_roce_v2_init_irq_work(hr_dev, eq, queue_num);
|
|
|
|
aeqe = next_aeqe_sw_v2(eq);
|
|
+ ++num_aeqes;
|
|
}
|
|
|
|
update_eq_db(eq);
|
|
@@ -6530,6 +6545,9 @@ static int hns_roce_v2_init_eq_table(struct hns_roce_dev *hr_dev)
|
|
int ret;
|
|
int i;
|
|
|
|
+ if (hr_dev->caps.aeqe_depth < HNS_AEQ_POLLING_BUDGET)
|
|
+ return -EINVAL;
|
|
+
|
|
other_num = hr_dev->caps.num_other_vectors;
|
|
comp_num = hr_dev->caps.num_comp_vectors;
|
|
aeq_num = hr_dev->caps.num_aeq_vectors;
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
|
|
index cd97cbee682a6a..b8e17721f6fdea 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
|
|
@@ -85,6 +85,11 @@
|
|
|
|
#define HNS_ROCE_V2_TABLE_CHUNK_SIZE (1 << 18)
|
|
|
|
+/* budget must be smaller than aeqe_depth to guarantee that we update
|
|
+ * the ci before we polled all the entries in the EQ.
|
|
+ */
|
|
+#define HNS_AEQ_POLLING_BUDGET 64
|
|
+
|
|
enum {
|
|
HNS_ROCE_CMD_FLAG_IN = BIT(0),
|
|
HNS_ROCE_CMD_FLAG_OUT = BIT(1),
|
|
@@ -894,6 +899,7 @@ struct hns_roce_v2_rc_send_wqe {
|
|
#define RC_SEND_WQE_OWNER RC_SEND_WQE_FIELD_LOC(7, 7)
|
|
#define RC_SEND_WQE_CQE RC_SEND_WQE_FIELD_LOC(8, 8)
|
|
#define RC_SEND_WQE_FENCE RC_SEND_WQE_FIELD_LOC(9, 9)
|
|
+#define RC_SEND_WQE_SO RC_SEND_WQE_FIELD_LOC(10, 10)
|
|
#define RC_SEND_WQE_SE RC_SEND_WQE_FIELD_LOC(11, 11)
|
|
#define RC_SEND_WQE_INLINE RC_SEND_WQE_FIELD_LOC(12, 12)
|
|
#define RC_SEND_WQE_WQE_INDEX RC_SEND_WQE_FIELD_LOC(30, 15)
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c
|
|
index 980261969b0c0a..7f29a55d378f02 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
|
|
@@ -130,8 +130,8 @@ static void hns_roce_mr_free(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr
|
|
key_to_hw_index(mr->key) &
|
|
(hr_dev->caps.num_mtpts - 1));
|
|
if (ret)
|
|
- ibdev_warn(ibdev, "failed to destroy mpt, ret = %d.\n",
|
|
- ret);
|
|
+ ibdev_warn_ratelimited(ibdev, "failed to destroy mpt, ret = %d.\n",
|
|
+ ret);
|
|
}
|
|
|
|
free_mr_pbl(hr_dev, mr);
|
|
@@ -415,15 +415,16 @@ static int hns_roce_set_page(struct ib_mr *ibmr, u64 addr)
|
|
}
|
|
|
|
int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
|
|
- unsigned int *sg_offset)
|
|
+ unsigned int *sg_offset_p)
|
|
{
|
|
+ unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
|
|
struct hns_roce_dev *hr_dev = to_hr_dev(ibmr->device);
|
|
struct ib_device *ibdev = &hr_dev->ib_dev;
|
|
struct hns_roce_mr *mr = to_hr_mr(ibmr);
|
|
struct hns_roce_mtr *mtr = &mr->pbl_mtr;
|
|
int ret, sg_num = 0;
|
|
|
|
- if (!IS_ALIGNED(*sg_offset, HNS_ROCE_FRMR_ALIGN_SIZE) ||
|
|
+ if (!IS_ALIGNED(sg_offset, HNS_ROCE_FRMR_ALIGN_SIZE) ||
|
|
ibmr->page_size < HNS_HW_PAGE_SIZE ||
|
|
ibmr->page_size > HNS_HW_MAX_PAGE_SIZE)
|
|
return sg_num;
|
|
@@ -434,7 +435,7 @@ int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
|
|
if (!mr->page_list)
|
|
return sg_num;
|
|
|
|
- sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, hns_roce_set_page);
|
|
+ sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset_p, hns_roce_set_page);
|
|
if (sg_num < 1) {
|
|
ibdev_err(ibdev, "failed to store sg pages %u %u, cnt = %d.\n",
|
|
mr->npages, mr->pbl_mtr.hem_cfg.buf_pg_count, sg_num);
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
|
|
index 04063cfacae5fc..88a4777d29f8b8 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
|
|
@@ -39,6 +39,25 @@
|
|
#include "hns_roce_device.h"
|
|
#include "hns_roce_hem.h"
|
|
|
|
+static struct hns_roce_qp *hns_roce_qp_lookup(struct hns_roce_dev *hr_dev,
|
|
+ u32 qpn)
|
|
+{
|
|
+ struct device *dev = hr_dev->dev;
|
|
+ struct hns_roce_qp *qp;
|
|
+ unsigned long flags;
|
|
+
|
|
+ xa_lock_irqsave(&hr_dev->qp_table_xa, flags);
|
|
+ qp = __hns_roce_qp_lookup(hr_dev, qpn);
|
|
+ if (qp)
|
|
+ refcount_inc(&qp->refcount);
|
|
+ xa_unlock_irqrestore(&hr_dev->qp_table_xa, flags);
|
|
+
|
|
+ if (!qp)
|
|
+ dev_warn(dev, "async event for bogus QP %08x\n", qpn);
|
|
+
|
|
+ return qp;
|
|
+}
|
|
+
|
|
static void flush_work_handle(struct work_struct *work)
|
|
{
|
|
struct hns_roce_work *flush_work = container_of(work,
|
|
@@ -95,31 +114,28 @@ void flush_cqe(struct hns_roce_dev *dev, struct hns_roce_qp *qp)
|
|
|
|
void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
|
|
{
|
|
- struct device *dev = hr_dev->dev;
|
|
struct hns_roce_qp *qp;
|
|
|
|
- xa_lock(&hr_dev->qp_table_xa);
|
|
- qp = __hns_roce_qp_lookup(hr_dev, qpn);
|
|
- if (qp)
|
|
- refcount_inc(&qp->refcount);
|
|
- xa_unlock(&hr_dev->qp_table_xa);
|
|
-
|
|
- if (!qp) {
|
|
- dev_warn(dev, "async event for bogus QP %08x\n", qpn);
|
|
+ qp = hns_roce_qp_lookup(hr_dev, qpn);
|
|
+ if (!qp)
|
|
return;
|
|
- }
|
|
|
|
- if (event_type == HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR ||
|
|
- event_type == HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR ||
|
|
- event_type == HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR ||
|
|
- event_type == HNS_ROCE_EVENT_TYPE_XRCD_VIOLATION ||
|
|
- event_type == HNS_ROCE_EVENT_TYPE_INVALID_XRCETH) {
|
|
- qp->state = IB_QPS_ERR;
|
|
+ qp->event(qp, (enum hns_roce_event)event_type);
|
|
|
|
- flush_cqe(hr_dev, qp);
|
|
- }
|
|
+ if (refcount_dec_and_test(&qp->refcount))
|
|
+ complete(&qp->free);
|
|
+}
|
|
|
|
- qp->event(qp, (enum hns_roce_event)event_type);
|
|
+void hns_roce_flush_cqe(struct hns_roce_dev *hr_dev, u32 qpn)
|
|
+{
|
|
+ struct hns_roce_qp *qp;
|
|
+
|
|
+ qp = hns_roce_qp_lookup(hr_dev, qpn);
|
|
+ if (!qp)
|
|
+ return;
|
|
+
|
|
+ qp->state = IB_QPS_ERR;
|
|
+ flush_cqe(hr_dev, qp);
|
|
|
|
if (refcount_dec_and_test(&qp->refcount))
|
|
complete(&qp->free);
|
|
diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c
|
|
index 727f926500712c..652508b660a060 100644
|
|
--- a/drivers/infiniband/hw/hns/hns_roce_srq.c
|
|
+++ b/drivers/infiniband/hw/hns/hns_roce_srq.c
|
|
@@ -150,8 +150,8 @@ static void free_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
|
|
ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_SRQ,
|
|
srq->srqn);
|
|
if (ret)
|
|
- dev_err(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n",
|
|
- ret, srq->srqn);
|
|
+ dev_err_ratelimited(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n",
|
|
+ ret, srq->srqn);
|
|
|
|
xa_erase_irq(&srq_table->xa, srq->srqn);
|
|
|
|
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
|
|
index 296af7a5c2794d..c510484e024b1a 100644
|
|
--- a/drivers/infiniband/hw/mlx5/main.c
|
|
+++ b/drivers/infiniband/hw/mlx5/main.c
|
|
@@ -2796,37 +2796,72 @@ static u8 mlx5_get_umr_fence(u8 umr_fence_cap)
|
|
}
|
|
}
|
|
|
|
-static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
|
|
+int mlx5_ib_dev_res_cq_init(struct mlx5_ib_dev *dev)
|
|
{
|
|
struct mlx5_ib_resources *devr = &dev->devr;
|
|
- struct ib_srq_init_attr attr;
|
|
- struct ib_device *ibdev;
|
|
struct ib_cq_init_attr cq_attr = {.cqe = 1};
|
|
- int port;
|
|
+ struct ib_device *ibdev;
|
|
+ struct ib_pd *pd;
|
|
+ struct ib_cq *cq;
|
|
int ret = 0;
|
|
|
|
- ibdev = &dev->ib_dev;
|
|
|
|
- if (!MLX5_CAP_GEN(dev->mdev, xrc))
|
|
- return -EOPNOTSUPP;
|
|
+ /*
|
|
+ * devr->c0 is set once, never changed until device unload.
|
|
+ * Avoid taking the mutex if initialization is already done.
|
|
+ */
|
|
+ if (devr->c0)
|
|
+ return 0;
|
|
|
|
- devr->p0 = ib_alloc_pd(ibdev, 0);
|
|
- if (IS_ERR(devr->p0))
|
|
- return PTR_ERR(devr->p0);
|
|
+ mutex_lock(&devr->cq_lock);
|
|
+ if (devr->c0)
|
|
+ goto unlock;
|
|
|
|
- devr->c0 = ib_create_cq(ibdev, NULL, NULL, NULL, &cq_attr);
|
|
- if (IS_ERR(devr->c0)) {
|
|
- ret = PTR_ERR(devr->c0);
|
|
- goto error1;
|
|
+ ibdev = &dev->ib_dev;
|
|
+ pd = ib_alloc_pd(ibdev, 0);
|
|
+ if (IS_ERR(pd)) {
|
|
+ ret = PTR_ERR(pd);
|
|
+ mlx5_ib_err(dev, "Couldn't allocate PD for res init, err=%d\n", ret);
|
|
+ goto unlock;
|
|
}
|
|
|
|
- ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn0, 0);
|
|
- if (ret)
|
|
- goto error2;
|
|
+ cq = ib_create_cq(ibdev, NULL, NULL, NULL, &cq_attr);
|
|
+ if (IS_ERR(cq)) {
|
|
+ ret = PTR_ERR(cq);
|
|
+ mlx5_ib_err(dev, "Couldn't create CQ for res init, err=%d\n", ret);
|
|
+ ib_dealloc_pd(pd);
|
|
+ goto unlock;
|
|
+ }
|
|
|
|
- ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn1, 0);
|
|
+ devr->p0 = pd;
|
|
+ devr->c0 = cq;
|
|
+
|
|
+unlock:
|
|
+ mutex_unlock(&devr->cq_lock);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int mlx5_ib_dev_res_srq_init(struct mlx5_ib_dev *dev)
|
|
+{
|
|
+ struct mlx5_ib_resources *devr = &dev->devr;
|
|
+ struct ib_srq_init_attr attr;
|
|
+ struct ib_srq *s0, *s1;
|
|
+ int ret = 0;
|
|
+
|
|
+ /*
|
|
+ * devr->s1 is set once, never changed until device unload.
|
|
+ * Avoid taking the mutex if initialization is already done.
|
|
+ */
|
|
+ if (devr->s1)
|
|
+ return 0;
|
|
+
|
|
+ mutex_lock(&devr->srq_lock);
|
|
+ if (devr->s1)
|
|
+ goto unlock;
|
|
+
|
|
+ ret = mlx5_ib_dev_res_cq_init(dev);
|
|
if (ret)
|
|
- goto error3;
|
|
+ goto unlock;
|
|
|
|
memset(&attr, 0, sizeof(attr));
|
|
attr.attr.max_sge = 1;
|
|
@@ -2834,10 +2869,11 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
|
|
attr.srq_type = IB_SRQT_XRC;
|
|
attr.ext.cq = devr->c0;
|
|
|
|
- devr->s0 = ib_create_srq(devr->p0, &attr);
|
|
- if (IS_ERR(devr->s0)) {
|
|
- ret = PTR_ERR(devr->s0);
|
|
- goto err_create;
|
|
+ s0 = ib_create_srq(devr->p0, &attr);
|
|
+ if (IS_ERR(s0)) {
|
|
+ ret = PTR_ERR(s0);
|
|
+ mlx5_ib_err(dev, "Couldn't create SRQ 0 for res init, err=%d\n", ret);
|
|
+ goto unlock;
|
|
}
|
|
|
|
memset(&attr, 0, sizeof(attr));
|
|
@@ -2845,51 +2881,63 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
|
|
attr.attr.max_wr = 1;
|
|
attr.srq_type = IB_SRQT_BASIC;
|
|
|
|
- devr->s1 = ib_create_srq(devr->p0, &attr);
|
|
- if (IS_ERR(devr->s1)) {
|
|
- ret = PTR_ERR(devr->s1);
|
|
- goto error6;
|
|
+ s1 = ib_create_srq(devr->p0, &attr);
|
|
+ if (IS_ERR(s1)) {
|
|
+ ret = PTR_ERR(s1);
|
|
+ mlx5_ib_err(dev, "Couldn't create SRQ 1 for res init, err=%d\n", ret);
|
|
+ ib_destroy_srq(s0);
|
|
}
|
|
|
|
- for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
|
|
- INIT_WORK(&devr->ports[port].pkey_change_work,
|
|
- pkey_change_handler);
|
|
-
|
|
- return 0;
|
|
+ devr->s0 = s0;
|
|
+ devr->s1 = s1;
|
|
|
|
-error6:
|
|
- ib_destroy_srq(devr->s0);
|
|
-err_create:
|
|
- mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0);
|
|
-error3:
|
|
- mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);
|
|
-error2:
|
|
- ib_destroy_cq(devr->c0);
|
|
-error1:
|
|
- ib_dealloc_pd(devr->p0);
|
|
+unlock:
|
|
+ mutex_unlock(&devr->srq_lock);
|
|
return ret;
|
|
}
|
|
|
|
-static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)
|
|
+static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
|
|
{
|
|
struct mlx5_ib_resources *devr = &dev->devr;
|
|
- int port;
|
|
+ int ret;
|
|
|
|
- /*
|
|
- * Make sure no change P_Key work items are still executing.
|
|
- *
|
|
- * At this stage, the mlx5_ib_event should be unregistered
|
|
- * and it ensures that no new works are added.
|
|
- */
|
|
- for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
|
|
- cancel_work_sync(&devr->ports[port].pkey_change_work);
|
|
+ if (!MLX5_CAP_GEN(dev->mdev, xrc))
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
+ ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn0, 0);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn1, 0);
|
|
+ if (ret) {
|
|
+ mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ mutex_init(&devr->cq_lock);
|
|
+ mutex_init(&devr->srq_lock);
|
|
|
|
- ib_destroy_srq(devr->s1);
|
|
- ib_destroy_srq(devr->s0);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)
|
|
+{
|
|
+ struct mlx5_ib_resources *devr = &dev->devr;
|
|
+
|
|
+ /* After s0/s1 init, they are not unset during the device lifetime. */
|
|
+ if (devr->s1) {
|
|
+ ib_destroy_srq(devr->s1);
|
|
+ ib_destroy_srq(devr->s0);
|
|
+ }
|
|
mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0);
|
|
mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);
|
|
- ib_destroy_cq(devr->c0);
|
|
- ib_dealloc_pd(devr->p0);
|
|
+ /* After p0/c0 init, they are not unset during the device lifetime. */
|
|
+ if (devr->c0) {
|
|
+ ib_destroy_cq(devr->c0);
|
|
+ ib_dealloc_pd(devr->p0);
|
|
+ }
|
|
+ mutex_destroy(&devr->cq_lock);
|
|
+ mutex_destroy(&devr->srq_lock);
|
|
}
|
|
|
|
static u32 get_core_cap_flags(struct ib_device *ibdev,
|
|
@@ -4138,6 +4186,13 @@ static void mlx5_ib_stage_delay_drop_cleanup(struct mlx5_ib_dev *dev)
|
|
|
|
static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev)
|
|
{
|
|
+ struct mlx5_ib_resources *devr = &dev->devr;
|
|
+ int port;
|
|
+
|
|
+ for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
|
|
+ INIT_WORK(&devr->ports[port].pkey_change_work,
|
|
+ pkey_change_handler);
|
|
+
|
|
dev->mdev_events.notifier_call = mlx5_ib_event;
|
|
mlx5_notifier_register(dev->mdev, &dev->mdev_events);
|
|
|
|
@@ -4148,8 +4203,14 @@ static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev)
|
|
|
|
static void mlx5_ib_stage_dev_notifier_cleanup(struct mlx5_ib_dev *dev)
|
|
{
|
|
+ struct mlx5_ib_resources *devr = &dev->devr;
|
|
+ int port;
|
|
+
|
|
mlx5r_macsec_event_unregister(dev);
|
|
mlx5_notifier_unregister(dev->mdev, &dev->mdev_events);
|
|
+
|
|
+ for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
|
|
+ cancel_work_sync(&devr->ports[port].pkey_change_work);
|
|
}
|
|
|
|
void __mlx5_ib_remove(struct mlx5_ib_dev *dev,
|
|
@@ -4223,9 +4284,6 @@ static const struct mlx5_ib_profile pf_profile = {
|
|
STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
|
|
mlx5_ib_dev_res_init,
|
|
mlx5_ib_dev_res_cleanup),
|
|
- STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
|
|
- mlx5_ib_stage_dev_notifier_init,
|
|
- mlx5_ib_stage_dev_notifier_cleanup),
|
|
STAGE_CREATE(MLX5_IB_STAGE_ODP,
|
|
mlx5_ib_odp_init_one,
|
|
mlx5_ib_odp_cleanup_one),
|
|
@@ -4250,6 +4308,9 @@ static const struct mlx5_ib_profile pf_profile = {
|
|
STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
|
|
mlx5_ib_stage_ib_reg_init,
|
|
mlx5_ib_stage_ib_reg_cleanup),
|
|
+ STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
|
|
+ mlx5_ib_stage_dev_notifier_init,
|
|
+ mlx5_ib_stage_dev_notifier_cleanup),
|
|
STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
|
|
mlx5_ib_stage_post_ib_reg_umr_init,
|
|
NULL),
|
|
@@ -4286,9 +4347,6 @@ const struct mlx5_ib_profile raw_eth_profile = {
|
|
STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
|
|
mlx5_ib_dev_res_init,
|
|
mlx5_ib_dev_res_cleanup),
|
|
- STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
|
|
- mlx5_ib_stage_dev_notifier_init,
|
|
- mlx5_ib_stage_dev_notifier_cleanup),
|
|
STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
|
|
mlx5_ib_counters_init,
|
|
mlx5_ib_counters_cleanup),
|
|
@@ -4310,6 +4368,9 @@ const struct mlx5_ib_profile raw_eth_profile = {
|
|
STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
|
|
mlx5_ib_stage_ib_reg_init,
|
|
mlx5_ib_stage_ib_reg_cleanup),
|
|
+ STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
|
|
+ mlx5_ib_stage_dev_notifier_init,
|
|
+ mlx5_ib_stage_dev_notifier_cleanup),
|
|
STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
|
|
mlx5_ib_stage_post_ib_reg_umr_init,
|
|
NULL),
|
|
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
|
|
index 43a963e205eb40..94678e5c59dd59 100644
|
|
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
|
|
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
|
|
@@ -820,11 +820,13 @@ struct mlx5_ib_port_resources {
|
|
|
|
struct mlx5_ib_resources {
|
|
struct ib_cq *c0;
|
|
+ struct mutex cq_lock;
|
|
u32 xrcdn0;
|
|
u32 xrcdn1;
|
|
struct ib_pd *p0;
|
|
struct ib_srq *s0;
|
|
struct ib_srq *s1;
|
|
+ struct mutex srq_lock;
|
|
struct mlx5_ib_port_resources ports[2];
|
|
};
|
|
|
|
@@ -952,7 +954,6 @@ enum mlx5_ib_stages {
|
|
MLX5_IB_STAGE_QP,
|
|
MLX5_IB_STAGE_SRQ,
|
|
MLX5_IB_STAGE_DEVICE_RESOURCES,
|
|
- MLX5_IB_STAGE_DEVICE_NOTIFIER,
|
|
MLX5_IB_STAGE_ODP,
|
|
MLX5_IB_STAGE_COUNTERS,
|
|
MLX5_IB_STAGE_CONG_DEBUGFS,
|
|
@@ -961,6 +962,7 @@ enum mlx5_ib_stages {
|
|
MLX5_IB_STAGE_PRE_IB_REG_UMR,
|
|
MLX5_IB_STAGE_WHITELIST_UID,
|
|
MLX5_IB_STAGE_IB_REG,
|
|
+ MLX5_IB_STAGE_DEVICE_NOTIFIER,
|
|
MLX5_IB_STAGE_POST_IB_REG_UMR,
|
|
MLX5_IB_STAGE_DELAY_DROP,
|
|
MLX5_IB_STAGE_RESTRACK,
|
|
@@ -1270,6 +1272,8 @@ to_mmmap(struct rdma_user_mmap_entry *rdma_entry)
|
|
struct mlx5_user_mmap_entry, rdma_entry);
|
|
}
|
|
|
|
+int mlx5_ib_dev_res_cq_init(struct mlx5_ib_dev *dev);
|
|
+int mlx5_ib_dev_res_srq_init(struct mlx5_ib_dev *dev);
|
|
int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context, unsigned long virt,
|
|
struct mlx5_db *db);
|
|
void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db);
|
|
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
|
|
index 93d9b15cbbb986..71a856409cee2c 100644
|
|
--- a/drivers/infiniband/hw/mlx5/qp.c
|
|
+++ b/drivers/infiniband/hw/mlx5/qp.c
|
|
@@ -3247,6 +3247,10 @@ int mlx5_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
|
|
enum ib_qp_type type;
|
|
int err;
|
|
|
|
+ err = mlx5_ib_dev_res_srq_init(dev);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
err = check_qp_type(dev, attr, &type);
|
|
if (err)
|
|
return err;
|
|
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c
|
|
index 84be0c3d569959..bcb6b324af5062 100644
|
|
--- a/drivers/infiniband/hw/mlx5/srq.c
|
|
+++ b/drivers/infiniband/hw/mlx5/srq.c
|
|
@@ -216,6 +216,10 @@ int mlx5_ib_create_srq(struct ib_srq *ib_srq,
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ err = mlx5_ib_dev_res_cq_init(dev);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
mutex_init(&srq->mutex);
|
|
spin_lock_init(&srq->lock);
|
|
srq->msrq.max = roundup_pow_of_two(init_attr->attr.max_wr + 1);
|
|
diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c
|
|
index 28e379c108bce0..3767d7fc0aac82 100644
|
|
--- a/drivers/infiniband/sw/rxe/rxe_qp.c
|
|
+++ b/drivers/infiniband/sw/rxe/rxe_qp.c
|
|
@@ -781,6 +781,7 @@ int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask)
|
|
* Yield the processor
|
|
*/
|
|
spin_lock_irqsave(&qp->state_lock, flags);
|
|
+ attr->cur_qp_state = qp_state(qp);
|
|
if (qp->attr.sq_draining) {
|
|
spin_unlock_irqrestore(&qp->state_lock, flags);
|
|
cond_resched();
|
|
diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
|
|
index 7a36080d2baef5..7ff152ffe15b9f 100644
|
|
--- a/drivers/infiniband/sw/rxe/rxe_req.c
|
|
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
|
|
@@ -693,10 +693,12 @@ int rxe_requester(struct rxe_qp *qp)
|
|
if (unlikely(qp_state(qp) == IB_QPS_ERR)) {
|
|
wqe = __req_next_wqe(qp);
|
|
spin_unlock_irqrestore(&qp->state_lock, flags);
|
|
- if (wqe)
|
|
+ if (wqe) {
|
|
+ wqe->status = IB_WC_WR_FLUSH_ERR;
|
|
goto err;
|
|
- else
|
|
+ } else {
|
|
goto exit;
|
|
+ }
|
|
}
|
|
|
|
if (unlikely(qp_state(qp) == IB_QPS_RESET)) {
|
|
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
|
|
index 3a7c647d3affa8..d6381c00bb8ddc 100644
|
|
--- a/drivers/iommu/intel/iommu.c
|
|
+++ b/drivers/iommu/intel/iommu.c
|
|
@@ -815,14 +815,15 @@ static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn,
|
|
while (1) {
|
|
offset = pfn_level_offset(pfn, level);
|
|
pte = &parent[offset];
|
|
- if (!pte || (dma_pte_superpage(pte) || !dma_pte_present(pte))) {
|
|
- pr_info("PTE not present at level %d\n", level);
|
|
- break;
|
|
- }
|
|
|
|
pr_info("pte level: %d, pte value: 0x%016llx\n", level, pte->val);
|
|
|
|
- if (level == 1)
|
|
+ if (!dma_pte_present(pte)) {
|
|
+ pr_info("page table not present at level %d\n", level - 1);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (level == 1 || dma_pte_superpage(pte))
|
|
break;
|
|
|
|
parent = phys_to_virt(dma_pte_addr(pte));
|
|
@@ -845,11 +846,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
|
|
pr_info("Dump %s table entries for IOVA 0x%llx\n", iommu->name, addr);
|
|
|
|
/* root entry dump */
|
|
- rt_entry = &iommu->root_entry[bus];
|
|
- if (!rt_entry) {
|
|
- pr_info("root table entry is not present\n");
|
|
+ if (!iommu->root_entry) {
|
|
+ pr_info("root table is not present\n");
|
|
return;
|
|
}
|
|
+ rt_entry = &iommu->root_entry[bus];
|
|
|
|
if (sm_supported(iommu))
|
|
pr_info("scalable mode root entry: hi 0x%016llx, low 0x%016llx\n",
|
|
@@ -860,7 +861,7 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
|
|
/* context entry dump */
|
|
ctx_entry = iommu_context_addr(iommu, bus, devfn, 0);
|
|
if (!ctx_entry) {
|
|
- pr_info("context table entry is not present\n");
|
|
+ pr_info("context table is not present\n");
|
|
return;
|
|
}
|
|
|
|
@@ -869,17 +870,23 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
|
|
|
|
/* legacy mode does not require PASID entries */
|
|
if (!sm_supported(iommu)) {
|
|
+ if (!context_present(ctx_entry)) {
|
|
+ pr_info("legacy mode page table is not present\n");
|
|
+ return;
|
|
+ }
|
|
level = agaw_to_level(ctx_entry->hi & 7);
|
|
pgtable = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
|
|
goto pgtable_walk;
|
|
}
|
|
|
|
- /* get the pointer to pasid directory entry */
|
|
- dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
|
|
- if (!dir) {
|
|
- pr_info("pasid directory entry is not present\n");
|
|
+ if (!context_present(ctx_entry)) {
|
|
+ pr_info("pasid directory table is not present\n");
|
|
return;
|
|
}
|
|
+
|
|
+ /* get the pointer to pasid directory entry */
|
|
+ dir = phys_to_virt(ctx_entry->lo & VTD_PAGE_MASK);
|
|
+
|
|
/* For request-without-pasid, get the pasid from context entry */
|
|
if (intel_iommu_sm && pasid == IOMMU_PASID_INVALID)
|
|
pasid = IOMMU_NO_PASID;
|
|
@@ -891,7 +898,7 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
|
|
/* get the pointer to the pasid table entry */
|
|
entries = get_pasid_table_from_pde(pde);
|
|
if (!entries) {
|
|
- pr_info("pasid table entry is not present\n");
|
|
+ pr_info("pasid table is not present\n");
|
|
return;
|
|
}
|
|
index = pasid & PASID_PTE_MASK;
|
|
@@ -899,6 +906,11 @@ void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id,
|
|
for (i = 0; i < ARRAY_SIZE(pte->val); i++)
|
|
pr_info("pasid table entry[%d]: 0x%016llx\n", i, pte->val[i]);
|
|
|
|
+ if (!pasid_pte_is_present(pte)) {
|
|
+ pr_info("scalable mode page table is not present\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (pasid_pte_get_pgtt(pte) == PASID_ENTRY_PGTT_FL_ONLY) {
|
|
level = pte->val[2] & BIT_ULL(2) ? 5 : 4;
|
|
pgtable = phys_to_virt(pte->val[2] & VTD_PAGE_MASK);
|
|
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
|
|
index 934dc97f5df9ed..bc758ab70f4940 100644
|
|
--- a/drivers/iommu/io-pgtable-arm.c
|
|
+++ b/drivers/iommu/io-pgtable-arm.c
|
|
@@ -180,6 +180,18 @@ static phys_addr_t iopte_to_paddr(arm_lpae_iopte pte,
|
|
return (paddr | (paddr << (48 - 12))) & (ARM_LPAE_PTE_ADDR_MASK << 4);
|
|
}
|
|
|
|
+/*
|
|
+ * Convert an index returned by ARM_LPAE_PGD_IDX(), which can point into
|
|
+ * a concatenated PGD, into the maximum number of entries that can be
|
|
+ * mapped in the same table page.
|
|
+ */
|
|
+static inline int arm_lpae_max_entries(int i, struct arm_lpae_io_pgtable *data)
|
|
+{
|
|
+ int ptes_per_table = ARM_LPAE_PTES_PER_TABLE(data);
|
|
+
|
|
+ return ptes_per_table - (i & (ptes_per_table - 1));
|
|
+}
|
|
+
|
|
static bool selftest_running = false;
|
|
|
|
static dma_addr_t __arm_lpae_dma_addr(void *pages)
|
|
@@ -357,7 +369,7 @@ static int __arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
|
|
|
|
/* If we can install a leaf entry at this level, then do so */
|
|
if (size == block_size) {
|
|
- max_entries = ARM_LPAE_PTES_PER_TABLE(data) - map_idx_start;
|
|
+ max_entries = arm_lpae_max_entries(map_idx_start, data);
|
|
num_entries = min_t(int, pgcount, max_entries);
|
|
ret = arm_lpae_init_pte(data, iova, paddr, prot, lvl, num_entries, ptep);
|
|
if (!ret)
|
|
@@ -557,7 +569,7 @@ static size_t arm_lpae_split_blk_unmap(struct arm_lpae_io_pgtable *data,
|
|
|
|
if (size == split_sz) {
|
|
unmap_idx_start = ARM_LPAE_LVL_IDX(iova, lvl, data);
|
|
- max_entries = ptes_per_table - unmap_idx_start;
|
|
+ max_entries = arm_lpae_max_entries(unmap_idx_start, data);
|
|
num_entries = min_t(int, pgcount, max_entries);
|
|
}
|
|
|
|
@@ -615,7 +627,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
|
|
|
|
/* If the size matches this level, we're in the right place */
|
|
if (size == ARM_LPAE_BLOCK_SIZE(lvl, data)) {
|
|
- max_entries = ARM_LPAE_PTES_PER_TABLE(data) - unmap_idx_start;
|
|
+ max_entries = arm_lpae_max_entries(unmap_idx_start, data);
|
|
num_entries = min_t(int, pgcount, max_entries);
|
|
|
|
while (i < num_entries) {
|
|
diff --git a/drivers/leds/flash/leds-mt6360.c b/drivers/leds/flash/leds-mt6360.c
|
|
index fdf0812774ceee..7abd535dce3198 100644
|
|
--- a/drivers/leds/flash/leds-mt6360.c
|
|
+++ b/drivers/leds/flash/leds-mt6360.c
|
|
@@ -774,7 +774,6 @@ static void mt6360_v4l2_flash_release(struct mt6360_priv *priv)
|
|
static int mt6360_led_probe(struct platform_device *pdev)
|
|
{
|
|
struct mt6360_priv *priv;
|
|
- struct fwnode_handle *child;
|
|
size_t count;
|
|
int i = 0, ret;
|
|
|
|
@@ -801,7 +800,7 @@ static int mt6360_led_probe(struct platform_device *pdev)
|
|
return -ENODEV;
|
|
}
|
|
|
|
- device_for_each_child_node(&pdev->dev, child) {
|
|
+ device_for_each_child_node_scoped(&pdev->dev, child) {
|
|
struct mt6360_led *led = priv->leds + i;
|
|
struct led_init_data init_data = { .fwnode = child, };
|
|
u32 reg, led_color;
|
|
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
|
|
index 77bb26906ea6e4..84028800aed33b 100644
|
|
--- a/drivers/leds/leds-lp55xx-common.c
|
|
+++ b/drivers/leds/leds-lp55xx-common.c
|
|
@@ -580,9 +580,6 @@ static int lp55xx_parse_common_child(struct device_node *np,
|
|
if (ret)
|
|
return ret;
|
|
|
|
- if (*chan_nr < 0 || *chan_nr > cfg->max_channel)
|
|
- return -EINVAL;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c
|
|
index 0ec21dcdbde723..cff7c343ee082a 100644
|
|
--- a/drivers/mailbox/arm_mhuv2.c
|
|
+++ b/drivers/mailbox/arm_mhuv2.c
|
|
@@ -500,7 +500,7 @@ static const struct mhuv2_protocol_ops mhuv2_data_transfer_ops = {
|
|
static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg)
|
|
{
|
|
struct mbox_chan *chans = mhu->mbox.chans;
|
|
- int channel = 0, i, offset = 0, windows, protocol, ch_wn;
|
|
+ int channel = 0, i, j, offset = 0, windows, protocol, ch_wn;
|
|
u32 stat;
|
|
|
|
for (i = 0; i < MHUV2_CMB_INT_ST_REG_CNT; i++) {
|
|
@@ -510,9 +510,9 @@ static struct mbox_chan *get_irq_chan_comb(struct mhuv2 *mhu, u32 __iomem *reg)
|
|
|
|
ch_wn = i * MHUV2_STAT_BITS + __builtin_ctz(stat);
|
|
|
|
- for (i = 0; i < mhu->length; i += 2) {
|
|
- protocol = mhu->protocols[i];
|
|
- windows = mhu->protocols[i + 1];
|
|
+ for (j = 0; j < mhu->length; j += 2) {
|
|
+ protocol = mhu->protocols[j];
|
|
+ windows = mhu->protocols[j + 1];
|
|
|
|
if (ch_wn >= offset + windows) {
|
|
if (protocol == DOORBELL)
|
|
diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
|
|
index 4d62b07c14118a..d5f5606585f4d8 100644
|
|
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
|
|
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
|
|
@@ -623,12 +623,6 @@ static int cmdq_probe(struct platform_device *pdev)
|
|
cmdq->mbox.chans[i].con_priv = (void *)&cmdq->thread[i];
|
|
}
|
|
|
|
- err = devm_mbox_controller_register(dev, &cmdq->mbox);
|
|
- if (err < 0) {
|
|
- dev_err(dev, "failed to register mailbox: %d\n", err);
|
|
- return err;
|
|
- }
|
|
-
|
|
platform_set_drvdata(pdev, cmdq);
|
|
|
|
WARN_ON(clk_bulk_prepare(cmdq->pdata->gce_num, cmdq->clocks));
|
|
@@ -642,6 +636,12 @@ static int cmdq_probe(struct platform_device *pdev)
|
|
return err;
|
|
}
|
|
|
|
+ err = devm_mbox_controller_register(dev, &cmdq->mbox);
|
|
+ if (err < 0) {
|
|
+ dev_err(dev, "failed to register mailbox: %d\n", err);
|
|
+ return err;
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/md/bcache/closure.c b/drivers/md/bcache/closure.c
|
|
index d8d9394a6beb10..18f21d4e9aaae8 100644
|
|
--- a/drivers/md/bcache/closure.c
|
|
+++ b/drivers/md/bcache/closure.c
|
|
@@ -17,10 +17,16 @@ static inline void closure_put_after_sub(struct closure *cl, int flags)
|
|
{
|
|
int r = flags & CLOSURE_REMAINING_MASK;
|
|
|
|
- BUG_ON(flags & CLOSURE_GUARD_MASK);
|
|
- BUG_ON(!r && (flags & ~CLOSURE_DESTRUCTOR));
|
|
+ if (WARN(flags & CLOSURE_GUARD_MASK,
|
|
+ "closure has guard bits set: %x (%u)",
|
|
+ flags & CLOSURE_GUARD_MASK, (unsigned) __fls(r)))
|
|
+ r &= ~CLOSURE_GUARD_MASK;
|
|
|
|
if (!r) {
|
|
+ WARN(flags & ~CLOSURE_DESTRUCTOR,
|
|
+ "closure ref hit 0 with incorrect flags set: %x (%u)",
|
|
+ flags & ~CLOSURE_DESTRUCTOR, (unsigned) __fls(flags));
|
|
+
|
|
if (cl->fn && !(flags & CLOSURE_DESTRUCTOR)) {
|
|
atomic_set(&cl->remaining,
|
|
CLOSURE_REMAINING_INITIALIZER);
|
|
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
|
|
index f1345781c861a8..30ddfb21f65818 100644
|
|
--- a/drivers/md/dm-bufio.c
|
|
+++ b/drivers/md/dm-bufio.c
|
|
@@ -2444,7 +2444,8 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
|
|
int r;
|
|
unsigned int num_locks;
|
|
struct dm_bufio_client *c;
|
|
- char slab_name[27];
|
|
+ char slab_name[64];
|
|
+ static atomic_t seqno = ATOMIC_INIT(0);
|
|
|
|
if (!block_size || block_size & ((1 << SECTOR_SHIFT) - 1)) {
|
|
DMERR("%s: block size not specified or is not multiple of 512b", __func__);
|
|
@@ -2495,7 +2496,8 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
|
|
(block_size < PAGE_SIZE || !is_power_of_2(block_size))) {
|
|
unsigned int align = min(1U << __ffs(block_size), (unsigned int)PAGE_SIZE);
|
|
|
|
- snprintf(slab_name, sizeof(slab_name), "dm_bufio_cache-%u", block_size);
|
|
+ snprintf(slab_name, sizeof(slab_name), "dm_bufio_cache-%u-%u",
|
|
+ block_size, atomic_inc_return(&seqno));
|
|
c->slab_cache = kmem_cache_create(slab_name, block_size, align,
|
|
SLAB_RECLAIM_ACCOUNT, NULL);
|
|
if (!c->slab_cache) {
|
|
@@ -2504,9 +2506,11 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
|
|
}
|
|
}
|
|
if (aux_size)
|
|
- snprintf(slab_name, sizeof(slab_name), "dm_bufio_buffer-%u", aux_size);
|
|
+ snprintf(slab_name, sizeof(slab_name), "dm_bufio_buffer-%u-%u",
|
|
+ aux_size, atomic_inc_return(&seqno));
|
|
else
|
|
- snprintf(slab_name, sizeof(slab_name), "dm_bufio_buffer");
|
|
+ snprintf(slab_name, sizeof(slab_name), "dm_bufio_buffer-%u",
|
|
+ atomic_inc_return(&seqno));
|
|
c->slab_buffer = kmem_cache_create(slab_name, sizeof(struct dm_buffer) + aux_size,
|
|
0, SLAB_RECLAIM_ACCOUNT, NULL);
|
|
if (!c->slab_buffer) {
|
|
diff --git a/drivers/md/dm-cache-background-tracker.c b/drivers/md/dm-cache-background-tracker.c
|
|
index 9c5308298cf124..f3051bd7d2df07 100644
|
|
--- a/drivers/md/dm-cache-background-tracker.c
|
|
+++ b/drivers/md/dm-cache-background-tracker.c
|
|
@@ -11,12 +11,6 @@
|
|
|
|
#define DM_MSG_PREFIX "dm-background-tracker"
|
|
|
|
-struct bt_work {
|
|
- struct list_head list;
|
|
- struct rb_node node;
|
|
- struct policy_work work;
|
|
-};
|
|
-
|
|
struct background_tracker {
|
|
unsigned int max_work;
|
|
atomic_t pending_promotes;
|
|
@@ -26,10 +20,10 @@ struct background_tracker {
|
|
struct list_head issued;
|
|
struct list_head queued;
|
|
struct rb_root pending;
|
|
-
|
|
- struct kmem_cache *work_cache;
|
|
};
|
|
|
|
+struct kmem_cache *btracker_work_cache = NULL;
|
|
+
|
|
struct background_tracker *btracker_create(unsigned int max_work)
|
|
{
|
|
struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL);
|
|
@@ -48,12 +42,6 @@ struct background_tracker *btracker_create(unsigned int max_work)
|
|
INIT_LIST_HEAD(&b->queued);
|
|
|
|
b->pending = RB_ROOT;
|
|
- b->work_cache = KMEM_CACHE(bt_work, 0);
|
|
- if (!b->work_cache) {
|
|
- DMERR("couldn't create mempool for background work items");
|
|
- kfree(b);
|
|
- b = NULL;
|
|
- }
|
|
|
|
return b;
|
|
}
|
|
@@ -66,10 +54,9 @@ void btracker_destroy(struct background_tracker *b)
|
|
BUG_ON(!list_empty(&b->issued));
|
|
list_for_each_entry_safe (w, tmp, &b->queued, list) {
|
|
list_del(&w->list);
|
|
- kmem_cache_free(b->work_cache, w);
|
|
+ kmem_cache_free(btracker_work_cache, w);
|
|
}
|
|
|
|
- kmem_cache_destroy(b->work_cache);
|
|
kfree(b);
|
|
}
|
|
EXPORT_SYMBOL_GPL(btracker_destroy);
|
|
@@ -180,7 +167,7 @@ static struct bt_work *alloc_work(struct background_tracker *b)
|
|
if (max_work_reached(b))
|
|
return NULL;
|
|
|
|
- return kmem_cache_alloc(b->work_cache, GFP_NOWAIT);
|
|
+ return kmem_cache_alloc(btracker_work_cache, GFP_NOWAIT);
|
|
}
|
|
|
|
int btracker_queue(struct background_tracker *b,
|
|
@@ -203,7 +190,7 @@ int btracker_queue(struct background_tracker *b,
|
|
* There was a race, we'll just ignore this second
|
|
* bit of work for the same oblock.
|
|
*/
|
|
- kmem_cache_free(b->work_cache, w);
|
|
+ kmem_cache_free(btracker_work_cache, w);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -244,7 +231,7 @@ void btracker_complete(struct background_tracker *b,
|
|
update_stats(b, &w->work, -1);
|
|
rb_erase(&w->node, &b->pending);
|
|
list_del(&w->list);
|
|
- kmem_cache_free(b->work_cache, w);
|
|
+ kmem_cache_free(btracker_work_cache, w);
|
|
}
|
|
EXPORT_SYMBOL_GPL(btracker_complete);
|
|
|
|
diff --git a/drivers/md/dm-cache-background-tracker.h b/drivers/md/dm-cache-background-tracker.h
|
|
index 5b8f5c667b81b4..09c8fc59f7bb7b 100644
|
|
--- a/drivers/md/dm-cache-background-tracker.h
|
|
+++ b/drivers/md/dm-cache-background-tracker.h
|
|
@@ -26,6 +26,14 @@
|
|
* protected with a spinlock.
|
|
*/
|
|
|
|
+struct bt_work {
|
|
+ struct list_head list;
|
|
+ struct rb_node node;
|
|
+ struct policy_work work;
|
|
+};
|
|
+
|
|
+extern struct kmem_cache *btracker_work_cache;
|
|
+
|
|
struct background_work;
|
|
struct background_tracker;
|
|
|
|
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
|
|
index fb809b46d6aa76..c5851c9f7ec041 100644
|
|
--- a/drivers/md/dm-cache-target.c
|
|
+++ b/drivers/md/dm-cache-target.c
|
|
@@ -10,6 +10,7 @@
|
|
#include "dm-bio-record.h"
|
|
#include "dm-cache-metadata.h"
|
|
#include "dm-io-tracker.h"
|
|
+#include "dm-cache-background-tracker.h"
|
|
|
|
#include <linux/dm-io.h>
|
|
#include <linux/dm-kcopyd.h>
|
|
@@ -2267,7 +2268,7 @@ static int parse_cache_args(struct cache_args *ca, int argc, char **argv,
|
|
|
|
/*----------------------------------------------------------------*/
|
|
|
|
-static struct kmem_cache *migration_cache;
|
|
+static struct kmem_cache *migration_cache = NULL;
|
|
|
|
#define NOT_CORE_OPTION 1
|
|
|
|
@@ -3455,22 +3456,36 @@ static int __init dm_cache_init(void)
|
|
int r;
|
|
|
|
migration_cache = KMEM_CACHE(dm_cache_migration, 0);
|
|
- if (!migration_cache)
|
|
- return -ENOMEM;
|
|
+ if (!migration_cache) {
|
|
+ r = -ENOMEM;
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ btracker_work_cache = kmem_cache_create("dm_cache_bt_work",
|
|
+ sizeof(struct bt_work), __alignof__(struct bt_work), 0, NULL);
|
|
+ if (!btracker_work_cache) {
|
|
+ r = -ENOMEM;
|
|
+ goto err;
|
|
+ }
|
|
|
|
r = dm_register_target(&cache_target);
|
|
if (r) {
|
|
- kmem_cache_destroy(migration_cache);
|
|
- return r;
|
|
+ goto err;
|
|
}
|
|
|
|
return 0;
|
|
+
|
|
+err:
|
|
+ kmem_cache_destroy(migration_cache);
|
|
+ kmem_cache_destroy(btracker_work_cache);
|
|
+ return r;
|
|
}
|
|
|
|
static void __exit dm_cache_exit(void)
|
|
{
|
|
dm_unregister_target(&cache_target);
|
|
kmem_cache_destroy(migration_cache);
|
|
+ kmem_cache_destroy(btracker_work_cache);
|
|
}
|
|
|
|
module_init(dm_cache_init);
|
|
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
|
|
index 07c7f9795b107b..032cefe3e351aa 100644
|
|
--- a/drivers/md/dm-thin.c
|
|
+++ b/drivers/md/dm-thin.c
|
|
@@ -2486,6 +2486,7 @@ static void pool_work_wait(struct pool_work *pw, struct pool *pool,
|
|
init_completion(&pw->complete);
|
|
queue_work(pool->wq, &pw->worker);
|
|
wait_for_completion(&pw->complete);
|
|
+ destroy_work_on_stack(&pw->worker);
|
|
}
|
|
|
|
/*----------------------------------------------------------------*/
|
|
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
|
|
index be65472d8f8b35..ba63076cd8f2b2 100644
|
|
--- a/drivers/md/md-bitmap.c
|
|
+++ b/drivers/md/md-bitmap.c
|
|
@@ -1089,6 +1089,7 @@ void md_bitmap_unplug_async(struct bitmap *bitmap)
|
|
|
|
queue_work(md_bitmap_wq, &unplug_work.work);
|
|
wait_for_completion(&done);
|
|
+ destroy_work_on_stack(&unplug_work.work);
|
|
}
|
|
EXPORT_SYMBOL(md_bitmap_unplug_async);
|
|
|
|
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c
|
|
index 591d1a43d03572..101736b80df826 100644
|
|
--- a/drivers/md/persistent-data/dm-space-map-common.c
|
|
+++ b/drivers/md/persistent-data/dm-space-map-common.c
|
|
@@ -51,7 +51,7 @@ static int index_check(struct dm_block_validator *v,
|
|
block_size - sizeof(__le32),
|
|
INDEX_CSUM_XOR));
|
|
if (csum_disk != mi_le->csum) {
|
|
- DMERR_LIMIT("i%s failed: csum %u != wanted %u", __func__,
|
|
+ DMERR_LIMIT("%s failed: csum %u != wanted %u", __func__,
|
|
le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
|
|
return -EILSEQ;
|
|
}
|
|
diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c
|
|
index a5ebce57f35e6e..d49facd92cc00c 100644
|
|
--- a/drivers/media/dvb-frontends/ts2020.c
|
|
+++ b/drivers/media/dvb-frontends/ts2020.c
|
|
@@ -553,13 +553,19 @@ static void ts2020_regmap_unlock(void *__dev)
|
|
static int ts2020_probe(struct i2c_client *client)
|
|
{
|
|
struct ts2020_config *pdata = client->dev.platform_data;
|
|
- struct dvb_frontend *fe = pdata->fe;
|
|
+ struct dvb_frontend *fe;
|
|
struct ts2020_priv *dev;
|
|
int ret;
|
|
u8 u8tmp;
|
|
unsigned int utmp;
|
|
char *chip_str;
|
|
|
|
+ if (!pdata) {
|
|
+ dev_err(&client->dev, "platform data is mandatory\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ fe = pdata->fe;
|
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
|
if (!dev) {
|
|
ret = -ENOMEM;
|
|
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
|
|
index d1609bd8f0485a..3bd31b5870233e 100644
|
|
--- a/drivers/media/i2c/adv7604.c
|
|
+++ b/drivers/media/i2c/adv7604.c
|
|
@@ -1405,12 +1405,13 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
|
|
if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0,
|
|
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
|
|
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
|
|
- false, timings))
|
|
+ false, adv76xx_get_dv_timings_cap(sd, -1), timings))
|
|
return 0;
|
|
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
|
|
(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
|
|
(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
|
|
- false, state->aspect_ratio, timings))
|
|
+ false, state->aspect_ratio,
|
|
+ adv76xx_get_dv_timings_cap(sd, -1), timings))
|
|
return 0;
|
|
|
|
v4l2_dbg(2, debug, sd,
|
|
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
|
|
index c1664a3620c8ed..cb90178ce4b176 100644
|
|
--- a/drivers/media/i2c/adv7842.c
|
|
+++ b/drivers/media/i2c/adv7842.c
|
|
@@ -1431,14 +1431,15 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
|
|
}
|
|
|
|
if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs, 0,
|
|
- (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
|
|
- (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
|
|
- false, timings))
|
|
+ (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
|
|
+ (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
|
|
+ false, adv7842_get_dv_timings_cap(sd), timings))
|
|
return 0;
|
|
if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
|
|
- (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
|
|
- (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
|
|
- false, state->aspect_ratio, timings))
|
|
+ (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
|
|
+ (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
|
|
+ false, state->aspect_ratio,
|
|
+ adv7842_get_dv_timings_cap(sd), timings))
|
|
return 0;
|
|
|
|
v4l2_dbg(2, debug, sd,
|
|
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
|
|
index 8ba5750f5a2319..7f30e8923633ef 100644
|
|
--- a/drivers/media/i2c/ds90ub960.c
|
|
+++ b/drivers/media/i2c/ds90ub960.c
|
|
@@ -1286,7 +1286,7 @@ static int ub960_rxport_get_strobe_pos(struct ub960_data *priv,
|
|
|
|
clk_delay += v & UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK;
|
|
|
|
- ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v);
|
|
+ ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v);
|
|
if (ret)
|
|
return ret;
|
|
|
|
diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c
|
|
index daabbece8c7e90..682a1aa7febd97 100644
|
|
--- a/drivers/media/i2c/dw9768.c
|
|
+++ b/drivers/media/i2c/dw9768.c
|
|
@@ -476,10 +476,9 @@ static int dw9768_probe(struct i2c_client *client)
|
|
* to be powered on in an ACPI system. Similarly for power off in
|
|
* remove.
|
|
*/
|
|
- pm_runtime_enable(dev);
|
|
full_power = (is_acpi_node(dev_fwnode(dev)) &&
|
|
acpi_dev_state_d0(dev)) ||
|
|
- (is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev));
|
|
+ (is_of_node(dev_fwnode(dev)) && !IS_ENABLED(CONFIG_PM));
|
|
if (full_power) {
|
|
ret = dw9768_runtime_resume(dev);
|
|
if (ret < 0) {
|
|
@@ -489,6 +488,7 @@ static int dw9768_probe(struct i2c_client *client)
|
|
pm_runtime_set_active(dev);
|
|
}
|
|
|
|
+ pm_runtime_enable(dev);
|
|
ret = v4l2_async_register_subdev(&dw9768->sd);
|
|
if (ret < 0) {
|
|
dev_err(dev, "failed to register V4L2 subdev: %d", ret);
|
|
@@ -500,12 +500,12 @@ static int dw9768_probe(struct i2c_client *client)
|
|
return 0;
|
|
|
|
err_power_off:
|
|
+ pm_runtime_disable(dev);
|
|
if (full_power) {
|
|
dw9768_runtime_suspend(dev);
|
|
pm_runtime_set_suspended(dev);
|
|
}
|
|
err_clean_entity:
|
|
- pm_runtime_disable(dev);
|
|
media_entity_cleanup(&dw9768->sd.entity);
|
|
err_free_handler:
|
|
v4l2_ctrl_handler_free(&dw9768->ctrls);
|
|
@@ -522,12 +522,12 @@ static void dw9768_remove(struct i2c_client *client)
|
|
v4l2_async_unregister_subdev(&dw9768->sd);
|
|
v4l2_ctrl_handler_free(&dw9768->ctrls);
|
|
media_entity_cleanup(&dw9768->sd.entity);
|
|
+ pm_runtime_disable(dev);
|
|
if ((is_acpi_node(dev_fwnode(dev)) && acpi_dev_state_d0(dev)) ||
|
|
- (is_of_node(dev_fwnode(dev)) && !pm_runtime_enabled(dev))) {
|
|
+ (is_of_node(dev_fwnode(dev)) && !IS_ENABLED(CONFIG_PM))) {
|
|
dw9768_runtime_suspend(dev);
|
|
pm_runtime_set_suspended(dev);
|
|
}
|
|
- pm_runtime_disable(dev);
|
|
}
|
|
|
|
static const struct of_device_id dw9768_of_table[] = {
|
|
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
|
|
index 558152575d1022..c81dd41834043f 100644
|
|
--- a/drivers/media/i2c/tc358743.c
|
|
+++ b/drivers/media/i2c/tc358743.c
|
|
@@ -2159,8 +2159,10 @@ static int tc358743_probe(struct i2c_client *client)
|
|
|
|
err_work_queues:
|
|
cec_unregister_adapter(state->cec_adap);
|
|
- if (!state->i2c_client->irq)
|
|
+ if (!state->i2c_client->irq) {
|
|
+ del_timer(&state->timer);
|
|
flush_work(&state->work_i2c_poll);
|
|
+ }
|
|
cancel_delayed_work(&state->delayed_work_enable_hotplug);
|
|
mutex_destroy(&state->confctl_mutex);
|
|
err_hdl:
|
|
diff --git a/drivers/media/platform/allegro-dvt/allegro-core.c b/drivers/media/platform/allegro-dvt/allegro-core.c
|
|
index da61f9beb6b4f5..7dffea2ad88a15 100644
|
|
--- a/drivers/media/platform/allegro-dvt/allegro-core.c
|
|
+++ b/drivers/media/platform/allegro-dvt/allegro-core.c
|
|
@@ -1509,8 +1509,10 @@ static int allocate_buffers_internal(struct allegro_channel *channel,
|
|
INIT_LIST_HEAD(&buffer->head);
|
|
|
|
err = allegro_alloc_buffer(dev, buffer, size);
|
|
- if (err)
|
|
+ if (err) {
|
|
+ kfree(buffer);
|
|
goto err;
|
|
+ }
|
|
list_add(&buffer->head, list);
|
|
}
|
|
|
|
diff --git a/drivers/media/platform/amphion/vpu_drv.c b/drivers/media/platform/amphion/vpu_drv.c
|
|
index 2bf70aafd2baab..51d5234869f57d 100644
|
|
--- a/drivers/media/platform/amphion/vpu_drv.c
|
|
+++ b/drivers/media/platform/amphion/vpu_drv.c
|
|
@@ -151,8 +151,8 @@ static int vpu_probe(struct platform_device *pdev)
|
|
media_device_cleanup(&vpu->mdev);
|
|
v4l2_device_unregister(&vpu->v4l2_dev);
|
|
err_vpu_deinit:
|
|
- pm_runtime_set_suspended(dev);
|
|
pm_runtime_disable(dev);
|
|
+ pm_runtime_set_suspended(dev);
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c
|
|
index d7e0de49b3dcef..61d27b63b99d47 100644
|
|
--- a/drivers/media/platform/amphion/vpu_v4l2.c
|
|
+++ b/drivers/media/platform/amphion/vpu_v4l2.c
|
|
@@ -825,6 +825,7 @@ int vpu_add_func(struct vpu_dev *vpu, struct vpu_func *func)
|
|
vfd->fops = vdec_get_fops();
|
|
vfd->ioctl_ops = vdec_get_ioctl_ops();
|
|
}
|
|
+ video_set_drvdata(vfd, vpu);
|
|
|
|
ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
|
|
if (ret) {
|
|
@@ -832,7 +833,6 @@ int vpu_add_func(struct vpu_dev *vpu, struct vpu_func *func)
|
|
v4l2_m2m_release(func->m2m_dev);
|
|
return ret;
|
|
}
|
|
- video_set_drvdata(vfd, vpu);
|
|
func->vfd = vfd;
|
|
|
|
ret = v4l2_m2m_register_media_controller(func->m2m_dev, func->vfd, func->function);
|
|
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
|
|
index c3456c700c07e2..4c7b46f5a7ddd5 100644
|
|
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
|
|
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
|
|
@@ -1294,6 +1294,11 @@ static int mtk_jpeg_single_core_init(struct platform_device *pdev,
|
|
return 0;
|
|
}
|
|
|
|
+static void mtk_jpeg_destroy_workqueue(void *data)
|
|
+{
|
|
+ destroy_workqueue(data);
|
|
+}
|
|
+
|
|
static int mtk_jpeg_probe(struct platform_device *pdev)
|
|
{
|
|
struct mtk_jpeg_dev *jpeg;
|
|
@@ -1338,6 +1343,11 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
|
|
| WQ_FREEZABLE);
|
|
if (!jpeg->workqueue)
|
|
return -EINVAL;
|
|
+ ret = devm_add_action_or_reset(&pdev->dev,
|
|
+ mtk_jpeg_destroy_workqueue,
|
|
+ jpeg->workqueue);
|
|
+ if (ret)
|
|
+ return ret;
|
|
}
|
|
|
|
ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
|
|
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
|
|
index 4a6ee211e18f97..2c5d74939d0a92 100644
|
|
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
|
|
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
|
|
@@ -578,11 +578,6 @@ static int mtk_jpegdec_hw_init_irq(struct mtk_jpegdec_comp_dev *dev)
|
|
return 0;
|
|
}
|
|
|
|
-static void mtk_jpegdec_destroy_workqueue(void *data)
|
|
-{
|
|
- destroy_workqueue(data);
|
|
-}
|
|
-
|
|
static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
|
|
{
|
|
struct mtk_jpegdec_clk *jpegdec_clk;
|
|
@@ -606,12 +601,6 @@ static int mtk_jpegdec_hw_probe(struct platform_device *pdev)
|
|
dev->plat_dev = pdev;
|
|
dev->dev = &pdev->dev;
|
|
|
|
- ret = devm_add_action_or_reset(&pdev->dev,
|
|
- mtk_jpegdec_destroy_workqueue,
|
|
- master_dev->workqueue);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
spin_lock_init(&dev->hw_lock);
|
|
dev->hw_state = MTK_JPEG_HW_IDLE;
|
|
|
|
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
|
|
index 2007152cd7a40d..e8dcd44f6e4692 100644
|
|
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
|
|
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
|
|
@@ -2674,6 +2674,8 @@ static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg)
|
|
int i;
|
|
|
|
for (i = 0; i < jpeg->num_domains; i++) {
|
|
+ if (jpeg->pd_dev[i] && !pm_runtime_suspended(jpeg->pd_dev[i]))
|
|
+ pm_runtime_force_suspend(jpeg->pd_dev[i]);
|
|
if (jpeg->pd_link[i] && !IS_ERR(jpeg->pd_link[i]))
|
|
device_link_del(jpeg->pd_link[i]);
|
|
if (jpeg->pd_dev[i] && !IS_ERR(jpeg->pd_dev[i]))
|
|
@@ -2837,6 +2839,7 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
|
|
jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
|
|
jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |
|
|
V4L2_CAP_VIDEO_M2M_MPLANE;
|
|
+ video_set_drvdata(jpeg->dec_vdev, jpeg);
|
|
if (mode == MXC_JPEG_ENCODE) {
|
|
v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_DECODER_CMD);
|
|
v4l2_disable_ioctl(jpeg->dec_vdev, VIDIOC_TRY_DECODER_CMD);
|
|
@@ -2849,7 +2852,6 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
|
|
dev_err(dev, "failed to register video device\n");
|
|
goto err_vdev_register;
|
|
}
|
|
- video_set_drvdata(jpeg->dec_vdev, jpeg);
|
|
if (mode == MXC_JPEG_ENCODE)
|
|
v4l2_info(&jpeg->v4l2_dev,
|
|
"encoder device registered as /dev/video%d (%d,%d)\n",
|
|
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
|
|
index 0fc9414f8f1849..b570eb8c37568f 100644
|
|
--- a/drivers/media/platform/qcom/venus/core.c
|
|
+++ b/drivers/media/platform/qcom/venus/core.c
|
|
@@ -406,8 +406,8 @@ static int venus_probe(struct platform_device *pdev)
|
|
of_platform_depopulate(dev);
|
|
err_runtime_disable:
|
|
pm_runtime_put_noidle(dev);
|
|
- pm_runtime_set_suspended(dev);
|
|
pm_runtime_disable(dev);
|
|
+ pm_runtime_set_suspended(dev);
|
|
hfi_destroy(core);
|
|
err_core_deinit:
|
|
hfi_core_deinit(core, false);
|
|
diff --git a/drivers/media/platform/samsung/exynos4-is/media-dev.h b/drivers/media/platform/samsung/exynos4-is/media-dev.h
|
|
index 786264cf79dc14..a50e58ab7ef773 100644
|
|
--- a/drivers/media/platform/samsung/exynos4-is/media-dev.h
|
|
+++ b/drivers/media/platform/samsung/exynos4-is/media-dev.h
|
|
@@ -178,8 +178,9 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
|
|
#ifdef CONFIG_OF
|
|
static inline bool fimc_md_is_isp_available(struct device_node *node)
|
|
{
|
|
- node = of_get_child_by_name(node, FIMC_IS_OF_NODE_NAME);
|
|
- return node ? of_device_is_available(node) : false;
|
|
+ struct device_node *child __free(device_node) =
|
|
+ of_get_child_by_name(node, FIMC_IS_OF_NODE_NAME);
|
|
+ return child ? of_device_is_available(child) : false;
|
|
}
|
|
#else
|
|
#define fimc_md_is_isp_available(node) (false)
|
|
diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
|
|
index cc4483857489c5..ff78b31728290d 100644
|
|
--- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
|
|
+++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c
|
|
@@ -161,8 +161,7 @@ static int rockchip_vpu981_av1_dec_frame_ref(struct hantro_ctx *ctx,
|
|
av1_dec->frame_refs[i].timestamp = timestamp;
|
|
av1_dec->frame_refs[i].frame_type = frame->frame_type;
|
|
av1_dec->frame_refs[i].order_hint = frame->order_hint;
|
|
- if (!av1_dec->frame_refs[i].vb2_ref)
|
|
- av1_dec->frame_refs[i].vb2_ref = hantro_get_dst_buf(ctx);
|
|
+ av1_dec->frame_refs[i].vb2_ref = hantro_get_dst_buf(ctx);
|
|
|
|
for (j = 0; j < V4L2_AV1_TOTAL_REFS_PER_FRAME; j++)
|
|
av1_dec->frame_refs[i].order_hints[j] = frame->order_hints[j];
|
|
diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c
|
|
index 3da8e5102becc2..1225dab9fc7d3e 100644
|
|
--- a/drivers/media/radio/wl128x/fmdrv_common.c
|
|
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
|
|
@@ -466,11 +466,12 @@ int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
|
|
jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
|
|
return -ETIMEDOUT;
|
|
}
|
|
+ spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
|
|
if (!fmdev->resp_skb) {
|
|
+ spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
|
|
fmerr("Response SKB is missing\n");
|
|
return -EFAULT;
|
|
}
|
|
- spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
|
|
skb = fmdev->resp_skb;
|
|
fmdev->resp_skb = NULL;
|
|
spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
|
|
diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
|
|
index 99325bfed64310..9443dbb04699a3 100644
|
|
--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c
|
|
+++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
|
|
@@ -1466,12 +1466,19 @@ static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings)
|
|
h_freq = (u32)bt->pixelclock / total_h_pixel;
|
|
|
|
if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_CVT)) {
|
|
+ struct v4l2_dv_timings cvt = {};
|
|
+
|
|
if (v4l2_detect_cvt(total_v_lines, h_freq, bt->vsync, bt->width,
|
|
- bt->polarities, bt->interlaced, timings))
|
|
+ bt->polarities, bt->interlaced,
|
|
+ &vivid_dv_timings_cap, &cvt) &&
|
|
+ cvt.bt.width == bt->width && cvt.bt.height == bt->height) {
|
|
+ *timings = cvt;
|
|
return true;
|
|
+ }
|
|
}
|
|
|
|
if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_GTF)) {
|
|
+ struct v4l2_dv_timings gtf = {};
|
|
struct v4l2_fract aspect_ratio;
|
|
|
|
find_aspect_ratio(bt->width, bt->height,
|
|
@@ -1479,8 +1486,12 @@ static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings)
|
|
&aspect_ratio.denominator);
|
|
if (v4l2_detect_gtf(total_v_lines, h_freq, bt->vsync,
|
|
bt->polarities, bt->interlaced,
|
|
- aspect_ratio, timings))
|
|
+ aspect_ratio, &vivid_dv_timings_cap,
|
|
+ >f) &&
|
|
+ gtf.bt.width == bt->width && gtf.bt.height == bt->height) {
|
|
+ *timings = gtf;
|
|
return true;
|
|
+ }
|
|
}
|
|
return false;
|
|
}
|
|
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c
|
|
index 8b6a57f170d0dd..bdff64a29a33a2 100644
|
|
--- a/drivers/media/usb/gspca/ov534.c
|
|
+++ b/drivers/media/usb/gspca/ov534.c
|
|
@@ -847,7 +847,7 @@ static void set_frame_rate(struct gspca_dev *gspca_dev)
|
|
r = rate_1;
|
|
i = ARRAY_SIZE(rate_1);
|
|
}
|
|
- while (--i > 0) {
|
|
+ while (--i >= 0) {
|
|
if (sd->frame_rate >= r->fps)
|
|
break;
|
|
r++;
|
|
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
|
|
index 37d75bc97fd8dc..1385cbf462d172 100644
|
|
--- a/drivers/media/usb/uvc/uvc_driver.c
|
|
+++ b/drivers/media/usb/uvc/uvc_driver.c
|
|
@@ -775,14 +775,27 @@ static const u8 uvc_media_transport_input_guid[16] =
|
|
UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT;
|
|
static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING;
|
|
|
|
-static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id,
|
|
- unsigned int num_pads, unsigned int extra_size)
|
|
+static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type,
|
|
+ u16 id, unsigned int num_pads,
|
|
+ unsigned int extra_size)
|
|
{
|
|
struct uvc_entity *entity;
|
|
unsigned int num_inputs;
|
|
unsigned int size;
|
|
unsigned int i;
|
|
|
|
+ /* Per UVC 1.1+ spec 3.7.2, the ID should be non-zero. */
|
|
+ if (id == 0) {
|
|
+ dev_err(&dev->udev->dev, "Found Unit with invalid ID 0.\n");
|
|
+ return ERR_PTR(-EINVAL);
|
|
+ }
|
|
+
|
|
+ /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */
|
|
+ if (uvc_entity_by_id(dev, id)) {
|
|
+ dev_err(&dev->udev->dev, "Found multiple Units with ID %u\n", id);
|
|
+ return ERR_PTR(-EINVAL);
|
|
+ }
|
|
+
|
|
extra_size = roundup(extra_size, sizeof(*entity->pads));
|
|
if (num_pads)
|
|
num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1;
|
|
@@ -792,7 +805,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id,
|
|
+ num_inputs;
|
|
entity = kzalloc(size, GFP_KERNEL);
|
|
if (entity == NULL)
|
|
- return NULL;
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
|
entity->id = id;
|
|
entity->type = type;
|
|
@@ -904,10 +917,10 @@ static int uvc_parse_vendor_control(struct uvc_device *dev,
|
|
break;
|
|
}
|
|
|
|
- unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
|
|
- p + 1, 2*n);
|
|
- if (unit == NULL)
|
|
- return -ENOMEM;
|
|
+ unit = uvc_alloc_new_entity(dev, UVC_VC_EXTENSION_UNIT,
|
|
+ buffer[3], p + 1, 2 * n);
|
|
+ if (IS_ERR(unit))
|
|
+ return PTR_ERR(unit);
|
|
|
|
memcpy(unit->guid, &buffer[4], 16);
|
|
unit->extension.bNumControls = buffer[20];
|
|
@@ -1016,10 +1029,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
|
|
- 1, n + p);
|
|
- if (term == NULL)
|
|
- return -ENOMEM;
|
|
+ term = uvc_alloc_new_entity(dev, type | UVC_TERM_INPUT,
|
|
+ buffer[3], 1, n + p);
|
|
+ if (IS_ERR(term))
|
|
+ return PTR_ERR(term);
|
|
|
|
if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
|
|
term->camera.bControlSize = n;
|
|
@@ -1075,10 +1088,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
return 0;
|
|
}
|
|
|
|
- term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
|
|
- 1, 0);
|
|
- if (term == NULL)
|
|
- return -ENOMEM;
|
|
+ term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT,
|
|
+ buffer[3], 1, 0);
|
|
+ if (IS_ERR(term))
|
|
+ return PTR_ERR(term);
|
|
|
|
memcpy(term->baSourceID, &buffer[7], 1);
|
|
|
|
@@ -1097,9 +1110,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
|
|
- if (unit == NULL)
|
|
- return -ENOMEM;
|
|
+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3],
|
|
+ p + 1, 0);
|
|
+ if (IS_ERR(unit))
|
|
+ return PTR_ERR(unit);
|
|
|
|
memcpy(unit->baSourceID, &buffer[5], p);
|
|
|
|
@@ -1119,9 +1133,9 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
|
|
- if (unit == NULL)
|
|
- return -ENOMEM;
|
|
+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], 2, n);
|
|
+ if (IS_ERR(unit))
|
|
+ return PTR_ERR(unit);
|
|
|
|
memcpy(unit->baSourceID, &buffer[4], 1);
|
|
unit->processing.wMaxMultiplier =
|
|
@@ -1148,9 +1162,10 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
|
|
- if (unit == NULL)
|
|
- return -ENOMEM;
|
|
+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3],
|
|
+ p + 1, n);
|
|
+ if (IS_ERR(unit))
|
|
+ return PTR_ERR(unit);
|
|
|
|
memcpy(unit->guid, &buffer[4], 16);
|
|
unit->extension.bNumControls = buffer[20];
|
|
@@ -1290,9 +1305,10 @@ static int uvc_gpio_parse(struct uvc_device *dev)
|
|
return dev_err_probe(&dev->udev->dev, irq,
|
|
"No IRQ for privacy GPIO\n");
|
|
|
|
- unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1);
|
|
- if (!unit)
|
|
- return -ENOMEM;
|
|
+ unit = uvc_alloc_new_entity(dev, UVC_EXT_GPIO_UNIT,
|
|
+ UVC_EXT_GPIO_UNIT_ID, 0, 1);
|
|
+ if (IS_ERR(unit))
|
|
+ return PTR_ERR(unit);
|
|
|
|
unit->gpio.gpio_privacy = gpio_privacy;
|
|
unit->gpio.irq = irq;
|
|
@@ -1919,11 +1935,41 @@ static void uvc_unregister_video(struct uvc_device *dev)
|
|
struct uvc_streaming *stream;
|
|
|
|
list_for_each_entry(stream, &dev->streams, list) {
|
|
+ /* Nothing to do here, continue. */
|
|
if (!video_is_registered(&stream->vdev))
|
|
continue;
|
|
|
|
+ /*
|
|
+ * For stream->vdev we follow the same logic as:
|
|
+ * vb2_video_unregister_device().
|
|
+ */
|
|
+
|
|
+ /* 1. Take a reference to vdev */
|
|
+ get_device(&stream->vdev.dev);
|
|
+
|
|
+ /* 2. Ensure that no new ioctls can be called. */
|
|
video_unregister_device(&stream->vdev);
|
|
- video_unregister_device(&stream->meta.vdev);
|
|
+
|
|
+ /* 3. Wait for old ioctls to finish. */
|
|
+ mutex_lock(&stream->mutex);
|
|
+
|
|
+ /* 4. Stop streaming. */
|
|
+ uvc_queue_release(&stream->queue);
|
|
+
|
|
+ mutex_unlock(&stream->mutex);
|
|
+
|
|
+ put_device(&stream->vdev.dev);
|
|
+
|
|
+ /*
|
|
+ * For stream->meta.vdev we can directly call:
|
|
+ * vb2_video_unregister_device().
|
|
+ */
|
|
+ vb2_video_unregister_device(&stream->meta.vdev);
|
|
+
|
|
+ /*
|
|
+ * Now both vdevs are not streaming and all the ioctls will
|
|
+ * return -ENODEV.
|
|
+ */
|
|
|
|
uvc_debugfs_cleanup_stream(stream);
|
|
}
|
|
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c
|
|
index 942d0005c55e82..2cf5dcee0ce800 100644
|
|
--- a/drivers/media/v4l2-core/v4l2-dv-timings.c
|
|
+++ b/drivers/media/v4l2-core/v4l2-dv-timings.c
|
|
@@ -481,25 +481,28 @@ EXPORT_SYMBOL_GPL(v4l2_calc_timeperframe);
|
|
* @polarities - the horizontal and vertical polarities (same as struct
|
|
* v4l2_bt_timings polarities).
|
|
* @interlaced - if this flag is true, it indicates interlaced format
|
|
- * @fmt - the resulting timings.
|
|
+ * @cap - the v4l2_dv_timings_cap capabilities.
|
|
+ * @timings - the resulting timings.
|
|
*
|
|
* This function will attempt to detect if the given values correspond to a
|
|
* valid CVT format. If so, then it will return true, and fmt will be filled
|
|
* in with the found CVT timings.
|
|
*/
|
|
-bool v4l2_detect_cvt(unsigned frame_height,
|
|
- unsigned hfreq,
|
|
- unsigned vsync,
|
|
- unsigned active_width,
|
|
+bool v4l2_detect_cvt(unsigned int frame_height,
|
|
+ unsigned int hfreq,
|
|
+ unsigned int vsync,
|
|
+ unsigned int active_width,
|
|
u32 polarities,
|
|
bool interlaced,
|
|
- struct v4l2_dv_timings *fmt)
|
|
+ const struct v4l2_dv_timings_cap *cap,
|
|
+ struct v4l2_dv_timings *timings)
|
|
{
|
|
- int v_fp, v_bp, h_fp, h_bp, hsync;
|
|
- int frame_width, image_height, image_width;
|
|
+ struct v4l2_dv_timings t = {};
|
|
+ int v_fp, v_bp, h_fp, h_bp, hsync;
|
|
+ int frame_width, image_height, image_width;
|
|
bool reduced_blanking;
|
|
bool rb_v2 = false;
|
|
- unsigned pix_clk;
|
|
+ unsigned int pix_clk;
|
|
|
|
if (vsync < 4 || vsync > 8)
|
|
return false;
|
|
@@ -625,36 +628,39 @@ bool v4l2_detect_cvt(unsigned frame_height,
|
|
h_fp = h_blank - hsync - h_bp;
|
|
}
|
|
|
|
- fmt->type = V4L2_DV_BT_656_1120;
|
|
- fmt->bt.polarities = polarities;
|
|
- fmt->bt.width = image_width;
|
|
- fmt->bt.height = image_height;
|
|
- fmt->bt.hfrontporch = h_fp;
|
|
- fmt->bt.vfrontporch = v_fp;
|
|
- fmt->bt.hsync = hsync;
|
|
- fmt->bt.vsync = vsync;
|
|
- fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
|
|
+ t.type = V4L2_DV_BT_656_1120;
|
|
+ t.bt.polarities = polarities;
|
|
+ t.bt.width = image_width;
|
|
+ t.bt.height = image_height;
|
|
+ t.bt.hfrontporch = h_fp;
|
|
+ t.bt.vfrontporch = v_fp;
|
|
+ t.bt.hsync = hsync;
|
|
+ t.bt.vsync = vsync;
|
|
+ t.bt.hbackporch = frame_width - image_width - h_fp - hsync;
|
|
|
|
if (!interlaced) {
|
|
- fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
|
|
- fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
|
|
+ t.bt.vbackporch = frame_height - image_height - v_fp - vsync;
|
|
+ t.bt.interlaced = V4L2_DV_PROGRESSIVE;
|
|
} else {
|
|
- fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
|
|
+ t.bt.vbackporch = (frame_height - image_height - 2 * v_fp -
|
|
2 * vsync) / 2;
|
|
- fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
|
|
- 2 * vsync - fmt->bt.vbackporch;
|
|
- fmt->bt.il_vfrontporch = v_fp;
|
|
- fmt->bt.il_vsync = vsync;
|
|
- fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
|
|
- fmt->bt.interlaced = V4L2_DV_INTERLACED;
|
|
+ t.bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
|
|
+ 2 * vsync - t.bt.vbackporch;
|
|
+ t.bt.il_vfrontporch = v_fp;
|
|
+ t.bt.il_vsync = vsync;
|
|
+ t.bt.flags |= V4L2_DV_FL_HALF_LINE;
|
|
+ t.bt.interlaced = V4L2_DV_INTERLACED;
|
|
}
|
|
|
|
- fmt->bt.pixelclock = pix_clk;
|
|
- fmt->bt.standards = V4L2_DV_BT_STD_CVT;
|
|
+ t.bt.pixelclock = pix_clk;
|
|
+ t.bt.standards = V4L2_DV_BT_STD_CVT;
|
|
|
|
if (reduced_blanking)
|
|
- fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
|
|
+ t.bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
|
|
|
|
+ if (!v4l2_valid_dv_timings(&t, cap, NULL, NULL))
|
|
+ return false;
|
|
+ *timings = t;
|
|
return true;
|
|
}
|
|
EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
|
|
@@ -699,22 +705,25 @@ EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
|
|
* image height, so it has to be passed explicitly. Usually
|
|
* the native screen aspect ratio is used for this. If it
|
|
* is not filled in correctly, then 16:9 will be assumed.
|
|
- * @fmt - the resulting timings.
|
|
+ * @cap - the v4l2_dv_timings_cap capabilities.
|
|
+ * @timings - the resulting timings.
|
|
*
|
|
* This function will attempt to detect if the given values correspond to a
|
|
* valid GTF format. If so, then it will return true, and fmt will be filled
|
|
* in with the found GTF timings.
|
|
*/
|
|
-bool v4l2_detect_gtf(unsigned frame_height,
|
|
- unsigned hfreq,
|
|
- unsigned vsync,
|
|
- u32 polarities,
|
|
- bool interlaced,
|
|
- struct v4l2_fract aspect,
|
|
- struct v4l2_dv_timings *fmt)
|
|
+bool v4l2_detect_gtf(unsigned int frame_height,
|
|
+ unsigned int hfreq,
|
|
+ unsigned int vsync,
|
|
+ u32 polarities,
|
|
+ bool interlaced,
|
|
+ struct v4l2_fract aspect,
|
|
+ const struct v4l2_dv_timings_cap *cap,
|
|
+ struct v4l2_dv_timings *timings)
|
|
{
|
|
+ struct v4l2_dv_timings t = {};
|
|
int pix_clk;
|
|
- int v_fp, v_bp, h_fp, hsync;
|
|
+ int v_fp, v_bp, h_fp, hsync;
|
|
int frame_width, image_height, image_width;
|
|
bool default_gtf;
|
|
int h_blank;
|
|
@@ -783,36 +792,39 @@ bool v4l2_detect_gtf(unsigned frame_height,
|
|
|
|
h_fp = h_blank / 2 - hsync;
|
|
|
|
- fmt->type = V4L2_DV_BT_656_1120;
|
|
- fmt->bt.polarities = polarities;
|
|
- fmt->bt.width = image_width;
|
|
- fmt->bt.height = image_height;
|
|
- fmt->bt.hfrontporch = h_fp;
|
|
- fmt->bt.vfrontporch = v_fp;
|
|
- fmt->bt.hsync = hsync;
|
|
- fmt->bt.vsync = vsync;
|
|
- fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
|
|
+ t.type = V4L2_DV_BT_656_1120;
|
|
+ t.bt.polarities = polarities;
|
|
+ t.bt.width = image_width;
|
|
+ t.bt.height = image_height;
|
|
+ t.bt.hfrontporch = h_fp;
|
|
+ t.bt.vfrontporch = v_fp;
|
|
+ t.bt.hsync = hsync;
|
|
+ t.bt.vsync = vsync;
|
|
+ t.bt.hbackporch = frame_width - image_width - h_fp - hsync;
|
|
|
|
if (!interlaced) {
|
|
- fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
|
|
- fmt->bt.interlaced = V4L2_DV_PROGRESSIVE;
|
|
+ t.bt.vbackporch = frame_height - image_height - v_fp - vsync;
|
|
+ t.bt.interlaced = V4L2_DV_PROGRESSIVE;
|
|
} else {
|
|
- fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp -
|
|
+ t.bt.vbackporch = (frame_height - image_height - 2 * v_fp -
|
|
2 * vsync) / 2;
|
|
- fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
|
|
- 2 * vsync - fmt->bt.vbackporch;
|
|
- fmt->bt.il_vfrontporch = v_fp;
|
|
- fmt->bt.il_vsync = vsync;
|
|
- fmt->bt.flags |= V4L2_DV_FL_HALF_LINE;
|
|
- fmt->bt.interlaced = V4L2_DV_INTERLACED;
|
|
+ t.bt.il_vbackporch = frame_height - image_height - 2 * v_fp -
|
|
+ 2 * vsync - t.bt.vbackporch;
|
|
+ t.bt.il_vfrontporch = v_fp;
|
|
+ t.bt.il_vsync = vsync;
|
|
+ t.bt.flags |= V4L2_DV_FL_HALF_LINE;
|
|
+ t.bt.interlaced = V4L2_DV_INTERLACED;
|
|
}
|
|
|
|
- fmt->bt.pixelclock = pix_clk;
|
|
- fmt->bt.standards = V4L2_DV_BT_STD_GTF;
|
|
+ t.bt.pixelclock = pix_clk;
|
|
+ t.bt.standards = V4L2_DV_BT_STD_GTF;
|
|
|
|
if (!default_gtf)
|
|
- fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
|
|
+ t.bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
|
|
|
|
+ if (!v4l2_valid_dv_timings(&t, cap, NULL, NULL))
|
|
+ return false;
|
|
+ *timings = t;
|
|
return true;
|
|
}
|
|
EXPORT_SYMBOL_GPL(v4l2_detect_gtf);
|
|
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
|
|
index 86f16f3ea47870..d97057f46ca864 100644
|
|
--- a/drivers/message/fusion/mptsas.c
|
|
+++ b/drivers/message/fusion/mptsas.c
|
|
@@ -4234,10 +4234,8 @@ mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
|
|
static void
|
|
mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
|
|
{
|
|
- int rc;
|
|
-
|
|
sdev->no_uld_attach = data ? 1 : 0;
|
|
- rc = scsi_device_reprobe(sdev);
|
|
+ WARN_ON(scsi_device_reprobe(sdev));
|
|
}
|
|
|
|
static void
|
|
diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c
|
|
index be5f2b34e18aeb..80fc5c0cac2fb0 100644
|
|
--- a/drivers/mfd/da9052-spi.c
|
|
+++ b/drivers/mfd/da9052-spi.c
|
|
@@ -37,7 +37,7 @@ static int da9052_spi_probe(struct spi_device *spi)
|
|
spi_set_drvdata(spi, da9052);
|
|
|
|
config = da9052_regmap_config;
|
|
- config.read_flag_mask = 1;
|
|
+ config.write_flag_mask = 1;
|
|
config.reg_bits = 7;
|
|
config.pad_bits = 1;
|
|
config.val_bits = 8;
|
|
diff --git a/drivers/mfd/intel_soc_pmic_bxtwc.c b/drivers/mfd/intel_soc_pmic_bxtwc.c
|
|
index 8dac0d41f64f3e..3aa7857271dadb 100644
|
|
--- a/drivers/mfd/intel_soc_pmic_bxtwc.c
|
|
+++ b/drivers/mfd/intel_soc_pmic_bxtwc.c
|
|
@@ -231,44 +231,55 @@ static const struct resource tmu_resources[] = {
|
|
};
|
|
|
|
static struct mfd_cell bxt_wc_dev[] = {
|
|
- {
|
|
- .name = "bxt_wcove_gpadc",
|
|
- .num_resources = ARRAY_SIZE(adc_resources),
|
|
- .resources = adc_resources,
|
|
- },
|
|
{
|
|
.name = "bxt_wcove_thermal",
|
|
.num_resources = ARRAY_SIZE(thermal_resources),
|
|
.resources = thermal_resources,
|
|
},
|
|
{
|
|
- .name = "bxt_wcove_usbc",
|
|
- .num_resources = ARRAY_SIZE(usbc_resources),
|
|
- .resources = usbc_resources,
|
|
+ .name = "bxt_wcove_gpio",
|
|
+ .num_resources = ARRAY_SIZE(gpio_resources),
|
|
+ .resources = gpio_resources,
|
|
},
|
|
{
|
|
- .name = "bxt_wcove_ext_charger",
|
|
- .num_resources = ARRAY_SIZE(charger_resources),
|
|
- .resources = charger_resources,
|
|
+ .name = "bxt_wcove_region",
|
|
+ },
|
|
+};
|
|
+
|
|
+static const struct mfd_cell bxt_wc_tmu_dev[] = {
|
|
+ {
|
|
+ .name = "bxt_wcove_tmu",
|
|
+ .num_resources = ARRAY_SIZE(tmu_resources),
|
|
+ .resources = tmu_resources,
|
|
},
|
|
+};
|
|
+
|
|
+static const struct mfd_cell bxt_wc_bcu_dev[] = {
|
|
{
|
|
.name = "bxt_wcove_bcu",
|
|
.num_resources = ARRAY_SIZE(bcu_resources),
|
|
.resources = bcu_resources,
|
|
},
|
|
+};
|
|
+
|
|
+static const struct mfd_cell bxt_wc_adc_dev[] = {
|
|
{
|
|
- .name = "bxt_wcove_tmu",
|
|
- .num_resources = ARRAY_SIZE(tmu_resources),
|
|
- .resources = tmu_resources,
|
|
+ .name = "bxt_wcove_gpadc",
|
|
+ .num_resources = ARRAY_SIZE(adc_resources),
|
|
+ .resources = adc_resources,
|
|
},
|
|
+};
|
|
|
|
+static struct mfd_cell bxt_wc_chgr_dev[] = {
|
|
{
|
|
- .name = "bxt_wcove_gpio",
|
|
- .num_resources = ARRAY_SIZE(gpio_resources),
|
|
- .resources = gpio_resources,
|
|
+ .name = "bxt_wcove_usbc",
|
|
+ .num_resources = ARRAY_SIZE(usbc_resources),
|
|
+ .resources = usbc_resources,
|
|
},
|
|
{
|
|
- .name = "bxt_wcove_region",
|
|
+ .name = "bxt_wcove_ext_charger",
|
|
+ .num_resources = ARRAY_SIZE(charger_resources),
|
|
+ .resources = charger_resources,
|
|
},
|
|
};
|
|
|
|
@@ -426,6 +437,26 @@ static int bxtwc_add_chained_irq_chip(struct intel_soc_pmic *pmic,
|
|
0, chip, data);
|
|
}
|
|
|
|
+static int bxtwc_add_chained_devices(struct intel_soc_pmic *pmic,
|
|
+ const struct mfd_cell *cells, int n_devs,
|
|
+ struct regmap_irq_chip_data *pdata,
|
|
+ int pirq, int irq_flags,
|
|
+ const struct regmap_irq_chip *chip,
|
|
+ struct regmap_irq_chip_data **data)
|
|
+{
|
|
+ struct device *dev = pmic->dev;
|
|
+ struct irq_domain *domain;
|
|
+ int ret;
|
|
+
|
|
+ ret = bxtwc_add_chained_irq_chip(pmic, pdata, pirq, irq_flags, chip, data);
|
|
+ if (ret)
|
|
+ return dev_err_probe(dev, ret, "Failed to add %s IRQ chip\n", chip->name);
|
|
+
|
|
+ domain = regmap_irq_get_domain(*data);
|
|
+
|
|
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, cells, n_devs, NULL, 0, domain);
|
|
+}
|
|
+
|
|
static int bxtwc_probe(struct platform_device *pdev)
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
@@ -467,6 +498,15 @@ static int bxtwc_probe(struct platform_device *pdev)
|
|
if (ret)
|
|
return dev_err_probe(dev, ret, "Failed to add IRQ chip\n");
|
|
|
|
+ ret = bxtwc_add_chained_devices(pmic, bxt_wc_tmu_dev, ARRAY_SIZE(bxt_wc_tmu_dev),
|
|
+ pmic->irq_chip_data,
|
|
+ BXTWC_TMU_LVL1_IRQ,
|
|
+ IRQF_ONESHOT,
|
|
+ &bxtwc_regmap_irq_chip_tmu,
|
|
+ &pmic->irq_chip_data_tmu);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
|
|
BXTWC_PWRBTN_LVL1_IRQ,
|
|
IRQF_ONESHOT,
|
|
@@ -475,40 +515,32 @@ static int bxtwc_probe(struct platform_device *pdev)
|
|
if (ret)
|
|
return dev_err_probe(dev, ret, "Failed to add PWRBTN IRQ chip\n");
|
|
|
|
- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
|
|
- BXTWC_TMU_LVL1_IRQ,
|
|
- IRQF_ONESHOT,
|
|
- &bxtwc_regmap_irq_chip_tmu,
|
|
- &pmic->irq_chip_data_tmu);
|
|
- if (ret)
|
|
- return dev_err_probe(dev, ret, "Failed to add TMU IRQ chip\n");
|
|
-
|
|
- /* Add chained IRQ handler for BCU IRQs */
|
|
- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
|
|
- BXTWC_BCU_LVL1_IRQ,
|
|
- IRQF_ONESHOT,
|
|
- &bxtwc_regmap_irq_chip_bcu,
|
|
- &pmic->irq_chip_data_bcu);
|
|
+ ret = bxtwc_add_chained_devices(pmic, bxt_wc_bcu_dev, ARRAY_SIZE(bxt_wc_bcu_dev),
|
|
+ pmic->irq_chip_data,
|
|
+ BXTWC_BCU_LVL1_IRQ,
|
|
+ IRQF_ONESHOT,
|
|
+ &bxtwc_regmap_irq_chip_bcu,
|
|
+ &pmic->irq_chip_data_bcu);
|
|
if (ret)
|
|
- return dev_err_probe(dev, ret, "Failed to add BUC IRQ chip\n");
|
|
+ return ret;
|
|
|
|
- /* Add chained IRQ handler for ADC IRQs */
|
|
- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
|
|
- BXTWC_ADC_LVL1_IRQ,
|
|
- IRQF_ONESHOT,
|
|
- &bxtwc_regmap_irq_chip_adc,
|
|
- &pmic->irq_chip_data_adc);
|
|
+ ret = bxtwc_add_chained_devices(pmic, bxt_wc_adc_dev, ARRAY_SIZE(bxt_wc_adc_dev),
|
|
+ pmic->irq_chip_data,
|
|
+ BXTWC_ADC_LVL1_IRQ,
|
|
+ IRQF_ONESHOT,
|
|
+ &bxtwc_regmap_irq_chip_adc,
|
|
+ &pmic->irq_chip_data_adc);
|
|
if (ret)
|
|
- return dev_err_probe(dev, ret, "Failed to add ADC IRQ chip\n");
|
|
+ return ret;
|
|
|
|
- /* Add chained IRQ handler for CHGR IRQs */
|
|
- ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
|
|
- BXTWC_CHGR_LVL1_IRQ,
|
|
- IRQF_ONESHOT,
|
|
- &bxtwc_regmap_irq_chip_chgr,
|
|
- &pmic->irq_chip_data_chgr);
|
|
+ ret = bxtwc_add_chained_devices(pmic, bxt_wc_chgr_dev, ARRAY_SIZE(bxt_wc_chgr_dev),
|
|
+ pmic->irq_chip_data,
|
|
+ BXTWC_CHGR_LVL1_IRQ,
|
|
+ IRQF_ONESHOT,
|
|
+ &bxtwc_regmap_irq_chip_chgr,
|
|
+ &pmic->irq_chip_data_chgr);
|
|
if (ret)
|
|
- return dev_err_probe(dev, ret, "Failed to add CHGR IRQ chip\n");
|
|
+ return ret;
|
|
|
|
/* Add chained IRQ handler for CRIT IRQs */
|
|
ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
|
|
diff --git a/drivers/mfd/rt5033.c b/drivers/mfd/rt5033.c
|
|
index 7e23ab3d5842c8..84ebc96f58e48d 100644
|
|
--- a/drivers/mfd/rt5033.c
|
|
+++ b/drivers/mfd/rt5033.c
|
|
@@ -81,8 +81,8 @@ static int rt5033_i2c_probe(struct i2c_client *i2c)
|
|
chip_rev = dev_id & RT5033_CHIP_REV_MASK;
|
|
dev_info(&i2c->dev, "Device found (rev. %d)\n", chip_rev);
|
|
|
|
- ret = regmap_add_irq_chip(rt5033->regmap, rt5033->irq,
|
|
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
|
+ ret = devm_regmap_add_irq_chip(rt5033->dev, rt5033->regmap,
|
|
+ rt5033->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
|
0, &rt5033_irq_chip, &rt5033->irq_data);
|
|
if (ret) {
|
|
dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
|
|
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
|
|
index 2b9105295f3012..710364435b6b9e 100644
|
|
--- a/drivers/mfd/tps65010.c
|
|
+++ b/drivers/mfd/tps65010.c
|
|
@@ -544,17 +544,13 @@ static int tps65010_probe(struct i2c_client *client)
|
|
*/
|
|
if (client->irq > 0) {
|
|
status = request_irq(client->irq, tps65010_irq,
|
|
- IRQF_TRIGGER_FALLING, DRIVER_NAME, tps);
|
|
+ IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN,
|
|
+ DRIVER_NAME, tps);
|
|
if (status < 0) {
|
|
dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
|
|
client->irq, status);
|
|
return status;
|
|
}
|
|
- /* annoying race here, ideally we'd have an option
|
|
- * to claim the irq now and enable it later.
|
|
- * FIXME genirq IRQF_NOAUTOEN now solves that ...
|
|
- */
|
|
- disable_irq(client->irq);
|
|
set_bit(FLAG_IRQ_ENABLE, &tps->flags);
|
|
} else
|
|
dev_warn(&client->dev, "IRQ not configured!\n");
|
|
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
|
|
index 92b92be91d6021..095344a312d2ad 100644
|
|
--- a/drivers/misc/apds990x.c
|
|
+++ b/drivers/misc/apds990x.c
|
|
@@ -1147,7 +1147,7 @@ static int apds990x_probe(struct i2c_client *client)
|
|
err = chip->pdata->setup_resources();
|
|
if (err) {
|
|
err = -EINVAL;
|
|
- goto fail3;
|
|
+ goto fail4;
|
|
}
|
|
}
|
|
|
|
@@ -1155,7 +1155,7 @@ static int apds990x_probe(struct i2c_client *client)
|
|
apds990x_attribute_group);
|
|
if (err < 0) {
|
|
dev_err(&chip->client->dev, "Sysfs registration failed\n");
|
|
- goto fail4;
|
|
+ goto fail5;
|
|
}
|
|
|
|
err = request_threaded_irq(client->irq, NULL,
|
|
@@ -1166,15 +1166,17 @@ static int apds990x_probe(struct i2c_client *client)
|
|
if (err) {
|
|
dev_err(&client->dev, "could not get IRQ %d\n",
|
|
client->irq);
|
|
- goto fail5;
|
|
+ goto fail6;
|
|
}
|
|
return err;
|
|
-fail5:
|
|
+fail6:
|
|
sysfs_remove_group(&chip->client->dev.kobj,
|
|
&apds990x_attribute_group[0]);
|
|
-fail4:
|
|
+fail5:
|
|
if (chip->pdata && chip->pdata->release_resources)
|
|
chip->pdata->release_resources();
|
|
+fail4:
|
|
+ pm_runtime_disable(&client->dev);
|
|
fail3:
|
|
regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
|
|
fail2:
|
|
diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
|
|
index c66cc05a68c454..473ec58f87a2eb 100644
|
|
--- a/drivers/misc/lkdtm/bugs.c
|
|
+++ b/drivers/misc/lkdtm/bugs.c
|
|
@@ -388,8 +388,8 @@ static void lkdtm_FAM_BOUNDS(void)
|
|
|
|
pr_err("FAIL: survived access of invalid flexible array member index!\n");
|
|
|
|
- if (!__has_attribute(__counted_by__))
|
|
- pr_warn("This is expected since this %s was built a compiler supporting __counted_by\n",
|
|
+ if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY))
|
|
+ pr_warn("This is expected since this %s was built with a compiler that does not support __counted_by\n",
|
|
lkdtm_kernel_info);
|
|
else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS))
|
|
pr_expected_config(CONFIG_UBSAN_TRAP);
|
|
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
|
|
index 2a99ffb61f8c04..30b93dc938f1ae 100644
|
|
--- a/drivers/mmc/host/mmc_spi.c
|
|
+++ b/drivers/mmc/host/mmc_spi.c
|
|
@@ -223,10 +223,6 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
|
|
u8 leftover = 0;
|
|
unsigned short rotator;
|
|
int i;
|
|
- char tag[32];
|
|
-
|
|
- snprintf(tag, sizeof(tag), " ... CMD%d response SPI_%s",
|
|
- cmd->opcode, maptype(cmd));
|
|
|
|
/* Except for data block reads, the whole response will already
|
|
* be stored in the scratch buffer. It's somewhere after the
|
|
@@ -379,8 +375,9 @@ static int mmc_spi_response_get(struct mmc_spi_host *host,
|
|
}
|
|
|
|
if (value < 0)
|
|
- dev_dbg(&host->spi->dev, "%s: resp %04x %08x\n",
|
|
- tag, cmd->resp[0], cmd->resp[1]);
|
|
+ dev_dbg(&host->spi->dev,
|
|
+ " ... CMD%d response SPI_%s: resp %04x %08x\n",
|
|
+ cmd->opcode, maptype(cmd), cmd->resp[0], cmd->resp[1]);
|
|
|
|
/* disable chipselect on errors and some success cases */
|
|
if (value >= 0 && cs_on)
|
|
diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c
|
|
index ef32fca5f785e3..e7a28f3316c3f2 100644
|
|
--- a/drivers/mtd/hyperbus/rpc-if.c
|
|
+++ b/drivers/mtd/hyperbus/rpc-if.c
|
|
@@ -154,20 +154,25 @@ static int rpcif_hb_probe(struct platform_device *pdev)
|
|
return error;
|
|
}
|
|
|
|
-static int rpcif_hb_remove(struct platform_device *pdev)
|
|
+static void rpcif_hb_remove(struct platform_device *pdev)
|
|
{
|
|
struct rpcif_hyperbus *hyperbus = platform_get_drvdata(pdev);
|
|
|
|
hyperbus_unregister_device(&hyperbus->hbdev);
|
|
|
|
pm_runtime_disable(hyperbus->rpc.dev);
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
+static const struct platform_device_id rpc_if_hyperflash_id_table[] = {
|
|
+ { .name = "rpc-if-hyperflash" },
|
|
+ { /* sentinel */ }
|
|
+};
|
|
+MODULE_DEVICE_TABLE(platform, rpc_if_hyperflash_id_table);
|
|
+
|
|
static struct platform_driver rpcif_platform_driver = {
|
|
.probe = rpcif_hb_probe,
|
|
- .remove = rpcif_hb_remove,
|
|
+ .remove_new = rpcif_hb_remove,
|
|
+ .id_table = rpc_if_hyperflash_id_table,
|
|
.driver = {
|
|
.name = "rpc-if-hyperflash",
|
|
},
|
|
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c
|
|
index 4d7dc8a9c37385..a22aab4ed4e8ab 100644
|
|
--- a/drivers/mtd/nand/raw/atmel/pmecc.c
|
|
+++ b/drivers/mtd/nand/raw/atmel/pmecc.c
|
|
@@ -362,7 +362,7 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
|
|
size = ALIGN(size, sizeof(s32));
|
|
size += (req->ecc.strength + 1) * sizeof(s32) * 3;
|
|
|
|
- user = kzalloc(size, GFP_KERNEL);
|
|
+ user = devm_kzalloc(pmecc->dev, size, GFP_KERNEL);
|
|
if (!user)
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
@@ -408,12 +408,6 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
|
|
}
|
|
EXPORT_SYMBOL_GPL(atmel_pmecc_create_user);
|
|
|
|
-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user)
|
|
-{
|
|
- kfree(user);
|
|
-}
|
|
-EXPORT_SYMBOL_GPL(atmel_pmecc_destroy_user);
|
|
-
|
|
static int get_strength(struct atmel_pmecc_user *user)
|
|
{
|
|
const int *strengths = user->pmecc->caps->strengths;
|
|
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.h b/drivers/mtd/nand/raw/atmel/pmecc.h
|
|
index 7851c05126cf15..cc0c5af1f4f1ab 100644
|
|
--- a/drivers/mtd/nand/raw/atmel/pmecc.h
|
|
+++ b/drivers/mtd/nand/raw/atmel/pmecc.h
|
|
@@ -55,8 +55,6 @@ struct atmel_pmecc *devm_atmel_pmecc_get(struct device *dev);
|
|
struct atmel_pmecc_user *
|
|
atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
|
|
struct atmel_pmecc_user_req *req);
|
|
-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
|
|
-
|
|
void atmel_pmecc_reset(struct atmel_pmecc *pmecc);
|
|
int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
|
|
void atmel_pmecc_disable(struct atmel_pmecc_user *user);
|
|
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
|
|
index 1b0c6770c14e46..8d75a66775cb1f 100644
|
|
--- a/drivers/mtd/spi-nor/core.c
|
|
+++ b/drivers/mtd/spi-nor/core.c
|
|
@@ -89,7 +89,7 @@ void spi_nor_spimem_setup_op(const struct spi_nor *nor,
|
|
op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto);
|
|
|
|
if (op->dummy.nbytes)
|
|
- op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto);
|
|
+ op->dummy.buswidth = spi_nor_get_protocol_data_nbits(proto);
|
|
|
|
if (op->data.nbytes)
|
|
op->data.buswidth = spi_nor_get_protocol_data_nbits(proto);
|
|
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
|
|
index 709822fced867f..828b442735ee83 100644
|
|
--- a/drivers/mtd/spi-nor/spansion.c
|
|
+++ b/drivers/mtd/spi-nor/spansion.c
|
|
@@ -105,6 +105,7 @@ static int cypress_nor_sr_ready_and_clear_reg(struct spi_nor *nor, u64 addr)
|
|
int ret;
|
|
|
|
if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
|
|
+ op.addr.nbytes = nor->addr_nbytes;
|
|
op.dummy.nbytes = params->rdsr_dummy;
|
|
op.data.nbytes = 2;
|
|
}
|
|
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
|
|
index ae5abe492b52ab..adc47b87b38a5f 100644
|
|
--- a/drivers/mtd/ubi/attach.c
|
|
+++ b/drivers/mtd/ubi/attach.c
|
|
@@ -1447,7 +1447,7 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai,
|
|
return err;
|
|
}
|
|
|
|
-static struct ubi_attach_info *alloc_ai(void)
|
|
+static struct ubi_attach_info *alloc_ai(const char *slab_name)
|
|
{
|
|
struct ubi_attach_info *ai;
|
|
|
|
@@ -1461,7 +1461,7 @@ static struct ubi_attach_info *alloc_ai(void)
|
|
INIT_LIST_HEAD(&ai->alien);
|
|
INIT_LIST_HEAD(&ai->fastmap);
|
|
ai->volumes = RB_ROOT;
|
|
- ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
|
|
+ ai->aeb_slab_cache = kmem_cache_create(slab_name,
|
|
sizeof(struct ubi_ainf_peb),
|
|
0, 0, NULL);
|
|
if (!ai->aeb_slab_cache) {
|
|
@@ -1491,7 +1491,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
|
|
|
|
err = -ENOMEM;
|
|
|
|
- scan_ai = alloc_ai();
|
|
+ scan_ai = alloc_ai("ubi_aeb_slab_cache_fastmap");
|
|
if (!scan_ai)
|
|
goto out;
|
|
|
|
@@ -1557,7 +1557,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
|
|
int err;
|
|
struct ubi_attach_info *ai;
|
|
|
|
- ai = alloc_ai();
|
|
+ ai = alloc_ai("ubi_aeb_slab_cache");
|
|
if (!ai)
|
|
return -ENOMEM;
|
|
|
|
@@ -1575,7 +1575,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
|
|
if (err > 0 || mtd_is_eccerr(err)) {
|
|
if (err != UBI_NO_FASTMAP) {
|
|
destroy_ai(ai);
|
|
- ai = alloc_ai();
|
|
+ ai = alloc_ai("ubi_aeb_slab_cache");
|
|
if (!ai)
|
|
return -ENOMEM;
|
|
|
|
@@ -1614,7 +1614,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
|
|
if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) {
|
|
struct ubi_attach_info *scan_ai;
|
|
|
|
- scan_ai = alloc_ai();
|
|
+ scan_ai = alloc_ai("ubi_aeb_slab_cache_dbg_chk_fastmap");
|
|
if (!scan_ai) {
|
|
err = -ENOMEM;
|
|
goto out_wl;
|
|
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
|
|
index 863f571f1adb54..79733163ab7d02 100644
|
|
--- a/drivers/mtd/ubi/fastmap-wl.c
|
|
+++ b/drivers/mtd/ubi/fastmap-wl.c
|
|
@@ -282,14 +282,27 @@ int ubi_wl_get_peb(struct ubi_device *ubi)
|
|
* WL sub-system.
|
|
*
|
|
* @ubi: UBI device description object
|
|
+ * @need_fill: whether to fill wear-leveling pool when no PEBs are found
|
|
*/
|
|
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi)
|
|
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
|
|
+ bool need_fill)
|
|
{
|
|
struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
|
|
int pnum;
|
|
|
|
- if (pool->used == pool->size)
|
|
+ if (pool->used == pool->size) {
|
|
+ if (need_fill && !ubi->fm_work_scheduled) {
|
|
+ /*
|
|
+ * We cannot update the fastmap here because this
|
|
+ * function is called in atomic context.
|
|
+ * Let's fail here and refill/update it as soon as
|
|
+ * possible.
|
|
+ */
|
|
+ ubi->fm_work_scheduled = 1;
|
|
+ schedule_work(&ubi->fm_work);
|
|
+ }
|
|
return NULL;
|
|
+ }
|
|
|
|
pnum = pool->pebs[pool->used];
|
|
return ubi->lookuptbl[pnum];
|
|
@@ -311,7 +324,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)
|
|
if (!ubi->used.rb_node)
|
|
return false;
|
|
|
|
- e = next_peb_for_wl(ubi);
|
|
+ e = next_peb_for_wl(ubi, false);
|
|
if (!e) {
|
|
if (!ubi->free.rb_node)
|
|
return false;
|
|
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
|
|
index 26a214f016c184..886d44019401a8 100644
|
|
--- a/drivers/mtd/ubi/wl.c
|
|
+++ b/drivers/mtd/ubi/wl.c
|
|
@@ -671,7 +671,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|
ubi_assert(!ubi->move_to_put);
|
|
|
|
#ifdef CONFIG_MTD_UBI_FASTMAP
|
|
- if (!next_peb_for_wl(ubi) ||
|
|
+ if (!next_peb_for_wl(ubi, true) ||
|
|
#else
|
|
if (!ubi->free.rb_node ||
|
|
#endif
|
|
@@ -834,7 +834,14 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
|
|
goto out_not_moved;
|
|
}
|
|
if (err == MOVE_RETRY) {
|
|
- scrubbing = 1;
|
|
+ /*
|
|
+ * For source PEB:
|
|
+ * 1. The scrubbing is set for scrub type PEB, it will
|
|
+ * be put back into ubi->scrub list.
|
|
+ * 2. Non-scrub type PEB will be put back into ubi->used
|
|
+ * list.
|
|
+ */
|
|
+ keep = 1;
|
|
dst_leb_clean = 1;
|
|
goto out_not_moved;
|
|
}
|
|
diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h
|
|
index 5ebe374a08aed9..1d83e552533a5d 100644
|
|
--- a/drivers/mtd/ubi/wl.h
|
|
+++ b/drivers/mtd/ubi/wl.h
|
|
@@ -5,7 +5,8 @@
|
|
static void update_fastmap_work_fn(struct work_struct *wrk);
|
|
static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
|
|
static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
|
|
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi);
|
|
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
|
|
+ bool need_fill);
|
|
static bool need_wear_leveling(struct ubi_device *ubi);
|
|
static void ubi_fastmap_close(struct ubi_device *ubi);
|
|
static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
|
|
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
index 58a7bb75506a3e..c440f4d8d43a27 100644
|
|
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
@@ -7597,7 +7597,6 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
|
|
struct hwrm_port_mac_ptp_qcfg_output *resp;
|
|
struct hwrm_port_mac_ptp_qcfg_input *req;
|
|
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
|
- bool phc_cfg;
|
|
u8 flags;
|
|
int rc;
|
|
|
|
@@ -7640,8 +7639,9 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
|
|
rc = -ENODEV;
|
|
goto exit;
|
|
}
|
|
- phc_cfg = (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0;
|
|
- rc = bnxt_ptp_init(bp, phc_cfg);
|
|
+ ptp->rtc_configured =
|
|
+ (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0;
|
|
+ rc = bnxt_ptp_init(bp);
|
|
if (rc)
|
|
netdev_warn(bp->dev, "PTP initialization failed.\n");
|
|
exit:
|
|
@@ -13857,6 +13857,7 @@ static void bnxt_shutdown(struct pci_dev *pdev)
|
|
if (netif_running(dev))
|
|
dev_close(dev);
|
|
|
|
+ bnxt_ptp_clear(bp);
|
|
bnxt_clear_int_mode(bp);
|
|
pci_disable_device(pdev);
|
|
|
|
@@ -13883,6 +13884,7 @@ static int bnxt_suspend(struct device *device)
|
|
rc = bnxt_close(dev);
|
|
}
|
|
bnxt_hwrm_func_drv_unrgtr(bp);
|
|
+ bnxt_ptp_clear(bp);
|
|
pci_disable_device(bp->pdev);
|
|
bnxt_free_ctx_mem(bp);
|
|
kfree(bp->ctx);
|
|
@@ -13926,6 +13928,10 @@ static int bnxt_resume(struct device *device)
|
|
goto resume_exit;
|
|
}
|
|
|
|
+ if (bnxt_ptp_init(bp)) {
|
|
+ kfree(bp->ptp_cfg);
|
|
+ bp->ptp_cfg = NULL;
|
|
+ }
|
|
bnxt_get_wol_settings(bp);
|
|
if (netif_running(dev)) {
|
|
rc = bnxt_open(dev);
|
|
@@ -14102,8 +14108,12 @@ static void bnxt_io_resume(struct pci_dev *pdev)
|
|
rtnl_lock();
|
|
|
|
err = bnxt_hwrm_func_qcaps(bp);
|
|
- if (!err && netif_running(netdev))
|
|
- err = bnxt_open(netdev);
|
|
+ if (!err) {
|
|
+ if (netif_running(netdev))
|
|
+ err = bnxt_open(netdev);
|
|
+ else
|
|
+ err = bnxt_reserve_rings(bp, true);
|
|
+ }
|
|
|
|
bnxt_ulp_start(bp, err);
|
|
if (!err) {
|
|
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
|
|
index 6e3da3362bd617..bbe8657f6545b3 100644
|
|
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
|
|
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
|
|
@@ -922,7 +922,7 @@ static void bnxt_ptp_free(struct bnxt *bp)
|
|
}
|
|
}
|
|
|
|
-int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
|
|
+int bnxt_ptp_init(struct bnxt *bp)
|
|
{
|
|
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
|
|
int rc;
|
|
@@ -944,7 +944,7 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
|
|
|
|
if (BNXT_PTP_USE_RTC(bp)) {
|
|
bnxt_ptp_timecounter_init(bp, false);
|
|
- rc = bnxt_ptp_init_rtc(bp, phc_cfg);
|
|
+ rc = bnxt_ptp_init_rtc(bp, ptp->rtc_configured);
|
|
if (rc)
|
|
goto out;
|
|
} else {
|
|
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
|
|
index 34162e07a1195c..7d6a215b10b1fa 100644
|
|
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
|
|
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
|
|
@@ -115,6 +115,7 @@ struct bnxt_ptp_cfg {
|
|
BNXT_PTP_MSG_PDELAY_REQ | \
|
|
BNXT_PTP_MSG_PDELAY_RESP)
|
|
u8 tx_tstamp_en:1;
|
|
+ u8 rtc_configured:1;
|
|
int rx_filter;
|
|
u32 tstamp_filters;
|
|
|
|
@@ -145,6 +146,6 @@ int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb);
|
|
int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts);
|
|
void bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns);
|
|
int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg);
|
|
-int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg);
|
|
+int bnxt_ptp_init(struct bnxt *bp);
|
|
void bnxt_ptp_clear(struct bnxt *bp);
|
|
#endif
|
|
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
|
|
index f1c8ff5b63acde..7f74e5e106d9d4 100644
|
|
--- a/drivers/net/ethernet/broadcom/tg3.c
|
|
+++ b/drivers/net/ethernet/broadcom/tg3.c
|
|
@@ -17731,6 +17731,9 @@ static int tg3_init_one(struct pci_dev *pdev,
|
|
} else
|
|
persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
|
|
|
|
+ if (tg3_asic_rev(tp) == ASIC_REV_57766)
|
|
+ persist_dma_mask = DMA_BIT_MASK(31);
|
|
+
|
|
/* Configure DMA attributes. */
|
|
if (dma_mask > DMA_BIT_MASK(32)) {
|
|
err = dma_set_mask(&pdev->dev, dma_mask);
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
|
|
index 6c6f267dcccc3f..9f7268bb2ee3b4 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
|
|
@@ -479,6 +479,9 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
|
|
if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)
|
|
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
|
|
|
|
+ if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_CRC)
|
|
+ vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_CRC;
|
|
+
|
|
if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED)
|
|
vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
|
|
|
|
@@ -1642,8 +1645,8 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
|
|
|
|
/* copy Tx queue info from VF into VSI */
|
|
if (qpi->txq.ring_len > 0) {
|
|
- vsi->tx_rings[i]->dma = qpi->txq.dma_ring_addr;
|
|
- vsi->tx_rings[i]->count = qpi->txq.ring_len;
|
|
+ vsi->tx_rings[q_idx]->dma = qpi->txq.dma_ring_addr;
|
|
+ vsi->tx_rings[q_idx]->count = qpi->txq.ring_len;
|
|
|
|
/* Disable any existing queue first */
|
|
if (ice_vf_vsi_dis_single_txq(vf, vsi, q_idx))
|
|
@@ -1652,7 +1655,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
|
|
/* Configure a queue with the requested settings */
|
|
if (ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx)) {
|
|
dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure TX queue %d\n",
|
|
- vf->vf_id, i);
|
|
+ vf->vf_id, q_idx);
|
|
goto error_param;
|
|
}
|
|
}
|
|
@@ -1660,17 +1663,28 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
|
|
/* copy Rx queue info from VF into VSI */
|
|
if (qpi->rxq.ring_len > 0) {
|
|
u16 max_frame_size = ice_vc_get_max_frame_size(vf);
|
|
+ struct ice_rx_ring *ring = vsi->rx_rings[q_idx];
|
|
u32 rxdid;
|
|
|
|
- vsi->rx_rings[i]->dma = qpi->rxq.dma_ring_addr;
|
|
- vsi->rx_rings[i]->count = qpi->rxq.ring_len;
|
|
+ ring->dma = qpi->rxq.dma_ring_addr;
|
|
+ ring->count = qpi->rxq.ring_len;
|
|
+
|
|
+ if (qpi->rxq.crc_disable &&
|
|
+ !(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_CRC)) {
|
|
+ goto error_param;
|
|
+ }
|
|
+
|
|
+ if (qpi->rxq.crc_disable)
|
|
+ ring->flags |= ICE_RX_FLAGS_CRC_STRIP_DIS;
|
|
+ else
|
|
+ ring->flags &= ~ICE_RX_FLAGS_CRC_STRIP_DIS;
|
|
|
|
if (qpi->rxq.databuffer_size != 0 &&
|
|
(qpi->rxq.databuffer_size > ((16 * 1024) - 128) ||
|
|
qpi->rxq.databuffer_size < 1024))
|
|
goto error_param;
|
|
vsi->rx_buf_len = qpi->rxq.databuffer_size;
|
|
- vsi->rx_rings[i]->rx_buf_len = vsi->rx_buf_len;
|
|
+ ring->rx_buf_len = vsi->rx_buf_len;
|
|
if (qpi->rxq.max_pkt_size > max_frame_size ||
|
|
qpi->rxq.max_pkt_size < 64)
|
|
goto error_param;
|
|
@@ -1685,7 +1699,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
|
|
|
|
if (ice_vsi_cfg_single_rxq(vsi, q_idx)) {
|
|
dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure RX queue %d\n",
|
|
- vf->vf_id, i);
|
|
+ vf->vf_id, q_idx);
|
|
goto error_param;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
|
|
index 2539c985f695a7..52792546fe00dd 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
|
|
@@ -24,6 +24,8 @@
|
|
#define DRV_NAME "Marvell-CGX/RPM"
|
|
#define DRV_STRING "Marvell CGX/RPM Driver"
|
|
|
|
+#define CGX_RX_STAT_GLOBAL_INDEX 9
|
|
+
|
|
static LIST_HEAD(cgx_list);
|
|
|
|
/* Convert firmware speed encoding to user format(Mbps) */
|
|
@@ -110,6 +112,11 @@ struct mac_ops *get_mac_ops(void *cgxd)
|
|
return ((struct cgx *)cgxd)->mac_ops;
|
|
}
|
|
|
|
+u32 cgx_get_fifo_len(void *cgxd)
|
|
+{
|
|
+ return ((struct cgx *)cgxd)->fifo_len;
|
|
+}
|
|
+
|
|
void cgx_write(struct cgx *cgx, u64 lmac, u64 offset, u64 val)
|
|
{
|
|
writeq(val, cgx->reg_base + (lmac << cgx->mac_ops->lmac_offset) +
|
|
@@ -207,6 +214,24 @@ u8 cgx_lmac_get_p2x(int cgx_id, int lmac_id)
|
|
return (cfg & CMR_P2X_SEL_MASK) >> CMR_P2X_SEL_SHIFT;
|
|
}
|
|
|
|
+static u8 cgx_get_nix_resetbit(struct cgx *cgx)
|
|
+{
|
|
+ int first_lmac;
|
|
+ u8 p2x;
|
|
+
|
|
+ /* non 98XX silicons supports only NIX0 block */
|
|
+ if (cgx->pdev->subsystem_device != PCI_SUBSYS_DEVID_98XX)
|
|
+ return CGX_NIX0_RESET;
|
|
+
|
|
+ first_lmac = find_first_bit(&cgx->lmac_bmap, cgx->max_lmac_per_mac);
|
|
+ p2x = cgx_lmac_get_p2x(cgx->cgx_id, first_lmac);
|
|
+
|
|
+ if (p2x == CMR_P2X_SEL_NIX1)
|
|
+ return CGX_NIX1_RESET;
|
|
+ else
|
|
+ return CGX_NIX0_RESET;
|
|
+}
|
|
+
|
|
/* Ensure the required lock for event queue(where asynchronous events are
|
|
* posted) is acquired before calling this API. Else an asynchronous event(with
|
|
* latest link status) can reach the destination before this function returns
|
|
@@ -499,7 +524,7 @@ static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id)
|
|
u8 num_lmacs;
|
|
u32 fifo_len;
|
|
|
|
- fifo_len = cgx->mac_ops->fifo_len;
|
|
+ fifo_len = cgx->fifo_len;
|
|
num_lmacs = cgx->mac_ops->get_nr_lmacs(cgx);
|
|
|
|
switch (num_lmacs) {
|
|
@@ -701,6 +726,30 @@ u64 cgx_features_get(void *cgxd)
|
|
return ((struct cgx *)cgxd)->hw_features;
|
|
}
|
|
|
|
+int cgx_stats_reset(void *cgxd, int lmac_id)
|
|
+{
|
|
+ struct cgx *cgx = cgxd;
|
|
+ int stat_id;
|
|
+
|
|
+ if (!is_lmac_valid(cgx, lmac_id))
|
|
+ return -ENODEV;
|
|
+
|
|
+ for (stat_id = 0 ; stat_id < CGX_RX_STATS_COUNT; stat_id++) {
|
|
+ if (stat_id >= CGX_RX_STAT_GLOBAL_INDEX)
|
|
+ /* pass lmac as 0 for CGX_CMR_RX_STAT9-12 */
|
|
+ cgx_write(cgx, 0,
|
|
+ (CGXX_CMRX_RX_STAT0 + (stat_id * 8)), 0);
|
|
+ else
|
|
+ cgx_write(cgx, lmac_id,
|
|
+ (CGXX_CMRX_RX_STAT0 + (stat_id * 8)), 0);
|
|
+ }
|
|
+
|
|
+ for (stat_id = 0 ; stat_id < CGX_TX_STATS_COUNT; stat_id++)
|
|
+ cgx_write(cgx, lmac_id, CGXX_CMRX_TX_STAT0 + (stat_id * 8), 0);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int cgx_set_fec_stats_count(struct cgx_link_user_info *linfo)
|
|
{
|
|
if (!linfo->fec)
|
|
@@ -1695,6 +1744,8 @@ static int cgx_lmac_init(struct cgx *cgx)
|
|
lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id);
|
|
}
|
|
|
|
+ /* Start X2P reset on given MAC block */
|
|
+ cgx->mac_ops->mac_x2p_reset(cgx, true);
|
|
return cgx_lmac_verify_fwi_version(cgx);
|
|
|
|
err_bitmap_free:
|
|
@@ -1740,7 +1791,7 @@ static void cgx_populate_features(struct cgx *cgx)
|
|
u64 cfg;
|
|
|
|
cfg = cgx_read(cgx, 0, CGX_CONST);
|
|
- cgx->mac_ops->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
|
|
+ cgx->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
|
|
cgx->max_lmac_per_mac = FIELD_GET(CGX_CONST_MAX_LMACS, cfg);
|
|
|
|
if (is_dev_rpm(cgx))
|
|
@@ -1760,6 +1811,45 @@ static u8 cgx_get_rxid_mapoffset(struct cgx *cgx)
|
|
return 0x60;
|
|
}
|
|
|
|
+static void cgx_x2p_reset(void *cgxd, bool enable)
|
|
+{
|
|
+ struct cgx *cgx = cgxd;
|
|
+ int lmac_id;
|
|
+ u64 cfg;
|
|
+
|
|
+ if (enable) {
|
|
+ for_each_set_bit(lmac_id, &cgx->lmac_bmap, cgx->max_lmac_per_mac)
|
|
+ cgx->mac_ops->mac_enadis_rx(cgx, lmac_id, false);
|
|
+
|
|
+ usleep_range(1000, 2000);
|
|
+
|
|
+ cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG);
|
|
+ cfg |= cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP;
|
|
+ cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg);
|
|
+ } else {
|
|
+ cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG);
|
|
+ cfg &= ~(cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP);
|
|
+ cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int cgx_enadis_rx(void *cgxd, int lmac_id, bool enable)
|
|
+{
|
|
+ struct cgx *cgx = cgxd;
|
|
+ u64 cfg;
|
|
+
|
|
+ if (!is_lmac_valid(cgx, lmac_id))
|
|
+ return -ENODEV;
|
|
+
|
|
+ cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
|
|
+ if (enable)
|
|
+ cfg |= DATA_PKT_RX_EN;
|
|
+ else
|
|
+ cfg &= ~DATA_PKT_RX_EN;
|
|
+ cgx_write(cgx, lmac_id, CGXX_CMRX_CFG, cfg);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static struct mac_ops cgx_mac_ops = {
|
|
.name = "cgx",
|
|
.csr_offset = 0,
|
|
@@ -1790,6 +1880,9 @@ static struct mac_ops cgx_mac_ops = {
|
|
.pfc_config = cgx_lmac_pfc_config,
|
|
.mac_get_pfc_frm_cfg = cgx_lmac_get_pfc_frm_cfg,
|
|
.mac_reset = cgx_lmac_reset,
|
|
+ .mac_stats_reset = cgx_stats_reset,
|
|
+ .mac_x2p_reset = cgx_x2p_reset,
|
|
+ .mac_enadis_rx = cgx_enadis_rx,
|
|
};
|
|
|
|
static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
|
|
index 6f7d1dee58308c..1cf12e5c7da873 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
|
|
@@ -32,6 +32,10 @@
|
|
#define CGX_LMAC_TYPE_MASK 0xF
|
|
#define CGXX_CMRX_INT 0x040
|
|
#define FW_CGX_INT BIT_ULL(1)
|
|
+#define CGXX_CMR_GLOBAL_CONFIG 0x08
|
|
+#define CGX_NIX0_RESET BIT_ULL(2)
|
|
+#define CGX_NIX1_RESET BIT_ULL(3)
|
|
+#define CGX_NSCI_DROP BIT_ULL(9)
|
|
#define CGXX_CMRX_INT_ENA_W1S 0x058
|
|
#define CGXX_CMRX_RX_ID_MAP 0x060
|
|
#define CGXX_CMRX_RX_STAT0 0x070
|
|
@@ -141,6 +145,7 @@ int cgx_lmac_evh_register(struct cgx_event_cb *cb, void *cgxd, int lmac_id);
|
|
int cgx_lmac_evh_unregister(void *cgxd, int lmac_id);
|
|
int cgx_get_tx_stats(void *cgxd, int lmac_id, int idx, u64 *tx_stat);
|
|
int cgx_get_rx_stats(void *cgxd, int lmac_id, int idx, u64 *rx_stat);
|
|
+int cgx_stats_reset(void *cgxd, int lmac_id);
|
|
int cgx_lmac_rx_tx_enable(void *cgxd, int lmac_id, bool enable);
|
|
int cgx_lmac_tx_enable(void *cgxd, int lmac_id, bool enable);
|
|
int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr);
|
|
@@ -184,4 +189,5 @@ int cgx_lmac_get_pfc_frm_cfg(void *cgxd, int lmac_id, u8 *tx_pause,
|
|
int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause,
|
|
int pfvf_idx);
|
|
int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr);
|
|
+u32 cgx_get_fifo_len(void *cgxd);
|
|
#endif /* CGX_H */
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
|
|
index 0b4cba03f2e837..6180e68e1765a7 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h
|
|
@@ -72,7 +72,6 @@ struct mac_ops {
|
|
u8 irq_offset;
|
|
u8 int_ena_bit;
|
|
u8 lmac_fwi;
|
|
- u32 fifo_len;
|
|
bool non_contiguous_serdes_lane;
|
|
/* RPM & CGX differs in number of Receive/transmit stats */
|
|
u8 rx_stats_cnt;
|
|
@@ -132,6 +131,9 @@ struct mac_ops {
|
|
/* FEC stats */
|
|
int (*get_fec_stats)(void *cgxd, int lmac_id,
|
|
struct cgx_fec_stats_rsp *rsp);
|
|
+ int (*mac_stats_reset)(void *cgxd, int lmac_id);
|
|
+ void (*mac_x2p_reset)(void *cgxd, bool enable);
|
|
+ int (*mac_enadis_rx)(void *cgxd, int lmac_id, bool enable);
|
|
};
|
|
|
|
struct cgx {
|
|
@@ -141,6 +143,10 @@ struct cgx {
|
|
u8 lmac_count;
|
|
/* number of LMACs per MAC could be 4 or 8 */
|
|
u8 max_lmac_per_mac;
|
|
+ /* length of fifo varies depending on the number
|
|
+ * of LMACS
|
|
+ */
|
|
+ u32 fifo_len;
|
|
#define MAX_LMAC_COUNT 8
|
|
struct lmac *lmac_idmap[MAX_LMAC_COUNT];
|
|
struct work_struct cgx_cmd_work;
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
|
|
index e883c0929b1a9b..b4b23e475c95f5 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
|
|
@@ -174,6 +174,7 @@ M(CGX_FEC_STATS, 0x217, cgx_fec_stats, msg_req, cgx_fec_stats_rsp) \
|
|
M(CGX_SET_LINK_MODE, 0x218, cgx_set_link_mode, cgx_set_link_mode_req,\
|
|
cgx_set_link_mode_rsp) \
|
|
M(CGX_GET_PHY_FEC_STATS, 0x219, cgx_get_phy_fec_stats, msg_req, msg_rsp) \
|
|
+M(CGX_STATS_RST, 0x21A, cgx_stats_rst, msg_req, msg_rsp) \
|
|
M(CGX_FEATURES_GET, 0x21B, cgx_features_get, msg_req, \
|
|
cgx_features_info_msg) \
|
|
M(RPM_STATS, 0x21C, rpm_stats, msg_req, rpm_stats_rsp) \
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
|
|
index 76218f1cb45958..2e9945446199ec 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
|
|
@@ -38,6 +38,9 @@ static struct mac_ops rpm_mac_ops = {
|
|
.pfc_config = rpm_lmac_pfc_config,
|
|
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
|
|
.mac_reset = rpm_lmac_reset,
|
|
+ .mac_stats_reset = rpm_stats_reset,
|
|
+ .mac_x2p_reset = rpm_x2p_reset,
|
|
+ .mac_enadis_rx = rpm_enadis_rx,
|
|
};
|
|
|
|
static struct mac_ops rpm2_mac_ops = {
|
|
@@ -70,6 +73,9 @@ static struct mac_ops rpm2_mac_ops = {
|
|
.pfc_config = rpm_lmac_pfc_config,
|
|
.mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
|
|
.mac_reset = rpm_lmac_reset,
|
|
+ .mac_stats_reset = rpm_stats_reset,
|
|
+ .mac_x2p_reset = rpm_x2p_reset,
|
|
+ .mac_enadis_rx = rpm_enadis_rx,
|
|
};
|
|
|
|
bool is_dev_rpm2(void *rpmd)
|
|
@@ -443,6 +449,21 @@ int rpm_get_tx_stats(void *rpmd, int lmac_id, int idx, u64 *tx_stat)
|
|
return 0;
|
|
}
|
|
|
|
+int rpm_stats_reset(void *rpmd, int lmac_id)
|
|
+{
|
|
+ rpm_t *rpm = rpmd;
|
|
+ u64 cfg;
|
|
+
|
|
+ if (!is_lmac_valid(rpm, lmac_id))
|
|
+ return -ENODEV;
|
|
+
|
|
+ cfg = rpm_read(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL);
|
|
+ cfg |= RPMX_CMD_CLEAR_TX | RPMX_CMD_CLEAR_RX | BIT_ULL(lmac_id);
|
|
+ rpm_write(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL, cfg);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
u8 rpm_get_lmac_type(void *rpmd, int lmac_id)
|
|
{
|
|
rpm_t *rpm = rpmd;
|
|
@@ -450,7 +471,7 @@ u8 rpm_get_lmac_type(void *rpmd, int lmac_id)
|
|
int err;
|
|
|
|
req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_LINK_STS, req);
|
|
- err = cgx_fwi_cmd_generic(req, &resp, rpm, 0);
|
|
+ err = cgx_fwi_cmd_generic(req, &resp, rpm, lmac_id);
|
|
if (!err)
|
|
return FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, resp);
|
|
return err;
|
|
@@ -463,7 +484,7 @@ u32 rpm_get_lmac_fifo_len(void *rpmd, int lmac_id)
|
|
u8 num_lmacs;
|
|
u32 fifo_len;
|
|
|
|
- fifo_len = rpm->mac_ops->fifo_len;
|
|
+ fifo_len = rpm->fifo_len;
|
|
num_lmacs = rpm->mac_ops->get_nr_lmacs(rpm);
|
|
|
|
switch (num_lmacs) {
|
|
@@ -516,9 +537,9 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id)
|
|
*/
|
|
max_lmac = (rpm_read(rpm, 0, CGX_CONST) >> 24) & 0xFF;
|
|
if (max_lmac > 4)
|
|
- fifo_len = rpm->mac_ops->fifo_len / 2;
|
|
+ fifo_len = rpm->fifo_len / 2;
|
|
else
|
|
- fifo_len = rpm->mac_ops->fifo_len;
|
|
+ fifo_len = rpm->fifo_len;
|
|
|
|
if (lmac_id < 4) {
|
|
num_lmacs = hweight8(lmac_info & 0xF);
|
|
@@ -682,46 +703,51 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp)
|
|
if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE)
|
|
return 0;
|
|
|
|
+ /* latched registers FCFECX_CW_HI/RSFEC_STAT_FAST_DATA_HI_CDC are common
|
|
+ * for all counters. Acquire lock to ensure serialized reads
|
|
+ */
|
|
+ mutex_lock(&rpm->lock);
|
|
if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_BASER) {
|
|
- val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_CCW_LO);
|
|
- val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI);
|
|
+ val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_CCW_LO(lmac_id));
|
|
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id));
|
|
rsp->fec_corr_blks = (val_hi << 16 | val_lo);
|
|
|
|
- val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_NCCW_LO);
|
|
- val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI);
|
|
+ val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_NCCW_LO(lmac_id));
|
|
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id));
|
|
rsp->fec_uncorr_blks = (val_hi << 16 | val_lo);
|
|
|
|
/* 50G uses 2 Physical serdes lines */
|
|
if (rpm->lmac_idmap[lmac_id]->link_info.lmac_type_id ==
|
|
LMAC_MODE_50G_R) {
|
|
- val_lo = rpm_read(rpm, lmac_id,
|
|
- RPMX_MTI_FCFECX_VL1_CCW_LO);
|
|
- val_hi = rpm_read(rpm, lmac_id,
|
|
- RPMX_MTI_FCFECX_CW_HI);
|
|
+ val_lo = rpm_read(rpm, 0,
|
|
+ RPMX_MTI_FCFECX_VL1_CCW_LO(lmac_id));
|
|
+ val_hi = rpm_read(rpm, 0,
|
|
+ RPMX_MTI_FCFECX_CW_HI(lmac_id));
|
|
rsp->fec_corr_blks += (val_hi << 16 | val_lo);
|
|
|
|
- val_lo = rpm_read(rpm, lmac_id,
|
|
- RPMX_MTI_FCFECX_VL1_NCCW_LO);
|
|
- val_hi = rpm_read(rpm, lmac_id,
|
|
- RPMX_MTI_FCFECX_CW_HI);
|
|
+ val_lo = rpm_read(rpm, 0,
|
|
+ RPMX_MTI_FCFECX_VL1_NCCW_LO(lmac_id));
|
|
+ val_hi = rpm_read(rpm, 0,
|
|
+ RPMX_MTI_FCFECX_CW_HI(lmac_id));
|
|
rsp->fec_uncorr_blks += (val_hi << 16 | val_lo);
|
|
}
|
|
} else {
|
|
/* enable RS-FEC capture */
|
|
- cfg = rpm_read(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL);
|
|
+ cfg = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL);
|
|
cfg |= RPMX_RSFEC_RX_CAPTURE | BIT(lmac_id);
|
|
- rpm_write(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL, cfg);
|
|
+ rpm_write(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL, cfg);
|
|
|
|
val_lo = rpm_read(rpm, 0,
|
|
RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2);
|
|
- val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
|
|
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC);
|
|
rsp->fec_corr_blks = (val_hi << 32 | val_lo);
|
|
|
|
val_lo = rpm_read(rpm, 0,
|
|
RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3);
|
|
- val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
|
|
+ val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC);
|
|
rsp->fec_uncorr_blks = (val_hi << 32 | val_lo);
|
|
}
|
|
+ mutex_unlock(&rpm->lock);
|
|
|
|
return 0;
|
|
}
|
|
@@ -746,3 +772,41 @@ int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr)
|
|
|
|
return 0;
|
|
}
|
|
+
|
|
+void rpm_x2p_reset(void *rpmd, bool enable)
|
|
+{
|
|
+ rpm_t *rpm = rpmd;
|
|
+ int lmac_id;
|
|
+ u64 cfg;
|
|
+
|
|
+ if (enable) {
|
|
+ for_each_set_bit(lmac_id, &rpm->lmac_bmap, rpm->max_lmac_per_mac)
|
|
+ rpm->mac_ops->mac_enadis_rx(rpm, lmac_id, false);
|
|
+
|
|
+ usleep_range(1000, 2000);
|
|
+
|
|
+ cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG);
|
|
+ rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg | RPM_NIX0_RESET);
|
|
+ } else {
|
|
+ cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG);
|
|
+ cfg &= ~RPM_NIX0_RESET;
|
|
+ rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg);
|
|
+ }
|
|
+}
|
|
+
|
|
+int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable)
|
|
+{
|
|
+ rpm_t *rpm = rpmd;
|
|
+ u64 cfg;
|
|
+
|
|
+ if (!is_lmac_valid(rpm, lmac_id))
|
|
+ return -ENODEV;
|
|
+
|
|
+ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
|
|
+ if (enable)
|
|
+ cfg |= RPM_RX_EN;
|
|
+ else
|
|
+ cfg &= ~RPM_RX_EN;
|
|
+ rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
|
|
+ return 0;
|
|
+}
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
|
|
index b79cfbc6f87705..b8d3972e096aed 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h
|
|
@@ -17,6 +17,8 @@
|
|
|
|
/* Registers */
|
|
#define RPMX_CMRX_CFG 0x00
|
|
+#define RPMX_CMR_GLOBAL_CFG 0x08
|
|
+#define RPM_NIX0_RESET BIT_ULL(3)
|
|
#define RPMX_RX_TS_PREPEND BIT_ULL(22)
|
|
#define RPMX_TX_PTP_1S_SUPPORT BIT_ULL(17)
|
|
#define RPMX_CMRX_RX_ID_MAP 0x80
|
|
@@ -84,14 +86,18 @@
|
|
/* FEC stats */
|
|
#define RPMX_MTI_STAT_STATN_CONTROL 0x10018
|
|
#define RPMX_MTI_STAT_DATA_HI_CDC 0x10038
|
|
-#define RPMX_RSFEC_RX_CAPTURE BIT_ULL(27)
|
|
+#define RPMX_RSFEC_RX_CAPTURE BIT_ULL(28)
|
|
+#define RPMX_CMD_CLEAR_RX BIT_ULL(30)
|
|
+#define RPMX_CMD_CLEAR_TX BIT_ULL(31)
|
|
+#define RPMX_MTI_RSFEC_STAT_STATN_CONTROL 0x40018
|
|
+#define RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC 0x40000
|
|
#define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2 0x40050
|
|
#define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3 0x40058
|
|
-#define RPMX_MTI_FCFECX_VL0_CCW_LO 0x38618
|
|
-#define RPMX_MTI_FCFECX_VL0_NCCW_LO 0x38620
|
|
-#define RPMX_MTI_FCFECX_VL1_CCW_LO 0x38628
|
|
-#define RPMX_MTI_FCFECX_VL1_NCCW_LO 0x38630
|
|
-#define RPMX_MTI_FCFECX_CW_HI 0x38638
|
|
+#define RPMX_MTI_FCFECX_VL0_CCW_LO(a) (0x38618 + ((a) * 0x40))
|
|
+#define RPMX_MTI_FCFECX_VL0_NCCW_LO(a) (0x38620 + ((a) * 0x40))
|
|
+#define RPMX_MTI_FCFECX_VL1_CCW_LO(a) (0x38628 + ((a) * 0x40))
|
|
+#define RPMX_MTI_FCFECX_VL1_NCCW_LO(a) (0x38630 + ((a) * 0x40))
|
|
+#define RPMX_MTI_FCFECX_CW_HI(a) (0x38638 + ((a) * 0x40))
|
|
|
|
/* CN10KB CSR Declaration */
|
|
#define RPM2_CMRX_SW_INT 0x1b0
|
|
@@ -134,4 +140,7 @@ int rpm2_get_nr_lmacs(void *rpmd);
|
|
bool is_dev_rpm2(void *rpmd);
|
|
int rpm_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp);
|
|
int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr);
|
|
+int rpm_stats_reset(void *rpmd, int lmac_id);
|
|
+void rpm_x2p_reset(void *rpmd, bool enable);
|
|
+int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable);
|
|
#endif /* RPM_H */
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
|
|
index 5906f5f8d19041..5241737222236a 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
|
|
@@ -1157,6 +1157,7 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
|
|
}
|
|
|
|
rvu_program_channels(rvu);
|
|
+ cgx_start_linkup(rvu);
|
|
|
|
err = rvu_mcs_init(rvu);
|
|
if (err) {
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
|
|
index e81cfcaf9ce4fe..a607c7294b0c59 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
|
|
@@ -912,6 +912,7 @@ int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_
|
|
int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause);
|
|
void rvu_mac_reset(struct rvu *rvu, u16 pcifunc);
|
|
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac);
|
|
+void cgx_start_linkup(struct rvu *rvu);
|
|
int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
|
|
int type);
|
|
bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr,
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
|
|
index 19075f217d00c5..d14cf2a9d207ed 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
|
|
@@ -349,6 +349,7 @@ static void rvu_cgx_wq_destroy(struct rvu *rvu)
|
|
|
|
int rvu_cgx_init(struct rvu *rvu)
|
|
{
|
|
+ struct mac_ops *mac_ops;
|
|
int cgx, err;
|
|
void *cgxd;
|
|
|
|
@@ -375,6 +376,15 @@ int rvu_cgx_init(struct rvu *rvu)
|
|
if (err)
|
|
return err;
|
|
|
|
+ /* Clear X2P reset on all MAC blocks */
|
|
+ for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++) {
|
|
+ cgxd = rvu_cgx_pdata(cgx, rvu);
|
|
+ if (!cgxd)
|
|
+ continue;
|
|
+ mac_ops = get_mac_ops(cgxd);
|
|
+ mac_ops->mac_x2p_reset(cgxd, false);
|
|
+ }
|
|
+
|
|
/* Register for CGX events */
|
|
err = cgx_lmac_event_handler_init(rvu);
|
|
if (err)
|
|
@@ -382,10 +392,26 @@ int rvu_cgx_init(struct rvu *rvu)
|
|
|
|
mutex_init(&rvu->cgx_cfg_lock);
|
|
|
|
- /* Ensure event handler registration is completed, before
|
|
- * we turn on the links
|
|
- */
|
|
- mb();
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void cgx_start_linkup(struct rvu *rvu)
|
|
+{
|
|
+ unsigned long lmac_bmap;
|
|
+ struct mac_ops *mac_ops;
|
|
+ int cgx, lmac, err;
|
|
+ void *cgxd;
|
|
+
|
|
+ /* Enable receive on all LMACS */
|
|
+ for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
|
|
+ cgxd = rvu_cgx_pdata(cgx, rvu);
|
|
+ if (!cgxd)
|
|
+ continue;
|
|
+ mac_ops = get_mac_ops(cgxd);
|
|
+ lmac_bmap = cgx_get_lmac_bmap(cgxd);
|
|
+ for_each_set_bit(lmac, &lmac_bmap, rvu->hw->lmac_per_cgx)
|
|
+ mac_ops->mac_enadis_rx(cgxd, lmac, true);
|
|
+ }
|
|
|
|
/* Do link up for all CGX ports */
|
|
for (cgx = 0; cgx <= rvu->cgx_cnt_max; cgx++) {
|
|
@@ -398,8 +424,6 @@ int rvu_cgx_init(struct rvu *rvu)
|
|
"Link up process failed to start on cgx %d\n",
|
|
cgx);
|
|
}
|
|
-
|
|
- return 0;
|
|
}
|
|
|
|
int rvu_cgx_exit(struct rvu *rvu)
|
|
@@ -604,6 +628,35 @@ int rvu_mbox_handler_rpm_stats(struct rvu *rvu, struct msg_req *req,
|
|
return rvu_lmac_get_stats(rvu, req, (void *)rsp);
|
|
}
|
|
|
|
+int rvu_mbox_handler_cgx_stats_rst(struct rvu *rvu, struct msg_req *req,
|
|
+ struct msg_rsp *rsp)
|
|
+{
|
|
+ int pf = rvu_get_pf(req->hdr.pcifunc);
|
|
+ struct rvu_pfvf *parent_pf;
|
|
+ struct mac_ops *mac_ops;
|
|
+ u8 cgx_idx, lmac;
|
|
+ void *cgxd;
|
|
+
|
|
+ if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
|
|
+ return LMAC_AF_ERR_PERM_DENIED;
|
|
+
|
|
+ parent_pf = &rvu->pf[pf];
|
|
+ /* To ensure reset cgx stats won't affect VF stats,
|
|
+ * check if it used by only PF interface.
|
|
+ * If not, return
|
|
+ */
|
|
+ if (parent_pf->cgx_users > 1) {
|
|
+ dev_info(rvu->dev, "CGX busy, could not reset statistics\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_idx, &lmac);
|
|
+ cgxd = rvu_cgx_pdata(cgx_idx, rvu);
|
|
+ mac_ops = get_mac_ops(cgxd);
|
|
+
|
|
+ return mac_ops->mac_stats_reset(cgxd, lmac);
|
|
+}
|
|
+
|
|
int rvu_mbox_handler_cgx_fec_stats(struct rvu *rvu,
|
|
struct msg_req *req,
|
|
struct cgx_fec_stats_rsp *rsp)
|
|
@@ -895,13 +948,12 @@ int rvu_mbox_handler_cgx_features_get(struct rvu *rvu,
|
|
|
|
u32 rvu_cgx_get_fifolen(struct rvu *rvu)
|
|
{
|
|
- struct mac_ops *mac_ops;
|
|
- u32 fifo_len;
|
|
+ void *cgxd = rvu_first_cgx_pdata(rvu);
|
|
|
|
- mac_ops = get_mac_ops(rvu_first_cgx_pdata(rvu));
|
|
- fifo_len = mac_ops ? mac_ops->fifo_len : 0;
|
|
+ if (!cgxd)
|
|
+ return 0;
|
|
|
|
- return fifo_len;
|
|
+ return cgx_get_fifo_len(cgxd);
|
|
}
|
|
|
|
u32 rvu_cgx_get_lmac_fifolen(struct rvu *rvu, int cgx, int lmac)
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
|
|
index c1c99d7054f87f..7417087b6db597 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
|
|
@@ -203,6 +203,11 @@ int cn10k_alloc_leaf_profile(struct otx2_nic *pfvf, u16 *leaf)
|
|
|
|
rsp = (struct nix_bandprof_alloc_rsp *)
|
|
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
|
|
+ if (IS_ERR(rsp)) {
|
|
+ rc = PTR_ERR(rsp);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
if (!rsp->prof_count[BAND_PROF_LEAF_LAYER]) {
|
|
rc = -EIO;
|
|
goto out;
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
|
|
index b3064377510ed9..47adccf7a77765 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
|
|
@@ -1837,6 +1837,10 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf)
|
|
if (!rc) {
|
|
rsp = (struct nix_hw_info *)
|
|
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
|
|
+ if (IS_ERR(rsp)) {
|
|
+ rc = PTR_ERR(rsp);
|
|
+ goto out;
|
|
+ }
|
|
|
|
/* HW counts VLAN insertion bytes (8 for double tag)
|
|
* irrespective of whether SQE is requesting to insert VLAN
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
|
|
index 7e16a341ec588f..c5de3ba33e2f0e 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
|
|
@@ -961,6 +961,7 @@ void otx2_get_mac_from_af(struct net_device *netdev);
|
|
void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx);
|
|
int otx2_config_pause_frm(struct otx2_nic *pfvf);
|
|
void otx2_setup_segmentation(struct otx2_nic *pfvf);
|
|
+int otx2_reset_mac_stats(struct otx2_nic *pfvf);
|
|
|
|
/* RVU block related APIs */
|
|
int otx2_attach_npa_nix(struct otx2_nic *pfvf);
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
|
|
index aa01110f04a339..294fba58b67095 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
|
|
@@ -315,6 +315,11 @@ int otx2_config_priority_flow_ctrl(struct otx2_nic *pfvf)
|
|
if (!otx2_sync_mbox_msg(&pfvf->mbox)) {
|
|
rsp = (struct cgx_pfc_rsp *)
|
|
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
|
|
+ if (IS_ERR(rsp)) {
|
|
+ err = PTR_ERR(rsp);
|
|
+ goto unlock;
|
|
+ }
|
|
+
|
|
if (req->rx_pause != rsp->rx_pause || req->tx_pause != rsp->tx_pause) {
|
|
dev_warn(pfvf->dev,
|
|
"Failed to config PFC\n");
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c
|
|
index 80d853b343f98f..2046dd0da00d85 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c
|
|
@@ -28,6 +28,11 @@ static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac,
|
|
if (!err) {
|
|
rsp = (struct cgx_mac_addr_add_rsp *)
|
|
otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
|
|
+ if (IS_ERR(rsp)) {
|
|
+ mutex_unlock(&pf->mbox.lock);
|
|
+ return PTR_ERR(rsp);
|
|
+ }
|
|
+
|
|
*dmac_index = rsp->index;
|
|
}
|
|
|
|
@@ -200,6 +205,10 @@ int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u32 bit_pos)
|
|
|
|
rsp = (struct cgx_mac_addr_update_rsp *)
|
|
otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
|
|
+ if (IS_ERR(rsp)) {
|
|
+ rc = PTR_ERR(rsp);
|
|
+ goto out;
|
|
+ }
|
|
|
|
pf->flow_cfg->bmap_to_dmacindex[bit_pos] = rsp->index;
|
|
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
|
|
index 8b7fc0af91ced2..532e84bc38c73c 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
|
|
@@ -343,6 +343,11 @@ static void otx2_get_pauseparam(struct net_device *netdev,
|
|
if (!otx2_sync_mbox_msg(&pfvf->mbox)) {
|
|
rsp = (struct cgx_pause_frm_cfg *)
|
|
otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
|
|
+ if (IS_ERR(rsp)) {
|
|
+ mutex_unlock(&pfvf->mbox.lock);
|
|
+ return;
|
|
+ }
|
|
+
|
|
pause->rx_pause = rsp->rx_pause;
|
|
pause->tx_pause = rsp->tx_pause;
|
|
}
|
|
@@ -1082,6 +1087,11 @@ static int otx2_set_fecparam(struct net_device *netdev,
|
|
|
|
rsp = (struct fec_mode *)otx2_mbox_get_rsp(&pfvf->mbox.mbox,
|
|
0, &req->hdr);
|
|
+ if (IS_ERR(rsp)) {
|
|
+ err = PTR_ERR(rsp);
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
if (rsp->fec >= 0)
|
|
pfvf->linfo.fec = rsp->fec;
|
|
else
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
|
|
index 97a71e9b856372..e6082f90f57a50 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
|
|
@@ -121,6 +121,8 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
|
|
|
|
rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
|
|
(&pfvf->mbox.mbox, 0, &req->hdr);
|
|
+ if (IS_ERR(rsp))
|
|
+ goto exit;
|
|
|
|
for (ent = 0; ent < rsp->count; ent++)
|
|
flow_cfg->flow_ent[ent + allocated] = rsp->entry_list[ent];
|
|
@@ -199,6 +201,10 @@ static int otx2_mcam_entry_init(struct otx2_nic *pfvf)
|
|
|
|
rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
|
|
(&pfvf->mbox.mbox, 0, &req->hdr);
|
|
+ if (IS_ERR(rsp)) {
|
|
+ mutex_unlock(&pfvf->mbox.lock);
|
|
+ return PTR_ERR(rsp);
|
|
+ }
|
|
|
|
if (rsp->count != req->count) {
|
|
netdev_info(pfvf->netdev,
|
|
@@ -234,6 +240,10 @@ static int otx2_mcam_entry_init(struct otx2_nic *pfvf)
|
|
|
|
frsp = (struct npc_get_field_status_rsp *)otx2_mbox_get_rsp
|
|
(&pfvf->mbox.mbox, 0, &freq->hdr);
|
|
+ if (IS_ERR(frsp)) {
|
|
+ mutex_unlock(&pfvf->mbox.lock);
|
|
+ return PTR_ERR(frsp);
|
|
+ }
|
|
|
|
if (frsp->enable) {
|
|
pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT;
|
|
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
|
|
index 3f46d5e0fb2ecb..b4194ec2a1f2d0 100644
|
|
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
|
|
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
|
|
@@ -1150,6 +1150,23 @@ static int otx2_cgx_config_linkevents(struct otx2_nic *pf, bool enable)
|
|
return err;
|
|
}
|
|
|
|
+int otx2_reset_mac_stats(struct otx2_nic *pfvf)
|
|
+{
|
|
+ struct msg_req *req;
|
|
+ int err;
|
|
+
|
|
+ mutex_lock(&pfvf->mbox.lock);
|
|
+ req = otx2_mbox_alloc_msg_cgx_stats_rst(&pfvf->mbox);
|
|
+ if (!req) {
|
|
+ mutex_unlock(&pfvf->mbox.lock);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ err = otx2_sync_mbox_msg(&pfvf->mbox);
|
|
+ mutex_unlock(&pfvf->mbox.lock);
|
|
+ return err;
|
|
+}
|
|
+
|
|
static int otx2_cgx_config_loopback(struct otx2_nic *pf, bool enable)
|
|
{
|
|
struct msg_req *msg;
|
|
@@ -3038,6 +3055,9 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
netdev->min_mtu = OTX2_MIN_MTU;
|
|
netdev->max_mtu = otx2_get_max_mtu(pf);
|
|
|
|
+ /* reset CGX/RPM MAC stats */
|
|
+ otx2_reset_mac_stats(pf);
|
|
+
|
|
err = register_netdev(netdev);
|
|
if (err) {
|
|
dev_err(dev, "Failed to register netdevice\n");
|
|
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
|
|
index d5691b6a2bc54e..f2ca4376b48c6f 100644
|
|
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
|
|
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
|
|
@@ -1394,18 +1394,15 @@ static int pxa168_eth_probe(struct platform_device *pdev)
|
|
|
|
printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n");
|
|
|
|
- clk = devm_clk_get(&pdev->dev, NULL);
|
|
+ clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
|
if (IS_ERR(clk)) {
|
|
- dev_err(&pdev->dev, "Fast Ethernet failed to get clock\n");
|
|
+ dev_err(&pdev->dev, "Fast Ethernet failed to get and enable clock\n");
|
|
return -ENODEV;
|
|
}
|
|
- clk_prepare_enable(clk);
|
|
|
|
dev = alloc_etherdev(sizeof(struct pxa168_eth_private));
|
|
- if (!dev) {
|
|
- err = -ENOMEM;
|
|
- goto err_clk;
|
|
- }
|
|
+ if (!dev)
|
|
+ return -ENOMEM;
|
|
|
|
platform_set_drvdata(pdev, dev);
|
|
pep = netdev_priv(dev);
|
|
@@ -1523,8 +1520,6 @@ static int pxa168_eth_probe(struct platform_device *pdev)
|
|
mdiobus_free(pep->smi_bus);
|
|
err_netdev:
|
|
free_netdev(dev);
|
|
-err_clk:
|
|
- clk_disable_unprepare(clk);
|
|
return err;
|
|
}
|
|
|
|
@@ -1542,7 +1537,6 @@ static int pxa168_eth_remove(struct platform_device *pdev)
|
|
if (dev->phydev)
|
|
phy_disconnect(dev->phydev);
|
|
|
|
- clk_disable_unprepare(pep->clk);
|
|
mdiobus_unregister(pep->smi_bus);
|
|
mdiobus_free(pep->smi_bus);
|
|
unregister_netdev(dev);
|
|
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
|
|
index 66ef14d95bf6f7..88744ae6529354 100644
|
|
--- a/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
|
|
+++ b/drivers/net/ethernet/microchip/vcap/vcap_api_kunit.c
|
|
@@ -366,12 +366,13 @@ static void vcap_api_iterator_init_test(struct kunit *test)
|
|
struct vcap_typegroup typegroups[] = {
|
|
{ .offset = 0, .width = 2, .value = 2, },
|
|
{ .offset = 156, .width = 1, .value = 0, },
|
|
- { .offset = 0, .width = 0, .value = 0, },
|
|
+ { }
|
|
};
|
|
struct vcap_typegroup typegroups2[] = {
|
|
{ .offset = 0, .width = 3, .value = 4, },
|
|
{ .offset = 49, .width = 2, .value = 0, },
|
|
{ .offset = 98, .width = 2, .value = 0, },
|
|
+ { }
|
|
};
|
|
|
|
vcap_iter_init(&iter, 52, typegroups, 86);
|
|
@@ -399,6 +400,7 @@ static void vcap_api_iterator_next_test(struct kunit *test)
|
|
{ .offset = 147, .width = 3, .value = 0, },
|
|
{ .offset = 196, .width = 2, .value = 0, },
|
|
{ .offset = 245, .width = 1, .value = 0, },
|
|
+ { }
|
|
};
|
|
int idx;
|
|
|
|
@@ -433,7 +435,7 @@ static void vcap_api_encode_typegroups_test(struct kunit *test)
|
|
{ .offset = 147, .width = 3, .value = 5, },
|
|
{ .offset = 196, .width = 2, .value = 2, },
|
|
{ .offset = 245, .width = 5, .value = 27, },
|
|
- { .offset = 0, .width = 0, .value = 0, },
|
|
+ { }
|
|
};
|
|
|
|
vcap_encode_typegroups(stream, 49, typegroups, false);
|
|
@@ -463,6 +465,7 @@ static void vcap_api_encode_bit_test(struct kunit *test)
|
|
{ .offset = 147, .width = 3, .value = 5, },
|
|
{ .offset = 196, .width = 2, .value = 2, },
|
|
{ .offset = 245, .width = 1, .value = 0, },
|
|
+ { }
|
|
};
|
|
|
|
vcap_iter_init(&iter, 49, typegroups, 44);
|
|
@@ -489,7 +492,7 @@ static void vcap_api_encode_field_test(struct kunit *test)
|
|
{ .offset = 147, .width = 3, .value = 5, },
|
|
{ .offset = 196, .width = 2, .value = 2, },
|
|
{ .offset = 245, .width = 5, .value = 27, },
|
|
- { .offset = 0, .width = 0, .value = 0, },
|
|
+ { }
|
|
};
|
|
struct vcap_field rf = {
|
|
.type = VCAP_FIELD_U32,
|
|
@@ -538,7 +541,7 @@ static void vcap_api_encode_short_field_test(struct kunit *test)
|
|
{ .offset = 0, .width = 3, .value = 7, },
|
|
{ .offset = 21, .width = 2, .value = 3, },
|
|
{ .offset = 42, .width = 1, .value = 1, },
|
|
- { .offset = 0, .width = 0, .value = 0, },
|
|
+ { }
|
|
};
|
|
struct vcap_field rf = {
|
|
.type = VCAP_FIELD_U32,
|
|
@@ -608,7 +611,7 @@ static void vcap_api_encode_keyfield_test(struct kunit *test)
|
|
struct vcap_typegroup tgt[] = {
|
|
{ .offset = 0, .width = 2, .value = 2, },
|
|
{ .offset = 156, .width = 1, .value = 1, },
|
|
- { .offset = 0, .width = 0, .value = 0, },
|
|
+ { }
|
|
};
|
|
|
|
vcap_test_api_init(&admin);
|
|
@@ -671,7 +674,7 @@ static void vcap_api_encode_max_keyfield_test(struct kunit *test)
|
|
struct vcap_typegroup tgt[] = {
|
|
{ .offset = 0, .width = 2, .value = 2, },
|
|
{ .offset = 156, .width = 1, .value = 1, },
|
|
- { .offset = 0, .width = 0, .value = 0, },
|
|
+ { }
|
|
};
|
|
u32 keyres[] = {
|
|
0x928e8a84,
|
|
@@ -732,7 +735,7 @@ static void vcap_api_encode_actionfield_test(struct kunit *test)
|
|
{ .offset = 0, .width = 2, .value = 2, },
|
|
{ .offset = 21, .width = 1, .value = 1, },
|
|
{ .offset = 42, .width = 1, .value = 0, },
|
|
- { .offset = 0, .width = 0, .value = 0, },
|
|
+ { }
|
|
};
|
|
|
|
vcap_encode_actionfield(&rule, &caf, &rf, tgt);
|
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
|
|
index 9bf102bbc6a004..5d20325a18dd3d 100644
|
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
|
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
|
|
@@ -429,6 +429,8 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
|
|
plat_dat->bsp_priv = dwmac;
|
|
plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
|
|
|
|
+ plat_dat->riwt_off = 1;
|
|
+
|
|
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
|
|
if (ret)
|
|
goto err_remove_config_dt;
|
|
diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c
|
|
index 78b93de636f57f..0e13fca8731ab3 100644
|
|
--- a/drivers/net/mdio/mdio-ipq4019.c
|
|
+++ b/drivers/net/mdio/mdio-ipq4019.c
|
|
@@ -255,8 +255,11 @@ static int ipq4019_mdio_probe(struct platform_device *pdev)
|
|
/* The platform resource is provided on the chipset IPQ5018 */
|
|
/* This resource is optional */
|
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
- if (res)
|
|
+ if (res) {
|
|
priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res);
|
|
+ if (IS_ERR(priv->eth_ldo_rdy))
|
|
+ return PTR_ERR(priv->eth_ldo_rdy);
|
|
+ }
|
|
|
|
bus->name = "ipq4019_mdio";
|
|
bus->read = ipq4019_mdio_read_c22;
|
|
diff --git a/drivers/net/netdevsim/ipsec.c b/drivers/net/netdevsim/ipsec.c
|
|
index f0d58092e7e961..3612b0633bd177 100644
|
|
--- a/drivers/net/netdevsim/ipsec.c
|
|
+++ b/drivers/net/netdevsim/ipsec.c
|
|
@@ -176,14 +176,13 @@ static int nsim_ipsec_add_sa(struct xfrm_state *xs,
|
|
return ret;
|
|
}
|
|
|
|
- if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) {
|
|
+ if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN)
|
|
sa.rx = true;
|
|
|
|
- if (xs->props.family == AF_INET6)
|
|
- memcpy(sa.ipaddr, &xs->id.daddr.a6, 16);
|
|
- else
|
|
- memcpy(&sa.ipaddr[3], &xs->id.daddr.a4, 4);
|
|
- }
|
|
+ if (xs->props.family == AF_INET6)
|
|
+ memcpy(sa.ipaddr, &xs->id.daddr.a6, 16);
|
|
+ else
|
|
+ memcpy(&sa.ipaddr[3], &xs->id.daddr.a4, 4);
|
|
|
|
/* the preparations worked, so save the info */
|
|
memcpy(&ipsec->sa[sa_idx], &sa, sizeof(sa));
|
|
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
|
|
index 921ae046f86041..09173d7b87ed5c 100644
|
|
--- a/drivers/net/usb/lan78xx.c
|
|
+++ b/drivers/net/usb/lan78xx.c
|
|
@@ -1657,13 +1657,13 @@ static int lan78xx_set_wol(struct net_device *netdev,
|
|
struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
|
|
int ret;
|
|
|
|
+ if (wol->wolopts & ~WAKE_ALL)
|
|
+ return -EINVAL;
|
|
+
|
|
ret = usb_autopm_get_interface(dev->intf);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- if (wol->wolopts & ~WAKE_ALL)
|
|
- return -EINVAL;
|
|
-
|
|
pdata->wol = wol->wolopts;
|
|
|
|
device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
|
|
@@ -2387,6 +2387,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
|
|
if (dev->chipid == ID_REV_CHIP_ID_7801_) {
|
|
if (phy_is_pseudo_fixed_link(phydev)) {
|
|
fixed_phy_unregister(phydev);
|
|
+ phy_device_free(phydev);
|
|
} else {
|
|
phy_unregister_fixup_for_uid(PHY_KSZ9031RNX,
|
|
0xfffffff0);
|
|
@@ -4246,8 +4247,10 @@ static void lan78xx_disconnect(struct usb_interface *intf)
|
|
|
|
phy_disconnect(net->phydev);
|
|
|
|
- if (phy_is_pseudo_fixed_link(phydev))
|
|
+ if (phy_is_pseudo_fixed_link(phydev)) {
|
|
fixed_phy_unregister(phydev);
|
|
+ phy_device_free(phydev);
|
|
+ }
|
|
|
|
usb_scuttle_anchored_urbs(&dev->deferred);
|
|
|
|
@@ -4414,29 +4417,30 @@ static int lan78xx_probe(struct usb_interface *intf,
|
|
|
|
period = ep_intr->desc.bInterval;
|
|
maxp = usb_maxpacket(dev->udev, dev->pipe_intr);
|
|
- buf = kmalloc(maxp, GFP_KERNEL);
|
|
- if (!buf) {
|
|
+
|
|
+ dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
|
|
+ if (!dev->urb_intr) {
|
|
ret = -ENOMEM;
|
|
goto out5;
|
|
}
|
|
|
|
- dev->urb_intr = usb_alloc_urb(0, GFP_KERNEL);
|
|
- if (!dev->urb_intr) {
|
|
+ buf = kmalloc(maxp, GFP_KERNEL);
|
|
+ if (!buf) {
|
|
ret = -ENOMEM;
|
|
- goto out6;
|
|
- } else {
|
|
- usb_fill_int_urb(dev->urb_intr, dev->udev,
|
|
- dev->pipe_intr, buf, maxp,
|
|
- intr_complete, dev, period);
|
|
- dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
|
|
+ goto free_urbs;
|
|
}
|
|
|
|
+ usb_fill_int_urb(dev->urb_intr, dev->udev,
|
|
+ dev->pipe_intr, buf, maxp,
|
|
+ intr_complete, dev, period);
|
|
+ dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
|
|
+
|
|
dev->maxpacket = usb_maxpacket(dev->udev, dev->pipe_out);
|
|
|
|
/* Reject broken descriptors. */
|
|
if (dev->maxpacket == 0) {
|
|
ret = -ENODEV;
|
|
- goto out6;
|
|
+ goto free_urbs;
|
|
}
|
|
|
|
/* driver requires remote-wakeup capability during autosuspend. */
|
|
@@ -4444,7 +4448,7 @@ static int lan78xx_probe(struct usb_interface *intf,
|
|
|
|
ret = lan78xx_phy_init(dev);
|
|
if (ret < 0)
|
|
- goto out7;
|
|
+ goto free_urbs;
|
|
|
|
ret = register_netdev(netdev);
|
|
if (ret != 0) {
|
|
@@ -4466,10 +4470,8 @@ static int lan78xx_probe(struct usb_interface *intf,
|
|
|
|
out8:
|
|
phy_disconnect(netdev->phydev);
|
|
-out7:
|
|
+free_urbs:
|
|
usb_free_urb(dev->urb_intr);
|
|
-out6:
|
|
- kfree(buf);
|
|
out5:
|
|
lan78xx_unbind(dev, intf);
|
|
out4:
|
|
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
|
|
index 2cf4324a12fd18..89775b6d0699a0 100644
|
|
--- a/drivers/net/usb/qmi_wwan.c
|
|
+++ b/drivers/net/usb/qmi_wwan.c
|
|
@@ -1084,6 +1084,7 @@ static const struct usb_device_id products[] = {
|
|
USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7),
|
|
.driver_info = (unsigned long)&qmi_wwan_info,
|
|
},
|
|
+ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0122)}, /* Quectel RG650V */
|
|
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */
|
|
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */
|
|
{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */
|
|
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
|
|
index ce19ebd180f126..3e5998555f9814 100644
|
|
--- a/drivers/net/usb/r8152.c
|
|
+++ b/drivers/net/usb/r8152.c
|
|
@@ -10016,6 +10016,7 @@ static const struct usb_device_id rtl8152_table[] = {
|
|
{ USB_DEVICE(VENDOR_ID_LENOVO, 0x3062) },
|
|
{ USB_DEVICE(VENDOR_ID_LENOVO, 0x3069) },
|
|
{ USB_DEVICE(VENDOR_ID_LENOVO, 0x3082) },
|
|
+ { USB_DEVICE(VENDOR_ID_LENOVO, 0x3098) },
|
|
{ USB_DEVICE(VENDOR_ID_LENOVO, 0x7205) },
|
|
{ USB_DEVICE(VENDOR_ID_LENOVO, 0x720c) },
|
|
{ USB_DEVICE(VENDOR_ID_LENOVO, 0x7214) },
|
|
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
|
|
index 03e7bc5b6c0bd0..d5e6e11f630b95 100644
|
|
--- a/drivers/net/wireless/ath/ath10k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath10k/mac.c
|
|
@@ -9119,7 +9119,7 @@ static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss1[
|
|
{6, {2633, 2925}, {1215, 1350}, {585, 650} },
|
|
{7, {2925, 3250}, {1350, 1500}, {650, 722} },
|
|
{8, {3510, 3900}, {1620, 1800}, {780, 867} },
|
|
- {9, {3900, 4333}, {1800, 2000}, {780, 867} }
|
|
+ {9, {3900, 4333}, {1800, 2000}, {865, 960} }
|
|
};
|
|
|
|
/*MCS parameters with Nss = 2 */
|
|
@@ -9134,7 +9134,7 @@ static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss2[
|
|
{6, {5265, 5850}, {2430, 2700}, {1170, 1300} },
|
|
{7, {5850, 6500}, {2700, 3000}, {1300, 1444} },
|
|
{8, {7020, 7800}, {3240, 3600}, {1560, 1733} },
|
|
- {9, {7800, 8667}, {3600, 4000}, {1560, 1733} }
|
|
+ {9, {7800, 8667}, {3600, 4000}, {1730, 1920} }
|
|
};
|
|
|
|
static void ath10k_mac_get_rate_flags_ht(struct ath10k *ar, u32 rate, u8 nss, u8 mcs,
|
|
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
|
|
index 83dc284392de22..fa46e645009cf6 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/qmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
|
|
@@ -2180,6 +2180,9 @@ static int ath11k_qmi_request_device_info(struct ath11k_base *ab)
|
|
ab->mem = bar_addr_va;
|
|
ab->mem_len = resp.bar_size;
|
|
|
|
+ if (!ab->hw_params.ce_remap)
|
|
+ ab->mem_ce = ab->mem;
|
|
+
|
|
return 0;
|
|
out:
|
|
return ret;
|
|
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
|
|
index 907655c45a4b9a..c663ff990b4791 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/dp.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/dp.c
|
|
@@ -1214,6 +1214,7 @@ static void ath12k_dp_cc_cleanup(struct ath12k_base *ab)
|
|
}
|
|
|
|
kfree(dp->spt_info);
|
|
+ dp->spt_info = NULL;
|
|
}
|
|
|
|
static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
|
|
@@ -1249,8 +1250,10 @@ void ath12k_dp_free(struct ath12k_base *ab)
|
|
|
|
ath12k_dp_rx_reo_cmd_list_cleanup(ab);
|
|
|
|
- for (i = 0; i < ab->hw_params->max_tx_ring; i++)
|
|
+ for (i = 0; i < ab->hw_params->max_tx_ring; i++) {
|
|
kfree(dp->tx_ring[i].tx_status);
|
|
+ dp->tx_ring[i].tx_status = NULL;
|
|
+ }
|
|
|
|
ath12k_dp_rx_free(ab);
|
|
/* Deinit any SOC level resource */
|
|
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
|
|
index 4bb30e40372877..f90191a290c26a 100644
|
|
--- a/drivers/net/wireless/ath/ath12k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/mac.c
|
|
@@ -775,7 +775,10 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
|
|
|
|
spin_lock_bh(&ab->base_lock);
|
|
list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
|
|
- ath12k_dp_rx_peer_tid_cleanup(ar, peer);
|
|
+ /* Skip Rx TID cleanup for self peer */
|
|
+ if (peer->sta)
|
|
+ ath12k_dp_rx_peer_tid_cleanup(ar, peer);
|
|
+
|
|
list_del(&peer->list);
|
|
kfree(peer);
|
|
}
|
|
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
|
|
index 99667aba289df0..00dc97ac53b9d8 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
|
|
@@ -294,6 +294,9 @@ int htc_connect_service(struct htc_target *target,
|
|
return -ETIMEDOUT;
|
|
}
|
|
|
|
+ if (target->conn_rsp_epid < 0 || target->conn_rsp_epid >= ENDPOINT_MAX)
|
|
+ return -EINVAL;
|
|
+
|
|
*conn_rsp_epid = target->conn_rsp_epid;
|
|
return 0;
|
|
err:
|
|
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
|
|
index f29ac6de713994..19702b6f09c329 100644
|
|
--- a/drivers/net/wireless/ath/wil6210/txrx.c
|
|
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
|
|
@@ -306,7 +306,7 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
|
|
struct sk_buff *skb)
|
|
{
|
|
struct wil6210_rtap {
|
|
- struct ieee80211_radiotap_header rthdr;
|
|
+ struct ieee80211_radiotap_header_fixed rthdr;
|
|
/* fields should be in the order of bits in rthdr.it_present */
|
|
/* flags */
|
|
u8 flags;
|
|
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
|
index e406e11481a621..73fc701204e29b 100644
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
|
|
@@ -109,9 +109,8 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
|
|
}
|
|
strreplace(board_type, '/', '-');
|
|
settings->board_type = board_type;
|
|
-
|
|
- of_node_put(root);
|
|
}
|
|
+ of_node_put(root);
|
|
|
|
if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
|
|
return;
|
|
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
|
|
index 0812db8936f132..9e9ff0cb724cac 100644
|
|
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
|
|
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
|
|
@@ -2520,7 +2520,7 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
|
|
* to build this manually element by element, we can write it much
|
|
* more efficiently than we can parse it. ORDER MATTERS HERE */
|
|
struct ipw_rt_hdr {
|
|
- struct ieee80211_radiotap_header rt_hdr;
|
|
+ struct ieee80211_radiotap_header_fixed rt_hdr;
|
|
s8 rt_dbmsignal; /* signal in dbM, kluged to signed */
|
|
} *ipw_rt;
|
|
|
|
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.h b/drivers/net/wireless/intel/ipw2x00/ipw2200.h
|
|
index 8ebf09121e173c..226286cb7eb822 100644
|
|
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.h
|
|
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.h
|
|
@@ -1143,7 +1143,7 @@ struct ipw_prom_priv {
|
|
* structure is provided regardless of any bits unset.
|
|
*/
|
|
struct ipw_rt_hdr {
|
|
- struct ieee80211_radiotap_header rt_hdr;
|
|
+ struct ieee80211_radiotap_header_fixed rt_hdr;
|
|
u64 rt_tsf; /* TSF */ /* XXX */
|
|
u8 rt_flags; /* radiotap packet flags */
|
|
u8 rt_rate; /* rate in 500kb/s */
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c
|
|
index 135bd48bfe9fa8..cf02a2afbee56f 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/fw/init.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c
|
|
@@ -39,10 +39,12 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
|
}
|
|
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
|
|
|
|
+/* Assumes the appropriate lock is held by the caller */
|
|
void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt)
|
|
{
|
|
iwl_fw_suspend_timestamp(fwrt);
|
|
- iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_START, NULL);
|
|
+ iwl_dbg_tlv_time_point_sync(fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_START,
|
|
+ NULL);
|
|
}
|
|
IWL_EXPORT_SYMBOL(iwl_fw_runtime_suspend);
|
|
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
|
|
index 08d1fab7f53c3a..592b9157d50c67 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
|
|
@@ -1382,7 +1382,9 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
|
|
|
iwl_mvm_pause_tcm(mvm, true);
|
|
|
|
+ mutex_lock(&mvm->mutex);
|
|
iwl_fw_runtime_suspend(&mvm->fwrt);
|
|
+ mutex_unlock(&mvm->mutex);
|
|
|
|
return __iwl_mvm_suspend(hw, wowlan, false);
|
|
}
|
|
diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c
|
|
index ce0179b8ab368f..90ebed33d792ba 100644
|
|
--- a/drivers/net/wireless/intersil/p54/p54spi.c
|
|
+++ b/drivers/net/wireless/intersil/p54/p54spi.c
|
|
@@ -624,7 +624,7 @@ static int p54spi_probe(struct spi_device *spi)
|
|
gpio_direction_input(p54spi_gpio_irq);
|
|
|
|
ret = request_irq(gpio_to_irq(p54spi_gpio_irq),
|
|
- p54spi_interrupt, 0, "p54spi",
|
|
+ p54spi_interrupt, IRQF_NO_AUTOEN, "p54spi",
|
|
priv->spi);
|
|
if (ret < 0) {
|
|
dev_err(&priv->spi->dev, "request_irq() failed");
|
|
@@ -633,8 +633,6 @@ static int p54spi_probe(struct spi_device *spi)
|
|
|
|
irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
|
|
|
|
- disable_irq(gpio_to_irq(p54spi_gpio_irq));
|
|
-
|
|
INIT_WORK(&priv->work, p54spi_work);
|
|
init_completion(&priv->fw_comp);
|
|
INIT_LIST_HEAD(&priv->tx_pending);
|
|
diff --git a/drivers/net/wireless/marvell/libertas/radiotap.h b/drivers/net/wireless/marvell/libertas/radiotap.h
|
|
index 1ed5608d353ff5..d543bfe739dcb9 100644
|
|
--- a/drivers/net/wireless/marvell/libertas/radiotap.h
|
|
+++ b/drivers/net/wireless/marvell/libertas/radiotap.h
|
|
@@ -2,7 +2,7 @@
|
|
#include <net/ieee80211_radiotap.h>
|
|
|
|
struct tx_radiotap_hdr {
|
|
- struct ieee80211_radiotap_header hdr;
|
|
+ struct ieee80211_radiotap_header_fixed hdr;
|
|
u8 rate;
|
|
u8 txpower;
|
|
u8 rts_retries;
|
|
@@ -31,7 +31,7 @@ struct tx_radiotap_hdr {
|
|
#define IEEE80211_FC_DSTODS 0x0300
|
|
|
|
struct rx_radiotap_hdr {
|
|
- struct ieee80211_radiotap_header hdr;
|
|
+ struct ieee80211_radiotap_header_fixed hdr;
|
|
u8 flags;
|
|
u8 rate;
|
|
u8 antsignal;
|
|
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
|
|
index a3be37526697b4..7b06a6d57ffb0b 100644
|
|
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
|
|
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
|
|
@@ -842,7 +842,7 @@ struct mwifiex_ietypes_chanstats {
|
|
struct mwifiex_ie_types_wildcard_ssid_params {
|
|
struct mwifiex_ie_types_header header;
|
|
u8 max_ssid_length;
|
|
- u8 ssid[1];
|
|
+ u8 ssid[];
|
|
} __packed;
|
|
|
|
#define TSF_DATA_SIZE 8
|
|
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
|
|
index d99127dc466ecb..6c60a4c21a3128 100644
|
|
--- a/drivers/net/wireless/marvell/mwifiex/main.c
|
|
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
|
|
@@ -1633,7 +1633,8 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
|
|
}
|
|
|
|
ret = devm_request_irq(dev, adapter->irq_wakeup,
|
|
- mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW,
|
|
+ mwifiex_irq_wakeup_handler,
|
|
+ IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN,
|
|
"wifi_wake", adapter);
|
|
if (ret) {
|
|
dev_err(dev, "Failed to request irq_wakeup %d (%d)\n",
|
|
@@ -1641,7 +1642,6 @@ static void mwifiex_probe_of(struct mwifiex_adapter *adapter)
|
|
goto err_exit;
|
|
}
|
|
|
|
- disable_irq(adapter->irq_wakeup);
|
|
if (device_init_wakeup(dev, true)) {
|
|
dev_err(dev, "fail to init wakeup for mwifiex\n");
|
|
goto err_exit;
|
|
diff --git a/drivers/net/wireless/microchip/wilc1000/mon.c b/drivers/net/wireless/microchip/wilc1000/mon.c
|
|
index 03b7229a0ff5aa..c3d27aaec29742 100644
|
|
--- a/drivers/net/wireless/microchip/wilc1000/mon.c
|
|
+++ b/drivers/net/wireless/microchip/wilc1000/mon.c
|
|
@@ -7,12 +7,12 @@
|
|
#include "cfg80211.h"
|
|
|
|
struct wilc_wfi_radiotap_hdr {
|
|
- struct ieee80211_radiotap_header hdr;
|
|
+ struct ieee80211_radiotap_header_fixed hdr;
|
|
u8 rate;
|
|
} __packed;
|
|
|
|
struct wilc_wfi_radiotap_cb_hdr {
|
|
- struct ieee80211_radiotap_header hdr;
|
|
+ struct ieee80211_radiotap_header_fixed hdr;
|
|
u8 rate;
|
|
u8 dump;
|
|
u16 tx_flags;
|
|
diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c
|
|
index 2e945554ed6d59..6c8efd2b264269 100644
|
|
--- a/drivers/net/wireless/realtek/rtlwifi/efuse.c
|
|
+++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c
|
|
@@ -162,10 +162,19 @@ void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value)
|
|
void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf)
|
|
{
|
|
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
|
+ u16 max_attempts = 10000;
|
|
u32 value32;
|
|
u8 readbyte;
|
|
u16 retry;
|
|
|
|
+ /*
|
|
+ * In case of USB devices, transfer speeds are limited, hence
|
|
+ * efuse I/O reads could be (way) slower. So, decrease (a lot)
|
|
+ * the read attempts in case of failures.
|
|
+ */
|
|
+ if (rtlpriv->rtlhal.interface == INTF_USB)
|
|
+ max_attempts = 10;
|
|
+
|
|
rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1,
|
|
(_offset & 0xff));
|
|
readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2);
|
|
@@ -178,7 +187,7 @@ void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf)
|
|
|
|
retry = 0;
|
|
value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]);
|
|
- while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) {
|
|
+ while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < max_attempts)) {
|
|
value32 = rtl_read_dword(rtlpriv,
|
|
rtlpriv->cfg->maps[EFUSE_CTRL]);
|
|
retry++;
|
|
diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c
|
|
index ede822d771aafb..f2409830d87e30 100644
|
|
--- a/drivers/net/wireless/silabs/wfx/main.c
|
|
+++ b/drivers/net/wireless/silabs/wfx/main.c
|
|
@@ -475,10 +475,23 @@ static int __init wfx_core_init(void)
|
|
{
|
|
int ret = 0;
|
|
|
|
- if (IS_ENABLED(CONFIG_SPI))
|
|
+ if (IS_ENABLED(CONFIG_SPI)) {
|
|
ret = spi_register_driver(&wfx_spi_driver);
|
|
- if (IS_ENABLED(CONFIG_MMC) && !ret)
|
|
+ if (ret)
|
|
+ goto out;
|
|
+ }
|
|
+ if (IS_ENABLED(CONFIG_MMC)) {
|
|
ret = sdio_register_driver(&wfx_sdio_driver);
|
|
+ if (ret)
|
|
+ goto unregister_spi;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+unregister_spi:
|
|
+ if (IS_ENABLED(CONFIG_SPI))
|
|
+ spi_unregister_driver(&wfx_spi_driver);
|
|
+out:
|
|
return ret;
|
|
}
|
|
module_init(wfx_core_init);
|
|
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
|
|
index 07be0adc13ec5c..d86a1bd7aab089 100644
|
|
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
|
|
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
|
|
@@ -736,7 +736,7 @@ static const struct rhashtable_params hwsim_rht_params = {
|
|
};
|
|
|
|
struct hwsim_radiotap_hdr {
|
|
- struct ieee80211_radiotap_header hdr;
|
|
+ struct ieee80211_radiotap_header_fixed hdr;
|
|
__le64 rt_tsft;
|
|
u8 rt_flags;
|
|
u8 rt_rate;
|
|
@@ -745,7 +745,7 @@ struct hwsim_radiotap_hdr {
|
|
} __packed;
|
|
|
|
struct hwsim_radiotap_ack_hdr {
|
|
- struct ieee80211_radiotap_header hdr;
|
|
+ struct ieee80211_radiotap_header_fixed hdr;
|
|
u8 rt_flags;
|
|
u8 pad;
|
|
__le16 rt_channel;
|
|
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
|
|
index 596bb11eeba5a9..396eb943765979 100644
|
|
--- a/drivers/nvme/host/apple.c
|
|
+++ b/drivers/nvme/host/apple.c
|
|
@@ -1387,7 +1387,7 @@ static void devm_apple_nvme_mempool_destroy(void *data)
|
|
mempool_destroy(data);
|
|
}
|
|
|
|
-static int apple_nvme_probe(struct platform_device *pdev)
|
|
+static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
|
|
{
|
|
struct device *dev = &pdev->dev;
|
|
struct apple_nvme *anv;
|
|
@@ -1395,7 +1395,7 @@ static int apple_nvme_probe(struct platform_device *pdev)
|
|
|
|
anv = devm_kzalloc(dev, sizeof(*anv), GFP_KERNEL);
|
|
if (!anv)
|
|
- return -ENOMEM;
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
|
anv->dev = get_device(dev);
|
|
anv->adminq.is_adminq = true;
|
|
@@ -1515,10 +1515,26 @@ static int apple_nvme_probe(struct platform_device *pdev)
|
|
goto put_dev;
|
|
}
|
|
|
|
+ return anv;
|
|
+put_dev:
|
|
+ put_device(anv->dev);
|
|
+ return ERR_PTR(ret);
|
|
+}
|
|
+
|
|
+static int apple_nvme_probe(struct platform_device *pdev)
|
|
+{
|
|
+ struct apple_nvme *anv;
|
|
+ int ret;
|
|
+
|
|
+ anv = apple_nvme_alloc(pdev);
|
|
+ if (IS_ERR(anv))
|
|
+ return PTR_ERR(anv);
|
|
+
|
|
anv->ctrl.admin_q = blk_mq_init_queue(&anv->admin_tagset);
|
|
if (IS_ERR(anv->ctrl.admin_q)) {
|
|
ret = -ENOMEM;
|
|
- goto put_dev;
|
|
+ anv->ctrl.admin_q = NULL;
|
|
+ goto out_uninit_ctrl;
|
|
}
|
|
|
|
nvme_reset_ctrl(&anv->ctrl);
|
|
@@ -1526,8 +1542,9 @@ static int apple_nvme_probe(struct platform_device *pdev)
|
|
|
|
return 0;
|
|
|
|
-put_dev:
|
|
- put_device(anv->dev);
|
|
+out_uninit_ctrl:
|
|
+ nvme_uninit_ctrl(&anv->ctrl);
|
|
+ nvme_put_ctrl(&anv->ctrl);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
|
|
index 965ca7d7a3de22..5b6a6bd4e6e800 100644
|
|
--- a/drivers/nvme/host/core.c
|
|
+++ b/drivers/nvme/host/core.c
|
|
@@ -109,7 +109,7 @@ struct workqueue_struct *nvme_delete_wq;
|
|
EXPORT_SYMBOL_GPL(nvme_delete_wq);
|
|
|
|
static LIST_HEAD(nvme_subsystems);
|
|
-static DEFINE_MUTEX(nvme_subsystems_lock);
|
|
+DEFINE_MUTEX(nvme_subsystems_lock);
|
|
|
|
static DEFINE_IDA(nvme_instance_ida);
|
|
static dev_t nvme_ctrl_base_chr_devt;
|
|
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
|
|
index 875dee6ecd4081..19a7f0160618d1 100644
|
|
--- a/drivers/nvme/host/ioctl.c
|
|
+++ b/drivers/nvme/host/ioctl.c
|
|
@@ -3,6 +3,7 @@
|
|
* Copyright (c) 2011-2014, Intel Corporation.
|
|
* Copyright (c) 2017-2021 Christoph Hellwig.
|
|
*/
|
|
+#include <linux/blk-integrity.h>
|
|
#include <linux/ptrace.h> /* for force_successful_syscall_return */
|
|
#include <linux/nvme_ioctl.h>
|
|
#include <linux/io_uring.h>
|
|
@@ -171,10 +172,15 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
|
|
struct request_queue *q = req->q;
|
|
struct nvme_ns *ns = q->queuedata;
|
|
struct block_device *bdev = ns ? ns->disk->part0 : NULL;
|
|
+ bool supports_metadata = bdev && blk_get_integrity(bdev->bd_disk);
|
|
+ bool has_metadata = meta_buffer && meta_len;
|
|
struct bio *bio = NULL;
|
|
void *meta = NULL;
|
|
int ret;
|
|
|
|
+ if (has_metadata && !supports_metadata)
|
|
+ return -EINVAL;
|
|
+
|
|
if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) {
|
|
struct iov_iter iter;
|
|
|
|
@@ -198,7 +204,7 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
|
|
if (bdev)
|
|
bio_set_dev(bio, bdev);
|
|
|
|
- if (bdev && meta_buffer && meta_len) {
|
|
+ if (has_metadata) {
|
|
meta = nvme_add_user_metadata(req, meta_buffer, meta_len,
|
|
meta_seed);
|
|
if (IS_ERR(meta)) {
|
|
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
|
|
index ede2a14dad8be7..32283301199f01 100644
|
|
--- a/drivers/nvme/host/multipath.c
|
|
+++ b/drivers/nvme/host/multipath.c
|
|
@@ -17,6 +17,7 @@ MODULE_PARM_DESC(multipath,
|
|
static const char *nvme_iopolicy_names[] = {
|
|
[NVME_IOPOLICY_NUMA] = "numa",
|
|
[NVME_IOPOLICY_RR] = "round-robin",
|
|
+ [NVME_IOPOLICY_QD] = "queue-depth",
|
|
};
|
|
|
|
static int iopolicy = NVME_IOPOLICY_NUMA;
|
|
@@ -29,6 +30,8 @@ static int nvme_set_iopolicy(const char *val, const struct kernel_param *kp)
|
|
iopolicy = NVME_IOPOLICY_NUMA;
|
|
else if (!strncmp(val, "round-robin", 11))
|
|
iopolicy = NVME_IOPOLICY_RR;
|
|
+ else if (!strncmp(val, "queue-depth", 11))
|
|
+ iopolicy = NVME_IOPOLICY_QD;
|
|
else
|
|
return -EINVAL;
|
|
|
|
@@ -43,7 +46,7 @@ static int nvme_get_iopolicy(char *buf, const struct kernel_param *kp)
|
|
module_param_call(iopolicy, nvme_set_iopolicy, nvme_get_iopolicy,
|
|
&iopolicy, 0644);
|
|
MODULE_PARM_DESC(iopolicy,
|
|
- "Default multipath I/O policy; 'numa' (default) or 'round-robin'");
|
|
+ "Default multipath I/O policy; 'numa' (default), 'round-robin' or 'queue-depth'");
|
|
|
|
void nvme_mpath_default_iopolicy(struct nvme_subsystem *subsys)
|
|
{
|
|
@@ -128,6 +131,11 @@ void nvme_mpath_start_request(struct request *rq)
|
|
struct nvme_ns *ns = rq->q->queuedata;
|
|
struct gendisk *disk = ns->head->disk;
|
|
|
|
+ if (READ_ONCE(ns->head->subsys->iopolicy) == NVME_IOPOLICY_QD) {
|
|
+ atomic_inc(&ns->ctrl->nr_active);
|
|
+ nvme_req(rq)->flags |= NVME_MPATH_CNT_ACTIVE;
|
|
+ }
|
|
+
|
|
if (!blk_queue_io_stat(disk->queue) || blk_rq_is_passthrough(rq))
|
|
return;
|
|
|
|
@@ -141,6 +149,9 @@ void nvme_mpath_end_request(struct request *rq)
|
|
{
|
|
struct nvme_ns *ns = rq->q->queuedata;
|
|
|
|
+ if (nvme_req(rq)->flags & NVME_MPATH_CNT_ACTIVE)
|
|
+ atomic_dec_if_positive(&ns->ctrl->nr_active);
|
|
+
|
|
if (!(nvme_req(rq)->flags & NVME_MPATH_IO_STATS))
|
|
return;
|
|
bdev_end_io_acct(ns->head->disk->part0, req_op(rq),
|
|
@@ -154,7 +165,8 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
|
|
int srcu_idx;
|
|
|
|
srcu_idx = srcu_read_lock(&ctrl->srcu);
|
|
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
|
|
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
|
|
+ srcu_read_lock_held(&ctrl->srcu)) {
|
|
if (!ns->head->disk)
|
|
continue;
|
|
kblockd_schedule_work(&ns->head->requeue_work);
|
|
@@ -198,7 +210,8 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
|
|
int srcu_idx;
|
|
|
|
srcu_idx = srcu_read_lock(&ctrl->srcu);
|
|
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
|
|
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
|
|
+ srcu_read_lock_held(&ctrl->srcu)) {
|
|
nvme_mpath_clear_current_path(ns);
|
|
kblockd_schedule_work(&ns->head->requeue_work);
|
|
}
|
|
@@ -213,7 +226,8 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
|
|
int srcu_idx;
|
|
|
|
srcu_idx = srcu_read_lock(&head->srcu);
|
|
- list_for_each_entry_rcu(ns, &head->list, siblings) {
|
|
+ list_for_each_entry_srcu(ns, &head->list, siblings,
|
|
+ srcu_read_lock_held(&head->srcu)) {
|
|
if (capacity != get_capacity(ns->disk))
|
|
clear_bit(NVME_NS_READY, &ns->flags);
|
|
}
|
|
@@ -245,7 +259,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
|
|
int found_distance = INT_MAX, fallback_distance = INT_MAX, distance;
|
|
struct nvme_ns *found = NULL, *fallback = NULL, *ns;
|
|
|
|
- list_for_each_entry_rcu(ns, &head->list, siblings) {
|
|
+ list_for_each_entry_srcu(ns, &head->list, siblings,
|
|
+ srcu_read_lock_held(&head->srcu)) {
|
|
if (nvme_path_is_disabled(ns))
|
|
continue;
|
|
|
|
@@ -290,10 +305,15 @@ static struct nvme_ns *nvme_next_ns(struct nvme_ns_head *head,
|
|
return list_first_or_null_rcu(&head->list, struct nvme_ns, siblings);
|
|
}
|
|
|
|
-static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head,
|
|
- int node, struct nvme_ns *old)
|
|
+static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head)
|
|
{
|
|
struct nvme_ns *ns, *found = NULL;
|
|
+ int node = numa_node_id();
|
|
+ struct nvme_ns *old = srcu_dereference(head->current_path[node],
|
|
+ &head->srcu);
|
|
+
|
|
+ if (unlikely(!old))
|
|
+ return __nvme_find_path(head, node);
|
|
|
|
if (list_is_singular(&head->list)) {
|
|
if (nvme_path_is_disabled(old))
|
|
@@ -333,13 +353,50 @@ static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head,
|
|
return found;
|
|
}
|
|
|
|
+static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head)
|
|
+{
|
|
+ struct nvme_ns *best_opt = NULL, *best_nonopt = NULL, *ns;
|
|
+ unsigned int min_depth_opt = UINT_MAX, min_depth_nonopt = UINT_MAX;
|
|
+ unsigned int depth;
|
|
+
|
|
+ list_for_each_entry_srcu(ns, &head->list, siblings,
|
|
+ srcu_read_lock_held(&head->srcu)) {
|
|
+ if (nvme_path_is_disabled(ns))
|
|
+ continue;
|
|
+
|
|
+ depth = atomic_read(&ns->ctrl->nr_active);
|
|
+
|
|
+ switch (ns->ana_state) {
|
|
+ case NVME_ANA_OPTIMIZED:
|
|
+ if (depth < min_depth_opt) {
|
|
+ min_depth_opt = depth;
|
|
+ best_opt = ns;
|
|
+ }
|
|
+ break;
|
|
+ case NVME_ANA_NONOPTIMIZED:
|
|
+ if (depth < min_depth_nonopt) {
|
|
+ min_depth_nonopt = depth;
|
|
+ best_nonopt = ns;
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (min_depth_opt == 0)
|
|
+ return best_opt;
|
|
+ }
|
|
+
|
|
+ return best_opt ? best_opt : best_nonopt;
|
|
+}
|
|
+
|
|
static inline bool nvme_path_is_optimized(struct nvme_ns *ns)
|
|
{
|
|
return ns->ctrl->state == NVME_CTRL_LIVE &&
|
|
ns->ana_state == NVME_ANA_OPTIMIZED;
|
|
}
|
|
|
|
-inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
|
|
+static struct nvme_ns *nvme_numa_path(struct nvme_ns_head *head)
|
|
{
|
|
int node = numa_node_id();
|
|
struct nvme_ns *ns;
|
|
@@ -347,19 +404,32 @@ inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
|
|
ns = srcu_dereference(head->current_path[node], &head->srcu);
|
|
if (unlikely(!ns))
|
|
return __nvme_find_path(head, node);
|
|
-
|
|
- if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_RR)
|
|
- return nvme_round_robin_path(head, node, ns);
|
|
if (unlikely(!nvme_path_is_optimized(ns)))
|
|
return __nvme_find_path(head, node);
|
|
return ns;
|
|
}
|
|
|
|
+inline struct nvme_ns *nvme_find_path(struct nvme_ns_head *head)
|
|
+{
|
|
+ switch (READ_ONCE(head->subsys->iopolicy)) {
|
|
+ case NVME_IOPOLICY_QD:
|
|
+ return nvme_queue_depth_path(head);
|
|
+ case NVME_IOPOLICY_RR:
|
|
+ return nvme_round_robin_path(head);
|
|
+ default:
|
|
+ return nvme_numa_path(head);
|
|
+ }
|
|
+}
|
|
+
|
|
static bool nvme_available_path(struct nvme_ns_head *head)
|
|
{
|
|
struct nvme_ns *ns;
|
|
|
|
- list_for_each_entry_rcu(ns, &head->list, siblings) {
|
|
+ if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
|
|
+ return NULL;
|
|
+
|
|
+ list_for_each_entry_srcu(ns, &head->list, siblings,
|
|
+ srcu_read_lock_held(&head->srcu)) {
|
|
if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags))
|
|
continue;
|
|
switch (ns->ctrl->state) {
|
|
@@ -720,7 +790,8 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
|
|
return 0;
|
|
|
|
srcu_idx = srcu_read_lock(&ctrl->srcu);
|
|
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
|
|
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
|
|
+ srcu_read_lock_held(&ctrl->srcu)) {
|
|
unsigned nsid;
|
|
again:
|
|
nsid = le32_to_cpu(desc->nsids[n]);
|
|
@@ -827,6 +898,29 @@ static ssize_t nvme_subsys_iopolicy_show(struct device *dev,
|
|
nvme_iopolicy_names[READ_ONCE(subsys->iopolicy)]);
|
|
}
|
|
|
|
+static void nvme_subsys_iopolicy_update(struct nvme_subsystem *subsys,
|
|
+ int iopolicy)
|
|
+{
|
|
+ struct nvme_ctrl *ctrl;
|
|
+ int old_iopolicy = READ_ONCE(subsys->iopolicy);
|
|
+
|
|
+ if (old_iopolicy == iopolicy)
|
|
+ return;
|
|
+
|
|
+ WRITE_ONCE(subsys->iopolicy, iopolicy);
|
|
+
|
|
+ /* iopolicy changes clear the mpath by design */
|
|
+ mutex_lock(&nvme_subsystems_lock);
|
|
+ list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
|
|
+ nvme_mpath_clear_ctrl_paths(ctrl);
|
|
+ mutex_unlock(&nvme_subsystems_lock);
|
|
+
|
|
+ pr_notice("subsysnqn %s iopolicy changed from %s to %s\n",
|
|
+ subsys->subnqn,
|
|
+ nvme_iopolicy_names[old_iopolicy],
|
|
+ nvme_iopolicy_names[iopolicy]);
|
|
+}
|
|
+
|
|
static ssize_t nvme_subsys_iopolicy_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
@@ -836,7 +930,7 @@ static ssize_t nvme_subsys_iopolicy_store(struct device *dev,
|
|
|
|
for (i = 0; i < ARRAY_SIZE(nvme_iopolicy_names); i++) {
|
|
if (sysfs_streq(buf, nvme_iopolicy_names[i])) {
|
|
- WRITE_ONCE(subsys->iopolicy, i);
|
|
+ nvme_subsys_iopolicy_update(subsys, i);
|
|
return count;
|
|
}
|
|
}
|
|
@@ -912,8 +1006,7 @@ void nvme_mpath_shutdown_disk(struct nvme_ns_head *head)
|
|
{
|
|
if (!head->disk)
|
|
return;
|
|
- kblockd_schedule_work(&head->requeue_work);
|
|
- if (test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) {
|
|
+ if (test_and_clear_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) {
|
|
nvme_cdev_del(&head->cdev, &head->cdev_device);
|
|
/*
|
|
* requeue I/O after NVME_NSHEAD_DISK_LIVE has been cleared
|
|
@@ -923,6 +1016,12 @@ void nvme_mpath_shutdown_disk(struct nvme_ns_head *head)
|
|
kblockd_schedule_work(&head->requeue_work);
|
|
del_gendisk(head->disk);
|
|
}
|
|
+ /*
|
|
+ * requeue I/O after NVME_NSHEAD_DISK_LIVE has been cleared
|
|
+ * to allow multipath to fail all I/O.
|
|
+ */
|
|
+ synchronize_srcu(&head->srcu);
|
|
+ kblockd_schedule_work(&head->requeue_work);
|
|
}
|
|
|
|
void nvme_mpath_remove_disk(struct nvme_ns_head *head)
|
|
@@ -954,6 +1053,9 @@ int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
|
|
!(ctrl->subsys->cmic & NVME_CTRL_CMIC_ANA))
|
|
return 0;
|
|
|
|
+ /* initialize this in the identify path to cover controller resets */
|
|
+ atomic_set(&ctrl->nr_active, 0);
|
|
+
|
|
if (!ctrl->max_namespaces ||
|
|
ctrl->max_namespaces > le32_to_cpu(id->nn)) {
|
|
dev_err(ctrl->device,
|
|
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
|
|
index 14a867245c29f3..bddc068d58c7ea 100644
|
|
--- a/drivers/nvme/host/nvme.h
|
|
+++ b/drivers/nvme/host/nvme.h
|
|
@@ -48,6 +48,7 @@ extern unsigned int admin_timeout;
|
|
extern struct workqueue_struct *nvme_wq;
|
|
extern struct workqueue_struct *nvme_reset_wq;
|
|
extern struct workqueue_struct *nvme_delete_wq;
|
|
+extern struct mutex nvme_subsystems_lock;
|
|
|
|
/*
|
|
* List of workarounds for devices that required behavior not specified in
|
|
@@ -199,6 +200,7 @@ enum {
|
|
NVME_REQ_CANCELLED = (1 << 0),
|
|
NVME_REQ_USERCMD = (1 << 1),
|
|
NVME_MPATH_IO_STATS = (1 << 2),
|
|
+ NVME_MPATH_CNT_ACTIVE = (1 << 3),
|
|
};
|
|
|
|
static inline struct nvme_request *nvme_req(struct request *req)
|
|
@@ -364,6 +366,7 @@ struct nvme_ctrl {
|
|
size_t ana_log_size;
|
|
struct timer_list anatt_timer;
|
|
struct work_struct ana_work;
|
|
+ atomic_t nr_active;
|
|
#endif
|
|
|
|
#ifdef CONFIG_NVME_AUTH
|
|
@@ -411,6 +414,7 @@ static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
|
|
enum nvme_iopolicy {
|
|
NVME_IOPOLICY_NUMA,
|
|
NVME_IOPOLICY_RR,
|
|
+ NVME_IOPOLICY_QD,
|
|
};
|
|
|
|
struct nvme_subsystem {
|
|
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
|
|
index b701969cf1c2aa..d525fa1229d791 100644
|
|
--- a/drivers/nvme/host/pci.c
|
|
+++ b/drivers/nvme/host/pci.c
|
|
@@ -153,6 +153,7 @@ struct nvme_dev {
|
|
/* host memory buffer support: */
|
|
u64 host_mem_size;
|
|
u32 nr_host_mem_descs;
|
|
+ u32 host_mem_descs_size;
|
|
dma_addr_t host_mem_descs_dma;
|
|
struct nvme_host_mem_buf_desc *host_mem_descs;
|
|
void **host_mem_desc_bufs;
|
|
@@ -904,9 +905,10 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
|
|
|
|
static void nvme_submit_cmds(struct nvme_queue *nvmeq, struct request **rqlist)
|
|
{
|
|
+ struct request *req;
|
|
+
|
|
spin_lock(&nvmeq->sq_lock);
|
|
- while (!rq_list_empty(*rqlist)) {
|
|
- struct request *req = rq_list_pop(rqlist);
|
|
+ while ((req = rq_list_pop(rqlist))) {
|
|
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
|
|
|
|
nvme_sq_copy_cmd(nvmeq, &iod->cmd);
|
|
@@ -932,31 +934,25 @@ static bool nvme_prep_rq_batch(struct nvme_queue *nvmeq, struct request *req)
|
|
|
|
static void nvme_queue_rqs(struct request **rqlist)
|
|
{
|
|
- struct request *req, *next, *prev = NULL;
|
|
+ struct request *submit_list = NULL;
|
|
struct request *requeue_list = NULL;
|
|
+ struct request **requeue_lastp = &requeue_list;
|
|
+ struct nvme_queue *nvmeq = NULL;
|
|
+ struct request *req;
|
|
|
|
- rq_list_for_each_safe(rqlist, req, next) {
|
|
- struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
|
|
-
|
|
- if (!nvme_prep_rq_batch(nvmeq, req)) {
|
|
- /* detach 'req' and add to remainder list */
|
|
- rq_list_move(rqlist, &requeue_list, req, prev);
|
|
-
|
|
- req = prev;
|
|
- if (!req)
|
|
- continue;
|
|
- }
|
|
+ while ((req = rq_list_pop(rqlist))) {
|
|
+ if (nvmeq && nvmeq != req->mq_hctx->driver_data)
|
|
+ nvme_submit_cmds(nvmeq, &submit_list);
|
|
+ nvmeq = req->mq_hctx->driver_data;
|
|
|
|
- if (!next || req->mq_hctx != next->mq_hctx) {
|
|
- /* detach rest of list, and submit */
|
|
- req->rq_next = NULL;
|
|
- nvme_submit_cmds(nvmeq, rqlist);
|
|
- *rqlist = next;
|
|
- prev = NULL;
|
|
- } else
|
|
- prev = req;
|
|
+ if (nvme_prep_rq_batch(nvmeq, req))
|
|
+ rq_list_add(&submit_list, req); /* reverse order */
|
|
+ else
|
|
+ rq_list_add_tail(&requeue_lastp, req);
|
|
}
|
|
|
|
+ if (nvmeq)
|
|
+ nvme_submit_cmds(nvmeq, &submit_list);
|
|
*rqlist = requeue_list;
|
|
}
|
|
|
|
@@ -1929,10 +1925,10 @@ static void nvme_free_host_mem(struct nvme_dev *dev)
|
|
|
|
kfree(dev->host_mem_desc_bufs);
|
|
dev->host_mem_desc_bufs = NULL;
|
|
- dma_free_coherent(dev->dev,
|
|
- dev->nr_host_mem_descs * sizeof(*dev->host_mem_descs),
|
|
+ dma_free_coherent(dev->dev, dev->host_mem_descs_size,
|
|
dev->host_mem_descs, dev->host_mem_descs_dma);
|
|
dev->host_mem_descs = NULL;
|
|
+ dev->host_mem_descs_size = 0;
|
|
dev->nr_host_mem_descs = 0;
|
|
}
|
|
|
|
@@ -1940,7 +1936,7 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
|
|
u32 chunk_size)
|
|
{
|
|
struct nvme_host_mem_buf_desc *descs;
|
|
- u32 max_entries, len;
|
|
+ u32 max_entries, len, descs_size;
|
|
dma_addr_t descs_dma;
|
|
int i = 0;
|
|
void **bufs;
|
|
@@ -1953,8 +1949,9 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
|
|
if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
|
|
max_entries = dev->ctrl.hmmaxd;
|
|
|
|
- descs = dma_alloc_coherent(dev->dev, max_entries * sizeof(*descs),
|
|
- &descs_dma, GFP_KERNEL);
|
|
+ descs_size = max_entries * sizeof(*descs);
|
|
+ descs = dma_alloc_coherent(dev->dev, descs_size, &descs_dma,
|
|
+ GFP_KERNEL);
|
|
if (!descs)
|
|
goto out;
|
|
|
|
@@ -1983,6 +1980,7 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
|
|
dev->host_mem_size = size;
|
|
dev->host_mem_descs = descs;
|
|
dev->host_mem_descs_dma = descs_dma;
|
|
+ dev->host_mem_descs_size = descs_size;
|
|
dev->host_mem_desc_bufs = bufs;
|
|
return 0;
|
|
|
|
@@ -1997,8 +1995,7 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
|
|
|
|
kfree(bufs);
|
|
out_free_descs:
|
|
- dma_free_coherent(dev->dev, max_entries * sizeof(*descs), descs,
|
|
- descs_dma);
|
|
+ dma_free_coherent(dev->dev, descs_size, descs, descs_dma);
|
|
out:
|
|
dev->host_mem_descs = NULL;
|
|
return -ENOMEM;
|
|
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
|
|
index bf502ba8da9586..366fbdc56dec10 100644
|
|
--- a/drivers/of/fdt.c
|
|
+++ b/drivers/of/fdt.c
|
|
@@ -471,6 +471,7 @@ int __initdata dt_root_addr_cells;
|
|
int __initdata dt_root_size_cells;
|
|
|
|
void *initial_boot_params __ro_after_init;
|
|
+phys_addr_t initial_boot_params_pa __ro_after_init;
|
|
|
|
#ifdef CONFIG_OF_EARLY_FLATTREE
|
|
|
|
@@ -1270,17 +1271,18 @@ static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
|
return ptr;
|
|
}
|
|
|
|
-bool __init early_init_dt_verify(void *params)
|
|
+bool __init early_init_dt_verify(void *dt_virt, phys_addr_t dt_phys)
|
|
{
|
|
- if (!params)
|
|
+ if (!dt_virt)
|
|
return false;
|
|
|
|
/* check device tree validity */
|
|
- if (fdt_check_header(params))
|
|
+ if (fdt_check_header(dt_virt))
|
|
return false;
|
|
|
|
/* Setup flat device-tree pointer */
|
|
- initial_boot_params = params;
|
|
+ initial_boot_params = dt_virt;
|
|
+ initial_boot_params_pa = dt_phys;
|
|
of_fdt_crc32 = crc32_be(~0, initial_boot_params,
|
|
fdt_totalsize(initial_boot_params));
|
|
return true;
|
|
@@ -1306,11 +1308,11 @@ void __init early_init_dt_scan_nodes(void)
|
|
early_init_dt_check_for_usable_mem_range();
|
|
}
|
|
|
|
-bool __init early_init_dt_scan(void *params)
|
|
+bool __init early_init_dt_scan(void *dt_virt, phys_addr_t dt_phys)
|
|
{
|
|
bool status;
|
|
|
|
- status = early_init_dt_verify(params);
|
|
+ status = early_init_dt_verify(dt_virt, dt_phys);
|
|
if (!status)
|
|
return false;
|
|
|
|
diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c
|
|
index 68278340cecfe5..3b98a57f1f0743 100644
|
|
--- a/drivers/of/kexec.c
|
|
+++ b/drivers/of/kexec.c
|
|
@@ -301,7 +301,7 @@ void *of_kexec_alloc_and_setup_fdt(const struct kimage *image,
|
|
}
|
|
|
|
/* Remove memory reservation for the current device tree. */
|
|
- ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params),
|
|
+ ret = fdt_find_and_del_mem_rsv(fdt, initial_boot_params_pa,
|
|
fdt_totalsize(initial_boot_params));
|
|
if (ret == -EINVAL) {
|
|
pr_err("Error removing memory reservation.\n");
|
|
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
|
|
index 4f58345b5c683d..7986113adc7d31 100644
|
|
--- a/drivers/of/unittest.c
|
|
+++ b/drivers/of/unittest.c
|
|
@@ -4017,10 +4017,6 @@ static int __init of_unittest(void)
|
|
add_taint(TAINT_TEST, LOCKDEP_STILL_OK);
|
|
|
|
/* adding data for unittest */
|
|
-
|
|
- if (IS_ENABLED(CONFIG_UML))
|
|
- unittest_unflatten_overlay_base();
|
|
-
|
|
res = unittest_data_add();
|
|
if (res)
|
|
return res;
|
|
diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
|
|
index 2c87e7728a653b..f76a358e2b5b6f 100644
|
|
--- a/drivers/pci/controller/cadence/pci-j721e.c
|
|
+++ b/drivers/pci/controller/cadence/pci-j721e.c
|
|
@@ -7,6 +7,8 @@
|
|
*/
|
|
|
|
#include <linux/clk.h>
|
|
+#include <linux/clk-provider.h>
|
|
+#include <linux/container_of.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/gpio/consumer.h>
|
|
#include <linux/io.h>
|
|
@@ -22,6 +24,8 @@
|
|
#include "../../pci.h"
|
|
#include "pcie-cadence.h"
|
|
|
|
+#define cdns_pcie_to_rc(p) container_of(p, struct cdns_pcie_rc, pcie)
|
|
+
|
|
#define ENABLE_REG_SYS_2 0x108
|
|
#define STATUS_REG_SYS_2 0x508
|
|
#define STATUS_CLR_REG_SYS_2 0x708
|
|
@@ -42,18 +46,17 @@ enum link_status {
|
|
};
|
|
|
|
#define J721E_MODE_RC BIT(7)
|
|
-#define LANE_COUNT_MASK BIT(8)
|
|
#define LANE_COUNT(n) ((n) << 8)
|
|
|
|
#define GENERATION_SEL_MASK GENMASK(1, 0)
|
|
|
|
-#define MAX_LANES 2
|
|
-
|
|
struct j721e_pcie {
|
|
struct cdns_pcie *cdns_pcie;
|
|
struct clk *refclk;
|
|
u32 mode;
|
|
u32 num_lanes;
|
|
+ u32 max_lanes;
|
|
+ struct gpio_desc *reset_gpio;
|
|
void __iomem *user_cfg_base;
|
|
void __iomem *intd_cfg_base;
|
|
u32 linkdown_irq_regfield;
|
|
@@ -71,6 +74,7 @@ struct j721e_pcie_data {
|
|
unsigned int quirk_disable_flr:1;
|
|
u32 linkdown_irq_regfield;
|
|
unsigned int byte_access_allowed:1;
|
|
+ unsigned int max_lanes;
|
|
};
|
|
|
|
static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset)
|
|
@@ -206,11 +210,15 @@ static int j721e_pcie_set_lane_count(struct j721e_pcie *pcie,
|
|
{
|
|
struct device *dev = pcie->cdns_pcie->dev;
|
|
u32 lanes = pcie->num_lanes;
|
|
+ u32 mask = BIT(8);
|
|
u32 val = 0;
|
|
int ret;
|
|
|
|
+ if (pcie->max_lanes == 4)
|
|
+ mask = GENMASK(9, 8);
|
|
+
|
|
val = LANE_COUNT(lanes - 1);
|
|
- ret = regmap_update_bits(syscon, offset, LANE_COUNT_MASK, val);
|
|
+ ret = regmap_update_bits(syscon, offset, mask, val);
|
|
if (ret)
|
|
dev_err(dev, "failed to set link count\n");
|
|
|
|
@@ -290,11 +298,13 @@ static const struct j721e_pcie_data j721e_pcie_rc_data = {
|
|
.quirk_retrain_flag = true,
|
|
.byte_access_allowed = false,
|
|
.linkdown_irq_regfield = LINK_DOWN,
|
|
+ .max_lanes = 2,
|
|
};
|
|
|
|
static const struct j721e_pcie_data j721e_pcie_ep_data = {
|
|
.mode = PCI_MODE_EP,
|
|
.linkdown_irq_regfield = LINK_DOWN,
|
|
+ .max_lanes = 2,
|
|
};
|
|
|
|
static const struct j721e_pcie_data j7200_pcie_rc_data = {
|
|
@@ -302,23 +312,27 @@ static const struct j721e_pcie_data j7200_pcie_rc_data = {
|
|
.quirk_detect_quiet_flag = true,
|
|
.linkdown_irq_regfield = J7200_LINK_DOWN,
|
|
.byte_access_allowed = true,
|
|
+ .max_lanes = 2,
|
|
};
|
|
|
|
static const struct j721e_pcie_data j7200_pcie_ep_data = {
|
|
.mode = PCI_MODE_EP,
|
|
.quirk_detect_quiet_flag = true,
|
|
.quirk_disable_flr = true,
|
|
+ .max_lanes = 2,
|
|
};
|
|
|
|
static const struct j721e_pcie_data am64_pcie_rc_data = {
|
|
.mode = PCI_MODE_RC,
|
|
.linkdown_irq_regfield = J7200_LINK_DOWN,
|
|
.byte_access_allowed = true,
|
|
+ .max_lanes = 1,
|
|
};
|
|
|
|
static const struct j721e_pcie_data am64_pcie_ep_data = {
|
|
.mode = PCI_MODE_EP,
|
|
.linkdown_irq_regfield = J7200_LINK_DOWN,
|
|
+ .max_lanes = 1,
|
|
};
|
|
|
|
static const struct of_device_id of_j721e_pcie_match[] = {
|
|
@@ -432,9 +446,13 @@ static int j721e_pcie_probe(struct platform_device *pdev)
|
|
pcie->user_cfg_base = base;
|
|
|
|
ret = of_property_read_u32(node, "num-lanes", &num_lanes);
|
|
- if (ret || num_lanes > MAX_LANES)
|
|
+ if (ret || num_lanes > data->max_lanes) {
|
|
+ dev_warn(dev, "num-lanes property not provided or invalid, setting num-lanes to 1\n");
|
|
num_lanes = 1;
|
|
+ }
|
|
+
|
|
pcie->num_lanes = num_lanes;
|
|
+ pcie->max_lanes = data->max_lanes;
|
|
|
|
if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48)))
|
|
return -EINVAL;
|
|
@@ -475,6 +493,7 @@ static int j721e_pcie_probe(struct platform_device *pdev)
|
|
dev_err(dev, "Failed to get reset GPIO\n");
|
|
goto err_get_sync;
|
|
}
|
|
+ pcie->reset_gpio = gpiod;
|
|
|
|
ret = cdns_pcie_init_phy(dev, cdns_pcie);
|
|
if (ret) {
|
|
@@ -497,15 +516,14 @@ static int j721e_pcie_probe(struct platform_device *pdev)
|
|
pcie->refclk = clk;
|
|
|
|
/*
|
|
- * "Power Sequencing and Reset Signal Timings" table in
|
|
- * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 3.0
|
|
- * indicates PERST# should be deasserted after minimum of 100us
|
|
- * once REFCLK is stable. The REFCLK to the connector in RC
|
|
- * mode is selected while enabling the PHY. So deassert PERST#
|
|
- * after 100 us.
|
|
+ * Section 2.2 of the PCI Express Card Electromechanical
|
|
+ * Specification (Revision 5.1) mandates that the deassertion
|
|
+ * of the PERST# signal should be delayed by 100 ms (TPVPERL).
|
|
+ * This shall ensure that the power and the reference clock
|
|
+ * are stable.
|
|
*/
|
|
if (gpiod) {
|
|
- usleep_range(100, 200);
|
|
+ msleep(PCIE_T_PVPERL_MS);
|
|
gpiod_set_value_cansleep(gpiod, 1);
|
|
}
|
|
|
|
@@ -554,6 +572,86 @@ static void j721e_pcie_remove(struct platform_device *pdev)
|
|
pm_runtime_disable(dev);
|
|
}
|
|
|
|
+static int j721e_pcie_suspend_noirq(struct device *dev)
|
|
+{
|
|
+ struct j721e_pcie *pcie = dev_get_drvdata(dev);
|
|
+
|
|
+ if (pcie->mode == PCI_MODE_RC) {
|
|
+ gpiod_set_value_cansleep(pcie->reset_gpio, 0);
|
|
+ clk_disable_unprepare(pcie->refclk);
|
|
+ }
|
|
+
|
|
+ cdns_pcie_disable_phy(pcie->cdns_pcie);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int j721e_pcie_resume_noirq(struct device *dev)
|
|
+{
|
|
+ struct j721e_pcie *pcie = dev_get_drvdata(dev);
|
|
+ struct cdns_pcie *cdns_pcie = pcie->cdns_pcie;
|
|
+ int ret;
|
|
+
|
|
+ ret = j721e_pcie_ctrl_init(pcie);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ j721e_pcie_config_link_irq(pcie);
|
|
+
|
|
+ /*
|
|
+ * This is not called explicitly in the probe, it is called by
|
|
+ * cdns_pcie_init_phy().
|
|
+ */
|
|
+ ret = cdns_pcie_enable_phy(pcie->cdns_pcie);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ if (pcie->mode == PCI_MODE_RC) {
|
|
+ struct cdns_pcie_rc *rc = cdns_pcie_to_rc(cdns_pcie);
|
|
+
|
|
+ ret = clk_prepare_enable(pcie->refclk);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /*
|
|
+ * Section 2.2 of the PCI Express Card Electromechanical
|
|
+ * Specification (Revision 5.1) mandates that the deassertion
|
|
+ * of the PERST# signal should be delayed by 100 ms (TPVPERL).
|
|
+ * This shall ensure that the power and the reference clock
|
|
+ * are stable.
|
|
+ */
|
|
+ if (pcie->reset_gpio) {
|
|
+ msleep(PCIE_T_PVPERL_MS);
|
|
+ gpiod_set_value_cansleep(pcie->reset_gpio, 1);
|
|
+ }
|
|
+
|
|
+ ret = cdns_pcie_host_link_setup(rc);
|
|
+ if (ret < 0) {
|
|
+ clk_disable_unprepare(pcie->refclk);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Reset internal status of BARs to force reinitialization in
|
|
+ * cdns_pcie_host_init().
|
|
+ */
|
|
+ for (enum cdns_pcie_rp_bar bar = RP_BAR0; bar <= RP_NO_BAR; bar++)
|
|
+ rc->avail_ib_bar[bar] = true;
|
|
+
|
|
+ ret = cdns_pcie_host_init(rc);
|
|
+ if (ret) {
|
|
+ clk_disable_unprepare(pcie->refclk);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static DEFINE_NOIRQ_DEV_PM_OPS(j721e_pcie_pm_ops,
|
|
+ j721e_pcie_suspend_noirq,
|
|
+ j721e_pcie_resume_noirq);
|
|
+
|
|
static struct platform_driver j721e_pcie_driver = {
|
|
.probe = j721e_pcie_probe,
|
|
.remove_new = j721e_pcie_remove,
|
|
@@ -561,6 +659,7 @@ static struct platform_driver j721e_pcie_driver = {
|
|
.name = "j721e-pcie",
|
|
.of_match_table = of_j721e_pcie_match,
|
|
.suppress_bind_attrs = true,
|
|
+ .pm = pm_sleep_ptr(&j721e_pcie_pm_ops),
|
|
},
|
|
};
|
|
builtin_platform_driver(j721e_pcie_driver);
|
|
diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
|
|
index 5b14f7ee3c798e..8af95e9da7cec6 100644
|
|
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c
|
|
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
|
|
@@ -485,8 +485,7 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
|
|
return cdns_pcie_host_map_dma_ranges(rc);
|
|
}
|
|
|
|
-static int cdns_pcie_host_init(struct device *dev,
|
|
- struct cdns_pcie_rc *rc)
|
|
+int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
|
|
{
|
|
int err;
|
|
|
|
@@ -497,6 +496,30 @@ static int cdns_pcie_host_init(struct device *dev,
|
|
return cdns_pcie_host_init_address_translation(rc);
|
|
}
|
|
|
|
+int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
|
|
+{
|
|
+ struct cdns_pcie *pcie = &rc->pcie;
|
|
+ struct device *dev = rc->pcie.dev;
|
|
+ int ret;
|
|
+
|
|
+ if (rc->quirk_detect_quiet_flag)
|
|
+ cdns_pcie_detect_quiet_min_delay_set(&rc->pcie);
|
|
+
|
|
+ cdns_pcie_host_enable_ptm_response(pcie);
|
|
+
|
|
+ ret = cdns_pcie_start_link(pcie);
|
|
+ if (ret) {
|
|
+ dev_err(dev, "Failed to start link\n");
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = cdns_pcie_host_start_link(rc);
|
|
+ if (ret)
|
|
+ dev_dbg(dev, "PCIe link never came up\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
|
|
{
|
|
struct device *dev = rc->pcie.dev;
|
|
@@ -533,25 +556,14 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
|
|
return PTR_ERR(rc->cfg_base);
|
|
rc->cfg_res = res;
|
|
|
|
- if (rc->quirk_detect_quiet_flag)
|
|
- cdns_pcie_detect_quiet_min_delay_set(&rc->pcie);
|
|
-
|
|
- cdns_pcie_host_enable_ptm_response(pcie);
|
|
-
|
|
- ret = cdns_pcie_start_link(pcie);
|
|
- if (ret) {
|
|
- dev_err(dev, "Failed to start link\n");
|
|
- return ret;
|
|
- }
|
|
-
|
|
- ret = cdns_pcie_host_start_link(rc);
|
|
+ ret = cdns_pcie_host_link_setup(rc);
|
|
if (ret)
|
|
- dev_dbg(dev, "PCIe link never came up\n");
|
|
+ return ret;
|
|
|
|
for (bar = RP_BAR0; bar <= RP_NO_BAR; bar++)
|
|
rc->avail_ib_bar[bar] = true;
|
|
|
|
- ret = cdns_pcie_host_init(dev, rc);
|
|
+ ret = cdns_pcie_host_init(rc);
|
|
if (ret)
|
|
return ret;
|
|
|
|
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
|
|
index 373cb50fcd159d..d55dfd173f228f 100644
|
|
--- a/drivers/pci/controller/cadence/pcie-cadence.h
|
|
+++ b/drivers/pci/controller/cadence/pcie-cadence.h
|
|
@@ -515,10 +515,22 @@ static inline bool cdns_pcie_link_up(struct cdns_pcie *pcie)
|
|
}
|
|
|
|
#ifdef CONFIG_PCIE_CADENCE_HOST
|
|
+int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc);
|
|
+int cdns_pcie_host_init(struct cdns_pcie_rc *rc);
|
|
int cdns_pcie_host_setup(struct cdns_pcie_rc *rc);
|
|
void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
|
|
int where);
|
|
#else
|
|
+static inline int cdns_pcie_host_link_setup(struct cdns_pcie_rc *rc)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline int cdns_pcie_host_init(struct cdns_pcie_rc *rc)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static inline int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
|
|
{
|
|
return 0;
|
|
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
|
|
index c5475830c835f5..bf9a961c9f2766 100644
|
|
--- a/drivers/pci/controller/dwc/pci-keystone.c
|
|
+++ b/drivers/pci/controller/dwc/pci-keystone.c
|
|
@@ -464,6 +464,17 @@ static void __iomem *ks_pcie_other_map_bus(struct pci_bus *bus,
|
|
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
|
|
u32 reg;
|
|
|
|
+ /*
|
|
+ * Checking whether the link is up here is a last line of defense
|
|
+ * against platforms that forward errors on the system bus as
|
|
+ * SError upon PCI configuration transactions issued when the link
|
|
+ * is down. This check is racy by definition and does not stop
|
|
+ * the system from triggering an SError if the link goes down
|
|
+ * after this check is performed.
|
|
+ */
|
|
+ if (!dw_pcie_link_up(pci))
|
|
+ return NULL;
|
|
+
|
|
reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) |
|
|
CFG_FUNC(PCI_FUNC(devfn));
|
|
if (!pci_is_root_bus(bus->parent))
|
|
@@ -1104,6 +1115,7 @@ static int ks_pcie_am654_set_mode(struct device *dev,
|
|
|
|
static const struct ks_pcie_of_data ks_pcie_rc_of_data = {
|
|
.host_ops = &ks_pcie_host_ops,
|
|
+ .mode = DW_PCIE_RC_TYPE,
|
|
.version = DW_PCIE_VER_365A,
|
|
};
|
|
|
|
diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c
|
|
index 1e3c3192d122cb..954b773eebb197 100644
|
|
--- a/drivers/pci/controller/pcie-rockchip-ep.c
|
|
+++ b/drivers/pci/controller/pcie-rockchip-ep.c
|
|
@@ -63,15 +63,25 @@ static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip,
|
|
ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region));
|
|
}
|
|
|
|
+static int rockchip_pcie_ep_ob_atu_num_bits(struct rockchip_pcie *rockchip,
|
|
+ u64 pci_addr, size_t size)
|
|
+{
|
|
+ int num_pass_bits = fls64(pci_addr ^ (pci_addr + size - 1));
|
|
+
|
|
+ return clamp(num_pass_bits,
|
|
+ ROCKCHIP_PCIE_AT_MIN_NUM_BITS,
|
|
+ ROCKCHIP_PCIE_AT_MAX_NUM_BITS);
|
|
+}
|
|
+
|
|
static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn,
|
|
u32 r, u64 cpu_addr, u64 pci_addr,
|
|
size_t size)
|
|
{
|
|
- int num_pass_bits = fls64(size - 1);
|
|
+ int num_pass_bits;
|
|
u32 addr0, addr1, desc0;
|
|
|
|
- if (num_pass_bits < 8)
|
|
- num_pass_bits = 8;
|
|
+ num_pass_bits = rockchip_pcie_ep_ob_atu_num_bits(rockchip,
|
|
+ pci_addr, size);
|
|
|
|
addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
|
|
(lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
|
|
diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h
|
|
index 6111de35f84ca2..15ee949f2485e3 100644
|
|
--- a/drivers/pci/controller/pcie-rockchip.h
|
|
+++ b/drivers/pci/controller/pcie-rockchip.h
|
|
@@ -245,6 +245,10 @@
|
|
(PCIE_EP_PF_CONFIG_REGS_BASE + (((fn) << 12) & GENMASK(19, 12)))
|
|
#define ROCKCHIP_PCIE_EP_VIRT_FUNC_BASE(fn) \
|
|
(PCIE_EP_PF_CONFIG_REGS_BASE + 0x10000 + (((fn) << 12) & GENMASK(19, 12)))
|
|
+
|
|
+#define ROCKCHIP_PCIE_AT_MIN_NUM_BITS 8
|
|
+#define ROCKCHIP_PCIE_AT_MAX_NUM_BITS 20
|
|
+
|
|
#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \
|
|
(PCIE_CORE_AXI_CONF_BASE + 0x0828 + (fn) * 0x0040 + (bar) * 0x0008)
|
|
#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \
|
|
diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c
|
|
index 34e7191f950867..87154992ea11b9 100644
|
|
--- a/drivers/pci/endpoint/functions/pci-epf-mhi.c
|
|
+++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c
|
|
@@ -600,12 +600,18 @@ static int pci_epf_mhi_bind(struct pci_epf *epf)
|
|
{
|
|
struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
|
|
struct pci_epc *epc = epf->epc;
|
|
+ struct device *dev = &epf->dev;
|
|
struct platform_device *pdev = to_platform_device(epc->dev.parent);
|
|
struct resource *res;
|
|
int ret;
|
|
|
|
/* Get MMIO base address from Endpoint controller */
|
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio");
|
|
+ if (!res) {
|
|
+ dev_err(dev, "Failed to get \"mmio\" resource\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
epf_mhi->mmio_phys = res->start;
|
|
epf_mhi->mmio_size = resource_size(res);
|
|
|
|
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
|
|
index a7d3a92391a418..d06623c751f84e 100644
|
|
--- a/drivers/pci/endpoint/pci-epc-core.c
|
|
+++ b/drivers/pci/endpoint/pci-epc-core.c
|
|
@@ -663,18 +663,18 @@ void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf,
|
|
if (!epc || IS_ERR(epc) || !epf)
|
|
return;
|
|
|
|
+ mutex_lock(&epc->list_lock);
|
|
if (type == PRIMARY_INTERFACE) {
|
|
func_no = epf->func_no;
|
|
list = &epf->list;
|
|
+ epf->epc = NULL;
|
|
} else {
|
|
func_no = epf->sec_epc_func_no;
|
|
list = &epf->sec_epc_list;
|
|
+ epf->sec_epc = NULL;
|
|
}
|
|
-
|
|
- mutex_lock(&epc->list_lock);
|
|
clear_bit(func_no, &epc->function_num_map);
|
|
list_del(list);
|
|
- epf->epc = NULL;
|
|
mutex_unlock(&epc->list_lock);
|
|
}
|
|
EXPORT_SYMBOL_GPL(pci_epc_remove_epf);
|
|
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
|
|
index 3b248426a9f424..a35af42d6a3d8f 100644
|
|
--- a/drivers/pci/hotplug/cpqphp_pci.c
|
|
+++ b/drivers/pci/hotplug/cpqphp_pci.c
|
|
@@ -135,11 +135,13 @@ int cpqhp_unconfigure_device(struct pci_func *func)
|
|
static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value)
|
|
{
|
|
u32 vendID = 0;
|
|
+ int ret;
|
|
|
|
- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
|
|
- return -1;
|
|
- if (vendID == 0xffffffff)
|
|
- return -1;
|
|
+ ret = pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID);
|
|
+ if (ret != PCIBIOS_SUCCESSFUL)
|
|
+ return PCIBIOS_DEVICE_NOT_FOUND;
|
|
+ if (PCI_POSSIBLE_ERROR(vendID))
|
|
+ return PCIBIOS_DEVICE_NOT_FOUND;
|
|
return pci_bus_read_config_dword(bus, devfn, offset, value);
|
|
}
|
|
|
|
@@ -202,13 +204,15 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_
|
|
{
|
|
u16 tdevice;
|
|
u32 work;
|
|
+ int ret;
|
|
u8 tbus;
|
|
|
|
ctrl->pci_bus->number = bus_num;
|
|
|
|
for (tdevice = 0; tdevice < 0xFF; tdevice++) {
|
|
/* Scan for access first */
|
|
- if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
|
|
+ ret = PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work);
|
|
+ if (ret)
|
|
continue;
|
|
dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
|
|
/* Yep we got one. Not a bridge ? */
|
|
@@ -220,7 +224,8 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_
|
|
}
|
|
for (tdevice = 0; tdevice < 0xFF; tdevice++) {
|
|
/* Scan for access first */
|
|
- if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
|
|
+ ret = PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work);
|
|
+ if (ret)
|
|
continue;
|
|
dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
|
|
/* Yep we got one. bridge ? */
|
|
@@ -253,7 +258,7 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
|
|
*dev_num = tdevice;
|
|
ctrl->pci_bus->number = tbus;
|
|
pci_bus_read_config_dword(ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
|
|
- if (!nobridge || (work == 0xffffffff))
|
|
+ if (!nobridge || PCI_POSSIBLE_ERROR(work))
|
|
return 0;
|
|
|
|
dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
|
|
diff --git a/drivers/pci/of_property.c b/drivers/pci/of_property.c
|
|
index 03539e5053720f..ec63e9b9e238f5 100644
|
|
--- a/drivers/pci/of_property.c
|
|
+++ b/drivers/pci/of_property.c
|
|
@@ -126,7 +126,7 @@ static int of_pci_prop_ranges(struct pci_dev *pdev, struct of_changeset *ocs,
|
|
if (of_pci_get_addr_flags(&res[j], &flags))
|
|
continue;
|
|
|
|
- val64 = res[j].start;
|
|
+ val64 = pci_bus_address(pdev, &res[j] - pdev->resource);
|
|
of_pci_set_address(pdev, rp[i].parent_addr, val64, 0, flags,
|
|
false);
|
|
if (pci_is_bridge(pdev)) {
|
|
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
|
|
index 93f2f4dcf6d696..830877efe50597 100644
|
|
--- a/drivers/pci/pci.c
|
|
+++ b/drivers/pci/pci.c
|
|
@@ -5444,7 +5444,7 @@ static ssize_t reset_method_store(struct device *dev,
|
|
const char *buf, size_t count)
|
|
{
|
|
struct pci_dev *pdev = to_pci_dev(dev);
|
|
- char *options, *name;
|
|
+ char *options, *tmp_options, *name;
|
|
int m, n;
|
|
u8 reset_methods[PCI_NUM_RESET_METHODS] = { 0 };
|
|
|
|
@@ -5464,7 +5464,8 @@ static ssize_t reset_method_store(struct device *dev,
|
|
return -ENOMEM;
|
|
|
|
n = 0;
|
|
- while ((name = strsep(&options, " ")) != NULL) {
|
|
+ tmp_options = options;
|
|
+ while ((name = strsep(&tmp_options, " ")) != NULL) {
|
|
if (sysfs_streq(name, ""))
|
|
continue;
|
|
|
|
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
|
|
index d5e9010a135a14..67ec4cf2fdb4c6 100644
|
|
--- a/drivers/pci/pci.h
|
|
+++ b/drivers/pci/pci.h
|
|
@@ -13,6 +13,9 @@
|
|
|
|
#define PCIE_LINK_RETRAIN_TIMEOUT_MS 1000
|
|
|
|
+/* Power stable to PERST# inactive from PCIe card Electromechanical Spec */
|
|
+#define PCIE_T_PVPERL_MS 100
|
|
+
|
|
/*
|
|
* PCIe r6.0, sec 5.3.3.2.1 <PME Synchronization>
|
|
* Recommends 1ms to 10ms timeout to check L2 ready.
|
|
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
|
|
index 0f87cade10f74b..ed645c7a4e4b41 100644
|
|
--- a/drivers/pci/slot.c
|
|
+++ b/drivers/pci/slot.c
|
|
@@ -79,6 +79,7 @@ static void pci_slot_release(struct kobject *kobj)
|
|
up_read(&pci_bus_sem);
|
|
|
|
list_del(&slot->list);
|
|
+ pci_bus_put(slot->bus);
|
|
|
|
kfree(slot);
|
|
}
|
|
@@ -261,7 +262,7 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
|
|
goto err;
|
|
}
|
|
|
|
- slot->bus = parent;
|
|
+ slot->bus = pci_bus_get(parent);
|
|
slot->number = slot_nr;
|
|
|
|
slot->kobj.kset = pci_slots_kset;
|
|
@@ -269,6 +270,7 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
|
|
slot_name = make_slot_name(name);
|
|
if (!slot_name) {
|
|
err = -ENOMEM;
|
|
+ pci_bus_put(slot->bus);
|
|
kfree(slot);
|
|
goto err;
|
|
}
|
|
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
|
|
index 0b3ce77136456a..7bd1733d797703 100644
|
|
--- a/drivers/perf/arm-cmn.c
|
|
+++ b/drivers/perf/arm-cmn.c
|
|
@@ -2075,8 +2075,6 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
|
|
continue;
|
|
|
|
xp = arm_cmn_node_to_xp(cmn, dn);
|
|
- dn->portid_bits = xp->portid_bits;
|
|
- dn->deviceid_bits = xp->deviceid_bits;
|
|
dn->dtc = xp->dtc;
|
|
dn->dtm = xp->dtm;
|
|
if (cmn->multi_dtm)
|
|
@@ -2307,6 +2305,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
|
|
}
|
|
|
|
arm_cmn_init_node_info(cmn, reg & CMN_CHILD_NODE_ADDR, dn);
|
|
+ dn->portid_bits = xp->portid_bits;
|
|
+ dn->deviceid_bits = xp->deviceid_bits;
|
|
|
|
switch (dn->type) {
|
|
case CMN_TYPE_DTC:
|
|
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
|
|
index 6303b82566f981..31e491e7f2065a 100644
|
|
--- a/drivers/perf/arm_smmuv3_pmu.c
|
|
+++ b/drivers/perf/arm_smmuv3_pmu.c
|
|
@@ -431,6 +431,17 @@ static int smmu_pmu_event_init(struct perf_event *event)
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ /*
|
|
+ * Ensure all events are on the same cpu so all events are in the
|
|
+ * same cpu context, to avoid races on pmu_enable etc.
|
|
+ */
|
|
+ event->cpu = smmu_pmu->on_cpu;
|
|
+
|
|
+ hwc->idx = -1;
|
|
+
|
|
+ if (event->group_leader == event)
|
|
+ return 0;
|
|
+
|
|
for_each_sibling_event(sibling, event->group_leader) {
|
|
if (is_software_event(sibling))
|
|
continue;
|
|
@@ -442,14 +453,6 @@ static int smmu_pmu_event_init(struct perf_event *event)
|
|
return -EINVAL;
|
|
}
|
|
|
|
- hwc->idx = -1;
|
|
-
|
|
- /*
|
|
- * Ensure all events are on the same cpu so all events are in the
|
|
- * same cpu context, to avoid races on pmu_enable etc.
|
|
- */
|
|
- event->cpu = smmu_pmu->on_cpu;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
|
|
index b6d1ed9ec9a3c9..7c05dbf533e7a3 100644
|
|
--- a/drivers/pinctrl/pinctrl-k210.c
|
|
+++ b/drivers/pinctrl/pinctrl-k210.c
|
|
@@ -183,7 +183,7 @@ static const u32 k210_pinconf_mode_id_to_mode[] = {
|
|
[K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
|
|
};
|
|
|
|
-#undef DEFAULT
|
|
+#undef K210_PC_DEFAULT
|
|
|
|
/*
|
|
* Pin functions configuration information.
|
|
diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c
|
|
index f2be341f73e13e..1528f4097ff8a3 100644
|
|
--- a/drivers/pinctrl/pinctrl-zynqmp.c
|
|
+++ b/drivers/pinctrl/pinctrl-zynqmp.c
|
|
@@ -48,7 +48,6 @@
|
|
* @name: Name of the pin mux function
|
|
* @groups: List of pin groups for this function
|
|
* @ngroups: Number of entries in @groups
|
|
- * @node: Firmware node matching with the function
|
|
*
|
|
* This structure holds information about pin control function
|
|
* and function group names supporting that function.
|
|
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
|
|
index 5817c52cee6bad..8acaae88b87e8b 100644
|
|
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
|
|
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
|
|
@@ -667,7 +667,7 @@ static void pmic_gpio_config_dbg_show(struct pinctrl_dev *pctldev,
|
|
"push-pull", "open-drain", "open-source"
|
|
};
|
|
static const char *const strengths[] = {
|
|
- "no", "high", "medium", "low"
|
|
+ "no", "low", "medium", "high"
|
|
};
|
|
|
|
pad = pctldev->desc->pins[pin].drv_data;
|
|
diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
|
|
index d0b4d3fc40ed8f..66fdc6fa73ec54 100644
|
|
--- a/drivers/platform/chrome/cros_ec_typec.c
|
|
+++ b/drivers/platform/chrome/cros_ec_typec.c
|
|
@@ -390,6 +390,7 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
|
|
return 0;
|
|
|
|
unregister_ports:
|
|
+ fwnode_handle_put(fwnode);
|
|
cros_unregister_ports(typec);
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c
|
|
index 6fb538a1386894..9a9b9feac41664 100644
|
|
--- a/drivers/platform/x86/dell/dell-smbios-base.c
|
|
+++ b/drivers/platform/x86/dell/dell-smbios-base.c
|
|
@@ -544,6 +544,7 @@ static int __init dell_smbios_init(void)
|
|
int ret, wmi, smm;
|
|
|
|
if (!dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL) &&
|
|
+ !dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Alienware", NULL) &&
|
|
!dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "www.dell.com", NULL)) {
|
|
pr_err("Unable to run on non-Dell system\n");
|
|
return -ENODEV;
|
|
diff --git a/drivers/platform/x86/dell/dell-wmi-base.c b/drivers/platform/x86/dell/dell-wmi-base.c
|
|
index 24fd7ffadda952..841a5414d28a68 100644
|
|
--- a/drivers/platform/x86/dell/dell-wmi-base.c
|
|
+++ b/drivers/platform/x86/dell/dell-wmi-base.c
|
|
@@ -80,6 +80,12 @@ static const struct dmi_system_id dell_wmi_smbios_list[] __initconst = {
|
|
static const struct key_entry dell_wmi_keymap_type_0000[] = {
|
|
{ KE_IGNORE, 0x003a, { KEY_CAPSLOCK } },
|
|
|
|
+ /* Meta key lock */
|
|
+ { KE_IGNORE, 0xe000, { KEY_RIGHTMETA } },
|
|
+
|
|
+ /* Meta key unlock */
|
|
+ { KE_IGNORE, 0xe001, { KEY_RIGHTMETA } },
|
|
+
|
|
/* Key code is followed by brightness level */
|
|
{ KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
|
|
{ KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
|
|
diff --git a/drivers/platform/x86/intel/bxtwc_tmu.c b/drivers/platform/x86/intel/bxtwc_tmu.c
|
|
index d0e2a3c293b0b0..9ac801b929b93c 100644
|
|
--- a/drivers/platform/x86/intel/bxtwc_tmu.c
|
|
+++ b/drivers/platform/x86/intel/bxtwc_tmu.c
|
|
@@ -48,9 +48,8 @@ static irqreturn_t bxt_wcove_tmu_irq_handler(int irq, void *data)
|
|
static int bxt_wcove_tmu_probe(struct platform_device *pdev)
|
|
{
|
|
struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
|
|
- struct regmap_irq_chip_data *regmap_irq_chip;
|
|
struct wcove_tmu *wctmu;
|
|
- int ret, virq, irq;
|
|
+ int ret;
|
|
|
|
wctmu = devm_kzalloc(&pdev->dev, sizeof(*wctmu), GFP_KERNEL);
|
|
if (!wctmu)
|
|
@@ -59,27 +58,18 @@ static int bxt_wcove_tmu_probe(struct platform_device *pdev)
|
|
wctmu->dev = &pdev->dev;
|
|
wctmu->regmap = pmic->regmap;
|
|
|
|
- irq = platform_get_irq(pdev, 0);
|
|
- if (irq < 0)
|
|
- return irq;
|
|
+ wctmu->irq = platform_get_irq(pdev, 0);
|
|
+ if (wctmu->irq < 0)
|
|
+ return wctmu->irq;
|
|
|
|
- regmap_irq_chip = pmic->irq_chip_data_tmu;
|
|
- virq = regmap_irq_get_virq(regmap_irq_chip, irq);
|
|
- if (virq < 0) {
|
|
- dev_err(&pdev->dev,
|
|
- "failed to get virtual interrupt=%d\n", irq);
|
|
- return virq;
|
|
- }
|
|
-
|
|
- ret = devm_request_threaded_irq(&pdev->dev, virq,
|
|
+ ret = devm_request_threaded_irq(&pdev->dev, wctmu->irq,
|
|
NULL, bxt_wcove_tmu_irq_handler,
|
|
IRQF_ONESHOT, "bxt_wcove_tmu", wctmu);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "request irq failed: %d,virq: %d\n",
|
|
- ret, virq);
|
|
+ ret, wctmu->irq);
|
|
return ret;
|
|
}
|
|
- wctmu->irq = virq;
|
|
|
|
/* Unmask TMU second level Wake & System alarm */
|
|
regmap_update_bits(wctmu->regmap, BXTWC_MTMUIRQ_REG,
|
|
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
|
|
index ebd81846e2d564..7365286f6d2dc1 100644
|
|
--- a/drivers/platform/x86/panasonic-laptop.c
|
|
+++ b/drivers/platform/x86/panasonic-laptop.c
|
|
@@ -602,8 +602,7 @@ static ssize_t eco_mode_show(struct device *dev, struct device_attribute *attr,
|
|
result = 1;
|
|
break;
|
|
default:
|
|
- result = -EIO;
|
|
- break;
|
|
+ return -EIO;
|
|
}
|
|
return sysfs_emit(buf, "%u\n", result);
|
|
}
|
|
@@ -749,7 +748,12 @@ static ssize_t current_brightness_store(struct device *dev, struct device_attrib
|
|
static ssize_t cdpower_show(struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
- return sysfs_emit(buf, "%d\n", get_optd_power_state());
|
|
+ int state = get_optd_power_state();
|
|
+
|
|
+ if (state < 0)
|
|
+ return state;
|
|
+
|
|
+ return sysfs_emit(buf, "%d\n", state);
|
|
}
|
|
|
|
static ssize_t cdpower_store(struct device *dev, struct device_attribute *attr,
|
|
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
|
|
index 5b1f08eabd9232..964670d4ca1e2a 100644
|
|
--- a/drivers/platform/x86/thinkpad_acpi.c
|
|
+++ b/drivers/platform/x86/thinkpad_acpi.c
|
|
@@ -8013,6 +8013,7 @@ static u8 fan_control_resume_level;
|
|
static int fan_watchdog_maxinterval;
|
|
|
|
static bool fan_with_ns_addr;
|
|
+static bool ecfw_with_fan_dec_rpm;
|
|
|
|
static struct mutex fan_mutex;
|
|
|
|
@@ -8655,7 +8656,11 @@ static ssize_t fan_fan1_input_show(struct device *dev,
|
|
if (res < 0)
|
|
return res;
|
|
|
|
- return sysfs_emit(buf, "%u\n", speed);
|
|
+ /* Check for fan speeds displayed in hexadecimal */
|
|
+ if (!ecfw_with_fan_dec_rpm)
|
|
+ return sysfs_emit(buf, "%u\n", speed);
|
|
+ else
|
|
+ return sysfs_emit(buf, "%x\n", speed);
|
|
}
|
|
|
|
static DEVICE_ATTR(fan1_input, S_IRUGO, fan_fan1_input_show, NULL);
|
|
@@ -8672,7 +8677,11 @@ static ssize_t fan_fan2_input_show(struct device *dev,
|
|
if (res < 0)
|
|
return res;
|
|
|
|
- return sysfs_emit(buf, "%u\n", speed);
|
|
+ /* Check for fan speeds displayed in hexadecimal */
|
|
+ if (!ecfw_with_fan_dec_rpm)
|
|
+ return sysfs_emit(buf, "%u\n", speed);
|
|
+ else
|
|
+ return sysfs_emit(buf, "%x\n", speed);
|
|
}
|
|
|
|
static DEVICE_ATTR(fan2_input, S_IRUGO, fan_fan2_input_show, NULL);
|
|
@@ -8748,6 +8757,7 @@ static const struct attribute_group fan_driver_attr_group = {
|
|
#define TPACPI_FAN_2CTL 0x0004 /* selects fan2 control */
|
|
#define TPACPI_FAN_NOFAN 0x0008 /* no fan available */
|
|
#define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */
|
|
+#define TPACPI_FAN_DECRPM 0x0020 /* For ECFW's with RPM in register as decimal */
|
|
|
|
static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
|
|
TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1),
|
|
@@ -8769,6 +8779,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
|
|
TPACPI_Q_LNV3('R', '1', 'F', TPACPI_FAN_NS), /* L13 Yoga Gen 2 */
|
|
TPACPI_Q_LNV3('N', '2', 'U', TPACPI_FAN_NS), /* X13 Yoga Gen 2*/
|
|
TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */
|
|
+ TPACPI_Q_LNV3('R', '0', 'Q', TPACPI_FAN_DECRPM),/* L480 */
|
|
};
|
|
|
|
static int __init fan_init(struct ibm_init_struct *iibm)
|
|
@@ -8809,6 +8820,13 @@ static int __init fan_init(struct ibm_init_struct *iibm)
|
|
tp_features.fan_ctrl_status_undef = 1;
|
|
}
|
|
|
|
+ /* Check for the EC/BIOS with RPM reported in decimal*/
|
|
+ if (quirks & TPACPI_FAN_DECRPM) {
|
|
+ pr_info("ECFW with fan RPM as decimal in EC register\n");
|
|
+ ecfw_with_fan_dec_rpm = 1;
|
|
+ tp_features.fan_ctrl_status_undef = 1;
|
|
+ }
|
|
+
|
|
if (gfan_handle) {
|
|
/* 570, 600e/x, 770e, 770x */
|
|
fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
|
|
@@ -9020,7 +9038,11 @@ static int fan_read(struct seq_file *m)
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
- seq_printf(m, "speed:\t\t%d\n", speed);
|
|
+ /* Check for fan speeds displayed in hexadecimal */
|
|
+ if (!ecfw_with_fan_dec_rpm)
|
|
+ seq_printf(m, "speed:\t\t%d\n", speed);
|
|
+ else
|
|
+ seq_printf(m, "speed:\t\t%x\n", speed);
|
|
|
|
if (fan_status_access_mode == TPACPI_FAN_RD_TPEC_NS) {
|
|
/*
|
|
diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c
|
|
index a0fa0b6859c9ca..63a348af83db15 100644
|
|
--- a/drivers/platform/x86/x86-android-tablets/core.c
|
|
+++ b/drivers/platform/x86/x86-android-tablets/core.c
|
|
@@ -230,20 +230,20 @@ static void x86_android_tablet_remove(struct platform_device *pdev)
|
|
{
|
|
int i;
|
|
|
|
- for (i = 0; i < serdev_count; i++) {
|
|
+ for (i = serdev_count - 1; i >= 0; i--) {
|
|
if (serdevs[i])
|
|
serdev_device_remove(serdevs[i]);
|
|
}
|
|
|
|
kfree(serdevs);
|
|
|
|
- for (i = 0; i < pdev_count; i++)
|
|
+ for (i = pdev_count - 1; i >= 0; i--)
|
|
platform_device_unregister(pdevs[i]);
|
|
|
|
kfree(pdevs);
|
|
kfree(buttons);
|
|
|
|
- for (i = 0; i < i2c_client_count; i++)
|
|
+ for (i = i2c_client_count - 1; i >= 0; i--)
|
|
i2c_unregister_device(i2c_clients[i]);
|
|
|
|
kfree(i2c_clients);
|
|
diff --git a/drivers/pmdomain/ti/ti_sci_pm_domains.c b/drivers/pmdomain/ti/ti_sci_pm_domains.c
|
|
index f520228e1b6ae9..4449d36042c22f 100644
|
|
--- a/drivers/pmdomain/ti/ti_sci_pm_domains.c
|
|
+++ b/drivers/pmdomain/ti/ti_sci_pm_domains.c
|
|
@@ -161,6 +161,7 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
|
break;
|
|
|
|
if (args.args_count >= 1 && args.np == dev->of_node) {
|
|
+ of_node_put(args.np);
|
|
if (args.args[0] > max_id) {
|
|
max_id = args.args[0];
|
|
} else {
|
|
@@ -188,7 +189,10 @@ static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
|
pm_genpd_init(&pd->pd, NULL, true);
|
|
|
|
list_add(&pd->node, &pd_provider->pd_list);
|
|
+ } else {
|
|
+ of_node_put(args.np);
|
|
}
|
|
+
|
|
index++;
|
|
}
|
|
}
|
|
diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
|
|
index 4296600e8912a3..23c87365675742 100644
|
|
--- a/drivers/power/supply/bq27xxx_battery.c
|
|
+++ b/drivers/power/supply/bq27xxx_battery.c
|
|
@@ -449,9 +449,29 @@ static u8
|
|
[BQ27XXX_REG_AP] = 0x18,
|
|
BQ27XXX_DM_REG_ROWS,
|
|
},
|
|
+ bq27426_regs[BQ27XXX_REG_MAX] = {
|
|
+ [BQ27XXX_REG_CTRL] = 0x00,
|
|
+ [BQ27XXX_REG_TEMP] = 0x02,
|
|
+ [BQ27XXX_REG_INT_TEMP] = 0x1e,
|
|
+ [BQ27XXX_REG_VOLT] = 0x04,
|
|
+ [BQ27XXX_REG_AI] = 0x10,
|
|
+ [BQ27XXX_REG_FLAGS] = 0x06,
|
|
+ [BQ27XXX_REG_TTE] = INVALID_REG_ADDR,
|
|
+ [BQ27XXX_REG_TTF] = INVALID_REG_ADDR,
|
|
+ [BQ27XXX_REG_TTES] = INVALID_REG_ADDR,
|
|
+ [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR,
|
|
+ [BQ27XXX_REG_NAC] = 0x08,
|
|
+ [BQ27XXX_REG_RC] = 0x0c,
|
|
+ [BQ27XXX_REG_FCC] = 0x0e,
|
|
+ [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR,
|
|
+ [BQ27XXX_REG_AE] = INVALID_REG_ADDR,
|
|
+ [BQ27XXX_REG_SOC] = 0x1c,
|
|
+ [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
|
|
+ [BQ27XXX_REG_AP] = 0x18,
|
|
+ BQ27XXX_DM_REG_ROWS,
|
|
+ },
|
|
#define bq27411_regs bq27421_regs
|
|
#define bq27425_regs bq27421_regs
|
|
-#define bq27426_regs bq27421_regs
|
|
#define bq27441_regs bq27421_regs
|
|
#define bq27621_regs bq27421_regs
|
|
bq27z561_regs[BQ27XXX_REG_MAX] = {
|
|
@@ -769,10 +789,23 @@ static enum power_supply_property bq27421_props[] = {
|
|
};
|
|
#define bq27411_props bq27421_props
|
|
#define bq27425_props bq27421_props
|
|
-#define bq27426_props bq27421_props
|
|
#define bq27441_props bq27421_props
|
|
#define bq27621_props bq27421_props
|
|
|
|
+static enum power_supply_property bq27426_props[] = {
|
|
+ POWER_SUPPLY_PROP_STATUS,
|
|
+ POWER_SUPPLY_PROP_PRESENT,
|
|
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
|
+ POWER_SUPPLY_PROP_CURRENT_NOW,
|
|
+ POWER_SUPPLY_PROP_CAPACITY,
|
|
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
|
|
+ POWER_SUPPLY_PROP_TEMP,
|
|
+ POWER_SUPPLY_PROP_TECHNOLOGY,
|
|
+ POWER_SUPPLY_PROP_CHARGE_FULL,
|
|
+ POWER_SUPPLY_PROP_CHARGE_NOW,
|
|
+ POWER_SUPPLY_PROP_MANUFACTURER,
|
|
+};
|
|
+
|
|
static enum power_supply_property bq27z561_props[] = {
|
|
POWER_SUPPLY_PROP_STATUS,
|
|
POWER_SUPPLY_PROP_PRESENT,
|
|
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
|
|
index 416409e2fd6da2..1893d37dd575de 100644
|
|
--- a/drivers/power/supply/power_supply_core.c
|
|
+++ b/drivers/power/supply/power_supply_core.c
|
|
@@ -480,8 +480,6 @@ EXPORT_SYMBOL_GPL(power_supply_get_by_name);
|
|
*/
|
|
void power_supply_put(struct power_supply *psy)
|
|
{
|
|
- might_sleep();
|
|
-
|
|
atomic_dec(&psy->use_cnt);
|
|
put_device(&psy->dev);
|
|
}
|
|
diff --git a/drivers/power/supply/rt9471.c b/drivers/power/supply/rt9471.c
|
|
index 868b0703d15c52..522a67736fa5a9 100644
|
|
--- a/drivers/power/supply/rt9471.c
|
|
+++ b/drivers/power/supply/rt9471.c
|
|
@@ -139,6 +139,19 @@ enum {
|
|
RT9471_PORTSTAT_DCP,
|
|
};
|
|
|
|
+enum {
|
|
+ RT9471_ICSTAT_SLEEP = 0,
|
|
+ RT9471_ICSTAT_VBUSRDY,
|
|
+ RT9471_ICSTAT_TRICKLECHG,
|
|
+ RT9471_ICSTAT_PRECHG,
|
|
+ RT9471_ICSTAT_FASTCHG,
|
|
+ RT9471_ICSTAT_IEOC,
|
|
+ RT9471_ICSTAT_BGCHG,
|
|
+ RT9471_ICSTAT_CHGDONE,
|
|
+ RT9471_ICSTAT_CHGFAULT,
|
|
+ RT9471_ICSTAT_OTG = 15,
|
|
+};
|
|
+
|
|
struct rt9471_chip {
|
|
struct device *dev;
|
|
struct regmap *regmap;
|
|
@@ -153,8 +166,8 @@ struct rt9471_chip {
|
|
};
|
|
|
|
static const struct reg_field rt9471_reg_fields[F_MAX_FIELDS] = {
|
|
- [F_WDT] = REG_FIELD(RT9471_REG_TOP, 0, 0),
|
|
- [F_WDT_RST] = REG_FIELD(RT9471_REG_TOP, 1, 1),
|
|
+ [F_WDT] = REG_FIELD(RT9471_REG_TOP, 0, 1),
|
|
+ [F_WDT_RST] = REG_FIELD(RT9471_REG_TOP, 2, 2),
|
|
[F_CHG_EN] = REG_FIELD(RT9471_REG_FUNC, 0, 0),
|
|
[F_HZ] = REG_FIELD(RT9471_REG_FUNC, 5, 5),
|
|
[F_BATFET_DIS] = REG_FIELD(RT9471_REG_FUNC, 7, 7),
|
|
@@ -255,31 +268,32 @@ static int rt9471_get_ieoc(struct rt9471_chip *chip, int *microamp)
|
|
|
|
static int rt9471_get_status(struct rt9471_chip *chip, int *status)
|
|
{
|
|
- unsigned int chg_ready, chg_done, fault_stat;
|
|
+ unsigned int ic_stat;
|
|
int ret;
|
|
|
|
- ret = regmap_field_read(chip->rm_fields[F_ST_CHG_RDY], &chg_ready);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- ret = regmap_field_read(chip->rm_fields[F_ST_CHG_DONE], &chg_done);
|
|
+ ret = regmap_field_read(chip->rm_fields[F_IC_STAT], &ic_stat);
|
|
if (ret)
|
|
return ret;
|
|
|
|
- ret = regmap_read(chip->regmap, RT9471_REG_STAT1, &fault_stat);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- fault_stat &= RT9471_CHGFAULT_MASK;
|
|
-
|
|
- if (chg_ready && chg_done)
|
|
- *status = POWER_SUPPLY_STATUS_FULL;
|
|
- else if (chg_ready && fault_stat)
|
|
+ switch (ic_stat) {
|
|
+ case RT9471_ICSTAT_VBUSRDY:
|
|
+ case RT9471_ICSTAT_CHGFAULT:
|
|
*status = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
|
- else if (chg_ready && !fault_stat)
|
|
+ break;
|
|
+ case RT9471_ICSTAT_TRICKLECHG ... RT9471_ICSTAT_BGCHG:
|
|
*status = POWER_SUPPLY_STATUS_CHARGING;
|
|
- else
|
|
+ break;
|
|
+ case RT9471_ICSTAT_CHGDONE:
|
|
+ *status = POWER_SUPPLY_STATUS_FULL;
|
|
+ break;
|
|
+ case RT9471_ICSTAT_SLEEP:
|
|
+ case RT9471_ICSTAT_OTG:
|
|
*status = POWER_SUPPLY_STATUS_DISCHARGING;
|
|
+ break;
|
|
+ default:
|
|
+ *status = POWER_SUPPLY_STATUS_UNKNOWN;
|
|
+ break;
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
|
|
index 29a3089c534cda..660a71b7263ce0 100644
|
|
--- a/drivers/pwm/pwm-imx27.c
|
|
+++ b/drivers/pwm/pwm-imx27.c
|
|
@@ -26,6 +26,7 @@
|
|
#define MX3_PWMSR 0x04 /* PWM Status Register */
|
|
#define MX3_PWMSAR 0x0C /* PWM Sample Register */
|
|
#define MX3_PWMPR 0x10 /* PWM Period Register */
|
|
+#define MX3_PWMCNR 0x14 /* PWM Counter Register */
|
|
|
|
#define MX3_PWMCR_FWM GENMASK(27, 26)
|
|
#define MX3_PWMCR_STOPEN BIT(25)
|
|
@@ -217,11 +218,13 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
|
|
static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
const struct pwm_state *state)
|
|
{
|
|
- unsigned long period_cycles, duty_cycles, prescale;
|
|
+ unsigned long period_cycles, duty_cycles, prescale, period_us, tmp;
|
|
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
|
|
struct pwm_state cstate;
|
|
unsigned long long c;
|
|
unsigned long long clkrate;
|
|
+ unsigned long flags;
|
|
+ int val;
|
|
int ret;
|
|
u32 cr;
|
|
|
|
@@ -264,7 +267,98 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
pwm_imx27_sw_reset(chip);
|
|
}
|
|
|
|
- writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
|
|
+ val = readl(imx->mmio_base + MX3_PWMPR);
|
|
+ val = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val;
|
|
+ cr = readl(imx->mmio_base + MX3_PWMCR);
|
|
+ tmp = NSEC_PER_SEC * (u64)(val + 2) * MX3_PWMCR_PRESCALER_GET(cr);
|
|
+ tmp = DIV_ROUND_UP_ULL(tmp, clkrate);
|
|
+ period_us = DIV_ROUND_UP_ULL(tmp, 1000);
|
|
+
|
|
+ /*
|
|
+ * ERR051198:
|
|
+ * PWM: PWM output may not function correctly if the FIFO is empty when
|
|
+ * a new SAR value is programmed
|
|
+ *
|
|
+ * Description:
|
|
+ * When the PWM FIFO is empty, a new value programmed to the PWM Sample
|
|
+ * register (PWM_PWMSAR) will be directly applied even if the current
|
|
+ * timer period has not expired.
|
|
+ *
|
|
+ * If the new SAMPLE value programmed in the PWM_PWMSAR register is
|
|
+ * less than the previous value, and the PWM counter register
|
|
+ * (PWM_PWMCNR) that contains the current COUNT value is greater than
|
|
+ * the new programmed SAMPLE value, the current period will not flip
|
|
+ * the level. This may result in an output pulse with a duty cycle of
|
|
+ * 100%.
|
|
+ *
|
|
+ * Consider a change from
|
|
+ * ________
|
|
+ * / \______/
|
|
+ * ^ * ^
|
|
+ * to
|
|
+ * ____
|
|
+ * / \__________/
|
|
+ * ^ ^
|
|
+ * At the time marked by *, the new write value will be directly applied
|
|
+ * to SAR even the current period is not over if FIFO is empty.
|
|
+ *
|
|
+ * ________ ____________________
|
|
+ * / \______/ \__________/
|
|
+ * ^ ^ * ^ ^
|
|
+ * |<-- old SAR -->| |<-- new SAR -->|
|
|
+ *
|
|
+ * That is the output is active for a whole period.
|
|
+ *
|
|
+ * Workaround:
|
|
+ * Check new SAR less than old SAR and current counter is in errata
|
|
+ * windows, write extra old SAR into FIFO and new SAR will effect at
|
|
+ * next period.
|
|
+ *
|
|
+ * Sometime period is quite long, such as over 1 second. If add old SAR
|
|
+ * into FIFO unconditional, new SAR have to wait for next period. It
|
|
+ * may be too long.
|
|
+ *
|
|
+ * Turn off the interrupt to ensure that not IRQ and schedule happen
|
|
+ * during above operations. If any irq and schedule happen, counter
|
|
+ * in PWM will be out of data and take wrong action.
|
|
+ *
|
|
+ * Add a safety margin 1.5us because it needs some time to complete
|
|
+ * IO write.
|
|
+ *
|
|
+ * Use writel_relaxed() to minimize the interval between two writes to
|
|
+ * the SAR register to increase the fastest PWM frequency supported.
|
|
+ *
|
|
+ * When the PWM period is longer than 2us(or <500kHz), this workaround
|
|
+ * can solve this problem. No software workaround is available if PWM
|
|
+ * period is shorter than IO write. Just try best to fill old data
|
|
+ * into FIFO.
|
|
+ */
|
|
+ c = clkrate * 1500;
|
|
+ do_div(c, NSEC_PER_SEC);
|
|
+
|
|
+ local_irq_save(flags);
|
|
+ val = FIELD_GET(MX3_PWMSR_FIFOAV, readl_relaxed(imx->mmio_base + MX3_PWMSR));
|
|
+
|
|
+ if (duty_cycles < imx->duty_cycle && (cr & MX3_PWMCR_EN)) {
|
|
+ if (period_us < 2) { /* 2us = 500 kHz */
|
|
+ /* Best effort attempt to fix up >500 kHz case */
|
|
+ udelay(3 * period_us);
|
|
+ writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR);
|
|
+ writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR);
|
|
+ } else if (val < MX3_PWMSR_FIFOAV_2WORDS) {
|
|
+ val = readl_relaxed(imx->mmio_base + MX3_PWMCNR);
|
|
+ /*
|
|
+ * If counter is close to period, controller may roll over when
|
|
+ * next IO write.
|
|
+ */
|
|
+ if ((val + c >= duty_cycles && val < imx->duty_cycle) ||
|
|
+ val + c >= period_cycles)
|
|
+ writel_relaxed(imx->duty_cycle, imx->mmio_base + MX3_PWMSAR);
|
|
+ }
|
|
+ }
|
|
+ writel_relaxed(duty_cycles, imx->mmio_base + MX3_PWMSAR);
|
|
+ local_irq_restore(flags);
|
|
+
|
|
writel(period_cycles, imx->mmio_base + MX3_PWMPR);
|
|
|
|
/*
|
|
diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c
|
|
index 867a2cf243f686..374d80dc6d17ab 100644
|
|
--- a/drivers/regulator/rk808-regulator.c
|
|
+++ b/drivers/regulator/rk808-regulator.c
|
|
@@ -1286,6 +1286,8 @@ static const struct regulator_desc rk809_reg[] = {
|
|
.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
|
|
.vsel_reg = RK817_BUCK3_ON_VSEL_REG,
|
|
.vsel_mask = RK817_BUCK_VSEL_MASK,
|
|
+ .apply_reg = RK817_POWER_CONFIG,
|
|
+ .apply_bit = RK817_BUCK3_FB_RES_INTER,
|
|
.enable_reg = RK817_POWER_EN_REG(0),
|
|
.enable_mask = ENABLE_MASK(RK817_ID_DCDC3),
|
|
.enable_val = ENABLE_MASK(RK817_ID_DCDC3),
|
|
@@ -1647,7 +1649,7 @@ static int rk808_regulator_dt_parse_pdata(struct device *dev,
|
|
}
|
|
|
|
if (!pdata->dvs_gpio[i]) {
|
|
- dev_info(dev, "there is no dvs%d gpio\n", i);
|
|
+ dev_dbg(dev, "there is no dvs%d gpio\n", i);
|
|
continue;
|
|
}
|
|
|
|
@@ -1683,12 +1685,6 @@ static int rk808_regulator_probe(struct platform_device *pdev)
|
|
if (!pdata)
|
|
return -ENOMEM;
|
|
|
|
- ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata);
|
|
- if (ret < 0)
|
|
- return ret;
|
|
-
|
|
- platform_set_drvdata(pdev, pdata);
|
|
-
|
|
switch (rk808->variant) {
|
|
case RK805_ID:
|
|
regulators = rk805_reg;
|
|
@@ -1699,6 +1695,11 @@ static int rk808_regulator_probe(struct platform_device *pdev)
|
|
nregulators = ARRAY_SIZE(rk806_reg);
|
|
break;
|
|
case RK808_ID:
|
|
+ /* DVS0/1 GPIOs are supported on the RK808 only */
|
|
+ ret = rk808_regulator_dt_parse_pdata(&pdev->dev, regmap, pdata);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
regulators = rk808_reg;
|
|
nregulators = RK808_NUM_REGULATORS;
|
|
break;
|
|
@@ -1720,6 +1721,8 @@ static int rk808_regulator_probe(struct platform_device *pdev)
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ platform_set_drvdata(pdev, pdata);
|
|
+
|
|
config.dev = &pdev->dev;
|
|
config.driver_data = pdata;
|
|
config.regmap = regmap;
|
|
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
|
|
index 22fe7b5f5236da..2d717f2ed396c6 100644
|
|
--- a/drivers/remoteproc/qcom_q6v5_mss.c
|
|
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
|
|
@@ -1161,6 +1161,9 @@ static int q6v5_mba_load(struct q6v5 *qproc)
|
|
goto disable_active_clks;
|
|
}
|
|
|
|
+ if (qproc->has_mba_logs)
|
|
+ qcom_pil_info_store("mba", qproc->mba_phys, MBA_LOG_SIZE);
|
|
+
|
|
writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG);
|
|
if (qproc->dp_size) {
|
|
writel(qproc->mba_phys + SZ_1M, qproc->rmb_base + RMB_PMI_CODE_START_REG);
|
|
@@ -1171,9 +1174,6 @@ static int q6v5_mba_load(struct q6v5 *qproc)
|
|
if (ret)
|
|
goto reclaim_mba;
|
|
|
|
- if (qproc->has_mba_logs)
|
|
- qcom_pil_info_store("mba", qproc->mba_phys, MBA_LOG_SIZE);
|
|
-
|
|
ret = q6v5_rmb_mba_wait(qproc, 0, 5000);
|
|
if (ret == -ETIMEDOUT) {
|
|
dev_err(qproc->dev, "MBA boot timed out\n");
|
|
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
|
|
index b5447dd2dd35e4..6235721f2c1aec 100644
|
|
--- a/drivers/remoteproc/qcom_q6v5_pas.c
|
|
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
|
|
@@ -832,6 +832,7 @@ static const struct adsp_data sm8250_adsp_resource = {
|
|
.crash_reason_smem = 423,
|
|
.firmware_name = "adsp.mdt",
|
|
.pas_id = 1,
|
|
+ .minidump_id = 5,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"lcx",
|
|
@@ -973,6 +974,7 @@ static const struct adsp_data sm8350_cdsp_resource = {
|
|
.crash_reason_smem = 601,
|
|
.firmware_name = "cdsp.mdt",
|
|
.pas_id = 18,
|
|
+ .minidump_id = 7,
|
|
.auto_boot = true,
|
|
.proxy_pd_names = (char*[]){
|
|
"cx",
|
|
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
|
|
index d877a1a1aeb4bf..c7f91a82e634f4 100644
|
|
--- a/drivers/rpmsg/qcom_glink_native.c
|
|
+++ b/drivers/rpmsg/qcom_glink_native.c
|
|
@@ -1117,7 +1117,8 @@ void qcom_glink_native_rx(struct qcom_glink *glink)
|
|
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
|
|
break;
|
|
case GLINK_CMD_OPEN:
|
|
- ret = qcom_glink_rx_defer(glink, param2);
|
|
+ /* upper 16 bits of param2 are the "prio" field */
|
|
+ ret = qcom_glink_rx_defer(glink, param2 & 0xffff);
|
|
break;
|
|
case GLINK_CMD_TX_DATA:
|
|
case GLINK_CMD_TX_DATA_CONT:
|
|
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
|
|
index 0b23706d9fd3cc..4a7c41a6c21e7d 100644
|
|
--- a/drivers/rtc/interface.c
|
|
+++ b/drivers/rtc/interface.c
|
|
@@ -904,13 +904,18 @@ void rtc_timer_do_work(struct work_struct *work)
|
|
struct timerqueue_node *next;
|
|
ktime_t now;
|
|
struct rtc_time tm;
|
|
+ int err;
|
|
|
|
struct rtc_device *rtc =
|
|
container_of(work, struct rtc_device, irqwork);
|
|
|
|
mutex_lock(&rtc->ops_lock);
|
|
again:
|
|
- __rtc_read_time(rtc, &tm);
|
|
+ err = __rtc_read_time(rtc, &tm);
|
|
+ if (err) {
|
|
+ mutex_unlock(&rtc->ops_lock);
|
|
+ return;
|
|
+ }
|
|
now = rtc_tm_to_ktime(tm);
|
|
while ((next = timerqueue_getnext(&rtc->timerqueue))) {
|
|
if (next->expires > now)
|
|
diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c
|
|
index 04e1b8e93bc1cb..79d5ee7b818c57 100644
|
|
--- a/drivers/rtc/rtc-ab-eoz9.c
|
|
+++ b/drivers/rtc/rtc-ab-eoz9.c
|
|
@@ -396,13 +396,6 @@ static int abeoz9z3_temp_read(struct device *dev,
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- if ((val & ABEOZ9_REG_CTRL_STATUS_V1F) ||
|
|
- (val & ABEOZ9_REG_CTRL_STATUS_V2F)) {
|
|
- dev_err(dev,
|
|
- "thermometer might be disabled due to low voltage\n");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
switch (attr) {
|
|
case hwmon_temp_input:
|
|
ret = regmap_read(regmap, ABEOZ9_REG_REG_TEMP, &val);
|
|
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
|
|
index 1298962402ff47..3fee27914ba805 100644
|
|
--- a/drivers/rtc/rtc-abx80x.c
|
|
+++ b/drivers/rtc/rtc-abx80x.c
|
|
@@ -39,7 +39,7 @@
|
|
#define ABX8XX_REG_STATUS 0x0f
|
|
#define ABX8XX_STATUS_AF BIT(2)
|
|
#define ABX8XX_STATUS_BLF BIT(4)
|
|
-#define ABX8XX_STATUS_WDT BIT(6)
|
|
+#define ABX8XX_STATUS_WDT BIT(5)
|
|
|
|
#define ABX8XX_REG_CTRL1 0x10
|
|
#define ABX8XX_CTRL_WRITE BIT(0)
|
|
diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c
|
|
index 56ebbd4d048147..8570c8e63d70c3 100644
|
|
--- a/drivers/rtc/rtc-rzn1.c
|
|
+++ b/drivers/rtc/rtc-rzn1.c
|
|
@@ -111,8 +111,8 @@ static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|
tm->tm_hour = bcd2bin(tm->tm_hour);
|
|
tm->tm_wday = bcd2bin(tm->tm_wday);
|
|
tm->tm_mday = bcd2bin(tm->tm_mday);
|
|
- tm->tm_mon = bcd2bin(tm->tm_mon);
|
|
- tm->tm_year = bcd2bin(tm->tm_year);
|
|
+ tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
|
|
+ tm->tm_year = bcd2bin(tm->tm_year) + 100;
|
|
|
|
return 0;
|
|
}
|
|
@@ -128,8 +128,8 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|
tm->tm_hour = bin2bcd(tm->tm_hour);
|
|
tm->tm_wday = bin2bcd(rzn1_rtc_tm_to_wday(tm));
|
|
tm->tm_mday = bin2bcd(tm->tm_mday);
|
|
- tm->tm_mon = bin2bcd(tm->tm_mon);
|
|
- tm->tm_year = bin2bcd(tm->tm_year);
|
|
+ tm->tm_mon = bin2bcd(tm->tm_mon + 1);
|
|
+ tm->tm_year = bin2bcd(tm->tm_year - 100);
|
|
|
|
val = readl(rtc->base + RZN1_RTC_CTL2);
|
|
if (!(val & RZN1_RTC_CTL2_STOPPED)) {
|
|
diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
|
|
index d492a2d26600c1..c6d4522411b312 100644
|
|
--- a/drivers/rtc/rtc-st-lpc.c
|
|
+++ b/drivers/rtc/rtc-st-lpc.c
|
|
@@ -218,15 +218,14 @@ static int st_rtc_probe(struct platform_device *pdev)
|
|
return -EINVAL;
|
|
}
|
|
|
|
- ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler, 0,
|
|
- pdev->name, rtc);
|
|
+ ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler,
|
|
+ IRQF_NO_AUTOEN, pdev->name, rtc);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "Failed to request irq %i\n", rtc->irq);
|
|
return ret;
|
|
}
|
|
|
|
enable_irq_wake(rtc->irq);
|
|
- disable_irq(rtc->irq);
|
|
|
|
rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
|
|
if (IS_ERR(rtc->clk))
|
|
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
|
|
index 6127add746d181..81ef9002f06400 100644
|
|
--- a/drivers/s390/cio/cio.c
|
|
+++ b/drivers/s390/cio/cio.c
|
|
@@ -459,10 +459,14 @@ int cio_update_schib(struct subchannel *sch)
|
|
{
|
|
struct schib schib;
|
|
|
|
- if (stsch(sch->schid, &schib) || !css_sch_is_valid(&schib))
|
|
+ if (stsch(sch->schid, &schib))
|
|
return -ENODEV;
|
|
|
|
memcpy(&sch->schib, &schib, sizeof(schib));
|
|
+
|
|
+ if (!css_sch_is_valid(&schib))
|
|
+ return -EACCES;
|
|
+
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(cio_update_schib);
|
|
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
|
|
index 57e0050dbaa538..6b374026cd4f44 100644
|
|
--- a/drivers/s390/cio/device.c
|
|
+++ b/drivers/s390/cio/device.c
|
|
@@ -1387,14 +1387,18 @@ enum io_sch_action {
|
|
IO_SCH_VERIFY,
|
|
IO_SCH_DISC,
|
|
IO_SCH_NOP,
|
|
+ IO_SCH_ORPH_CDEV,
|
|
};
|
|
|
|
static enum io_sch_action sch_get_action(struct subchannel *sch)
|
|
{
|
|
struct ccw_device *cdev;
|
|
+ int rc;
|
|
|
|
cdev = sch_get_cdev(sch);
|
|
- if (cio_update_schib(sch)) {
|
|
+ rc = cio_update_schib(sch);
|
|
+
|
|
+ if (rc == -ENODEV) {
|
|
/* Not operational. */
|
|
if (!cdev)
|
|
return IO_SCH_UNREG;
|
|
@@ -1402,6 +1406,16 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
|
|
return IO_SCH_UNREG;
|
|
return IO_SCH_ORPH_UNREG;
|
|
}
|
|
+
|
|
+ /* Avoid unregistering subchannels without working device. */
|
|
+ if (rc == -EACCES) {
|
|
+ if (!cdev)
|
|
+ return IO_SCH_NOP;
|
|
+ if (ccw_device_notify(cdev, CIO_GONE) != NOTIFY_OK)
|
|
+ return IO_SCH_UNREG_CDEV;
|
|
+ return IO_SCH_ORPH_CDEV;
|
|
+ }
|
|
+
|
|
/* Operational. */
|
|
if (!cdev)
|
|
return IO_SCH_ATTACH;
|
|
@@ -1471,6 +1485,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
|
|
rc = 0;
|
|
goto out_unlock;
|
|
case IO_SCH_ORPH_UNREG:
|
|
+ case IO_SCH_ORPH_CDEV:
|
|
case IO_SCH_ORPH_ATTACH:
|
|
ccw_device_set_disconnected(cdev);
|
|
break;
|
|
@@ -1502,6 +1517,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
|
|
/* Handle attached ccw device. */
|
|
switch (action) {
|
|
case IO_SCH_ORPH_UNREG:
|
|
+ case IO_SCH_ORPH_CDEV:
|
|
case IO_SCH_ORPH_ATTACH:
|
|
/* Move ccw device to orphanage. */
|
|
rc = ccw_device_move_to_orph(cdev);
|
|
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
|
|
index d2ffdf2491da04..70fcb5c40cfe32 100644
|
|
--- a/drivers/s390/crypto/pkey_api.c
|
|
+++ b/drivers/s390/crypto/pkey_api.c
|
|
@@ -1366,9 +1366,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
|
|
rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
|
|
kcs.clrkey.clrkey, kcs.seckey.seckey);
|
|
DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc);
|
|
- if (rc)
|
|
- break;
|
|
- if (copy_to_user(ucs, &kcs, sizeof(kcs)))
|
|
+ if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))
|
|
rc = -EFAULT;
|
|
memzero_explicit(&kcs, sizeof(kcs));
|
|
break;
|
|
@@ -1401,9 +1399,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
|
|
kcp.protkey.protkey,
|
|
&kcp.protkey.len, &kcp.protkey.type);
|
|
DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc);
|
|
- if (rc)
|
|
- break;
|
|
- if (copy_to_user(ucp, &kcp, sizeof(kcp)))
|
|
+ if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp)))
|
|
rc = -EFAULT;
|
|
memzero_explicit(&kcp, sizeof(kcp));
|
|
break;
|
|
@@ -1555,11 +1551,14 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
|
|
if (copy_from_user(&kcs, ucs, sizeof(kcs)))
|
|
return -EFAULT;
|
|
apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
|
|
- if (IS_ERR(apqns))
|
|
+ if (IS_ERR(apqns)) {
|
|
+ memzero_explicit(&kcs, sizeof(kcs));
|
|
return PTR_ERR(apqns);
|
|
+ }
|
|
kkey = kzalloc(klen, GFP_KERNEL);
|
|
if (!kkey) {
|
|
kfree(apqns);
|
|
+ memzero_explicit(&kcs, sizeof(kcs));
|
|
return -ENOMEM;
|
|
}
|
|
rc = pkey_clr2seckey2(apqns, kcs.apqn_entries,
|
|
@@ -1569,15 +1568,18 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
|
|
kfree(apqns);
|
|
if (rc) {
|
|
kfree(kkey);
|
|
+ memzero_explicit(&kcs, sizeof(kcs));
|
|
break;
|
|
}
|
|
if (kcs.key) {
|
|
if (kcs.keylen < klen) {
|
|
kfree(kkey);
|
|
+ memzero_explicit(&kcs, sizeof(kcs));
|
|
return -EINVAL;
|
|
}
|
|
if (copy_to_user(kcs.key, kkey, klen)) {
|
|
kfree(kkey);
|
|
+ memzero_explicit(&kcs, sizeof(kcs));
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
|
|
index 62cb7a864fd53d..70c7515a822f52 100644
|
|
--- a/drivers/scsi/bfa/bfad.c
|
|
+++ b/drivers/scsi/bfa/bfad.c
|
|
@@ -1693,9 +1693,8 @@ bfad_init(void)
|
|
|
|
error = bfad_im_module_init();
|
|
if (error) {
|
|
- error = -ENOMEM;
|
|
printk(KERN_WARNING "bfad_im_module_init failure\n");
|
|
- goto ext;
|
|
+ return -ENOMEM;
|
|
}
|
|
|
|
if (strcmp(FCPI_NAME, " fcpim") == 0)
|
|
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
index e4363b8c6ad268..db9ae206974c21 100644
|
|
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
|
|
@@ -1539,10 +1539,16 @@ void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba)
|
|
/* Init and wait for PHYs to come up and all libsas event finished. */
|
|
for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
|
|
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
|
|
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
|
|
|
|
- if (!(hisi_hba->phy_state & BIT(phy_no)))
|
|
+ if (!sas_phy->phy->enabled)
|
|
continue;
|
|
|
|
+ if (!(hisi_hba->phy_state & BIT(phy_no))) {
|
|
+ hisi_sas_phy_enable(hisi_hba, phy_no, 1);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
async_schedule_domain(hisi_sas_async_init_wait_phyup,
|
|
phy, &async);
|
|
}
|
|
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
index 0a01575ab06dd6..0ad8a10002ce36 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
|
|
@@ -175,7 +175,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
|
|
ndlp->nlp_state, ndlp->fc4_xpt_flags);
|
|
|
|
/* Don't schedule a worker thread event if the vport is going down. */
|
|
- if (vport->load_flag & FC_UNLOADING) {
|
|
+ if ((vport->load_flag & FC_UNLOADING) ||
|
|
+ !(phba->hba_flag & HBA_SETUP)) {
|
|
spin_lock_irqsave(&ndlp->lock, iflags);
|
|
ndlp->rport = NULL;
|
|
|
|
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
|
|
index cf506556f3b0bd..070654cc929208 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_scsi.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
|
|
@@ -5546,11 +5546,20 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
|
|
|
|
iocb = &lpfc_cmd->cur_iocbq;
|
|
if (phba->sli_rev == LPFC_SLI_REV4) {
|
|
- pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring;
|
|
- if (!pring_s4) {
|
|
+ /* if the io_wq & pring are gone, the port was reset. */
|
|
+ if (!phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq ||
|
|
+ !phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring) {
|
|
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
|
|
+ "2877 SCSI Layer I/O Abort Request "
|
|
+ "IO CMPL Status x%x ID %d LUN %llu "
|
|
+ "HBA_SETUP %d\n", FAILED,
|
|
+ cmnd->device->id,
|
|
+ (u64)cmnd->device->lun,
|
|
+ (HBA_SETUP & phba->hba_flag));
|
|
ret = FAILED;
|
|
goto out_unlock_hba;
|
|
}
|
|
+ pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring;
|
|
spin_lock(&pring_s4->ring_lock);
|
|
}
|
|
/* the command is in process of being cancelled */
|
|
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
|
|
index 9cd22588c8eb33..9b1ffa84a06291 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_sli.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_sli.c
|
|
@@ -4684,6 +4684,17 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)
|
|
/* Look on all the FCP Rings for the iotag */
|
|
if (phba->sli_rev >= LPFC_SLI_REV4) {
|
|
for (i = 0; i < phba->cfg_hdw_queue; i++) {
|
|
+ if (!phba->sli4_hba.hdwq ||
|
|
+ !phba->sli4_hba.hdwq[i].io_wq) {
|
|
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
|
+ "7777 hdwq's deleted %lx "
|
|
+ "%lx %x %x\n",
|
|
+ (unsigned long)phba->pport->load_flag,
|
|
+ (unsigned long)phba->hba_flag,
|
|
+ phba->link_state,
|
|
+ phba->sli.sli_flag);
|
|
+ return;
|
|
+ }
|
|
pring = phba->sli4_hba.hdwq[i].io_wq->pring;
|
|
|
|
spin_lock_irq(&pring->ring_lock);
|
|
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
|
|
index 14625e6bc88246..9a81d14aef6b99 100644
|
|
--- a/drivers/scsi/qedf/qedf_main.c
|
|
+++ b/drivers/scsi/qedf/qedf_main.c
|
|
@@ -2737,6 +2737,7 @@ static int qedf_alloc_and_init_sb(struct qedf_ctx *qedf,
|
|
sb_id, QED_SB_TYPE_STORAGE);
|
|
|
|
if (ret) {
|
|
+ dma_free_coherent(&qedf->pdev->dev, sizeof(*sb_virt), sb_virt, sb_phys);
|
|
QEDF_ERR(&qedf->dbg_ctx,
|
|
"Status block initialization failed (0x%x) for id = %d.\n",
|
|
ret, sb_id);
|
|
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
|
|
index cd0180b1f5b9da..ede8d1f6ae2361 100644
|
|
--- a/drivers/scsi/qedi/qedi_main.c
|
|
+++ b/drivers/scsi/qedi/qedi_main.c
|
|
@@ -369,6 +369,7 @@ static int qedi_alloc_and_init_sb(struct qedi_ctx *qedi,
|
|
ret = qedi_ops->common->sb_init(qedi->cdev, sb_info, sb_virt, sb_phys,
|
|
sb_id, QED_SB_TYPE_STORAGE);
|
|
if (ret) {
|
|
+ dma_free_coherent(&qedi->pdev->dev, sizeof(*sb_virt), sb_virt, sb_phys);
|
|
QEDI_ERR(&qedi->dbg_ctx,
|
|
"Status block initialization failed for id = %d.\n",
|
|
sb_id);
|
|
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
|
|
index e6d8beb8777669..dc9722b290f20d 100644
|
|
--- a/drivers/scsi/sg.c
|
|
+++ b/drivers/scsi/sg.c
|
|
@@ -307,10 +307,6 @@ sg_open(struct inode *inode, struct file *filp)
|
|
if (retval)
|
|
goto sg_put;
|
|
|
|
- retval = scsi_autopm_get_device(device);
|
|
- if (retval)
|
|
- goto sdp_put;
|
|
-
|
|
/* scsi_block_when_processing_errors() may block so bypass
|
|
* check if O_NONBLOCK. Permits SCSI commands to be issued
|
|
* during error recovery. Tread carefully. */
|
|
@@ -318,7 +314,7 @@ sg_open(struct inode *inode, struct file *filp)
|
|
scsi_block_when_processing_errors(device))) {
|
|
retval = -ENXIO;
|
|
/* we are in error recovery for this device */
|
|
- goto error_out;
|
|
+ goto sdp_put;
|
|
}
|
|
|
|
mutex_lock(&sdp->open_rel_lock);
|
|
@@ -371,8 +367,6 @@ sg_open(struct inode *inode, struct file *filp)
|
|
}
|
|
error_mutex_locked:
|
|
mutex_unlock(&sdp->open_rel_lock);
|
|
-error_out:
|
|
- scsi_autopm_put_device(device);
|
|
sdp_put:
|
|
kref_put(&sdp->d_ref, sg_device_destroy);
|
|
scsi_device_put(device);
|
|
@@ -392,7 +386,6 @@ sg_release(struct inode *inode, struct file *filp)
|
|
SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_release\n"));
|
|
|
|
mutex_lock(&sdp->open_rel_lock);
|
|
- scsi_autopm_put_device(sdp->device);
|
|
kref_put(&sfp->f_ref, sg_remove_sfp);
|
|
sdp->open_cnt--;
|
|
|
|
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
|
|
index ca4f4ca413f11d..b19388b349be36 100644
|
|
--- a/drivers/sh/intc/core.c
|
|
+++ b/drivers/sh/intc/core.c
|
|
@@ -209,7 +209,6 @@ int __init register_intc_controller(struct intc_desc *desc)
|
|
goto err0;
|
|
|
|
INIT_LIST_HEAD(&d->list);
|
|
- list_add_tail(&d->list, &intc_list);
|
|
|
|
raw_spin_lock_init(&d->lock);
|
|
INIT_RADIX_TREE(&d->tree, GFP_ATOMIC);
|
|
@@ -369,6 +368,7 @@ int __init register_intc_controller(struct intc_desc *desc)
|
|
|
|
d->skip_suspend = desc->skip_syscore_suspend;
|
|
|
|
+ list_add_tail(&d->list, &intc_list);
|
|
nr_intc_controllers++;
|
|
|
|
return 0;
|
|
diff --git a/drivers/soc/fsl/rcpm.c b/drivers/soc/fsl/rcpm.c
|
|
index 3d0cae30c769ea..06bd94b29fb321 100644
|
|
--- a/drivers/soc/fsl/rcpm.c
|
|
+++ b/drivers/soc/fsl/rcpm.c
|
|
@@ -36,6 +36,7 @@ static void copy_ippdexpcr1_setting(u32 val)
|
|
return;
|
|
|
|
regs = of_iomap(np, 0);
|
|
+ of_node_put(np);
|
|
if (!regs)
|
|
return;
|
|
|
|
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
|
|
index ba788762835fad..e339253ccba863 100644
|
|
--- a/drivers/soc/qcom/qcom-geni-se.c
|
|
+++ b/drivers/soc/qcom/qcom-geni-se.c
|
|
@@ -586,7 +586,8 @@ int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl)
|
|
|
|
for (i = 0; i < MAX_CLK_PERF_LEVEL; i++) {
|
|
freq = clk_round_rate(se->clk, freq + 1);
|
|
- if (freq <= 0 || freq == se->clk_perf_tbl[i - 1])
|
|
+ if (freq <= 0 ||
|
|
+ (i > 0 && freq == se->clk_perf_tbl[i - 1]))
|
|
break;
|
|
se->clk_perf_tbl[i] = freq;
|
|
}
|
|
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
|
|
index 880b41a57da019..2af2b2406fdf39 100644
|
|
--- a/drivers/soc/qcom/socinfo.c
|
|
+++ b/drivers/soc/qcom/socinfo.c
|
|
@@ -757,10 +757,16 @@ static int qcom_socinfo_probe(struct platform_device *pdev)
|
|
qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u",
|
|
SOCINFO_MAJOR(le32_to_cpu(info->ver)),
|
|
SOCINFO_MINOR(le32_to_cpu(info->ver)));
|
|
- if (offsetof(struct socinfo, serial_num) <= item_size)
|
|
+ if (!qs->attr.soc_id || !qs->attr.revision)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ if (offsetof(struct socinfo, serial_num) <= item_size) {
|
|
qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
|
"%u",
|
|
le32_to_cpu(info->serial_num));
|
|
+ if (!qs->attr.serial_number)
|
|
+ return -ENOMEM;
|
|
+ }
|
|
|
|
qs->soc_dev = soc_device_register(&qs->attr);
|
|
if (IS_ERR(qs->soc_dev))
|
|
diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c
|
|
index 62b2f1464e4674..55c48ddcf50da4 100644
|
|
--- a/drivers/soc/ti/smartreflex.c
|
|
+++ b/drivers/soc/ti/smartreflex.c
|
|
@@ -202,10 +202,10 @@ static int sr_late_init(struct omap_sr *sr_info)
|
|
|
|
if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
|
|
ret = devm_request_irq(&sr_info->pdev->dev, sr_info->irq,
|
|
- sr_interrupt, 0, sr_info->name, sr_info);
|
|
+ sr_interrupt, IRQF_NO_AUTOEN,
|
|
+ sr_info->name, sr_info);
|
|
if (ret)
|
|
goto error;
|
|
- disable_irq(sr_info->irq);
|
|
}
|
|
|
|
return ret;
|
|
diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c
|
|
index 098a2ecfd5c689..8f6a2614d8eb41 100644
|
|
--- a/drivers/soc/xilinx/xlnx_event_manager.c
|
|
+++ b/drivers/soc/xilinx/xlnx_event_manager.c
|
|
@@ -174,8 +174,10 @@ static int xlnx_add_cb_for_suspend(event_cb_func_t cb_fun, void *data)
|
|
INIT_LIST_HEAD(&eve_data->cb_list_head);
|
|
|
|
cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL);
|
|
- if (!cb_data)
|
|
+ if (!cb_data) {
|
|
+ kfree(eve_data);
|
|
return -ENOMEM;
|
|
+ }
|
|
cb_data->eve_cb = cb_fun;
|
|
cb_data->agent_data = data;
|
|
|
|
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
|
|
index 6f9e9d87167758..e7ae7cb4b92a8b 100644
|
|
--- a/drivers/spi/atmel-quadspi.c
|
|
+++ b/drivers/spi/atmel-quadspi.c
|
|
@@ -183,7 +183,7 @@ static const char *atmel_qspi_reg_name(u32 offset, char *tmp, size_t sz)
|
|
case QSPI_MR:
|
|
return "MR";
|
|
case QSPI_RD:
|
|
- return "MR";
|
|
+ return "RD";
|
|
case QSPI_TD:
|
|
return "TD";
|
|
case QSPI_SR:
|
|
diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
|
|
index 13313f07839b6f..514a2c5c84226c 100644
|
|
--- a/drivers/spi/spi-fsl-lpspi.c
|
|
+++ b/drivers/spi/spi-fsl-lpspi.c
|
|
@@ -891,7 +891,7 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
|
|
return ret;
|
|
}
|
|
|
|
- ret = devm_request_irq(&pdev->dev, irq, fsl_lpspi_isr, 0,
|
|
+ ret = devm_request_irq(&pdev->dev, irq, fsl_lpspi_isr, IRQF_NO_AUTOEN,
|
|
dev_name(&pdev->dev), fsl_lpspi);
|
|
if (ret) {
|
|
dev_err(&pdev->dev, "can't get irq%d: %d\n", irq, ret);
|
|
@@ -948,14 +948,10 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
|
|
ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller);
|
|
if (ret == -EPROBE_DEFER)
|
|
goto out_pm_get;
|
|
- if (ret < 0)
|
|
+ if (ret < 0) {
|
|
dev_warn(&pdev->dev, "dma setup error %d, use pio\n", ret);
|
|
- else
|
|
- /*
|
|
- * disable LPSPI module IRQ when enable DMA mode successfully,
|
|
- * to prevent the unexpected LPSPI module IRQ events.
|
|
- */
|
|
- disable_irq(irq);
|
|
+ enable_irq(irq);
|
|
+ }
|
|
|
|
ret = devm_spi_register_controller(&pdev->dev, controller);
|
|
if (ret < 0) {
|
|
diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c
|
|
index e9ad9b0b598b50..d1afa4140e8a26 100644
|
|
--- a/drivers/spi/spi-tegra210-quad.c
|
|
+++ b/drivers/spi/spi-tegra210-quad.c
|
|
@@ -341,7 +341,7 @@ tegra_qspi_fill_tx_fifo_from_client_txbuf(struct tegra_qspi *tqspi, struct spi_t
|
|
for (count = 0; count < max_n_32bit; count++) {
|
|
u32 x = 0;
|
|
|
|
- for (i = 0; len && (i < bytes_per_word); i++, len--)
|
|
+ for (i = 0; len && (i < min(4, bytes_per_word)); i++, len--)
|
|
x |= (u32)(*tx_buf++) << (i * 8);
|
|
tegra_qspi_writel(tqspi, x, QSPI_TX_FIFO);
|
|
}
|
|
diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
|
|
index 9a46b2478f4e98..3503e6c0a5c983 100644
|
|
--- a/drivers/spi/spi-zynqmp-gqspi.c
|
|
+++ b/drivers/spi/spi-zynqmp-gqspi.c
|
|
@@ -1341,6 +1341,7 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
|
|
|
|
clk_dis_all:
|
|
pm_runtime_disable(&pdev->dev);
|
|
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
|
|
pm_runtime_put_noidle(&pdev->dev);
|
|
pm_runtime_set_suspended(&pdev->dev);
|
|
clk_disable_unprepare(xqspi->refclk);
|
|
@@ -1371,6 +1372,7 @@ static void zynqmp_qspi_remove(struct platform_device *pdev)
|
|
zynqmp_gqspi_write(xqspi, GQSPI_EN_OFST, 0x0);
|
|
|
|
pm_runtime_disable(&pdev->dev);
|
|
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
|
|
pm_runtime_put_noidle(&pdev->dev);
|
|
pm_runtime_set_suspended(&pdev->dev);
|
|
clk_disable_unprepare(xqspi->refclk);
|
|
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
|
|
index 5c57c7378ee708..72e514cee056dd 100644
|
|
--- a/drivers/spi/spi.c
|
|
+++ b/drivers/spi/spi.c
|
|
@@ -426,6 +426,16 @@ static int spi_probe(struct device *dev)
|
|
spi->irq = 0;
|
|
}
|
|
|
|
+ if (has_acpi_companion(dev) && spi->irq < 0) {
|
|
+ struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
|
|
+
|
|
+ spi->irq = acpi_dev_gpio_irq_get(adev, 0);
|
|
+ if (spi->irq == -EPROBE_DEFER)
|
|
+ return -EPROBE_DEFER;
|
|
+ if (spi->irq < 0)
|
|
+ spi->irq = 0;
|
|
+ }
|
|
+
|
|
ret = dev_pm_domain_attach(dev, true);
|
|
if (ret)
|
|
return ret;
|
|
@@ -2706,9 +2716,6 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
|
|
acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias,
|
|
sizeof(spi->modalias));
|
|
|
|
- if (spi->irq < 0)
|
|
- spi->irq = acpi_dev_gpio_irq_get(adev, 0);
|
|
-
|
|
acpi_device_set_enumerated(adev);
|
|
|
|
adev->power.flags.ignore_parent = true;
|
|
diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c
|
|
index 588f2adab058cd..760fe9bef21190 100644
|
|
--- a/drivers/staging/media/atomisp/pci/sh_css_params.c
|
|
+++ b/drivers/staging/media/atomisp/pci/sh_css_params.c
|
|
@@ -4144,6 +4144,8 @@ ia_css_3a_statistics_allocate(const struct ia_css_3a_grid_info *grid)
|
|
goto err;
|
|
/* No weighted histogram, no structure, treat the histogram data as a byte dump in a byte array */
|
|
me->rgby_data = kvmalloc(sizeof_hmem(HMEM0_ID), GFP_KERNEL);
|
|
+ if (!me->rgby_data)
|
|
+ goto err;
|
|
|
|
IA_CSS_LEAVE("return=%p", me);
|
|
return me;
|
|
diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
|
|
index ffc2871a021cf6..f252bac676bcaf 100644
|
|
--- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
|
|
+++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
|
|
@@ -144,7 +144,7 @@ static ssize_t current_uuid_show(struct device *dev,
|
|
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
|
|
int i, length = 0;
|
|
|
|
- if (priv->current_uuid_index > 0)
|
|
+ if (priv->current_uuid_index >= 0)
|
|
return sprintf(buf, "%s\n",
|
|
int3400_thermal_uuids[priv->current_uuid_index]);
|
|
|
|
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
|
|
index d7ac7eef680e12..dad909547179f8 100644
|
|
--- a/drivers/thermal/thermal_core.c
|
|
+++ b/drivers/thermal/thermal_core.c
|
|
@@ -1336,6 +1336,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
|
|
thermal_zone_destroy_device_groups(tz);
|
|
goto remove_id;
|
|
}
|
|
+ thermal_zone_device_init(tz);
|
|
result = device_register(&tz->device);
|
|
if (result)
|
|
goto release_device;
|
|
@@ -1381,7 +1382,6 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
|
|
|
|
INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
|
|
|
|
- thermal_zone_device_init(tz);
|
|
/* Update the new thermal zone and mark it as already updated. */
|
|
if (atomic_cmpxchg(&tz->need_update, 1, 0))
|
|
thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
|
|
diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c
|
|
index e2aa2a1a02ddf5..ecbce226b8747e 100644
|
|
--- a/drivers/tty/serial/8250/8250_fintek.c
|
|
+++ b/drivers/tty/serial/8250/8250_fintek.c
|
|
@@ -21,6 +21,7 @@
|
|
#define CHIP_ID_F81866 0x1010
|
|
#define CHIP_ID_F81966 0x0215
|
|
#define CHIP_ID_F81216AD 0x1602
|
|
+#define CHIP_ID_F81216E 0x1617
|
|
#define CHIP_ID_F81216H 0x0501
|
|
#define CHIP_ID_F81216 0x0802
|
|
#define VENDOR_ID1 0x23
|
|
@@ -158,6 +159,7 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata)
|
|
case CHIP_ID_F81866:
|
|
case CHIP_ID_F81966:
|
|
case CHIP_ID_F81216AD:
|
|
+ case CHIP_ID_F81216E:
|
|
case CHIP_ID_F81216H:
|
|
case CHIP_ID_F81216:
|
|
break;
|
|
@@ -181,6 +183,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min,
|
|
return 0;
|
|
|
|
case CHIP_ID_F81216AD:
|
|
+ case CHIP_ID_F81216E:
|
|
case CHIP_ID_F81216H:
|
|
case CHIP_ID_F81216:
|
|
*min = F81216_LDN_LOW;
|
|
@@ -250,6 +253,7 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level)
|
|
break;
|
|
|
|
case CHIP_ID_F81216AD:
|
|
+ case CHIP_ID_F81216E:
|
|
case CHIP_ID_F81216H:
|
|
case CHIP_ID_F81216:
|
|
sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE,
|
|
@@ -263,7 +267,8 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level)
|
|
static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata)
|
|
{
|
|
switch (pdata->pid) {
|
|
- case CHIP_ID_F81216H: /* 128Bytes FIFO */
|
|
+ case CHIP_ID_F81216E: /* 128Bytes FIFO */
|
|
+ case CHIP_ID_F81216H:
|
|
case CHIP_ID_F81966:
|
|
case CHIP_ID_F81866:
|
|
sio_write_mask_reg(pdata, FIFO_CTRL,
|
|
@@ -297,6 +302,7 @@ static void fintek_8250_set_termios(struct uart_port *port,
|
|
goto exit;
|
|
|
|
switch (pdata->pid) {
|
|
+ case CHIP_ID_F81216E:
|
|
case CHIP_ID_F81216H:
|
|
reg = RS485;
|
|
break;
|
|
@@ -346,6 +352,7 @@ static void fintek_8250_set_termios_handler(struct uart_8250_port *uart)
|
|
struct fintek_8250 *pdata = uart->port.private_data;
|
|
|
|
switch (pdata->pid) {
|
|
+ case CHIP_ID_F81216E:
|
|
case CHIP_ID_F81216H:
|
|
case CHIP_ID_F81966:
|
|
case CHIP_ID_F81866:
|
|
@@ -438,6 +445,11 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart)
|
|
uart->port.rs485_supported = fintek_8250_rs485_supported;
|
|
break;
|
|
|
|
+ case CHIP_ID_F81216E: /* F81216E does not support RS485 delays */
|
|
+ uart->port.rs485_config = fintek_8250_rs485_config;
|
|
+ uart->port.rs485_supported = fintek_8250_rs485_supported;
|
|
+ break;
|
|
+
|
|
default: /* No RS485 Auto direction functional */
|
|
break;
|
|
}
|
|
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
|
|
index 4caecc3525bfd1..9ed62bc7cdd83a 100644
|
|
--- a/drivers/tty/serial/8250/8250_omap.c
|
|
+++ b/drivers/tty/serial/8250/8250_omap.c
|
|
@@ -766,12 +766,12 @@ static void omap_8250_shutdown(struct uart_port *port)
|
|
struct uart_8250_port *up = up_to_u8250p(port);
|
|
struct omap8250_priv *priv = port->private_data;
|
|
|
|
+ pm_runtime_get_sync(port->dev);
|
|
+
|
|
flush_work(&priv->qos_work);
|
|
if (up->dma)
|
|
omap_8250_rx_dma_flush(up);
|
|
|
|
- pm_runtime_get_sync(port->dev);
|
|
-
|
|
serial_out(up, UART_OMAP_WER, 0);
|
|
if (priv->habit & UART_HAS_EFR2)
|
|
serial_out(up, UART_OMAP_EFR2, 0x0);
|
|
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
|
|
index 7a9924d9b294e9..f290fbe21d633e 100644
|
|
--- a/drivers/tty/serial/sc16is7xx.c
|
|
+++ b/drivers/tty/serial/sc16is7xx.c
|
|
@@ -545,6 +545,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
|
|
SC16IS7XX_MCR_CLKSEL_BIT,
|
|
prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT);
|
|
|
|
+ mutex_lock(&one->efr_lock);
|
|
+
|
|
/* Open the LCR divisors for configuration */
|
|
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
|
|
SC16IS7XX_LCR_CONF_MODE_A);
|
|
@@ -558,6 +560,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
|
|
/* Put LCR back to the normal mode */
|
|
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
|
|
|
|
+ mutex_unlock(&one->efr_lock);
|
|
+
|
|
return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div);
|
|
}
|
|
|
|
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
|
|
index 493fc4742895f1..117abcf366d95f 100644
|
|
--- a/drivers/tty/tty_io.c
|
|
+++ b/drivers/tty/tty_io.c
|
|
@@ -3607,7 +3607,7 @@ static struct ctl_table tty_table[] = {
|
|
.data = &tty_ldisc_autoload,
|
|
.maxlen = sizeof(tty_ldisc_autoload),
|
|
.mode = 0644,
|
|
- .proc_handler = proc_dointvec,
|
|
+ .proc_handler = proc_dointvec_minmax,
|
|
.extra1 = SYSCTL_ZERO,
|
|
.extra2 = SYSCTL_ONE,
|
|
},
|
|
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
|
|
index 3396e0388512c7..268189f01e15bc 100644
|
|
--- a/drivers/ufs/host/ufs-exynos.c
|
|
+++ b/drivers/ufs/host/ufs-exynos.c
|
|
@@ -1228,12 +1228,12 @@ static void exynos_ufs_dev_hw_reset(struct ufs_hba *hba)
|
|
hci_writel(ufs, 1 << 0, HCI_GPIO_OUT);
|
|
}
|
|
|
|
-static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, u8 enter)
|
|
+static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, enum uic_cmd_dme cmd)
|
|
{
|
|
struct exynos_ufs *ufs = ufshcd_get_variant(hba);
|
|
struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
|
|
|
|
- if (!enter) {
|
|
+ if (cmd == UIC_CMD_DME_HIBER_EXIT) {
|
|
if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL)
|
|
exynos_ufs_disable_auto_ctrl_hcc(ufs);
|
|
exynos_ufs_ungate_clks(ufs);
|
|
@@ -1261,11 +1261,11 @@ static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, u8 enter)
|
|
}
|
|
}
|
|
|
|
-static void exynos_ufs_post_hibern8(struct ufs_hba *hba, u8 enter)
|
|
+static void exynos_ufs_post_hibern8(struct ufs_hba *hba, enum uic_cmd_dme cmd)
|
|
{
|
|
struct exynos_ufs *ufs = ufshcd_get_variant(hba);
|
|
|
|
- if (!enter) {
|
|
+ if (cmd == UIC_CMD_DME_HIBER_EXIT) {
|
|
u32 cur_mode = 0;
|
|
u32 pwrmode;
|
|
|
|
@@ -1284,7 +1284,7 @@ static void exynos_ufs_post_hibern8(struct ufs_hba *hba, u8 enter)
|
|
|
|
if (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB))
|
|
exynos_ufs_establish_connt(ufs);
|
|
- } else {
|
|
+ } else if (cmd == UIC_CMD_DME_HIBER_ENTER) {
|
|
ufs->entry_hibern8_t = ktime_get();
|
|
exynos_ufs_gate_clks(ufs);
|
|
if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL)
|
|
@@ -1371,15 +1371,15 @@ static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba,
|
|
}
|
|
|
|
static void exynos_ufs_hibern8_notify(struct ufs_hba *hba,
|
|
- enum uic_cmd_dme enter,
|
|
+ enum uic_cmd_dme cmd,
|
|
enum ufs_notify_change_status notify)
|
|
{
|
|
switch ((u8)notify) {
|
|
case PRE_CHANGE:
|
|
- exynos_ufs_pre_hibern8(hba, enter);
|
|
+ exynos_ufs_pre_hibern8(hba, cmd);
|
|
break;
|
|
case POST_CHANGE:
|
|
- exynos_ufs_post_hibern8(hba, enter);
|
|
+ exynos_ufs_post_hibern8(hba, cmd);
|
|
break;
|
|
}
|
|
}
|
|
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
|
|
index 867000cdeb9653..9971076c31de64 100644
|
|
--- a/drivers/usb/dwc3/gadget.c
|
|
+++ b/drivers/usb/dwc3/gadget.c
|
|
@@ -1196,11 +1196,14 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
|
|
* pending to be processed by the driver.
|
|
*/
|
|
if (dep->trb_enqueue == dep->trb_dequeue) {
|
|
+ struct dwc3_request *req;
|
|
+
|
|
/*
|
|
- * If there is any request remained in the started_list at
|
|
- * this point, that means there is no TRB available.
|
|
+ * If there is any request remained in the started_list with
|
|
+ * active TRBs at this point, then there is no TRB available.
|
|
*/
|
|
- if (!list_empty(&dep->started_list))
|
|
+ req = next_request(&dep->started_list);
|
|
+ if (req && req->num_trbs)
|
|
return 0;
|
|
|
|
return DWC3_TRB_NUM - 1;
|
|
@@ -1433,8 +1436,8 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
|
|
struct scatterlist *s;
|
|
int i;
|
|
unsigned int length = req->request.length;
|
|
- unsigned int remaining = req->request.num_mapped_sgs
|
|
- - req->num_queued_sgs;
|
|
+ unsigned int remaining = req->num_pending_sgs;
|
|
+ unsigned int num_queued_sgs = req->request.num_mapped_sgs - remaining;
|
|
unsigned int num_trbs = req->num_trbs;
|
|
bool needs_extra_trb = dwc3_needs_extra_trb(dep, req);
|
|
|
|
@@ -1442,7 +1445,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
|
|
* If we resume preparing the request, then get the remaining length of
|
|
* the request and resume where we left off.
|
|
*/
|
|
- for_each_sg(req->request.sg, s, req->num_queued_sgs, i)
|
|
+ for_each_sg(req->request.sg, s, num_queued_sgs, i)
|
|
length -= sg_dma_len(s);
|
|
|
|
for_each_sg(sg, s, remaining, i) {
|
|
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
|
|
index 0e151b54aae82a..9225c21d118453 100644
|
|
--- a/drivers/usb/gadget/composite.c
|
|
+++ b/drivers/usb/gadget/composite.c
|
|
@@ -2111,8 +2111,20 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|
memset(buf, 0, w_length);
|
|
buf[5] = 0x01;
|
|
switch (ctrl->bRequestType & USB_RECIP_MASK) {
|
|
+ /*
|
|
+ * The Microsoft CompatID OS Descriptor Spec(w_index = 0x4) and
|
|
+ * Extended Prop OS Desc Spec(w_index = 0x5) state that the
|
|
+ * HighByte of wValue is the InterfaceNumber and the LowByte is
|
|
+ * the PageNumber. This high/low byte ordering is incorrectly
|
|
+ * documented in the Spec. USB analyzer output on the below
|
|
+ * request packets show the high/low byte inverted i.e LowByte
|
|
+ * is the InterfaceNumber and the HighByte is the PageNumber.
|
|
+ * Since we dont support >64KB CompatID/ExtendedProp descriptors,
|
|
+ * PageNumber is set to 0. Hence verify that the HighByte is 0
|
|
+ * for below two cases.
|
|
+ */
|
|
case USB_RECIP_DEVICE:
|
|
- if (w_index != 0x4 || (w_value & 0xff))
|
|
+ if (w_index != 0x4 || (w_value >> 8))
|
|
break;
|
|
buf[6] = w_index;
|
|
/* Number of ext compat interfaces */
|
|
@@ -2128,9 +2140,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|
}
|
|
break;
|
|
case USB_RECIP_INTERFACE:
|
|
- if (w_index != 0x5 || (w_value & 0xff))
|
|
+ if (w_index != 0x5 || (w_value >> 8))
|
|
break;
|
|
- interface = w_value >> 8;
|
|
+ interface = w_value & 0xFF;
|
|
if (interface >= MAX_CONFIG_INTERFACES ||
|
|
!os_desc_cfg->interface[interface])
|
|
break;
|
|
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
|
|
index d0e94e4c9fe274..11294f196ee335 100644
|
|
--- a/drivers/usb/host/ehci-spear.c
|
|
+++ b/drivers/usb/host/ehci-spear.c
|
|
@@ -105,7 +105,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
|
|
/* registers start at offset 0x0 */
|
|
hcd_to_ehci(hcd)->caps = hcd->regs;
|
|
|
|
- clk_prepare_enable(sehci->clk);
|
|
+ retval = clk_prepare_enable(sehci->clk);
|
|
+ if (retval)
|
|
+ goto err_put_hcd;
|
|
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
|
if (retval)
|
|
goto err_stop_ehci;
|
|
@@ -130,8 +132,7 @@ static void spear_ehci_hcd_drv_remove(struct platform_device *pdev)
|
|
|
|
usb_remove_hcd(hcd);
|
|
|
|
- if (sehci->clk)
|
|
- clk_disable_unprepare(sehci->clk);
|
|
+ clk_disable_unprepare(sehci->clk);
|
|
usb_put_hcd(hcd);
|
|
}
|
|
|
|
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
|
|
index 6e38b6b480e098..258e64d6522c65 100644
|
|
--- a/drivers/usb/host/xhci-ring.c
|
|
+++ b/drivers/usb/host/xhci-ring.c
|
|
@@ -994,6 +994,13 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
|
|
unsigned int slot_id = ep->vdev->slot_id;
|
|
int err;
|
|
|
|
+ /*
|
|
+ * This is not going to work if the hardware is changing its dequeue
|
|
+ * pointers as we look at them. Completion handler will call us later.
|
|
+ */
|
|
+ if (ep->ep_state & SET_DEQ_PENDING)
|
|
+ return 0;
|
|
+
|
|
xhci = ep->xhci;
|
|
|
|
list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
|
|
@@ -1354,7 +1361,6 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
|
|
struct xhci_ep_ctx *ep_ctx;
|
|
struct xhci_slot_ctx *slot_ctx;
|
|
struct xhci_td *td, *tmp_td;
|
|
- bool deferred = false;
|
|
|
|
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
|
|
stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
|
|
@@ -1455,8 +1461,6 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
|
|
xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n",
|
|
__func__, td->urb);
|
|
xhci_td_cleanup(ep->xhci, td, ep_ring, td->status);
|
|
- } else if (td->cancel_status == TD_CLEARING_CACHE_DEFERRED) {
|
|
- deferred = true;
|
|
} else {
|
|
xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n",
|
|
__func__, td->urb, td->cancel_status);
|
|
@@ -1467,11 +1471,15 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
|
|
ep->queued_deq_seg = NULL;
|
|
ep->queued_deq_ptr = NULL;
|
|
|
|
- if (deferred) {
|
|
- /* We have more streams to clear */
|
|
+ /* Check for deferred or newly cancelled TDs */
|
|
+ if (!list_empty(&ep->cancelled_td_list)) {
|
|
xhci_dbg(ep->xhci, "%s: Pending TDs to clear, continuing with invalidation\n",
|
|
__func__);
|
|
xhci_invalidate_cancelled_tds(ep);
|
|
+ /* Try to restart the endpoint if all is done */
|
|
+ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
|
|
+ /* Start giving back any TDs invalidated above */
|
|
+ xhci_giveback_invalidated_tds(ep);
|
|
} else {
|
|
/* Restart any rings with pending URBs */
|
|
xhci_dbg(ep->xhci, "%s: All TDs cleared, ring doorbell\n", __func__);
|
|
diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
|
|
index 6fb5140e29b9dd..225863321dc479 100644
|
|
--- a/drivers/usb/misc/chaoskey.c
|
|
+++ b/drivers/usb/misc/chaoskey.c
|
|
@@ -27,6 +27,8 @@ static struct usb_class_driver chaoskey_class;
|
|
static int chaoskey_rng_read(struct hwrng *rng, void *data,
|
|
size_t max, bool wait);
|
|
|
|
+static DEFINE_MUTEX(chaoskey_list_lock);
|
|
+
|
|
#define usb_dbg(usb_if, format, arg...) \
|
|
dev_dbg(&(usb_if)->dev, format, ## arg)
|
|
|
|
@@ -233,6 +235,7 @@ static void chaoskey_disconnect(struct usb_interface *interface)
|
|
usb_deregister_dev(interface, &chaoskey_class);
|
|
|
|
usb_set_intfdata(interface, NULL);
|
|
+ mutex_lock(&chaoskey_list_lock);
|
|
mutex_lock(&dev->lock);
|
|
|
|
dev->present = false;
|
|
@@ -244,6 +247,7 @@ static void chaoskey_disconnect(struct usb_interface *interface)
|
|
} else
|
|
mutex_unlock(&dev->lock);
|
|
|
|
+ mutex_unlock(&chaoskey_list_lock);
|
|
usb_dbg(interface, "disconnect done");
|
|
}
|
|
|
|
@@ -251,6 +255,7 @@ static int chaoskey_open(struct inode *inode, struct file *file)
|
|
{
|
|
struct chaoskey *dev;
|
|
struct usb_interface *interface;
|
|
+ int rv = 0;
|
|
|
|
/* get the interface from minor number and driver information */
|
|
interface = usb_find_interface(&chaoskey_driver, iminor(inode));
|
|
@@ -266,18 +271,23 @@ static int chaoskey_open(struct inode *inode, struct file *file)
|
|
}
|
|
|
|
file->private_data = dev;
|
|
+ mutex_lock(&chaoskey_list_lock);
|
|
mutex_lock(&dev->lock);
|
|
- ++dev->open;
|
|
+ if (dev->present)
|
|
+ ++dev->open;
|
|
+ else
|
|
+ rv = -ENODEV;
|
|
mutex_unlock(&dev->lock);
|
|
+ mutex_unlock(&chaoskey_list_lock);
|
|
|
|
- usb_dbg(interface, "open success");
|
|
- return 0;
|
|
+ return rv;
|
|
}
|
|
|
|
static int chaoskey_release(struct inode *inode, struct file *file)
|
|
{
|
|
struct chaoskey *dev = file->private_data;
|
|
struct usb_interface *interface;
|
|
+ int rv = 0;
|
|
|
|
if (dev == NULL)
|
|
return -ENODEV;
|
|
@@ -286,14 +296,15 @@ static int chaoskey_release(struct inode *inode, struct file *file)
|
|
|
|
usb_dbg(interface, "release");
|
|
|
|
+ mutex_lock(&chaoskey_list_lock);
|
|
mutex_lock(&dev->lock);
|
|
|
|
usb_dbg(interface, "open count at release is %d", dev->open);
|
|
|
|
if (dev->open <= 0) {
|
|
usb_dbg(interface, "invalid open count (%d)", dev->open);
|
|
- mutex_unlock(&dev->lock);
|
|
- return -ENODEV;
|
|
+ rv = -ENODEV;
|
|
+ goto bail;
|
|
}
|
|
|
|
--dev->open;
|
|
@@ -302,13 +313,15 @@ static int chaoskey_release(struct inode *inode, struct file *file)
|
|
if (dev->open == 0) {
|
|
mutex_unlock(&dev->lock);
|
|
chaoskey_free(dev);
|
|
- } else
|
|
- mutex_unlock(&dev->lock);
|
|
- } else
|
|
- mutex_unlock(&dev->lock);
|
|
-
|
|
+ goto destruction;
|
|
+ }
|
|
+ }
|
|
+bail:
|
|
+ mutex_unlock(&dev->lock);
|
|
+destruction:
|
|
+ mutex_unlock(&chaoskey_list_lock);
|
|
usb_dbg(interface, "release success");
|
|
- return 0;
|
|
+ return rv;
|
|
}
|
|
|
|
static void chaos_read_callback(struct urb *urb)
|
|
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
|
|
index 1e3df27bab58fd..4fae04094021e3 100644
|
|
--- a/drivers/usb/misc/iowarrior.c
|
|
+++ b/drivers/usb/misc/iowarrior.c
|
|
@@ -277,28 +277,45 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer,
|
|
struct iowarrior *dev;
|
|
int read_idx;
|
|
int offset;
|
|
+ int retval;
|
|
|
|
dev = file->private_data;
|
|
|
|
+ if (file->f_flags & O_NONBLOCK) {
|
|
+ retval = mutex_trylock(&dev->mutex);
|
|
+ if (!retval)
|
|
+ return -EAGAIN;
|
|
+ } else {
|
|
+ retval = mutex_lock_interruptible(&dev->mutex);
|
|
+ if (retval)
|
|
+ return -ERESTARTSYS;
|
|
+ }
|
|
+
|
|
/* verify that the device wasn't unplugged */
|
|
- if (!dev || !dev->present)
|
|
- return -ENODEV;
|
|
+ if (!dev->present) {
|
|
+ retval = -ENODEV;
|
|
+ goto exit;
|
|
+ }
|
|
|
|
dev_dbg(&dev->interface->dev, "minor %d, count = %zd\n",
|
|
dev->minor, count);
|
|
|
|
/* read count must be packet size (+ time stamp) */
|
|
if ((count != dev->report_size)
|
|
- && (count != (dev->report_size + 1)))
|
|
- return -EINVAL;
|
|
+ && (count != (dev->report_size + 1))) {
|
|
+ retval = -EINVAL;
|
|
+ goto exit;
|
|
+ }
|
|
|
|
/* repeat until no buffer overrun in callback handler occur */
|
|
do {
|
|
atomic_set(&dev->overflow_flag, 0);
|
|
if ((read_idx = read_index(dev)) == -1) {
|
|
/* queue empty */
|
|
- if (file->f_flags & O_NONBLOCK)
|
|
- return -EAGAIN;
|
|
+ if (file->f_flags & O_NONBLOCK) {
|
|
+ retval = -EAGAIN;
|
|
+ goto exit;
|
|
+ }
|
|
else {
|
|
//next line will return when there is either new data, or the device is unplugged
|
|
int r = wait_event_interruptible(dev->read_wait,
|
|
@@ -309,28 +326,37 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer,
|
|
-1));
|
|
if (r) {
|
|
//we were interrupted by a signal
|
|
- return -ERESTART;
|
|
+ retval = -ERESTART;
|
|
+ goto exit;
|
|
}
|
|
if (!dev->present) {
|
|
//The device was unplugged
|
|
- return -ENODEV;
|
|
+ retval = -ENODEV;
|
|
+ goto exit;
|
|
}
|
|
if (read_idx == -1) {
|
|
// Can this happen ???
|
|
- return 0;
|
|
+ retval = 0;
|
|
+ goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
offset = read_idx * (dev->report_size + 1);
|
|
if (copy_to_user(buffer, dev->read_queue + offset, count)) {
|
|
- return -EFAULT;
|
|
+ retval = -EFAULT;
|
|
+ goto exit;
|
|
}
|
|
} while (atomic_read(&dev->overflow_flag));
|
|
|
|
read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
|
|
atomic_set(&dev->read_idx, read_idx);
|
|
+ mutex_unlock(&dev->mutex);
|
|
return count;
|
|
+
|
|
+exit:
|
|
+ mutex_unlock(&dev->mutex);
|
|
+ return retval;
|
|
}
|
|
|
|
/*
|
|
@@ -886,7 +912,6 @@ static int iowarrior_probe(struct usb_interface *interface,
|
|
static void iowarrior_disconnect(struct usb_interface *interface)
|
|
{
|
|
struct iowarrior *dev = usb_get_intfdata(interface);
|
|
- int minor = dev->minor;
|
|
|
|
usb_deregister_dev(interface, &iowarrior_class);
|
|
|
|
@@ -910,9 +935,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
|
|
mutex_unlock(&dev->mutex);
|
|
iowarrior_delete(dev);
|
|
}
|
|
-
|
|
- dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
|
|
- minor - IOWARRIOR_MINOR_BASE);
|
|
}
|
|
|
|
/* usb specific object needed to register this driver with the usb subsystem */
|
|
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
|
|
index c313cd41f7a5a5..0eed614ac12739 100644
|
|
--- a/drivers/usb/misc/yurex.c
|
|
+++ b/drivers/usb/misc/yurex.c
|
|
@@ -441,7 +441,10 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer,
|
|
if (count == 0)
|
|
goto error;
|
|
|
|
- mutex_lock(&dev->io_mutex);
|
|
+ retval = mutex_lock_interruptible(&dev->io_mutex);
|
|
+ if (retval < 0)
|
|
+ return -EINTR;
|
|
+
|
|
if (dev->disconnected) { /* already disconnected */
|
|
mutex_unlock(&dev->io_mutex);
|
|
retval = -ENODEV;
|
|
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
|
|
index 051c6da7cf6d74..f175cb2c3e7bd2 100644
|
|
--- a/drivers/usb/musb/musb_gadget.c
|
|
+++ b/drivers/usb/musb/musb_gadget.c
|
|
@@ -1170,12 +1170,19 @@ struct free_record {
|
|
*/
|
|
void musb_ep_restart(struct musb *musb, struct musb_request *req)
|
|
{
|
|
+ u16 csr;
|
|
+ void __iomem *epio = req->ep->hw_ep->regs;
|
|
+
|
|
trace_musb_req_start(req);
|
|
musb_ep_select(musb->mregs, req->epnum);
|
|
- if (req->tx)
|
|
+ if (req->tx) {
|
|
txstate(musb, req);
|
|
- else
|
|
- rxstate(musb, req);
|
|
+ } else {
|
|
+ csr = musb_readw(epio, MUSB_RXCSR);
|
|
+ csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_P_WZC_BITS;
|
|
+ musb_writew(epio, MUSB_RXCSR, csr);
|
|
+ musb_writew(epio, MUSB_RXCSR, csr);
|
|
+ }
|
|
}
|
|
|
|
static int musb_ep_restart_resume_work(struct musb *musb, void *data)
|
|
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
|
|
index 64bdba7ea9938a..afb7192adc8e68 100644
|
|
--- a/drivers/usb/typec/class.c
|
|
+++ b/drivers/usb/typec/class.c
|
|
@@ -2147,14 +2147,16 @@ void typec_port_register_altmodes(struct typec_port *port,
|
|
const struct typec_altmode_ops *ops, void *drvdata,
|
|
struct typec_altmode **altmodes, size_t n)
|
|
{
|
|
- struct fwnode_handle *altmodes_node, *child;
|
|
+ struct fwnode_handle *child;
|
|
struct typec_altmode_desc desc;
|
|
struct typec_altmode *alt;
|
|
size_t index = 0;
|
|
u32 svid, vdo;
|
|
int ret;
|
|
|
|
- altmodes_node = device_get_named_child_node(&port->dev, "altmodes");
|
|
+ struct fwnode_handle *altmodes_node __free(fwnode_handle) =
|
|
+ device_get_named_child_node(&port->dev, "altmodes");
|
|
+
|
|
if (!altmodes_node)
|
|
return; /* No altmodes specified */
|
|
|
|
diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c
|
|
index 87d4abde0ea279..e08244f555f039 100644
|
|
--- a/drivers/usb/typec/tcpm/wcove.c
|
|
+++ b/drivers/usb/typec/tcpm/wcove.c
|
|
@@ -621,10 +621,6 @@ static int wcove_typec_probe(struct platform_device *pdev)
|
|
if (irq < 0)
|
|
return irq;
|
|
|
|
- irq = regmap_irq_get_virq(pmic->irq_chip_data_chgr, irq);
|
|
- if (irq < 0)
|
|
- return irq;
|
|
-
|
|
ret = guid_parse(WCOVE_DSM_UUID, &wcove->guid);
|
|
if (ret)
|
|
return ret;
|
|
diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
|
|
index 59fa9f3d5ec873..aa4ab4c847fdcc 100644
|
|
--- a/drivers/vdpa/mlx5/core/mr.c
|
|
+++ b/drivers/vdpa/mlx5/core/mr.c
|
|
@@ -227,7 +227,6 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr
|
|
unsigned long lgcd = 0;
|
|
int log_entity_size;
|
|
unsigned long size;
|
|
- u64 start = 0;
|
|
int err;
|
|
struct page *pg;
|
|
unsigned int nsg;
|
|
@@ -238,10 +237,9 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr
|
|
struct device *dma = mvdev->vdev.dma_dev;
|
|
|
|
for (map = vhost_iotlb_itree_first(iotlb, mr->start, mr->end - 1);
|
|
- map; map = vhost_iotlb_itree_next(map, start, mr->end - 1)) {
|
|
+ map; map = vhost_iotlb_itree_next(map, mr->start, mr->end - 1)) {
|
|
size = maplen(map, mr);
|
|
lgcd = gcd(lgcd, size);
|
|
- start += size;
|
|
}
|
|
log_entity_size = ilog2(lgcd);
|
|
|
|
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
|
|
index 7e2e62ab0869cf..a2ad4f7c716bf3 100644
|
|
--- a/drivers/vfio/pci/vfio_pci_config.c
|
|
+++ b/drivers/vfio/pci/vfio_pci_config.c
|
|
@@ -313,6 +313,10 @@ static int vfio_virt_config_read(struct vfio_pci_core_device *vdev, int pos,
|
|
return count;
|
|
}
|
|
|
|
+static struct perm_bits direct_ro_perms = {
|
|
+ .readfn = vfio_direct_config_read,
|
|
+};
|
|
+
|
|
/* Default capability regions to read-only, no-virtualization */
|
|
static struct perm_bits cap_perms[PCI_CAP_ID_MAX + 1] = {
|
|
[0 ... PCI_CAP_ID_MAX] = { .readfn = vfio_direct_config_read }
|
|
@@ -1897,9 +1901,17 @@ static ssize_t vfio_config_do_rw(struct vfio_pci_core_device *vdev, char __user
|
|
cap_start = *ppos;
|
|
} else {
|
|
if (*ppos >= PCI_CFG_SPACE_SIZE) {
|
|
- WARN_ON(cap_id > PCI_EXT_CAP_ID_MAX);
|
|
+ /*
|
|
+ * We can get a cap_id that exceeds PCI_EXT_CAP_ID_MAX
|
|
+ * if we're hiding an unknown capability at the start
|
|
+ * of the extended capability list. Use default, ro
|
|
+ * access, which will virtualize the id and next values.
|
|
+ */
|
|
+ if (cap_id > PCI_EXT_CAP_ID_MAX)
|
|
+ perm = &direct_ro_perms;
|
|
+ else
|
|
+ perm = &ecap_perms[cap_id];
|
|
|
|
- perm = &ecap_perms[cap_id];
|
|
cap_start = vfio_find_cap_start(vdev, *ppos);
|
|
} else {
|
|
WARN_ON(cap_id > PCI_CAP_ID_MAX);
|
|
diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c
|
|
index 08a4943dc54184..d0ee5fec647adb 100644
|
|
--- a/drivers/video/fbdev/sh7760fb.c
|
|
+++ b/drivers/video/fbdev/sh7760fb.c
|
|
@@ -409,12 +409,11 @@ static int sh7760fb_alloc_mem(struct fb_info *info)
|
|
vram = PAGE_SIZE;
|
|
|
|
fbmem = dma_alloc_coherent(info->device, vram, &par->fbdma, GFP_KERNEL);
|
|
-
|
|
if (!fbmem)
|
|
return -ENOMEM;
|
|
|
|
if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) {
|
|
- sh7760fb_free_mem(info);
|
|
+ dma_free_coherent(info->device, vram, fbmem, par->fbdma);
|
|
dev_err(info->device, "kernel gave me memory at 0x%08lx, which is"
|
|
"unusable for the LCDC\n", (unsigned long)par->fbdma);
|
|
return -ENOMEM;
|
|
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
|
|
index 1a9ded0cddcb0f..25164d56c9d995 100644
|
|
--- a/drivers/xen/xenbus/xenbus_probe.c
|
|
+++ b/drivers/xen/xenbus/xenbus_probe.c
|
|
@@ -313,7 +313,7 @@ int xenbus_dev_probe(struct device *_dev)
|
|
if (err) {
|
|
dev_warn(&dev->dev, "watch_otherend on %s failed.\n",
|
|
dev->nodename);
|
|
- return err;
|
|
+ goto fail_remove;
|
|
}
|
|
|
|
dev->spurious_threshold = 1;
|
|
@@ -322,6 +322,12 @@ int xenbus_dev_probe(struct device *_dev)
|
|
dev->nodename);
|
|
|
|
return 0;
|
|
+fail_remove:
|
|
+ if (drv->remove) {
|
|
+ down(&dev->reclaim_sem);
|
|
+ drv->remove(dev);
|
|
+ up(&dev->reclaim_sem);
|
|
+ }
|
|
fail_put:
|
|
module_put(drv->driver.owner);
|
|
fail:
|
|
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
|
|
index 2eb4e03080ac9b..25c902e7556d57 100644
|
|
--- a/fs/btrfs/ctree.c
|
|
+++ b/fs/btrfs/ctree.c
|
|
@@ -617,10 +617,16 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
atomic_inc(&cow->refs);
|
|
rcu_assign_pointer(root->node, cow);
|
|
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
|
|
- parent_start, last_ref);
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
|
|
+ parent_start, last_ref);
|
|
free_extent_buffer(buf);
|
|
add_root_to_dirty_list(root);
|
|
+ if (ret < 0) {
|
|
+ btrfs_tree_unlock(cow);
|
|
+ free_extent_buffer(cow);
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
+ return ret;
|
|
+ }
|
|
} else {
|
|
WARN_ON(trans->transid != btrfs_header_generation(parent));
|
|
ret = btrfs_tree_mod_log_insert_key(parent, parent_slot,
|
|
@@ -645,8 +651,14 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
|
|
return ret;
|
|
}
|
|
}
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
|
|
- parent_start, last_ref);
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
|
|
+ parent_start, last_ref);
|
|
+ if (ret < 0) {
|
|
+ btrfs_tree_unlock(cow);
|
|
+ free_extent_buffer(cow);
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
+ return ret;
|
|
+ }
|
|
}
|
|
if (unlock_orig)
|
|
btrfs_tree_unlock(buf);
|
|
@@ -1121,9 +1133,13 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
|
|
free_extent_buffer(mid);
|
|
|
|
root_sub_used(root, mid->len);
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
|
|
/* once for the root ptr */
|
|
free_extent_buffer_stale(mid);
|
|
+ if (ret < 0) {
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
+ goto out;
|
|
+ }
|
|
return 0;
|
|
}
|
|
if (btrfs_header_nritems(mid) >
|
|
@@ -1191,10 +1207,14 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
|
|
goto out;
|
|
}
|
|
root_sub_used(root, right->len);
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(root), right,
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), right,
|
|
0, 1);
|
|
free_extent_buffer_stale(right);
|
|
right = NULL;
|
|
+ if (ret < 0) {
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
+ goto out;
|
|
+ }
|
|
} else {
|
|
struct btrfs_disk_key right_key;
|
|
btrfs_node_key(right, &right_key, 0);
|
|
@@ -1249,9 +1269,13 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
|
|
goto out;
|
|
}
|
|
root_sub_used(root, mid->len);
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
|
|
free_extent_buffer_stale(mid);
|
|
mid = NULL;
|
|
+ if (ret < 0) {
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
+ goto out;
|
|
+ }
|
|
} else {
|
|
/* update the parent key to reflect our changes */
|
|
struct btrfs_disk_key mid_key;
|
|
@@ -2133,7 +2157,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
|
const struct btrfs_key *key, struct btrfs_path *p,
|
|
int ins_len, int cow)
|
|
{
|
|
- struct btrfs_fs_info *fs_info = root->fs_info;
|
|
+ struct btrfs_fs_info *fs_info;
|
|
struct extent_buffer *b;
|
|
int slot;
|
|
int ret;
|
|
@@ -2146,6 +2170,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
|
int min_write_lock_level;
|
|
int prev_cmp;
|
|
|
|
+ if (!root)
|
|
+ return -EINVAL;
|
|
+
|
|
+ fs_info = root->fs_info;
|
|
might_sleep();
|
|
|
|
lowest_level = p->lowest_level;
|
|
@@ -3022,7 +3050,11 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
|
|
old = root->node;
|
|
ret = btrfs_tree_mod_log_insert_root(root->node, c, false);
|
|
if (ret < 0) {
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(root), c, 0, 1);
|
|
+ int ret2;
|
|
+
|
|
+ ret2 = btrfs_free_tree_block(trans, btrfs_root_id(root), c, 0, 1);
|
|
+ if (ret2 < 0)
|
|
+ btrfs_abort_transaction(trans, ret2);
|
|
btrfs_tree_unlock(c);
|
|
free_extent_buffer(c);
|
|
return ret;
|
|
@@ -4587,9 +4619,12 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
|
|
root_sub_used(root, leaf->len);
|
|
|
|
atomic_inc(&leaf->refs);
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1);
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1);
|
|
free_extent_buffer_stale(leaf);
|
|
- return 0;
|
|
+ if (ret < 0)
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
+
|
|
+ return ret;
|
|
}
|
|
/*
|
|
* delete the item at the leaf level in path. If that empties
|
|
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
|
|
index b3680e1c7054c4..7aa8c1a2161b8f 100644
|
|
--- a/fs/btrfs/extent-tree.c
|
|
+++ b/fs/btrfs/extent-tree.c
|
|
@@ -2401,7 +2401,7 @@ int btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset,
|
|
goto out;
|
|
|
|
ret = check_delayed_ref(root, path, objectid, offset, bytenr);
|
|
- } while (ret == -EAGAIN);
|
|
+ } while (ret == -EAGAIN && !path->nowait);
|
|
|
|
out:
|
|
btrfs_release_path(path);
|
|
@@ -3290,10 +3290,10 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
|
|
return 0;
|
|
}
|
|
|
|
-void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
|
- u64 root_id,
|
|
- struct extent_buffer *buf,
|
|
- u64 parent, int last_ref)
|
|
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
|
+ u64 root_id,
|
|
+ struct extent_buffer *buf,
|
|
+ u64 parent, int last_ref)
|
|
{
|
|
struct btrfs_fs_info *fs_info = trans->fs_info;
|
|
struct btrfs_ref generic_ref = { 0 };
|
|
@@ -3307,7 +3307,8 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
|
if (root_id != BTRFS_TREE_LOG_OBJECTID) {
|
|
btrfs_ref_tree_mod(fs_info, &generic_ref);
|
|
ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL);
|
|
- BUG_ON(ret); /* -ENOMEM */
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
}
|
|
|
|
if (last_ref && btrfs_header_generation(buf) == trans->transid) {
|
|
@@ -3371,6 +3372,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
|
*/
|
|
clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags);
|
|
}
|
|
+ return 0;
|
|
}
|
|
|
|
/* Can return -ENOMEM */
|
|
@@ -5168,7 +5170,6 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
|
|
eb->start, level, 1,
|
|
&wc->refs[level],
|
|
&wc->flags[level]);
|
|
- BUG_ON(ret == -ENOMEM);
|
|
if (ret)
|
|
return ret;
|
|
if (unlikely(wc->refs[level] == 0)) {
|
|
@@ -5474,7 +5475,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
|
|
struct walk_control *wc)
|
|
{
|
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
|
- int ret;
|
|
+ int ret = 0;
|
|
int level = wc->level;
|
|
struct extent_buffer *eb = path->nodes[level];
|
|
u64 parent = 0;
|
|
@@ -5565,12 +5566,14 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
|
|
goto owner_mismatch;
|
|
}
|
|
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(root), eb, parent,
|
|
- wc->refs[level] == 1);
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(root), eb, parent,
|
|
+ wc->refs[level] == 1);
|
|
+ if (ret < 0)
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
out:
|
|
wc->refs[level] = 0;
|
|
wc->flags[level] = 0;
|
|
- return 0;
|
|
+ return ret;
|
|
|
|
owner_mismatch:
|
|
btrfs_err_rl(fs_info, "unexpected tree owner, have %llu expect %llu",
|
|
diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h
|
|
index 88c249c37516a1..ef1c1c99294ebd 100644
|
|
--- a/fs/btrfs/extent-tree.h
|
|
+++ b/fs/btrfs/extent-tree.h
|
|
@@ -114,10 +114,10 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
|
|
int level, u64 hint,
|
|
u64 empty_size,
|
|
enum btrfs_lock_nesting nest);
|
|
-void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
|
- u64 root_id,
|
|
- struct extent_buffer *buf,
|
|
- u64 parent, int last_ref);
|
|
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
|
+ u64 root_id,
|
|
+ struct extent_buffer *buf,
|
|
+ u64 parent, int last_ref);
|
|
int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
|
|
struct btrfs_root *root, u64 owner,
|
|
u64 offset, u64 ram_bytes,
|
|
diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
|
|
index 7b598b070700e7..a0d8160b537572 100644
|
|
--- a/fs/btrfs/free-space-tree.c
|
|
+++ b/fs/btrfs/free-space-tree.c
|
|
@@ -1289,10 +1289,14 @@ int btrfs_delete_free_space_tree(struct btrfs_fs_info *fs_info)
|
|
btrfs_tree_lock(free_space_root->node);
|
|
btrfs_clear_buffer_dirty(trans, free_space_root->node);
|
|
btrfs_tree_unlock(free_space_root->node);
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(free_space_root),
|
|
- free_space_root->node, 0, 1);
|
|
-
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(free_space_root),
|
|
+ free_space_root->node, 0, 1);
|
|
btrfs_put_root(free_space_root);
|
|
+ if (ret < 0) {
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
+ btrfs_end_transaction(trans);
|
|
+ return ret;
|
|
+ }
|
|
|
|
return btrfs_commit_transaction(trans);
|
|
|
|
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
|
|
index 5f0c9c3f3bbf09..ae6806bc392916 100644
|
|
--- a/fs/btrfs/ioctl.c
|
|
+++ b/fs/btrfs/ioctl.c
|
|
@@ -707,6 +707,8 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
|
|
ret = btrfs_insert_root(trans, fs_info->tree_root, &key,
|
|
root_item);
|
|
if (ret) {
|
|
+ int ret2;
|
|
+
|
|
/*
|
|
* Since we don't abort the transaction in this case, free the
|
|
* tree block so that we don't leak space and leave the
|
|
@@ -717,7 +719,9 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
|
|
btrfs_tree_lock(leaf);
|
|
btrfs_clear_buffer_dirty(trans, leaf);
|
|
btrfs_tree_unlock(leaf);
|
|
- btrfs_free_tree_block(trans, objectid, leaf, 0, 1);
|
|
+ ret2 = btrfs_free_tree_block(trans, objectid, leaf, 0, 1);
|
|
+ if (ret2 < 0)
|
|
+ btrfs_abort_transaction(trans, ret2);
|
|
free_extent_buffer(leaf);
|
|
goto out;
|
|
}
|
|
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
|
|
index 74b82390fe8470..1b9f4f16d12404 100644
|
|
--- a/fs/btrfs/qgroup.c
|
|
+++ b/fs/btrfs/qgroup.c
|
|
@@ -1320,9 +1320,11 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
|
|
btrfs_tree_lock(quota_root->node);
|
|
btrfs_clear_buffer_dirty(trans, quota_root->node);
|
|
btrfs_tree_unlock(quota_root->node);
|
|
- btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
|
|
- quota_root->node, 0, 1);
|
|
+ ret = btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
|
|
+ quota_root->node, 0, 1);
|
|
|
|
+ if (ret < 0)
|
|
+ btrfs_abort_transaction(trans, ret);
|
|
|
|
out:
|
|
btrfs_put_root(quota_root);
|
|
diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c
|
|
index 1ea5bfb8876e41..28ac7995716e04 100644
|
|
--- a/fs/btrfs/ref-verify.c
|
|
+++ b/fs/btrfs/ref-verify.c
|
|
@@ -849,6 +849,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
|
|
"dropping a ref for a root that doesn't have a ref on the block");
|
|
dump_block_entry(fs_info, be);
|
|
dump_ref_action(fs_info, ra);
|
|
+ rb_erase(&ref->node, &be->refs);
|
|
kfree(ref);
|
|
kfree(ra);
|
|
goto out_unlock;
|
|
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
|
|
index 2185e2908dba89..d1a0264b08a6c1 100644
|
|
--- a/fs/cachefiles/ondemand.c
|
|
+++ b/fs/cachefiles/ondemand.c
|
|
@@ -78,8 +78,10 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
|
|
|
|
trace_cachefiles_ondemand_fd_write(object, file_inode(file), pos, len);
|
|
ret = __cachefiles_write(object, file, pos, iter, NULL, NULL);
|
|
- if (!ret)
|
|
+ if (!ret) {
|
|
ret = len;
|
|
+ kiocb->ki_pos += ret;
|
|
+ }
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
|
|
index ec51e398562c6f..4f51a2e74d074b 100644
|
|
--- a/fs/ceph/super.c
|
|
+++ b/fs/ceph/super.c
|
|
@@ -281,7 +281,9 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
|
|
size_t len;
|
|
struct ceph_fsid fsid;
|
|
struct ceph_parse_opts_ctx *pctx = fc->fs_private;
|
|
+ struct ceph_options *opts = pctx->copts;
|
|
struct ceph_mount_options *fsopt = pctx->opts;
|
|
+ const char *name_start = dev_name;
|
|
char *fsid_start, *fs_name_start;
|
|
|
|
if (*dev_name_end != '=') {
|
|
@@ -292,8 +294,14 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
|
|
fsid_start = strchr(dev_name, '@');
|
|
if (!fsid_start)
|
|
return invalfc(fc, "missing cluster fsid");
|
|
- ++fsid_start; /* start of cluster fsid */
|
|
+ len = fsid_start - name_start;
|
|
+ kfree(opts->name);
|
|
+ opts->name = kstrndup(name_start, len, GFP_KERNEL);
|
|
+ if (!opts->name)
|
|
+ return -ENOMEM;
|
|
+ dout("using %s entity name", opts->name);
|
|
|
|
+ ++fsid_start; /* start of cluster fsid */
|
|
fs_name_start = strchr(fsid_start, '.');
|
|
if (!fs_name_start)
|
|
return invalfc(fc, "missing file system name");
|
|
diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c
|
|
index 6bd435a565f614..76566c2cbf63eb 100644
|
|
--- a/fs/erofs/zmap.c
|
|
+++ b/fs/erofs/zmap.c
|
|
@@ -234,7 +234,7 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m,
|
|
unsigned int amortizedshift;
|
|
erofs_off_t pos;
|
|
|
|
- if (lcn >= totalidx)
|
|
+ if (lcn >= totalidx || vi->z_logical_clusterbits > 14)
|
|
return -EINVAL;
|
|
|
|
m->lcn = lcn;
|
|
@@ -409,7 +409,7 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
|
|
u64 lcn = m->lcn, headlcn = map->m_la >> lclusterbits;
|
|
int err;
|
|
|
|
- do {
|
|
+ while (1) {
|
|
/* handle the last EOF pcluster (no next HEAD lcluster) */
|
|
if ((lcn << lclusterbits) >= inode->i_size) {
|
|
map->m_llen = inode->i_size - map->m_la;
|
|
@@ -421,14 +421,16 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
|
|
return err;
|
|
|
|
if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
|
|
- DBG_BUGON(!m->delta[1] &&
|
|
- m->clusterofs != 1 << lclusterbits);
|
|
+ /* work around invalid d1 generated by pre-1.0 mkfs */
|
|
+ if (unlikely(!m->delta[1])) {
|
|
+ m->delta[1] = 1;
|
|
+ DBG_BUGON(1);
|
|
+ }
|
|
} else if (m->type == Z_EROFS_LCLUSTER_TYPE_PLAIN ||
|
|
m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1 ||
|
|
m->type == Z_EROFS_LCLUSTER_TYPE_HEAD2) {
|
|
- /* go on until the next HEAD lcluster */
|
|
if (lcn != headlcn)
|
|
- break;
|
|
+ break; /* ends at the next HEAD lcluster */
|
|
m->delta[1] = 1;
|
|
} else {
|
|
erofs_err(inode->i_sb, "unknown type %u @ lcn %llu of nid %llu",
|
|
@@ -437,8 +439,7 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
|
|
return -EOPNOTSUPP;
|
|
}
|
|
lcn += m->delta[1];
|
|
- } while (m->delta[1]);
|
|
-
|
|
+ }
|
|
map->m_llen = (lcn << lclusterbits) + m->clusterofs - map->m_la;
|
|
return 0;
|
|
}
|
|
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
|
|
index 95c51b025b9176..f340e96b499f1c 100644
|
|
--- a/fs/exfat/namei.c
|
|
+++ b/fs/exfat/namei.c
|
|
@@ -377,6 +377,7 @@ static int exfat_find_empty_entry(struct inode *inode,
|
|
if (ei->start_clu == EXFAT_EOF_CLUSTER) {
|
|
ei->start_clu = clu.dir;
|
|
p_dir->dir = clu.dir;
|
|
+ hint_femp.eidx = 0;
|
|
}
|
|
|
|
/* append to the FAT chain */
|
|
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
|
|
index 79b20d6ae39ec4..396474e9e2bffe 100644
|
|
--- a/fs/ext4/balloc.c
|
|
+++ b/fs/ext4/balloc.c
|
|
@@ -545,7 +545,8 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group,
|
|
trace_ext4_read_block_bitmap_load(sb, block_group, ignore_locked);
|
|
ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO |
|
|
(ignore_locked ? REQ_RAHEAD : 0),
|
|
- ext4_end_bitmap_read);
|
|
+ ext4_end_bitmap_read,
|
|
+ ext4_simulate_fail(sb, EXT4_SIM_BBITMAP_EIO));
|
|
return bh;
|
|
verify:
|
|
err = ext4_validate_block_bitmap(sb, desc, block_group, bh);
|
|
@@ -569,7 +570,6 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
|
|
if (!desc)
|
|
return -EFSCORRUPTED;
|
|
wait_on_buffer(bh);
|
|
- ext4_simulate_fail_bh(sb, bh, EXT4_SIM_BBITMAP_EIO);
|
|
if (!buffer_uptodate(bh)) {
|
|
ext4_error_err(sb, EIO, "Cannot read block bitmap - "
|
|
"block_group = %u, block_bitmap = %llu",
|
|
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
|
|
index 7bbf0b9bdff239..3db01b933c3e8b 100644
|
|
--- a/fs/ext4/ext4.h
|
|
+++ b/fs/ext4/ext4.h
|
|
@@ -1849,14 +1849,6 @@ static inline bool ext4_simulate_fail(struct super_block *sb,
|
|
return false;
|
|
}
|
|
|
|
-static inline void ext4_simulate_fail_bh(struct super_block *sb,
|
|
- struct buffer_head *bh,
|
|
- unsigned long code)
|
|
-{
|
|
- if (!IS_ERR(bh) && ext4_simulate_fail(sb, code))
|
|
- clear_buffer_uptodate(bh);
|
|
-}
|
|
-
|
|
/*
|
|
* Error number codes for s_{first,last}_error_errno
|
|
*
|
|
@@ -3072,9 +3064,9 @@ extern struct buffer_head *ext4_sb_bread(struct super_block *sb,
|
|
extern struct buffer_head *ext4_sb_bread_unmovable(struct super_block *sb,
|
|
sector_t block);
|
|
extern void ext4_read_bh_nowait(struct buffer_head *bh, blk_opf_t op_flags,
|
|
- bh_end_io_t *end_io);
|
|
+ bh_end_io_t *end_io, bool simu_fail);
|
|
extern int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags,
|
|
- bh_end_io_t *end_io);
|
|
+ bh_end_io_t *end_io, bool simu_fail);
|
|
extern int ext4_read_bh_lock(struct buffer_head *bh, blk_opf_t op_flags, bool wait);
|
|
extern void ext4_sb_breadahead_unmovable(struct super_block *sb, sector_t block);
|
|
extern int ext4_seq_options_show(struct seq_file *seq, void *offset);
|
|
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
|
|
index 1c059ac1c1ef27..5ea75af6ca2239 100644
|
|
--- a/fs/ext4/extents.c
|
|
+++ b/fs/ext4/extents.c
|
|
@@ -564,7 +564,7 @@ __read_extent_tree_block(const char *function, unsigned int line,
|
|
|
|
if (!bh_uptodate_or_lock(bh)) {
|
|
trace_ext4_ext_load_extent(inode, pblk, _RET_IP_);
|
|
- err = ext4_read_bh(bh, 0, NULL);
|
|
+ err = ext4_read_bh(bh, 0, NULL, false);
|
|
if (err < 0)
|
|
goto errout;
|
|
}
|
|
diff --git a/fs/ext4/fsmap.c b/fs/ext4/fsmap.c
|
|
index cdf9bfe10137ff..53a05b8292f033 100644
|
|
--- a/fs/ext4/fsmap.c
|
|
+++ b/fs/ext4/fsmap.c
|
|
@@ -185,6 +185,56 @@ static inline ext4_fsblk_t ext4_fsmap_next_pblk(struct ext4_fsmap *fmr)
|
|
return fmr->fmr_physical + fmr->fmr_length;
|
|
}
|
|
|
|
+static int ext4_getfsmap_meta_helper(struct super_block *sb,
|
|
+ ext4_group_t agno, ext4_grpblk_t start,
|
|
+ ext4_grpblk_t len, void *priv)
|
|
+{
|
|
+ struct ext4_getfsmap_info *info = priv;
|
|
+ struct ext4_fsmap *p;
|
|
+ struct ext4_fsmap *tmp;
|
|
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
|
|
+ ext4_fsblk_t fsb, fs_start, fs_end;
|
|
+ int error;
|
|
+
|
|
+ fs_start = fsb = (EXT4_C2B(sbi, start) +
|
|
+ ext4_group_first_block_no(sb, agno));
|
|
+ fs_end = fs_start + EXT4_C2B(sbi, len);
|
|
+
|
|
+ /* Return relevant extents from the meta_list */
|
|
+ list_for_each_entry_safe(p, tmp, &info->gfi_meta_list, fmr_list) {
|
|
+ if (p->fmr_physical < info->gfi_next_fsblk) {
|
|
+ list_del(&p->fmr_list);
|
|
+ kfree(p);
|
|
+ continue;
|
|
+ }
|
|
+ if (p->fmr_physical <= fs_start ||
|
|
+ p->fmr_physical + p->fmr_length <= fs_end) {
|
|
+ /* Emit the retained free extent record if present */
|
|
+ if (info->gfi_lastfree.fmr_owner) {
|
|
+ error = ext4_getfsmap_helper(sb, info,
|
|
+ &info->gfi_lastfree);
|
|
+ if (error)
|
|
+ return error;
|
|
+ info->gfi_lastfree.fmr_owner = 0;
|
|
+ }
|
|
+ error = ext4_getfsmap_helper(sb, info, p);
|
|
+ if (error)
|
|
+ return error;
|
|
+ fsb = p->fmr_physical + p->fmr_length;
|
|
+ if (info->gfi_next_fsblk < fsb)
|
|
+ info->gfi_next_fsblk = fsb;
|
|
+ list_del(&p->fmr_list);
|
|
+ kfree(p);
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ if (info->gfi_next_fsblk < fsb)
|
|
+ info->gfi_next_fsblk = fsb;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
/* Transform a blockgroup's free record into a fsmap */
|
|
static int ext4_getfsmap_datadev_helper(struct super_block *sb,
|
|
ext4_group_t agno, ext4_grpblk_t start,
|
|
@@ -539,6 +589,7 @@ static int ext4_getfsmap_datadev(struct super_block *sb,
|
|
error = ext4_mballoc_query_range(sb, info->gfi_agno,
|
|
EXT4_B2C(sbi, info->gfi_low.fmr_physical),
|
|
EXT4_B2C(sbi, info->gfi_high.fmr_physical),
|
|
+ ext4_getfsmap_meta_helper,
|
|
ext4_getfsmap_datadev_helper, info);
|
|
if (error)
|
|
goto err;
|
|
@@ -560,7 +611,8 @@ static int ext4_getfsmap_datadev(struct super_block *sb,
|
|
|
|
/* Report any gaps at the end of the bg */
|
|
info->gfi_last = true;
|
|
- error = ext4_getfsmap_datadev_helper(sb, end_ag, last_cluster, 0, info);
|
|
+ error = ext4_getfsmap_datadev_helper(sb, end_ag, last_cluster + 1,
|
|
+ 0, info);
|
|
if (error)
|
|
goto err;
|
|
|
|
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
|
|
index 1a1e2214c581f3..d4d0ad689d3c1c 100644
|
|
--- a/fs/ext4/ialloc.c
|
|
+++ b/fs/ext4/ialloc.c
|
|
@@ -194,8 +194,9 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
|
|
* submit the buffer_head for reading
|
|
*/
|
|
trace_ext4_load_inode_bitmap(sb, block_group);
|
|
- ext4_read_bh(bh, REQ_META | REQ_PRIO, ext4_end_bitmap_read);
|
|
- ext4_simulate_fail_bh(sb, bh, EXT4_SIM_IBITMAP_EIO);
|
|
+ ext4_read_bh(bh, REQ_META | REQ_PRIO,
|
|
+ ext4_end_bitmap_read,
|
|
+ ext4_simulate_fail(sb, EXT4_SIM_IBITMAP_EIO));
|
|
if (!buffer_uptodate(bh)) {
|
|
put_bh(bh);
|
|
ext4_error_err(sb, EIO, "Cannot read inode bitmap - "
|
|
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
|
|
index a9f3716119d372..f2c495b745f1e4 100644
|
|
--- a/fs/ext4/indirect.c
|
|
+++ b/fs/ext4/indirect.c
|
|
@@ -170,7 +170,7 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth,
|
|
}
|
|
|
|
if (!bh_uptodate_or_lock(bh)) {
|
|
- if (ext4_read_bh(bh, 0, NULL) < 0) {
|
|
+ if (ext4_read_bh(bh, 0, NULL, false) < 0) {
|
|
put_bh(bh);
|
|
goto failure;
|
|
}
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index 14f7098bcefe1c..18ec9106c5b09f 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -4508,10 +4508,10 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino,
|
|
* Read the block from disk.
|
|
*/
|
|
trace_ext4_load_inode(sb, ino);
|
|
- ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO, NULL);
|
|
+ ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO, NULL,
|
|
+ ext4_simulate_fail(sb, EXT4_SIM_INODE_EIO));
|
|
blk_finish_plug(&plug);
|
|
wait_on_buffer(bh);
|
|
- ext4_simulate_fail_bh(sb, bh, EXT4_SIM_INODE_EIO);
|
|
if (!buffer_uptodate(bh)) {
|
|
if (ret_block)
|
|
*ret_block = block;
|
|
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
|
|
index 87ba7f58216f70..8a9f8c95c6f1eb 100644
|
|
--- a/fs/ext4/mballoc.c
|
|
+++ b/fs/ext4/mballoc.c
|
|
@@ -7155,13 +7155,14 @@ int
|
|
ext4_mballoc_query_range(
|
|
struct super_block *sb,
|
|
ext4_group_t group,
|
|
- ext4_grpblk_t start,
|
|
+ ext4_grpblk_t first,
|
|
ext4_grpblk_t end,
|
|
+ ext4_mballoc_query_range_fn meta_formatter,
|
|
ext4_mballoc_query_range_fn formatter,
|
|
void *priv)
|
|
{
|
|
void *bitmap;
|
|
- ext4_grpblk_t next;
|
|
+ ext4_grpblk_t start, next;
|
|
struct ext4_buddy e4b;
|
|
int error;
|
|
|
|
@@ -7172,10 +7173,19 @@ ext4_mballoc_query_range(
|
|
|
|
ext4_lock_group(sb, group);
|
|
|
|
- start = max(e4b.bd_info->bb_first_free, start);
|
|
+ start = max(e4b.bd_info->bb_first_free, first);
|
|
if (end >= EXT4_CLUSTERS_PER_GROUP(sb))
|
|
end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
|
|
-
|
|
+ if (meta_formatter && start != first) {
|
|
+ if (start > end)
|
|
+ start = end;
|
|
+ ext4_unlock_group(sb, group);
|
|
+ error = meta_formatter(sb, group, first, start - first,
|
|
+ priv);
|
|
+ if (error)
|
|
+ goto out_unload;
|
|
+ ext4_lock_group(sb, group);
|
|
+ }
|
|
while (start <= end) {
|
|
start = mb_find_next_zero_bit(bitmap, end + 1, start);
|
|
if (start > end)
|
|
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
|
|
index 498af2abc5d885..dd16050022f524 100644
|
|
--- a/fs/ext4/mballoc.h
|
|
+++ b/fs/ext4/mballoc.h
|
|
@@ -260,6 +260,7 @@ ext4_mballoc_query_range(
|
|
ext4_group_t agno,
|
|
ext4_grpblk_t start,
|
|
ext4_grpblk_t end,
|
|
+ ext4_mballoc_query_range_fn meta_formatter,
|
|
ext4_mballoc_query_range_fn formatter,
|
|
void *priv);
|
|
|
|
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
|
|
index bd946d0c71b700..d64c04ed061ae9 100644
|
|
--- a/fs/ext4/mmp.c
|
|
+++ b/fs/ext4/mmp.c
|
|
@@ -94,7 +94,7 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
|
|
}
|
|
|
|
lock_buffer(*bh);
|
|
- ret = ext4_read_bh(*bh, REQ_META | REQ_PRIO, NULL);
|
|
+ ret = ext4_read_bh(*bh, REQ_META | REQ_PRIO, NULL, false);
|
|
if (ret)
|
|
goto warn_exit;
|
|
|
|
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
|
|
index 0bfd5ff103aa44..5e6b07b3496006 100644
|
|
--- a/fs/ext4/move_extent.c
|
|
+++ b/fs/ext4/move_extent.c
|
|
@@ -165,15 +165,16 @@ mext_folio_double_lock(struct inode *inode1, struct inode *inode2,
|
|
return 0;
|
|
}
|
|
|
|
-/* Force page buffers uptodate w/o dropping page's lock */
|
|
-static int
|
|
-mext_page_mkuptodate(struct folio *folio, unsigned from, unsigned to)
|
|
+/* Force folio buffers uptodate w/o dropping folio's lock */
|
|
+static int mext_page_mkuptodate(struct folio *folio, size_t from, size_t to)
|
|
{
|
|
struct inode *inode = folio->mapping->host;
|
|
sector_t block;
|
|
- struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
|
|
+ struct buffer_head *bh, *head;
|
|
unsigned int blocksize, block_start, block_end;
|
|
- int i, err, nr = 0, partial = 0;
|
|
+ int nr = 0;
|
|
+ bool partial = false;
|
|
+
|
|
BUG_ON(!folio_test_locked(folio));
|
|
BUG_ON(folio_test_writeback(folio));
|
|
|
|
@@ -193,38 +194,44 @@ mext_page_mkuptodate(struct folio *folio, unsigned from, unsigned to)
|
|
block_end = block_start + blocksize;
|
|
if (block_end <= from || block_start >= to) {
|
|
if (!buffer_uptodate(bh))
|
|
- partial = 1;
|
|
+ partial = true;
|
|
continue;
|
|
}
|
|
if (buffer_uptodate(bh))
|
|
continue;
|
|
if (!buffer_mapped(bh)) {
|
|
- err = ext4_get_block(inode, block, bh, 0);
|
|
- if (err) {
|
|
- folio_set_error(folio);
|
|
+ int err = ext4_get_block(inode, block, bh, 0);
|
|
+ if (err)
|
|
return err;
|
|
- }
|
|
if (!buffer_mapped(bh)) {
|
|
folio_zero_range(folio, block_start, blocksize);
|
|
set_buffer_uptodate(bh);
|
|
continue;
|
|
}
|
|
}
|
|
- BUG_ON(nr >= MAX_BUF_PER_PAGE);
|
|
- arr[nr++] = bh;
|
|
+ lock_buffer(bh);
|
|
+ if (buffer_uptodate(bh)) {
|
|
+ unlock_buffer(bh);
|
|
+ continue;
|
|
+ }
|
|
+ ext4_read_bh_nowait(bh, 0, NULL, false);
|
|
+ nr++;
|
|
}
|
|
/* No io required */
|
|
if (!nr)
|
|
goto out;
|
|
|
|
- for (i = 0; i < nr; i++) {
|
|
- bh = arr[i];
|
|
- if (!bh_uptodate_or_lock(bh)) {
|
|
- err = ext4_read_bh(bh, 0, NULL);
|
|
- if (err)
|
|
- return err;
|
|
- }
|
|
- }
|
|
+ bh = head;
|
|
+ do {
|
|
+ if (bh_offset(bh) + blocksize <= from)
|
|
+ continue;
|
|
+ if (bh_offset(bh) > to)
|
|
+ break;
|
|
+ wait_on_buffer(bh);
|
|
+ if (buffer_uptodate(bh))
|
|
+ continue;
|
|
+ return -EIO;
|
|
+ } while ((bh = bh->b_this_page) != head);
|
|
out:
|
|
if (!partial)
|
|
folio_mark_uptodate(folio);
|
|
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
|
|
index dfdd7e5cf03890..7ab4f5a9bf5b87 100644
|
|
--- a/fs/ext4/page-io.c
|
|
+++ b/fs/ext4/page-io.c
|
|
@@ -117,7 +117,6 @@ static void ext4_finish_bio(struct bio *bio)
|
|
|
|
if (bio->bi_status) {
|
|
int err = blk_status_to_errno(bio->bi_status);
|
|
- folio_set_error(folio);
|
|
mapping_set_error(folio->mapping, err);
|
|
}
|
|
bh = head = folio_buffers(folio);
|
|
@@ -441,8 +440,6 @@ int ext4_bio_write_folio(struct ext4_io_submit *io, struct folio *folio,
|
|
BUG_ON(!folio_test_locked(folio));
|
|
BUG_ON(folio_test_writeback(folio));
|
|
|
|
- folio_clear_error(folio);
|
|
-
|
|
/*
|
|
* Comments copied from block_write_full_page:
|
|
*
|
|
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
|
|
index 3e7d160f543f0c..8cb83e7b699bd0 100644
|
|
--- a/fs/ext4/readpage.c
|
|
+++ b/fs/ext4/readpage.c
|
|
@@ -296,7 +296,6 @@ int ext4_mpage_readpages(struct inode *inode,
|
|
|
|
if (ext4_map_blocks(NULL, inode, &map, 0) < 0) {
|
|
set_error_page:
|
|
- folio_set_error(folio);
|
|
folio_zero_segment(folio, 0,
|
|
folio_size(folio));
|
|
folio_unlock(folio);
|
|
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
|
|
index 5f105171df7b56..b34007541e08cc 100644
|
|
--- a/fs/ext4/resize.c
|
|
+++ b/fs/ext4/resize.c
|
|
@@ -1301,7 +1301,7 @@ static struct buffer_head *ext4_get_bitmap(struct super_block *sb, __u64 block)
|
|
if (unlikely(!bh))
|
|
return NULL;
|
|
if (!bh_uptodate_or_lock(bh)) {
|
|
- if (ext4_read_bh(bh, 0, NULL) < 0) {
|
|
+ if (ext4_read_bh(bh, 0, NULL, false) < 0) {
|
|
brelse(bh);
|
|
return NULL;
|
|
}
|
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
index 1d14a38017a7f0..2346ef071b2421 100644
|
|
--- a/fs/ext4/super.c
|
|
+++ b/fs/ext4/super.c
|
|
@@ -161,8 +161,14 @@ MODULE_ALIAS("ext3");
|
|
|
|
|
|
static inline void __ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags,
|
|
- bh_end_io_t *end_io)
|
|
+ bh_end_io_t *end_io, bool simu_fail)
|
|
{
|
|
+ if (simu_fail) {
|
|
+ clear_buffer_uptodate(bh);
|
|
+ unlock_buffer(bh);
|
|
+ return;
|
|
+ }
|
|
+
|
|
/*
|
|
* buffer's verified bit is no longer valid after reading from
|
|
* disk again due to write out error, clear it to make sure we
|
|
@@ -176,7 +182,7 @@ static inline void __ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags,
|
|
}
|
|
|
|
void ext4_read_bh_nowait(struct buffer_head *bh, blk_opf_t op_flags,
|
|
- bh_end_io_t *end_io)
|
|
+ bh_end_io_t *end_io, bool simu_fail)
|
|
{
|
|
BUG_ON(!buffer_locked(bh));
|
|
|
|
@@ -184,10 +190,11 @@ void ext4_read_bh_nowait(struct buffer_head *bh, blk_opf_t op_flags,
|
|
unlock_buffer(bh);
|
|
return;
|
|
}
|
|
- __ext4_read_bh(bh, op_flags, end_io);
|
|
+ __ext4_read_bh(bh, op_flags, end_io, simu_fail);
|
|
}
|
|
|
|
-int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, bh_end_io_t *end_io)
|
|
+int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags,
|
|
+ bh_end_io_t *end_io, bool simu_fail)
|
|
{
|
|
BUG_ON(!buffer_locked(bh));
|
|
|
|
@@ -196,7 +203,7 @@ int ext4_read_bh(struct buffer_head *bh, blk_opf_t op_flags, bh_end_io_t *end_io
|
|
return 0;
|
|
}
|
|
|
|
- __ext4_read_bh(bh, op_flags, end_io);
|
|
+ __ext4_read_bh(bh, op_flags, end_io, simu_fail);
|
|
|
|
wait_on_buffer(bh);
|
|
if (buffer_uptodate(bh))
|
|
@@ -208,10 +215,10 @@ int ext4_read_bh_lock(struct buffer_head *bh, blk_opf_t op_flags, bool wait)
|
|
{
|
|
lock_buffer(bh);
|
|
if (!wait) {
|
|
- ext4_read_bh_nowait(bh, op_flags, NULL);
|
|
+ ext4_read_bh_nowait(bh, op_flags, NULL, false);
|
|
return 0;
|
|
}
|
|
- return ext4_read_bh(bh, op_flags, NULL);
|
|
+ return ext4_read_bh(bh, op_flags, NULL, false);
|
|
}
|
|
|
|
/*
|
|
@@ -259,7 +266,7 @@ void ext4_sb_breadahead_unmovable(struct super_block *sb, sector_t block)
|
|
|
|
if (likely(bh)) {
|
|
if (trylock_buffer(bh))
|
|
- ext4_read_bh_nowait(bh, REQ_RAHEAD, NULL);
|
|
+ ext4_read_bh_nowait(bh, REQ_RAHEAD, NULL, false);
|
|
brelse(bh);
|
|
}
|
|
}
|
|
@@ -339,9 +346,9 @@ __u32 ext4_free_group_clusters(struct super_block *sb,
|
|
__u32 ext4_free_inodes_count(struct super_block *sb,
|
|
struct ext4_group_desc *bg)
|
|
{
|
|
- return le16_to_cpu(bg->bg_free_inodes_count_lo) |
|
|
+ return le16_to_cpu(READ_ONCE(bg->bg_free_inodes_count_lo)) |
|
|
(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
|
|
- (__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0);
|
|
+ (__u32)le16_to_cpu(READ_ONCE(bg->bg_free_inodes_count_hi)) << 16 : 0);
|
|
}
|
|
|
|
__u32 ext4_used_dirs_count(struct super_block *sb,
|
|
@@ -395,9 +402,9 @@ void ext4_free_group_clusters_set(struct super_block *sb,
|
|
void ext4_free_inodes_set(struct super_block *sb,
|
|
struct ext4_group_desc *bg, __u32 count)
|
|
{
|
|
- bg->bg_free_inodes_count_lo = cpu_to_le16((__u16)count);
|
|
+ WRITE_ONCE(bg->bg_free_inodes_count_lo, cpu_to_le16((__u16)count));
|
|
if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
|
|
- bg->bg_free_inodes_count_hi = cpu_to_le16(count >> 16);
|
|
+ WRITE_ONCE(bg->bg_free_inodes_count_hi, cpu_to_le16(count >> 16));
|
|
}
|
|
|
|
void ext4_used_dirs_set(struct super_block *sb,
|
|
@@ -6544,9 +6551,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
|
|
goto restore_opts;
|
|
}
|
|
|
|
- if (test_opt2(sb, ABORT))
|
|
- ext4_abort(sb, ESHUTDOWN, "Abort forced by user");
|
|
-
|
|
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
|
|
(test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0);
|
|
|
|
@@ -6715,6 +6719,14 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
|
|
if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
|
|
ext4_stop_mmpd(sbi);
|
|
|
|
+ /*
|
|
+ * Handle aborting the filesystem as the last thing during remount to
|
|
+ * avoid obsure errors during remount when some option changes fail to
|
|
+ * apply due to shutdown filesystem.
|
|
+ */
|
|
+ if (test_opt2(sb, ABORT))
|
|
+ ext4_abort(sb, ESHUTDOWN, "Abort forced by user");
|
|
+
|
|
return 0;
|
|
|
|
restore_opts:
|
|
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
|
|
index 1a33a8c1623f24..c6317596e695cc 100644
|
|
--- a/fs/f2fs/checkpoint.c
|
|
+++ b/fs/f2fs/checkpoint.c
|
|
@@ -32,7 +32,7 @@ void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io,
|
|
f2fs_build_fault_attr(sbi, 0, 0);
|
|
if (!end_io)
|
|
f2fs_flush_merged_writes(sbi);
|
|
- f2fs_handle_critical_error(sbi, reason, end_io);
|
|
+ f2fs_handle_critical_error(sbi, reason);
|
|
}
|
|
|
|
/*
|
|
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
|
|
index 1c59a3b2b2c348..acd0764b0286c8 100644
|
|
--- a/fs/f2fs/data.c
|
|
+++ b/fs/f2fs/data.c
|
|
@@ -924,6 +924,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
|
|
#ifdef CONFIG_BLK_DEV_ZONED
|
|
static bool is_end_zone_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr)
|
|
{
|
|
+ struct block_device *bdev = sbi->sb->s_bdev;
|
|
int devi = 0;
|
|
|
|
if (f2fs_is_multi_device(sbi)) {
|
|
@@ -934,8 +935,9 @@ static bool is_end_zone_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr)
|
|
return false;
|
|
}
|
|
blkaddr -= FDEV(devi).start_blk;
|
|
+ bdev = FDEV(devi).bdev;
|
|
}
|
|
- return bdev_zoned_model(FDEV(devi).bdev) == BLK_ZONED_HM &&
|
|
+ return bdev_is_zoned(bdev) &&
|
|
f2fs_blkz_is_seq(sbi, devi, blkaddr) &&
|
|
(blkaddr % sbi->blocks_per_blkz == sbi->blocks_per_blkz - 1);
|
|
}
|
|
@@ -1873,25 +1875,6 @@ static int f2fs_xattr_fiemap(struct inode *inode,
|
|
return (err < 0 ? err : 0);
|
|
}
|
|
|
|
-static loff_t max_inode_blocks(struct inode *inode)
|
|
-{
|
|
- loff_t result = ADDRS_PER_INODE(inode);
|
|
- loff_t leaf_count = ADDRS_PER_BLOCK(inode);
|
|
-
|
|
- /* two direct node blocks */
|
|
- result += (leaf_count * 2);
|
|
-
|
|
- /* two indirect node blocks */
|
|
- leaf_count *= NIDS_PER_BLOCK;
|
|
- result += (leaf_count * 2);
|
|
-
|
|
- /* one double indirect node block */
|
|
- leaf_count *= NIDS_PER_BLOCK;
|
|
- result += leaf_count;
|
|
-
|
|
- return result;
|
|
-}
|
|
-
|
|
int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
|
u64 start, u64 len)
|
|
{
|
|
@@ -1964,8 +1947,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
|
if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) {
|
|
start_blk = next_pgofs;
|
|
|
|
- if (blks_to_bytes(inode, start_blk) < blks_to_bytes(inode,
|
|
- max_inode_blocks(inode)))
|
|
+ if (blks_to_bytes(inode, start_blk) < maxbytes)
|
|
goto prep_next;
|
|
|
|
flags |= FIEMAP_EXTENT_LAST;
|
|
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
|
|
index 7faf9446ea5dcb..33620642ae5ec8 100644
|
|
--- a/fs/f2fs/f2fs.h
|
|
+++ b/fs/f2fs/f2fs.h
|
|
@@ -3588,8 +3588,7 @@ int f2fs_quota_sync(struct super_block *sb, int type);
|
|
loff_t max_file_blocks(struct inode *inode);
|
|
void f2fs_quota_off_umount(struct super_block *sb);
|
|
void f2fs_save_errors(struct f2fs_sb_info *sbi, unsigned char flag);
|
|
-void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason,
|
|
- bool irq_context);
|
|
+void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason);
|
|
void f2fs_handle_error(struct f2fs_sb_info *sbi, unsigned char error);
|
|
void f2fs_handle_error_async(struct f2fs_sb_info *sbi, unsigned char error);
|
|
int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
|
|
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
|
|
index 74fac935bd0923..196755a34833d2 100644
|
|
--- a/fs/f2fs/file.c
|
|
+++ b/fs/f2fs/file.c
|
|
@@ -846,7 +846,11 @@ static bool f2fs_force_buffered_io(struct inode *inode, int rw)
|
|
return true;
|
|
if (f2fs_compressed_file(inode))
|
|
return true;
|
|
- if (f2fs_has_inline_data(inode))
|
|
+ /*
|
|
+ * only force direct read to use buffered IO, for direct write,
|
|
+ * it expects inline data conversion before committing IO.
|
|
+ */
|
|
+ if (f2fs_has_inline_data(inode) && rw == READ)
|
|
return true;
|
|
|
|
/* disallow direct IO if any of devices has unaligned blksize */
|
|
@@ -2308,9 +2312,12 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
|
|
if (readonly)
|
|
goto out;
|
|
|
|
- /* grab sb->s_umount to avoid racing w/ remount() */
|
|
+ /*
|
|
+ * grab sb->s_umount to avoid racing w/ remount() and other shutdown
|
|
+ * paths.
|
|
+ */
|
|
if (need_lock)
|
|
- down_read(&sbi->sb->s_umount);
|
|
+ down_write(&sbi->sb->s_umount);
|
|
|
|
f2fs_stop_gc_thread(sbi);
|
|
f2fs_stop_discard_thread(sbi);
|
|
@@ -2319,7 +2326,7 @@ int f2fs_do_shutdown(struct f2fs_sb_info *sbi, unsigned int flag,
|
|
clear_opt(sbi, DISCARD);
|
|
|
|
if (need_lock)
|
|
- up_read(&sbi->sb->s_umount);
|
|
+ up_write(&sbi->sb->s_umount);
|
|
|
|
f2fs_update_time(sbi, REQ_TIME);
|
|
out:
|
|
@@ -3755,7 +3762,7 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
|
|
to_reserved = cluster_size - compr_blocks - reserved;
|
|
|
|
/* for the case all blocks in cluster were reserved */
|
|
- if (to_reserved == 1) {
|
|
+ if (reserved && to_reserved == 1) {
|
|
dn->ofs_in_node += cluster_size;
|
|
goto next;
|
|
}
|
|
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
|
|
index 888c301ffe8f4c..e9904158241460 100644
|
|
--- a/fs/f2fs/gc.c
|
|
+++ b/fs/f2fs/gc.c
|
|
@@ -228,6 +228,8 @@ static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type)
|
|
|
|
switch (sbi->gc_mode) {
|
|
case GC_IDLE_CB:
|
|
+ case GC_URGENT_LOW:
|
|
+ case GC_URGENT_MID:
|
|
gc_mode = GC_CB;
|
|
break;
|
|
case GC_IDLE_GREEDY:
|
|
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
|
|
index c765bda3beaacb..a9ab93d30dceb8 100644
|
|
--- a/fs/f2fs/node.c
|
|
+++ b/fs/f2fs/node.c
|
|
@@ -905,6 +905,16 @@ static int truncate_node(struct dnode_of_data *dn)
|
|
if (err)
|
|
return err;
|
|
|
|
+ if (ni.blk_addr != NEW_ADDR &&
|
|
+ !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC_ENHANCE)) {
|
|
+ f2fs_err_ratelimited(sbi,
|
|
+ "nat entry is corrupted, run fsck to fix it, ino:%u, "
|
|
+ "nid:%u, blkaddr:%u", ni.ino, ni.nid, ni.blk_addr);
|
|
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
|
|
+ f2fs_handle_error(sbi, ERROR_INCONSISTENT_NAT);
|
|
+ return -EFSCORRUPTED;
|
|
+ }
|
|
+
|
|
/* Deallocate node address */
|
|
f2fs_invalidate_blocks(sbi, ni.blk_addr);
|
|
dec_valid_node_count(sbi, dn->inode, dn->nid == dn->inode->i_ino);
|
|
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
|
|
index c0ba379a6d8f3e..670104628ddbea 100644
|
|
--- a/fs/f2fs/segment.c
|
|
+++ b/fs/f2fs/segment.c
|
|
@@ -2848,7 +2848,8 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type)
|
|
struct f2fs_summary_block *sum_node;
|
|
struct page *sum_page;
|
|
|
|
- write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, curseg->segno));
|
|
+ if (curseg->inited)
|
|
+ write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, curseg->segno));
|
|
|
|
__set_test_and_inuse(sbi, new_segno);
|
|
|
|
@@ -3757,8 +3758,8 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
|
}
|
|
}
|
|
|
|
- f2fs_bug_on(sbi, !IS_DATASEG(type));
|
|
curseg = CURSEG_I(sbi, type);
|
|
+ f2fs_bug_on(sbi, !IS_DATASEG(curseg->seg_type));
|
|
|
|
mutex_lock(&curseg->curseg_mutex);
|
|
down_write(&sit_i->sentry_lock);
|
|
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
|
|
index 952970166d5da8..cd2ec6acc71776 100644
|
|
--- a/fs/f2fs/segment.h
|
|
+++ b/fs/f2fs/segment.h
|
|
@@ -559,18 +559,21 @@ static inline int reserved_sections(struct f2fs_sb_info *sbi)
|
|
}
|
|
|
|
static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
|
|
- unsigned int node_blocks, unsigned int dent_blocks)
|
|
+ unsigned int node_blocks, unsigned int data_blocks,
|
|
+ unsigned int dent_blocks)
|
|
{
|
|
|
|
- unsigned segno, left_blocks;
|
|
+ unsigned int segno, left_blocks, blocks;
|
|
int i;
|
|
|
|
- /* check current node sections in the worst case. */
|
|
- for (i = CURSEG_HOT_NODE; i <= CURSEG_COLD_NODE; i++) {
|
|
+ /* check current data/node sections in the worst case. */
|
|
+ for (i = CURSEG_HOT_DATA; i < NR_PERSISTENT_LOG; i++) {
|
|
segno = CURSEG_I(sbi, i)->segno;
|
|
left_blocks = CAP_BLKS_PER_SEC(sbi) -
|
|
get_ckpt_valid_blocks(sbi, segno, true);
|
|
- if (node_blocks > left_blocks)
|
|
+
|
|
+ blocks = i <= CURSEG_COLD_DATA ? data_blocks : node_blocks;
|
|
+ if (blocks > left_blocks)
|
|
return false;
|
|
}
|
|
|
|
@@ -584,8 +587,9 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
|
|
}
|
|
|
|
/*
|
|
- * calculate needed sections for dirty node/dentry
|
|
- * and call has_curseg_enough_space
|
|
+ * calculate needed sections for dirty node/dentry and call
|
|
+ * has_curseg_enough_space, please note that, it needs to account
|
|
+ * dirty data as well in lfs mode when checkpoint is disabled.
|
|
*/
|
|
static inline void __get_secs_required(struct f2fs_sb_info *sbi,
|
|
unsigned int *lower_p, unsigned int *upper_p, bool *curseg_p)
|
|
@@ -594,19 +598,30 @@ static inline void __get_secs_required(struct f2fs_sb_info *sbi,
|
|
get_pages(sbi, F2FS_DIRTY_DENTS) +
|
|
get_pages(sbi, F2FS_DIRTY_IMETA);
|
|
unsigned int total_dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS);
|
|
+ unsigned int total_data_blocks = 0;
|
|
unsigned int node_secs = total_node_blocks / CAP_BLKS_PER_SEC(sbi);
|
|
unsigned int dent_secs = total_dent_blocks / CAP_BLKS_PER_SEC(sbi);
|
|
+ unsigned int data_secs = 0;
|
|
unsigned int node_blocks = total_node_blocks % CAP_BLKS_PER_SEC(sbi);
|
|
unsigned int dent_blocks = total_dent_blocks % CAP_BLKS_PER_SEC(sbi);
|
|
+ unsigned int data_blocks = 0;
|
|
+
|
|
+ if (f2fs_lfs_mode(sbi) &&
|
|
+ unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
|
|
+ total_data_blocks = get_pages(sbi, F2FS_DIRTY_DATA);
|
|
+ data_secs = total_data_blocks / CAP_BLKS_PER_SEC(sbi);
|
|
+ data_blocks = total_data_blocks % CAP_BLKS_PER_SEC(sbi);
|
|
+ }
|
|
|
|
if (lower_p)
|
|
- *lower_p = node_secs + dent_secs;
|
|
+ *lower_p = node_secs + dent_secs + data_secs;
|
|
if (upper_p)
|
|
*upper_p = node_secs + dent_secs +
|
|
- (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0);
|
|
+ (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0) +
|
|
+ (data_blocks ? 1 : 0);
|
|
if (curseg_p)
|
|
*curseg_p = has_curseg_enough_space(sbi,
|
|
- node_blocks, dent_blocks);
|
|
+ node_blocks, data_blocks, dent_blocks);
|
|
}
|
|
|
|
static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
|
|
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
|
|
index 540fa1dfc77dff..f05d0e43db9e22 100644
|
|
--- a/fs/f2fs/super.c
|
|
+++ b/fs/f2fs/super.c
|
|
@@ -4093,8 +4093,7 @@ static bool system_going_down(void)
|
|
|| system_state == SYSTEM_RESTART;
|
|
}
|
|
|
|
-void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason,
|
|
- bool irq_context)
|
|
+void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason)
|
|
{
|
|
struct super_block *sb = sbi->sb;
|
|
bool shutdown = reason == STOP_CP_REASON_SHUTDOWN;
|
|
@@ -4106,10 +4105,12 @@ void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason,
|
|
if (!f2fs_hw_is_readonly(sbi)) {
|
|
save_stop_reason(sbi, reason);
|
|
|
|
- if (irq_context && !shutdown)
|
|
- schedule_work(&sbi->s_error_work);
|
|
- else
|
|
- f2fs_record_stop_reason(sbi);
|
|
+ /*
|
|
+ * always create an asynchronous task to record stop_reason
|
|
+ * in order to avoid potential deadlock when running into
|
|
+ * f2fs_record_stop_reason() synchronously.
|
|
+ */
|
|
+ schedule_work(&sbi->s_error_work);
|
|
}
|
|
|
|
/*
|
|
diff --git a/fs/fscache/volume.c b/fs/fscache/volume.c
|
|
index cb75c07b5281a5..ced14ac78cc1c2 100644
|
|
--- a/fs/fscache/volume.c
|
|
+++ b/fs/fscache/volume.c
|
|
@@ -322,8 +322,7 @@ void fscache_create_volume(struct fscache_volume *volume, bool wait)
|
|
}
|
|
return;
|
|
no_wait:
|
|
- clear_bit_unlock(FSCACHE_VOLUME_CREATING, &volume->flags);
|
|
- wake_up_bit(&volume->flags, FSCACHE_VOLUME_CREATING);
|
|
+ clear_and_wake_up_bit(FSCACHE_VOLUME_CREATING, &volume->flags);
|
|
}
|
|
|
|
/*
|
|
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
|
|
index 685e3ef9e9008d..2c0908a3021026 100644
|
|
--- a/fs/gfs2/glock.c
|
|
+++ b/fs/gfs2/glock.c
|
|
@@ -274,7 +274,7 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
|
|
* Enqueue the glock on the work queue. Passes one glock reference on to the
|
|
* work queue.
|
|
*/
|
|
-static void __gfs2_glock_queue_work(struct gfs2_glock *gl, unsigned long delay) {
|
|
+static void gfs2_glock_queue_work(struct gfs2_glock *gl, unsigned long delay) {
|
|
if (!queue_delayed_work(glock_workqueue, &gl->gl_work, delay)) {
|
|
/*
|
|
* We are holding the lockref spinlock, and the work was still
|
|
@@ -287,12 +287,6 @@ static void __gfs2_glock_queue_work(struct gfs2_glock *gl, unsigned long delay)
|
|
}
|
|
}
|
|
|
|
-static void gfs2_glock_queue_work(struct gfs2_glock *gl, unsigned long delay) {
|
|
- spin_lock(&gl->gl_lockref.lock);
|
|
- __gfs2_glock_queue_work(gl, delay);
|
|
- spin_unlock(&gl->gl_lockref.lock);
|
|
-}
|
|
-
|
|
static void __gfs2_glock_put(struct gfs2_glock *gl)
|
|
{
|
|
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
|
@@ -311,14 +305,6 @@ static void __gfs2_glock_put(struct gfs2_glock *gl)
|
|
sdp->sd_lockstruct.ls_ops->lm_put_lock(gl);
|
|
}
|
|
|
|
-/*
|
|
- * Cause the glock to be put in work queue context.
|
|
- */
|
|
-void gfs2_glock_queue_put(struct gfs2_glock *gl)
|
|
-{
|
|
- gfs2_glock_queue_work(gl, 0);
|
|
-}
|
|
-
|
|
/**
|
|
* gfs2_glock_put() - Decrement reference count on glock
|
|
* @gl: The glock to put
|
|
@@ -333,6 +319,23 @@ void gfs2_glock_put(struct gfs2_glock *gl)
|
|
__gfs2_glock_put(gl);
|
|
}
|
|
|
|
+/*
|
|
+ * gfs2_glock_put_async - Decrement reference count without sleeping
|
|
+ * @gl: The glock to put
|
|
+ *
|
|
+ * Decrement the reference count on glock immediately unless it is the last
|
|
+ * reference. Defer putting the last reference to work queue context.
|
|
+ */
|
|
+void gfs2_glock_put_async(struct gfs2_glock *gl)
|
|
+{
|
|
+ if (lockref_put_or_lock(&gl->gl_lockref))
|
|
+ return;
|
|
+
|
|
+ GLOCK_BUG_ON(gl, gl->gl_lockref.count != 1);
|
|
+ gfs2_glock_queue_work(gl, 0);
|
|
+ spin_unlock(&gl->gl_lockref.lock);
|
|
+}
|
|
+
|
|
/**
|
|
* may_grant - check if it's ok to grant a new lock
|
|
* @gl: The glock
|
|
@@ -806,7 +809,7 @@ __acquires(&gl->gl_lockref.lock)
|
|
*/
|
|
clear_bit(GLF_LOCK, &gl->gl_flags);
|
|
clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
|
|
- __gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
|
|
+ gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
|
|
return;
|
|
} else {
|
|
clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
|
|
@@ -836,7 +839,7 @@ __acquires(&gl->gl_lockref.lock)
|
|
|
|
/* Complete the operation now. */
|
|
finish_xmote(gl, target);
|
|
- __gfs2_glock_queue_work(gl, 0);
|
|
+ gfs2_glock_queue_work(gl, 0);
|
|
}
|
|
|
|
/**
|
|
@@ -883,7 +886,7 @@ __acquires(&gl->gl_lockref.lock)
|
|
clear_bit(GLF_LOCK, &gl->gl_flags);
|
|
smp_mb__after_atomic();
|
|
gl->gl_lockref.count++;
|
|
- __gfs2_glock_queue_work(gl, 0);
|
|
+ gfs2_glock_queue_work(gl, 0);
|
|
return;
|
|
|
|
out_unlock:
|
|
@@ -1020,14 +1023,15 @@ bool gfs2_queue_try_to_evict(struct gfs2_glock *gl)
|
|
&gl->gl_delete, 0);
|
|
}
|
|
|
|
-static bool gfs2_queue_verify_evict(struct gfs2_glock *gl)
|
|
+bool gfs2_queue_verify_delete(struct gfs2_glock *gl, bool later)
|
|
{
|
|
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
|
|
+ unsigned long delay;
|
|
|
|
- if (test_and_set_bit(GLF_VERIFY_EVICT, &gl->gl_flags))
|
|
+ if (test_and_set_bit(GLF_VERIFY_DELETE, &gl->gl_flags))
|
|
return false;
|
|
- return queue_delayed_work(sdp->sd_delete_wq,
|
|
- &gl->gl_delete, 5 * HZ);
|
|
+ delay = later ? 5 * HZ : 0;
|
|
+ return queue_delayed_work(sdp->sd_delete_wq, &gl->gl_delete, delay);
|
|
}
|
|
|
|
static void delete_work_func(struct work_struct *work)
|
|
@@ -1059,19 +1063,19 @@ static void delete_work_func(struct work_struct *work)
|
|
if (gfs2_try_evict(gl)) {
|
|
if (test_bit(SDF_KILL, &sdp->sd_flags))
|
|
goto out;
|
|
- if (gfs2_queue_verify_evict(gl))
|
|
+ if (gfs2_queue_verify_delete(gl, true))
|
|
return;
|
|
}
|
|
goto out;
|
|
}
|
|
|
|
- if (test_and_clear_bit(GLF_VERIFY_EVICT, &gl->gl_flags)) {
|
|
+ if (test_and_clear_bit(GLF_VERIFY_DELETE, &gl->gl_flags)) {
|
|
inode = gfs2_lookup_by_inum(sdp, no_addr, gl->gl_no_formal_ino,
|
|
GFS2_BLKST_UNLINKED);
|
|
if (IS_ERR(inode)) {
|
|
if (PTR_ERR(inode) == -EAGAIN &&
|
|
!test_bit(SDF_KILL, &sdp->sd_flags) &&
|
|
- gfs2_queue_verify_evict(gl))
|
|
+ gfs2_queue_verify_delete(gl, true))
|
|
return;
|
|
} else {
|
|
d_prune_aliases(inode);
|
|
@@ -1115,12 +1119,12 @@ static void glock_work_func(struct work_struct *work)
|
|
drop_refs--;
|
|
if (gl->gl_name.ln_type != LM_TYPE_INODE)
|
|
delay = 0;
|
|
- __gfs2_glock_queue_work(gl, delay);
|
|
+ gfs2_glock_queue_work(gl, delay);
|
|
}
|
|
|
|
/*
|
|
* Drop the remaining glock references manually here. (Mind that
|
|
- * __gfs2_glock_queue_work depends on the lockref spinlock begin held
|
|
+ * gfs2_glock_queue_work depends on the lockref spinlock begin held
|
|
* here as well.)
|
|
*/
|
|
gl->gl_lockref.count -= drop_refs;
|
|
@@ -1607,7 +1611,7 @@ int gfs2_glock_nq(struct gfs2_holder *gh)
|
|
test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))) {
|
|
set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
|
|
gl->gl_lockref.count++;
|
|
- __gfs2_glock_queue_work(gl, 0);
|
|
+ gfs2_glock_queue_work(gl, 0);
|
|
}
|
|
run_queue(gl, 1);
|
|
spin_unlock(&gl->gl_lockref.lock);
|
|
@@ -1672,7 +1676,7 @@ static void __gfs2_glock_dq(struct gfs2_holder *gh)
|
|
!test_bit(GLF_DEMOTE, &gl->gl_flags) &&
|
|
gl->gl_name.ln_type == LM_TYPE_INODE)
|
|
delay = gl->gl_hold_time;
|
|
- __gfs2_glock_queue_work(gl, delay);
|
|
+ gfs2_glock_queue_work(gl, delay);
|
|
}
|
|
}
|
|
|
|
@@ -1896,7 +1900,7 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
|
|
delay = gl->gl_hold_time;
|
|
}
|
|
handle_callback(gl, state, delay, true);
|
|
- __gfs2_glock_queue_work(gl, delay);
|
|
+ gfs2_glock_queue_work(gl, delay);
|
|
spin_unlock(&gl->gl_lockref.lock);
|
|
}
|
|
|
|
@@ -1956,7 +1960,7 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
|
|
|
|
gl->gl_lockref.count++;
|
|
set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
|
|
- __gfs2_glock_queue_work(gl, 0);
|
|
+ gfs2_glock_queue_work(gl, 0);
|
|
spin_unlock(&gl->gl_lockref.lock);
|
|
}
|
|
|
|
@@ -2009,15 +2013,14 @@ __acquires(&lru_lock)
|
|
atomic_inc(&lru_count);
|
|
continue;
|
|
}
|
|
- if (test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
|
|
+ if (test_bit(GLF_LOCK, &gl->gl_flags)) {
|
|
spin_unlock(&gl->gl_lockref.lock);
|
|
goto add_back_to_lru;
|
|
}
|
|
gl->gl_lockref.count++;
|
|
if (demote_ok(gl))
|
|
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
|
|
- WARN_ON(!test_and_clear_bit(GLF_LOCK, &gl->gl_flags));
|
|
- __gfs2_glock_queue_work(gl, 0);
|
|
+ gfs2_glock_queue_work(gl, 0);
|
|
spin_unlock(&gl->gl_lockref.lock);
|
|
cond_resched_lock(&lru_lock);
|
|
}
|
|
@@ -2117,7 +2120,7 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
|
|
void gfs2_cancel_delete_work(struct gfs2_glock *gl)
|
|
{
|
|
clear_bit(GLF_TRY_TO_EVICT, &gl->gl_flags);
|
|
- clear_bit(GLF_VERIFY_EVICT, &gl->gl_flags);
|
|
+ clear_bit(GLF_VERIFY_DELETE, &gl->gl_flags);
|
|
if (cancel_delayed_work(&gl->gl_delete))
|
|
gfs2_glock_put(gl);
|
|
}
|
|
@@ -2155,7 +2158,7 @@ static void thaw_glock(struct gfs2_glock *gl)
|
|
|
|
spin_lock(&gl->gl_lockref.lock);
|
|
set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
|
|
- __gfs2_glock_queue_work(gl, 0);
|
|
+ gfs2_glock_queue_work(gl, 0);
|
|
spin_unlock(&gl->gl_lockref.lock);
|
|
}
|
|
|
|
@@ -2174,7 +2177,7 @@ static void clear_glock(struct gfs2_glock *gl)
|
|
gl->gl_lockref.count++;
|
|
if (gl->gl_state != LM_ST_UNLOCKED)
|
|
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
|
|
- __gfs2_glock_queue_work(gl, 0);
|
|
+ gfs2_glock_queue_work(gl, 0);
|
|
}
|
|
spin_unlock(&gl->gl_lockref.lock);
|
|
}
|
|
@@ -2354,7 +2357,7 @@ static const char *gflags2str(char *buf, const struct gfs2_glock *gl)
|
|
*p++ = 'N';
|
|
if (test_bit(GLF_TRY_TO_EVICT, gflags))
|
|
*p++ = 'e';
|
|
- if (test_bit(GLF_VERIFY_EVICT, gflags))
|
|
+ if (test_bit(GLF_VERIFY_DELETE, gflags))
|
|
*p++ = 'E';
|
|
*p = 0;
|
|
return buf;
|
|
@@ -2533,8 +2536,7 @@ static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi, loff_t n)
|
|
if (gl) {
|
|
if (n == 0)
|
|
return;
|
|
- if (!lockref_put_not_zero(&gl->gl_lockref))
|
|
- gfs2_glock_queue_put(gl);
|
|
+ gfs2_glock_put_async(gl);
|
|
}
|
|
for (;;) {
|
|
gl = rhashtable_walk_next(&gi->hti);
|
|
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
|
|
index f7ee9ca948eeea..aae9fabbb76cc0 100644
|
|
--- a/fs/gfs2/glock.h
|
|
+++ b/fs/gfs2/glock.h
|
|
@@ -186,7 +186,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
|
|
int create, struct gfs2_glock **glp);
|
|
struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl);
|
|
void gfs2_glock_put(struct gfs2_glock *gl);
|
|
-void gfs2_glock_queue_put(struct gfs2_glock *gl);
|
|
+void gfs2_glock_put_async(struct gfs2_glock *gl);
|
|
|
|
void __gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
|
|
u16 flags, struct gfs2_holder *gh,
|
|
@@ -259,6 +259,7 @@ static inline int gfs2_glock_nq_init(struct gfs2_glock *gl,
|
|
void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state);
|
|
void gfs2_glock_complete(struct gfs2_glock *gl, int ret);
|
|
bool gfs2_queue_try_to_evict(struct gfs2_glock *gl);
|
|
+bool gfs2_queue_verify_delete(struct gfs2_glock *gl, bool later);
|
|
void gfs2_cancel_delete_work(struct gfs2_glock *gl);
|
|
void gfs2_flush_delete_work(struct gfs2_sbd *sdp);
|
|
void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
|
|
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
|
|
index 60abd7050c9983..853fad2bc48551 100644
|
|
--- a/fs/gfs2/incore.h
|
|
+++ b/fs/gfs2/incore.h
|
|
@@ -331,7 +331,7 @@ enum {
|
|
GLF_BLOCKING = 15,
|
|
GLF_FREEING = 16, /* Wait for glock to be freed */
|
|
GLF_TRY_TO_EVICT = 17, /* iopen glocks only */
|
|
- GLF_VERIFY_EVICT = 18, /* iopen glocks only */
|
|
+ GLF_VERIFY_DELETE = 18, /* iopen glocks only */
|
|
};
|
|
|
|
struct gfs2_glock {
|
|
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
|
|
index 767549066066c2..2be5551241b3ad 100644
|
|
--- a/fs/gfs2/log.c
|
|
+++ b/fs/gfs2/log.c
|
|
@@ -790,7 +790,7 @@ void gfs2_glock_remove_revoke(struct gfs2_glock *gl)
|
|
{
|
|
if (atomic_dec_return(&gl->gl_revokes) == 0) {
|
|
clear_bit(GLF_LFLUSH, &gl->gl_flags);
|
|
- gfs2_glock_queue_put(gl);
|
|
+ gfs2_glock_put_async(gl);
|
|
}
|
|
}
|
|
|
|
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
|
|
index 396d0f4a259d53..4a5e2732d1da2f 100644
|
|
--- a/fs/gfs2/rgrp.c
|
|
+++ b/fs/gfs2/rgrp.c
|
|
@@ -1879,7 +1879,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
|
|
*/
|
|
ip = gl->gl_object;
|
|
|
|
- if (ip || !gfs2_queue_try_to_evict(gl))
|
|
+ if (ip || !gfs2_queue_verify_delete(gl, false))
|
|
gfs2_glock_put(gl);
|
|
else
|
|
found++;
|
|
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
|
|
index 1200cb80599957..09285dc782cf8a 100644
|
|
--- a/fs/gfs2/super.c
|
|
+++ b/fs/gfs2/super.c
|
|
@@ -1053,8 +1053,8 @@ static int gfs2_drop_inode(struct inode *inode)
|
|
struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl;
|
|
|
|
gfs2_glock_hold(gl);
|
|
- if (!gfs2_queue_try_to_evict(gl))
|
|
- gfs2_glock_queue_put(gl);
|
|
+ if (!gfs2_queue_verify_delete(gl, true))
|
|
+ gfs2_glock_put_async(gl);
|
|
return 0;
|
|
}
|
|
|
|
@@ -1270,7 +1270,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
|
|
static void gfs2_glock_put_eventually(struct gfs2_glock *gl)
|
|
{
|
|
if (current->flags & PF_MEMALLOC)
|
|
- gfs2_glock_queue_put(gl);
|
|
+ gfs2_glock_put_async(gl);
|
|
else
|
|
gfs2_glock_put(gl);
|
|
}
|
|
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
|
|
index b65261e0cae3a8..268ff47b039636 100644
|
|
--- a/fs/gfs2/util.c
|
|
+++ b/fs/gfs2/util.c
|
|
@@ -255,7 +255,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)
|
|
gfs2_glock_nq(&sdp->sd_live_gh);
|
|
}
|
|
|
|
- gfs2_glock_queue_put(live_gl); /* drop extra reference we acquired */
|
|
+ gfs2_glock_put(live_gl); /* drop extra reference we acquired */
|
|
clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags);
|
|
|
|
/*
|
|
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
|
|
index 583c196ecd5206..1473b04fc0f311 100644
|
|
--- a/fs/hfsplus/hfsplus_fs.h
|
|
+++ b/fs/hfsplus/hfsplus_fs.h
|
|
@@ -156,6 +156,7 @@ struct hfsplus_sb_info {
|
|
|
|
/* Runtime variables */
|
|
u32 blockoffset;
|
|
+ u32 min_io_size;
|
|
sector_t part_start;
|
|
sector_t sect_count;
|
|
int fs_shift;
|
|
@@ -306,7 +307,7 @@ struct hfsplus_readdir_data {
|
|
*/
|
|
static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
|
|
{
|
|
- return max_t(unsigned short, bdev_logical_block_size(sb->s_bdev),
|
|
+ return max_t(unsigned short, HFSPLUS_SB(sb)->min_io_size,
|
|
HFSPLUS_SECTOR_SIZE);
|
|
}
|
|
|
|
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
|
|
index 0b791adf02e53d..a51a58db3fef04 100644
|
|
--- a/fs/hfsplus/wrapper.c
|
|
+++ b/fs/hfsplus/wrapper.c
|
|
@@ -171,6 +171,8 @@ int hfsplus_read_wrapper(struct super_block *sb)
|
|
if (!blocksize)
|
|
goto out;
|
|
|
|
+ sbi->min_io_size = blocksize;
|
|
+
|
|
if (hfsplus_get_last_session(sb, &part_start, &part_size))
|
|
goto out;
|
|
|
|
diff --git a/fs/inode.c b/fs/inode.c
|
|
index 9cafde77e2b038..030e07b169c276 100644
|
|
--- a/fs/inode.c
|
|
+++ b/fs/inode.c
|
|
@@ -593,6 +593,7 @@ void dump_mapping(const struct address_space *mapping)
|
|
struct hlist_node *dentry_first;
|
|
struct dentry *dentry_ptr;
|
|
struct dentry dentry;
|
|
+ char fname[64] = {};
|
|
unsigned long ino;
|
|
|
|
/*
|
|
@@ -628,11 +629,14 @@ void dump_mapping(const struct address_space *mapping)
|
|
return;
|
|
}
|
|
|
|
+ if (strncpy_from_kernel_nofault(fname, dentry.d_name.name, 63) < 0)
|
|
+ strscpy(fname, "<invalid>", 63);
|
|
/*
|
|
- * if dentry is corrupted, the %pd handler may still crash,
|
|
- * but it's unlikely that we reach here with a corrupt mapping
|
|
+ * Even if strncpy_from_kernel_nofault() succeeded,
|
|
+ * the fname could be unreliable
|
|
*/
|
|
- pr_warn("aops:%ps ino:%lx dentry name:\"%pd\"\n", a_ops, ino, &dentry);
|
|
+ pr_warn("aops:%ps ino:%lx dentry name(?):\"%s\"\n",
|
|
+ a_ops, ino, fname);
|
|
}
|
|
|
|
void clear_inode(struct inode *inode)
|
|
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
|
|
index acd32f05b51988..ef3a1e1b6cb065 100644
|
|
--- a/fs/jffs2/erase.c
|
|
+++ b/fs/jffs2/erase.c
|
|
@@ -338,10 +338,9 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
|
|
} while(--retlen);
|
|
mtd_unpoint(c->mtd, jeb->offset, c->sector_size);
|
|
if (retlen) {
|
|
- pr_warn("Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
|
|
- *wordebuf,
|
|
- jeb->offset +
|
|
- c->sector_size-retlen * sizeof(*wordebuf));
|
|
+ *bad_offset = jeb->offset + c->sector_size - retlen * sizeof(*wordebuf);
|
|
+ pr_warn("Newly-erased block contained word 0x%lx at offset 0x%08x\n",
|
|
+ *wordebuf, *bad_offset);
|
|
return -EIO;
|
|
}
|
|
return 0;
|
|
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
|
|
index 49e064c1f55179..7252941bf165bc 100644
|
|
--- a/fs/jfs/xattr.c
|
|
+++ b/fs/jfs/xattr.c
|
|
@@ -559,7 +559,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
|
|
|
|
size_check:
|
|
if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
|
|
- int size = min_t(int, EALIST_SIZE(ea_buf->xattr), ea_size);
|
|
+ int size = clamp_t(int, ea_size, 0, EALIST_SIZE(ea_buf->xattr));
|
|
|
|
printk(KERN_ERR "ea_get: invalid extended attribute\n");
|
|
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
|
|
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
|
|
index 8bceaac2205c87..a92b234ae0870b 100644
|
|
--- a/fs/nfs/internal.h
|
|
+++ b/fs/nfs/internal.h
|
|
@@ -11,7 +11,7 @@
|
|
#include <linux/nfs_page.h>
|
|
#include <linux/wait_bit.h>
|
|
|
|
-#define NFS_SB_MASK (SB_RDONLY|SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)
|
|
+#define NFS_SB_MASK (SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)
|
|
|
|
extern const struct export_operations nfs_export_ops;
|
|
|
|
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
|
|
index 299ea2b86df668..4b12e45f575394 100644
|
|
--- a/fs/nfs/nfs4proc.c
|
|
+++ b/fs/nfs/nfs4proc.c
|
|
@@ -2528,12 +2528,14 @@ static void nfs4_open_release(void *calldata)
|
|
struct nfs4_opendata *data = calldata;
|
|
struct nfs4_state *state = NULL;
|
|
|
|
+ /* In case of error, no cleanup! */
|
|
+ if (data->rpc_status != 0 || !data->rpc_done) {
|
|
+ nfs_release_seqid(data->o_arg.seqid);
|
|
+ goto out_free;
|
|
+ }
|
|
/* If this request hasn't been cancelled, do nothing */
|
|
if (!data->cancelled)
|
|
goto out_free;
|
|
- /* In case of error, no cleanup! */
|
|
- if (data->rpc_status != 0 || !data->rpc_done)
|
|
- goto out_free;
|
|
/* In case we need an open_confirm, no cleanup! */
|
|
if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
|
|
goto out_free;
|
|
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
|
|
index b7da17e530077e..d4d3ec58047e82 100644
|
|
--- a/fs/nfsd/export.c
|
|
+++ b/fs/nfsd/export.c
|
|
@@ -40,15 +40,24 @@
|
|
#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
|
|
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
|
|
|
|
-static void expkey_put(struct kref *ref)
|
|
+static void expkey_put_work(struct work_struct *work)
|
|
{
|
|
- struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
|
|
+ struct svc_expkey *key =
|
|
+ container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work);
|
|
|
|
if (test_bit(CACHE_VALID, &key->h.flags) &&
|
|
!test_bit(CACHE_NEGATIVE, &key->h.flags))
|
|
path_put(&key->ek_path);
|
|
auth_domain_put(key->ek_client);
|
|
- kfree_rcu(key, ek_rcu);
|
|
+ kfree(key);
|
|
+}
|
|
+
|
|
+static void expkey_put(struct kref *ref)
|
|
+{
|
|
+ struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
|
|
+
|
|
+ INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work);
|
|
+ queue_rcu_work(system_wq, &key->ek_rcu_work);
|
|
}
|
|
|
|
static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
|
|
@@ -351,16 +360,26 @@ static void export_stats_destroy(struct export_stats *stats)
|
|
EXP_STATS_COUNTERS_NUM);
|
|
}
|
|
|
|
-static void svc_export_put(struct kref *ref)
|
|
+static void svc_export_put_work(struct work_struct *work)
|
|
{
|
|
- struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
|
|
+ struct svc_export *exp =
|
|
+ container_of(to_rcu_work(work), struct svc_export, ex_rcu_work);
|
|
+
|
|
path_put(&exp->ex_path);
|
|
auth_domain_put(exp->ex_client);
|
|
nfsd4_fslocs_free(&exp->ex_fslocs);
|
|
export_stats_destroy(exp->ex_stats);
|
|
kfree(exp->ex_stats);
|
|
kfree(exp->ex_uuid);
|
|
- kfree_rcu(exp, ex_rcu);
|
|
+ kfree(exp);
|
|
+}
|
|
+
|
|
+static void svc_export_put(struct kref *ref)
|
|
+{
|
|
+ struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
|
|
+
|
|
+ INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work);
|
|
+ queue_rcu_work(system_wq, &exp->ex_rcu_work);
|
|
}
|
|
|
|
static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
|
|
@@ -1366,9 +1385,12 @@ static int e_show(struct seq_file *m, void *p)
|
|
return 0;
|
|
}
|
|
|
|
- exp_get(exp);
|
|
+ if (!cache_get_rcu(&exp->h))
|
|
+ return 0;
|
|
+
|
|
if (cache_check(cd, &exp->h, NULL))
|
|
return 0;
|
|
+
|
|
exp_put(exp);
|
|
return svc_export_show(m, cd, cp);
|
|
}
|
|
diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h
|
|
index ca9dc230ae3d0b..9d895570ceba05 100644
|
|
--- a/fs/nfsd/export.h
|
|
+++ b/fs/nfsd/export.h
|
|
@@ -75,7 +75,7 @@ struct svc_export {
|
|
u32 ex_layout_types;
|
|
struct nfsd4_deviceid_map *ex_devid_map;
|
|
struct cache_detail *cd;
|
|
- struct rcu_head ex_rcu;
|
|
+ struct rcu_work ex_rcu_work;
|
|
unsigned long ex_xprtsec_modes;
|
|
struct export_stats *ex_stats;
|
|
};
|
|
@@ -92,7 +92,7 @@ struct svc_expkey {
|
|
u32 ek_fsid[6];
|
|
|
|
struct path ek_path;
|
|
- struct rcu_head ek_rcu;
|
|
+ struct rcu_work ek_rcu_work;
|
|
};
|
|
|
|
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
|
|
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
|
|
index 4039ffcf90ba58..49a49529c6b8fb 100644
|
|
--- a/fs/nfsd/nfs4callback.c
|
|
+++ b/fs/nfsd/nfs4callback.c
|
|
@@ -297,17 +297,17 @@ static int decode_cb_compound4res(struct xdr_stream *xdr,
|
|
u32 length;
|
|
__be32 *p;
|
|
|
|
- p = xdr_inline_decode(xdr, 4 + 4);
|
|
+ p = xdr_inline_decode(xdr, XDR_UNIT);
|
|
if (unlikely(p == NULL))
|
|
goto out_overflow;
|
|
- hdr->status = be32_to_cpup(p++);
|
|
+ hdr->status = be32_to_cpup(p);
|
|
/* Ignore the tag */
|
|
- length = be32_to_cpup(p++);
|
|
- p = xdr_inline_decode(xdr, length + 4);
|
|
- if (unlikely(p == NULL))
|
|
+ if (xdr_stream_decode_u32(xdr, &length) < 0)
|
|
+ goto out_overflow;
|
|
+ if (xdr_inline_decode(xdr, length) == NULL)
|
|
+ goto out_overflow;
|
|
+ if (xdr_stream_decode_u32(xdr, &hdr->nops) < 0)
|
|
goto out_overflow;
|
|
- p += XDR_QUADLEN(length);
|
|
- hdr->nops = be32_to_cpup(p);
|
|
return 0;
|
|
out_overflow:
|
|
return -EIO;
|
|
@@ -1379,6 +1379,8 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
|
|
ses = c->cn_session;
|
|
}
|
|
spin_unlock(&clp->cl_lock);
|
|
+ if (!c)
|
|
+ return;
|
|
|
|
err = setup_callback_client(clp, &conn, ses);
|
|
if (err) {
|
|
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
|
|
index d64f792964e1a5..b3eca08f15b13e 100644
|
|
--- a/fs/nfsd/nfs4proc.c
|
|
+++ b/fs/nfsd/nfs4proc.c
|
|
@@ -1285,7 +1285,7 @@ static void nfsd4_stop_copy(struct nfsd4_copy *copy)
|
|
nfs4_put_copy(copy);
|
|
}
|
|
|
|
-static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp)
|
|
+static struct nfsd4_copy *nfsd4_unhash_copy(struct nfs4_client *clp)
|
|
{
|
|
struct nfsd4_copy *copy = NULL;
|
|
|
|
@@ -1294,6 +1294,9 @@ static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp)
|
|
copy = list_first_entry(&clp->async_copies, struct nfsd4_copy,
|
|
copies);
|
|
refcount_inc(©->refcount);
|
|
+ copy->cp_clp = NULL;
|
|
+ if (!list_empty(©->copies))
|
|
+ list_del_init(©->copies);
|
|
}
|
|
spin_unlock(&clp->async_lock);
|
|
return copy;
|
|
@@ -1303,7 +1306,7 @@ void nfsd4_shutdown_copy(struct nfs4_client *clp)
|
|
{
|
|
struct nfsd4_copy *copy;
|
|
|
|
- while ((copy = nfsd4_get_copy(clp)) != NULL)
|
|
+ while ((copy = nfsd4_unhash_copy(clp)) != NULL)
|
|
nfsd4_stop_copy(copy);
|
|
}
|
|
#ifdef CONFIG_NFSD_V4_2_INTER_SSC
|
|
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
|
|
index 4395577825a7fa..892fecce18b802 100644
|
|
--- a/fs/nfsd/nfs4recover.c
|
|
+++ b/fs/nfsd/nfs4recover.c
|
|
@@ -658,7 +658,8 @@ nfs4_reset_recoverydir(char *recdir)
|
|
return status;
|
|
status = -ENOTDIR;
|
|
if (d_is_dir(path.dentry)) {
|
|
- strcpy(user_recovery_dirname, recdir);
|
|
+ strscpy(user_recovery_dirname, recdir,
|
|
+ sizeof(user_recovery_dirname));
|
|
status = 0;
|
|
}
|
|
path_put(&path);
|
|
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
|
|
index 901fc68636cd59..a25cb2ff1b0b64 100644
|
|
--- a/fs/nfsd/nfs4state.c
|
|
+++ b/fs/nfsd/nfs4state.c
|
|
@@ -1625,6 +1625,14 @@ static void release_open_stateid(struct nfs4_ol_stateid *stp)
|
|
free_ol_stateid_reaplist(&reaplist);
|
|
}
|
|
|
|
+static bool nfs4_openowner_unhashed(struct nfs4_openowner *oo)
|
|
+{
|
|
+ lockdep_assert_held(&oo->oo_owner.so_client->cl_lock);
|
|
+
|
|
+ return list_empty(&oo->oo_owner.so_strhash) &&
|
|
+ list_empty(&oo->oo_perclient);
|
|
+}
|
|
+
|
|
static void unhash_openowner_locked(struct nfs4_openowner *oo)
|
|
{
|
|
struct nfs4_client *clp = oo->oo_owner.so_client;
|
|
@@ -4632,6 +4640,12 @@ init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
|
|
spin_lock(&oo->oo_owner.so_client->cl_lock);
|
|
spin_lock(&fp->fi_lock);
|
|
|
|
+ if (nfs4_openowner_unhashed(oo)) {
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
+ stp = NULL;
|
|
+ goto out_unlock;
|
|
+ }
|
|
+
|
|
retstp = nfsd4_find_existing_open(fp, open);
|
|
if (retstp)
|
|
goto out_unlock;
|
|
@@ -5751,6 +5765,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
|
|
|
if (!stp) {
|
|
stp = init_open_stateid(fp, open);
|
|
+ if (!stp) {
|
|
+ status = nfserr_jukebox;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
if (!open->op_stp)
|
|
new_stp = true;
|
|
}
|
|
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
|
|
index b5d8f238fce42a..9cc4ebb5350464 100644
|
|
--- a/fs/notify/fsnotify.c
|
|
+++ b/fs/notify/fsnotify.c
|
|
@@ -310,16 +310,19 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask,
|
|
if (!inode_mark)
|
|
return 0;
|
|
|
|
- if (mask & FS_EVENT_ON_CHILD) {
|
|
- /*
|
|
- * Some events can be sent on both parent dir and child marks
|
|
- * (e.g. FS_ATTRIB). If both parent dir and child are
|
|
- * watching, report the event once to parent dir with name (if
|
|
- * interested) and once to child without name (if interested).
|
|
- * The child watcher is expecting an event without a file name
|
|
- * and without the FS_EVENT_ON_CHILD flag.
|
|
- */
|
|
- mask &= ~FS_EVENT_ON_CHILD;
|
|
+ /*
|
|
+ * Some events can be sent on both parent dir and child marks (e.g.
|
|
+ * FS_ATTRIB). If both parent dir and child are watching, report the
|
|
+ * event once to parent dir with name (if interested) and once to child
|
|
+ * without name (if interested).
|
|
+ *
|
|
+ * In any case regardless whether the parent is watching or not, the
|
|
+ * child watcher is expecting an event without the FS_EVENT_ON_CHILD
|
|
+ * flag. The file name is expected if and only if this is a directory
|
|
+ * event.
|
|
+ */
|
|
+ mask &= ~FS_EVENT_ON_CHILD;
|
|
+ if (!(mask & ALL_FSNOTIFY_DIRENT_EVENTS)) {
|
|
dir = NULL;
|
|
name = NULL;
|
|
}
|
|
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
|
|
index 3a520117fa59f0..a9ce7947228c8d 100644
|
|
--- a/fs/ocfs2/aops.h
|
|
+++ b/fs/ocfs2/aops.h
|
|
@@ -70,6 +70,8 @@ enum ocfs2_iocb_lock_bits {
|
|
OCFS2_IOCB_NUM_LOCKS
|
|
};
|
|
|
|
+#define ocfs2_iocb_init_rw_locked(iocb) \
|
|
+ (iocb->private = NULL)
|
|
#define ocfs2_iocb_clear_rw_locked(iocb) \
|
|
clear_bit(OCFS2_IOCB_RW_LOCK, (unsigned long *)&iocb->private)
|
|
#define ocfs2_iocb_rw_locked_level(iocb) \
|
|
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
|
|
index e4acb795d11901..0585f281ff62f0 100644
|
|
--- a/fs/ocfs2/file.c
|
|
+++ b/fs/ocfs2/file.c
|
|
@@ -2397,6 +2397,8 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
|
|
} else
|
|
inode_lock(inode);
|
|
|
|
+ ocfs2_iocb_init_rw_locked(iocb);
|
|
+
|
|
/*
|
|
* Concurrent O_DIRECT writes are allowed with
|
|
* mount_option "coherency=buffered".
|
|
@@ -2543,6 +2545,8 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
|
|
if (!direct_io && nowait)
|
|
return -EOPNOTSUPP;
|
|
|
|
+ ocfs2_iocb_init_rw_locked(iocb);
|
|
+
|
|
/*
|
|
* buffered reads protect themselves in ->read_folio(). O_DIRECT reads
|
|
* need locks to protect pending reads from racing with truncate.
|
|
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
|
|
index fca29dba7b146a..9c42a30317d587 100644
|
|
--- a/fs/overlayfs/inode.c
|
|
+++ b/fs/overlayfs/inode.c
|
|
@@ -741,8 +741,13 @@ static int ovl_security_fileattr(const struct path *realpath, struct fileattr *f
|
|
struct file *file;
|
|
unsigned int cmd;
|
|
int err;
|
|
+ unsigned int flags;
|
|
+
|
|
+ flags = O_RDONLY;
|
|
+ if (force_o_largefile())
|
|
+ flags |= O_LARGEFILE;
|
|
|
|
- file = dentry_open(realpath, O_RDONLY, current_cred());
|
|
+ file = dentry_open(realpath, flags, current_cred());
|
|
if (IS_ERR(file))
|
|
return PTR_ERR(file);
|
|
|
|
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
|
|
index 89e0d60d35b6cf..0bf3ffcd072f6a 100644
|
|
--- a/fs/overlayfs/util.c
|
|
+++ b/fs/overlayfs/util.c
|
|
@@ -171,6 +171,9 @@ void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
|
|
|
|
bool ovl_dentry_weird(struct dentry *dentry)
|
|
{
|
|
+ if (!d_can_lookup(dentry) && !d_is_file(dentry) && !d_is_symlink(dentry))
|
|
+ return true;
|
|
+
|
|
return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT |
|
|
DCACHE_MANAGE_TRANSIT |
|
|
DCACHE_OP_HASH |
|
|
diff --git a/fs/proc/array.c b/fs/proc/array.c
|
|
index 37b8061d84bb79..34a47fb0c57f25 100644
|
|
--- a/fs/proc/array.c
|
|
+++ b/fs/proc/array.c
|
|
@@ -477,13 +477,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
|
|
int permitted;
|
|
struct mm_struct *mm;
|
|
unsigned long long start_time;
|
|
- unsigned long cmin_flt = 0, cmaj_flt = 0;
|
|
- unsigned long min_flt = 0, maj_flt = 0;
|
|
- u64 cutime, cstime, utime, stime;
|
|
- u64 cgtime, gtime;
|
|
+ unsigned long cmin_flt, cmaj_flt, min_flt, maj_flt;
|
|
+ u64 cutime, cstime, cgtime, utime, stime, gtime;
|
|
unsigned long rsslim = 0;
|
|
unsigned long flags;
|
|
int exit_code = task->exit_code;
|
|
+ struct signal_struct *sig = task->signal;
|
|
+ unsigned int seq = 1;
|
|
|
|
state = *get_task_state(task);
|
|
vsize = eip = esp = 0;
|
|
@@ -511,12 +511,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
|
|
|
|
sigemptyset(&sigign);
|
|
sigemptyset(&sigcatch);
|
|
- cutime = cstime = 0;
|
|
- cgtime = gtime = 0;
|
|
|
|
if (lock_task_sighand(task, &flags)) {
|
|
- struct signal_struct *sig = task->signal;
|
|
-
|
|
if (sig->tty) {
|
|
struct pid *pgrp = tty_get_pgrp(sig->tty);
|
|
tty_pgrp = pid_nr_ns(pgrp, ns);
|
|
@@ -527,26 +523,9 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
|
|
num_threads = get_nr_threads(task);
|
|
collect_sigign_sigcatch(task, &sigign, &sigcatch);
|
|
|
|
- cmin_flt = sig->cmin_flt;
|
|
- cmaj_flt = sig->cmaj_flt;
|
|
- cutime = sig->cutime;
|
|
- cstime = sig->cstime;
|
|
- cgtime = sig->cgtime;
|
|
rsslim = READ_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
|
|
|
|
- /* add up live thread stats at the group level */
|
|
if (whole) {
|
|
- struct task_struct *t = task;
|
|
- do {
|
|
- min_flt += t->min_flt;
|
|
- maj_flt += t->maj_flt;
|
|
- gtime += task_gtime(t);
|
|
- } while_each_thread(task, t);
|
|
-
|
|
- min_flt += sig->min_flt;
|
|
- maj_flt += sig->maj_flt;
|
|
- gtime += sig->gtime;
|
|
-
|
|
if (sig->flags & (SIGNAL_GROUP_EXIT | SIGNAL_STOP_STOPPED))
|
|
exit_code = sig->group_exit_code;
|
|
}
|
|
@@ -561,6 +540,34 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
|
|
if (permitted && (!whole || num_threads < 2))
|
|
wchan = !task_is_running(task);
|
|
|
|
+ do {
|
|
+ seq++; /* 2 on the 1st/lockless path, otherwise odd */
|
|
+ flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
|
|
+
|
|
+ cmin_flt = sig->cmin_flt;
|
|
+ cmaj_flt = sig->cmaj_flt;
|
|
+ cutime = sig->cutime;
|
|
+ cstime = sig->cstime;
|
|
+ cgtime = sig->cgtime;
|
|
+
|
|
+ if (whole) {
|
|
+ struct task_struct *t;
|
|
+
|
|
+ min_flt = sig->min_flt;
|
|
+ maj_flt = sig->maj_flt;
|
|
+ gtime = sig->gtime;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ __for_each_thread(sig, t) {
|
|
+ min_flt += t->min_flt;
|
|
+ maj_flt += t->maj_flt;
|
|
+ gtime += task_gtime(t);
|
|
+ }
|
|
+ rcu_read_unlock();
|
|
+ }
|
|
+ } while (need_seqretry(&sig->stats_lock, seq));
|
|
+ done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
|
|
+
|
|
if (whole) {
|
|
thread_group_cputime_adjusted(task, &utime, &stime);
|
|
} else {
|
|
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
|
|
index 7e4fa9c68c1dd0..1127457d0fcb37 100644
|
|
--- a/fs/proc/kcore.c
|
|
+++ b/fs/proc/kcore.c
|
|
@@ -493,13 +493,13 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|
* the previous entry, search for a matching entry.
|
|
*/
|
|
if (!m || start < m->addr || start >= m->addr + m->size) {
|
|
- struct kcore_list *iter;
|
|
+ struct kcore_list *pos;
|
|
|
|
m = NULL;
|
|
- list_for_each_entry(iter, &kclist_head, list) {
|
|
- if (start >= iter->addr &&
|
|
- start < iter->addr + iter->size) {
|
|
- m = iter;
|
|
+ list_for_each_entry(pos, &kclist_head, list) {
|
|
+ if (start >= pos->addr &&
|
|
+ start < pos->addr + pos->size) {
|
|
+ m = pos;
|
|
break;
|
|
}
|
|
}
|
|
@@ -599,6 +599,7 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|
ret = -EFAULT;
|
|
goto out;
|
|
}
|
|
+ ret = 0;
|
|
/*
|
|
* We know the bounce buffer is safe to copy from, so
|
|
* use _copy_to_iter() directly.
|
|
diff --git a/fs/proc/softirqs.c b/fs/proc/softirqs.c
|
|
index f4616083faef3b..04bb29721419b0 100644
|
|
--- a/fs/proc/softirqs.c
|
|
+++ b/fs/proc/softirqs.c
|
|
@@ -20,7 +20,7 @@ static int show_softirqs(struct seq_file *p, void *v)
|
|
for (i = 0; i < NR_SOFTIRQS; i++) {
|
|
seq_printf(p, "%12s:", softirq_to_name[i]);
|
|
for_each_possible_cpu(j)
|
|
- seq_printf(p, " %10u", kstat_softirqs_cpu(i, j));
|
|
+ seq_put_decimal_ull_width(p, " ", kstat_softirqs_cpu(i, j), 10);
|
|
seq_putc(p, '\n');
|
|
}
|
|
return 0;
|
|
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
|
|
index 23dbde1de25205..67562c78e57d53 100644
|
|
--- a/fs/quota/dquot.c
|
|
+++ b/fs/quota/dquot.c
|
|
@@ -690,6 +690,8 @@ int dquot_writeback_dquots(struct super_block *sb, int type)
|
|
|
|
WARN_ON_ONCE(!rwsem_is_locked(&sb->s_umount));
|
|
|
|
+ flush_delayed_work("a_release_work);
|
|
+
|
|
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
|
|
if (type != -1 && cnt != type)
|
|
continue;
|
|
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
|
|
index 0ff2491c311d8a..9c0ef4195b5829 100644
|
|
--- a/fs/smb/client/cached_dir.c
|
|
+++ b/fs/smb/client/cached_dir.c
|
|
@@ -17,6 +17,11 @@ static void free_cached_dir(struct cached_fid *cfid);
|
|
static void smb2_close_cached_fid(struct kref *ref);
|
|
static void cfids_laundromat_worker(struct work_struct *work);
|
|
|
|
+struct cached_dir_dentry {
|
|
+ struct list_head entry;
|
|
+ struct dentry *dentry;
|
|
+};
|
|
+
|
|
static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
|
|
const char *path,
|
|
bool lookup_only,
|
|
@@ -59,6 +64,16 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
|
|
list_add(&cfid->entry, &cfids->entries);
|
|
cfid->on_list = true;
|
|
kref_get(&cfid->refcount);
|
|
+ /*
|
|
+ * Set @cfid->has_lease to true during construction so that the lease
|
|
+ * reference can be put in cached_dir_lease_break() due to a potential
|
|
+ * lease break right after the request is sent or while @cfid is still
|
|
+ * being cached, or if a reconnection is triggered during construction.
|
|
+ * Concurrent processes won't be to use it yet due to @cfid->time being
|
|
+ * zero.
|
|
+ */
|
|
+ cfid->has_lease = true;
|
|
+
|
|
spin_unlock(&cfids->cfid_list_lock);
|
|
return cfid;
|
|
}
|
|
@@ -176,12 +191,12 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|
return -ENOENT;
|
|
}
|
|
/*
|
|
- * Return cached fid if it has a lease. Otherwise, it is either a new
|
|
- * entry or laundromat worker removed it from @cfids->entries. Caller
|
|
- * will put last reference if the latter.
|
|
+ * Return cached fid if it is valid (has a lease and has a time).
|
|
+ * Otherwise, it is either a new entry or laundromat worker removed it
|
|
+ * from @cfids->entries. Caller will put last reference if the latter.
|
|
*/
|
|
spin_lock(&cfids->cfid_list_lock);
|
|
- if (cfid->has_lease) {
|
|
+ if (cfid->has_lease && cfid->time) {
|
|
spin_unlock(&cfids->cfid_list_lock);
|
|
*ret_cfid = cfid;
|
|
kfree(utf16_path);
|
|
@@ -212,6 +227,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|
}
|
|
}
|
|
cfid->dentry = dentry;
|
|
+ cfid->tcon = tcon;
|
|
|
|
/*
|
|
* We do not hold the lock for the open because in case
|
|
@@ -267,15 +283,6 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|
|
|
smb2_set_related(&rqst[1]);
|
|
|
|
- /*
|
|
- * Set @cfid->has_lease to true before sending out compounded request so
|
|
- * its lease reference can be put in cached_dir_lease_break() due to a
|
|
- * potential lease break right after the request is sent or while @cfid
|
|
- * is still being cached. Concurrent processes won't be to use it yet
|
|
- * due to @cfid->time being zero.
|
|
- */
|
|
- cfid->has_lease = true;
|
|
-
|
|
if (retries) {
|
|
smb2_set_replay(server, &rqst[0]);
|
|
smb2_set_replay(server, &rqst[1]);
|
|
@@ -292,7 +299,6 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|
}
|
|
goto oshr_free;
|
|
}
|
|
- cfid->tcon = tcon;
|
|
cfid->is_open = true;
|
|
|
|
spin_lock(&cfids->cfid_list_lock);
|
|
@@ -347,6 +353,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|
SMB2_query_info_free(&rqst[1]);
|
|
free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
|
|
free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
|
|
+out:
|
|
if (rc) {
|
|
spin_lock(&cfids->cfid_list_lock);
|
|
if (cfid->on_list) {
|
|
@@ -358,23 +365,14 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
|
/*
|
|
* We are guaranteed to have two references at this
|
|
* point. One for the caller and one for a potential
|
|
- * lease. Release the Lease-ref so that the directory
|
|
- * will be closed when the caller closes the cached
|
|
- * handle.
|
|
+ * lease. Release one here, and the second below.
|
|
*/
|
|
cfid->has_lease = false;
|
|
- spin_unlock(&cfids->cfid_list_lock);
|
|
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
|
- goto out;
|
|
}
|
|
spin_unlock(&cfids->cfid_list_lock);
|
|
- }
|
|
-out:
|
|
- if (rc) {
|
|
- if (cfid->is_open)
|
|
- SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
|
|
- cfid->fid.volatile_fid);
|
|
- free_cached_dir(cfid);
|
|
+
|
|
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
|
|
} else {
|
|
*ret_cfid = cfid;
|
|
atomic_inc(&tcon->num_remote_opens);
|
|
@@ -401,7 +399,7 @@ int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
|
|
spin_lock(&cfids->cfid_list_lock);
|
|
list_for_each_entry(cfid, &cfids->entries, entry) {
|
|
if (dentry && cfid->dentry == dentry) {
|
|
- cifs_dbg(FYI, "found a cached root file handle by dentry\n");
|
|
+ cifs_dbg(FYI, "found a cached file handle by dentry\n");
|
|
kref_get(&cfid->refcount);
|
|
*ret_cfid = cfid;
|
|
spin_unlock(&cfids->cfid_list_lock);
|
|
@@ -477,7 +475,10 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
|
|
struct cifs_tcon *tcon;
|
|
struct tcon_link *tlink;
|
|
struct cached_fids *cfids;
|
|
+ struct cached_dir_dentry *tmp_list, *q;
|
|
+ LIST_HEAD(entry);
|
|
|
|
+ spin_lock(&cifs_sb->tlink_tree_lock);
|
|
for (node = rb_first(root); node; node = rb_next(node)) {
|
|
tlink = rb_entry(node, struct tcon_link, tl_rbnode);
|
|
tcon = tlink_tcon(tlink);
|
|
@@ -486,11 +487,30 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
|
|
cfids = tcon->cfids;
|
|
if (cfids == NULL)
|
|
continue;
|
|
+ spin_lock(&cfids->cfid_list_lock);
|
|
list_for_each_entry(cfid, &cfids->entries, entry) {
|
|
- dput(cfid->dentry);
|
|
+ tmp_list = kmalloc(sizeof(*tmp_list), GFP_ATOMIC);
|
|
+ if (tmp_list == NULL)
|
|
+ break;
|
|
+ spin_lock(&cfid->fid_lock);
|
|
+ tmp_list->dentry = cfid->dentry;
|
|
cfid->dentry = NULL;
|
|
+ spin_unlock(&cfid->fid_lock);
|
|
+
|
|
+ list_add_tail(&tmp_list->entry, &entry);
|
|
}
|
|
+ spin_unlock(&cfids->cfid_list_lock);
|
|
+ }
|
|
+ spin_unlock(&cifs_sb->tlink_tree_lock);
|
|
+
|
|
+ list_for_each_entry_safe(tmp_list, q, &entry, entry) {
|
|
+ list_del(&tmp_list->entry);
|
|
+ dput(tmp_list->dentry);
|
|
+ kfree(tmp_list);
|
|
}
|
|
+
|
|
+ /* Flush any pending work that will drop dentries */
|
|
+ flush_workqueue(cfid_put_wq);
|
|
}
|
|
|
|
/*
|
|
@@ -501,50 +521,71 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
|
|
{
|
|
struct cached_fids *cfids = tcon->cfids;
|
|
struct cached_fid *cfid, *q;
|
|
- LIST_HEAD(entry);
|
|
|
|
if (cfids == NULL)
|
|
return;
|
|
|
|
+ /*
|
|
+ * Mark all the cfids as closed, and move them to the cfids->dying list.
|
|
+ * They'll be cleaned up later by cfids_invalidation_worker. Take
|
|
+ * a reference to each cfid during this process.
|
|
+ */
|
|
spin_lock(&cfids->cfid_list_lock);
|
|
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
|
|
- list_move(&cfid->entry, &entry);
|
|
+ list_move(&cfid->entry, &cfids->dying);
|
|
cfids->num_entries--;
|
|
cfid->is_open = false;
|
|
cfid->on_list = false;
|
|
- /* To prevent race with smb2_cached_lease_break() */
|
|
- kref_get(&cfid->refcount);
|
|
- }
|
|
- spin_unlock(&cfids->cfid_list_lock);
|
|
-
|
|
- list_for_each_entry_safe(cfid, q, &entry, entry) {
|
|
- list_del(&cfid->entry);
|
|
- cancel_work_sync(&cfid->lease_break);
|
|
if (cfid->has_lease) {
|
|
/*
|
|
- * We lease was never cancelled from the server so we
|
|
- * need to drop the reference.
|
|
+ * The lease was never cancelled from the server,
|
|
+ * so steal that reference.
|
|
*/
|
|
- spin_lock(&cfids->cfid_list_lock);
|
|
cfid->has_lease = false;
|
|
- spin_unlock(&cfids->cfid_list_lock);
|
|
- kref_put(&cfid->refcount, smb2_close_cached_fid);
|
|
- }
|
|
- /* Drop the extra reference opened above*/
|
|
- kref_put(&cfid->refcount, smb2_close_cached_fid);
|
|
+ } else
|
|
+ kref_get(&cfid->refcount);
|
|
}
|
|
+ /*
|
|
+ * Queue dropping of the dentries once locks have been dropped
|
|
+ */
|
|
+ if (!list_empty(&cfids->dying))
|
|
+ queue_work(cfid_put_wq, &cfids->invalidation_work);
|
|
+ spin_unlock(&cfids->cfid_list_lock);
|
|
}
|
|
|
|
static void
|
|
-smb2_cached_lease_break(struct work_struct *work)
|
|
+cached_dir_offload_close(struct work_struct *work)
|
|
{
|
|
struct cached_fid *cfid = container_of(work,
|
|
- struct cached_fid, lease_break);
|
|
+ struct cached_fid, close_work);
|
|
+ struct cifs_tcon *tcon = cfid->tcon;
|
|
+
|
|
+ WARN_ON(cfid->on_list);
|
|
|
|
- spin_lock(&cfid->cfids->cfid_list_lock);
|
|
- cfid->has_lease = false;
|
|
- spin_unlock(&cfid->cfids->cfid_list_lock);
|
|
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
|
+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cached_close);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Release the cached directory's dentry, and then queue work to drop cached
|
|
+ * directory itself (closing on server if needed).
|
|
+ *
|
|
+ * Must be called with a reference to the cached_fid and a reference to the
|
|
+ * tcon.
|
|
+ */
|
|
+static void cached_dir_put_work(struct work_struct *work)
|
|
+{
|
|
+ struct cached_fid *cfid = container_of(work, struct cached_fid,
|
|
+ put_work);
|
|
+ struct dentry *dentry;
|
|
+
|
|
+ spin_lock(&cfid->fid_lock);
|
|
+ dentry = cfid->dentry;
|
|
+ cfid->dentry = NULL;
|
|
+ spin_unlock(&cfid->fid_lock);
|
|
+
|
|
+ dput(dentry);
|
|
+ queue_work(serverclose_wq, &cfid->close_work);
|
|
}
|
|
|
|
int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
|
|
@@ -561,6 +602,7 @@ int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
|
|
!memcmp(lease_key,
|
|
cfid->fid.lease_key,
|
|
SMB2_LEASE_KEY_SIZE)) {
|
|
+ cfid->has_lease = false;
|
|
cfid->time = 0;
|
|
/*
|
|
* We found a lease remove it from the list
|
|
@@ -570,8 +612,10 @@ int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
|
|
cfid->on_list = false;
|
|
cfids->num_entries--;
|
|
|
|
- queue_work(cifsiod_wq,
|
|
- &cfid->lease_break);
|
|
+ ++tcon->tc_count;
|
|
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
|
|
+ netfs_trace_tcon_ref_get_cached_lease_break);
|
|
+ queue_work(cfid_put_wq, &cfid->put_work);
|
|
spin_unlock(&cfids->cfid_list_lock);
|
|
return true;
|
|
}
|
|
@@ -593,7 +637,8 @@ static struct cached_fid *init_cached_dir(const char *path)
|
|
return NULL;
|
|
}
|
|
|
|
- INIT_WORK(&cfid->lease_break, smb2_cached_lease_break);
|
|
+ INIT_WORK(&cfid->close_work, cached_dir_offload_close);
|
|
+ INIT_WORK(&cfid->put_work, cached_dir_put_work);
|
|
INIT_LIST_HEAD(&cfid->entry);
|
|
INIT_LIST_HEAD(&cfid->dirents.entries);
|
|
mutex_init(&cfid->dirents.de_mutex);
|
|
@@ -606,6 +651,9 @@ static void free_cached_dir(struct cached_fid *cfid)
|
|
{
|
|
struct cached_dirent *dirent, *q;
|
|
|
|
+ WARN_ON(work_pending(&cfid->close_work));
|
|
+ WARN_ON(work_pending(&cfid->put_work));
|
|
+
|
|
dput(cfid->dentry);
|
|
cfid->dentry = NULL;
|
|
|
|
@@ -623,10 +671,30 @@ static void free_cached_dir(struct cached_fid *cfid)
|
|
kfree(cfid);
|
|
}
|
|
|
|
+static void cfids_invalidation_worker(struct work_struct *work)
|
|
+{
|
|
+ struct cached_fids *cfids = container_of(work, struct cached_fids,
|
|
+ invalidation_work);
|
|
+ struct cached_fid *cfid, *q;
|
|
+ LIST_HEAD(entry);
|
|
+
|
|
+ spin_lock(&cfids->cfid_list_lock);
|
|
+ /* move cfids->dying to the local list */
|
|
+ list_cut_before(&entry, &cfids->dying, &cfids->dying);
|
|
+ spin_unlock(&cfids->cfid_list_lock);
|
|
+
|
|
+ list_for_each_entry_safe(cfid, q, &entry, entry) {
|
|
+ list_del(&cfid->entry);
|
|
+ /* Drop the ref-count acquired in invalidate_all_cached_dirs */
|
|
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
|
|
+ }
|
|
+}
|
|
+
|
|
static void cfids_laundromat_worker(struct work_struct *work)
|
|
{
|
|
struct cached_fids *cfids;
|
|
struct cached_fid *cfid, *q;
|
|
+ struct dentry *dentry;
|
|
LIST_HEAD(entry);
|
|
|
|
cfids = container_of(work, struct cached_fids, laundromat_work.work);
|
|
@@ -638,33 +706,42 @@ static void cfids_laundromat_worker(struct work_struct *work)
|
|
cfid->on_list = false;
|
|
list_move(&cfid->entry, &entry);
|
|
cfids->num_entries--;
|
|
- /* To prevent race with smb2_cached_lease_break() */
|
|
- kref_get(&cfid->refcount);
|
|
+ if (cfid->has_lease) {
|
|
+ /*
|
|
+ * Our lease has not yet been cancelled from the
|
|
+ * server. Steal that reference.
|
|
+ */
|
|
+ cfid->has_lease = false;
|
|
+ } else
|
|
+ kref_get(&cfid->refcount);
|
|
}
|
|
}
|
|
spin_unlock(&cfids->cfid_list_lock);
|
|
|
|
list_for_each_entry_safe(cfid, q, &entry, entry) {
|
|
list_del(&cfid->entry);
|
|
- /*
|
|
- * Cancel and wait for the work to finish in case we are racing
|
|
- * with it.
|
|
- */
|
|
- cancel_work_sync(&cfid->lease_break);
|
|
- if (cfid->has_lease) {
|
|
+
|
|
+ spin_lock(&cfid->fid_lock);
|
|
+ dentry = cfid->dentry;
|
|
+ cfid->dentry = NULL;
|
|
+ spin_unlock(&cfid->fid_lock);
|
|
+
|
|
+ dput(dentry);
|
|
+ if (cfid->is_open) {
|
|
+ spin_lock(&cifs_tcp_ses_lock);
|
|
+ ++cfid->tcon->tc_count;
|
|
+ trace_smb3_tcon_ref(cfid->tcon->debug_id, cfid->tcon->tc_count,
|
|
+ netfs_trace_tcon_ref_get_cached_laundromat);
|
|
+ spin_unlock(&cifs_tcp_ses_lock);
|
|
+ queue_work(serverclose_wq, &cfid->close_work);
|
|
+ } else
|
|
/*
|
|
- * Our lease has not yet been cancelled from the server
|
|
- * so we need to drop the reference.
|
|
+ * Drop the ref-count from above, either the lease-ref (if there
|
|
+ * was one) or the extra one acquired.
|
|
*/
|
|
- spin_lock(&cfids->cfid_list_lock);
|
|
- cfid->has_lease = false;
|
|
- spin_unlock(&cfids->cfid_list_lock);
|
|
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
|
- }
|
|
- /* Drop the extra reference opened above */
|
|
- kref_put(&cfid->refcount, smb2_close_cached_fid);
|
|
}
|
|
- queue_delayed_work(cifsiod_wq, &cfids->laundromat_work,
|
|
+ queue_delayed_work(cfid_put_wq, &cfids->laundromat_work,
|
|
dir_cache_timeout * HZ);
|
|
}
|
|
|
|
@@ -677,9 +754,11 @@ struct cached_fids *init_cached_dirs(void)
|
|
return NULL;
|
|
spin_lock_init(&cfids->cfid_list_lock);
|
|
INIT_LIST_HEAD(&cfids->entries);
|
|
+ INIT_LIST_HEAD(&cfids->dying);
|
|
|
|
+ INIT_WORK(&cfids->invalidation_work, cfids_invalidation_worker);
|
|
INIT_DELAYED_WORK(&cfids->laundromat_work, cfids_laundromat_worker);
|
|
- queue_delayed_work(cifsiod_wq, &cfids->laundromat_work,
|
|
+ queue_delayed_work(cfid_put_wq, &cfids->laundromat_work,
|
|
dir_cache_timeout * HZ);
|
|
|
|
return cfids;
|
|
@@ -698,6 +777,7 @@ void free_cached_dirs(struct cached_fids *cfids)
|
|
return;
|
|
|
|
cancel_delayed_work_sync(&cfids->laundromat_work);
|
|
+ cancel_work_sync(&cfids->invalidation_work);
|
|
|
|
spin_lock(&cfids->cfid_list_lock);
|
|
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
|
|
@@ -705,6 +785,11 @@ void free_cached_dirs(struct cached_fids *cfids)
|
|
cfid->is_open = false;
|
|
list_move(&cfid->entry, &entry);
|
|
}
|
|
+ list_for_each_entry_safe(cfid, q, &cfids->dying, entry) {
|
|
+ cfid->on_list = false;
|
|
+ cfid->is_open = false;
|
|
+ list_move(&cfid->entry, &entry);
|
|
+ }
|
|
spin_unlock(&cfids->cfid_list_lock);
|
|
|
|
list_for_each_entry_safe(cfid, q, &entry, entry) {
|
|
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
|
|
index 81ba0fd5cc16d6..1dfe79d947a62f 100644
|
|
--- a/fs/smb/client/cached_dir.h
|
|
+++ b/fs/smb/client/cached_dir.h
|
|
@@ -44,7 +44,8 @@ struct cached_fid {
|
|
spinlock_t fid_lock;
|
|
struct cifs_tcon *tcon;
|
|
struct dentry *dentry;
|
|
- struct work_struct lease_break;
|
|
+ struct work_struct put_work;
|
|
+ struct work_struct close_work;
|
|
struct smb2_file_all_info file_all_info;
|
|
struct cached_dirents dirents;
|
|
};
|
|
@@ -53,10 +54,13 @@ struct cached_fid {
|
|
struct cached_fids {
|
|
/* Must be held when:
|
|
* - accessing the cfids->entries list
|
|
+ * - accessing the cfids->dying list
|
|
*/
|
|
spinlock_t cfid_list_lock;
|
|
int num_entries;
|
|
struct list_head entries;
|
|
+ struct list_head dying;
|
|
+ struct work_struct invalidation_work;
|
|
struct delayed_work laundromat_work;
|
|
};
|
|
|
|
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
|
|
index 2d9f8bdb6d4efe..6ed0f2548232f9 100644
|
|
--- a/fs/smb/client/cifsfs.c
|
|
+++ b/fs/smb/client/cifsfs.c
|
|
@@ -156,6 +156,7 @@ struct workqueue_struct *fileinfo_put_wq;
|
|
struct workqueue_struct *cifsoplockd_wq;
|
|
struct workqueue_struct *deferredclose_wq;
|
|
struct workqueue_struct *serverclose_wq;
|
|
+struct workqueue_struct *cfid_put_wq;
|
|
__u32 cifs_lock_secret;
|
|
|
|
/*
|
|
@@ -1899,9 +1900,16 @@ init_cifs(void)
|
|
goto out_destroy_deferredclose_wq;
|
|
}
|
|
|
|
+ cfid_put_wq = alloc_workqueue("cfid_put_wq",
|
|
+ WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
|
|
+ if (!cfid_put_wq) {
|
|
+ rc = -ENOMEM;
|
|
+ goto out_destroy_serverclose_wq;
|
|
+ }
|
|
+
|
|
rc = cifs_init_inodecache();
|
|
if (rc)
|
|
- goto out_destroy_serverclose_wq;
|
|
+ goto out_destroy_cfid_put_wq;
|
|
|
|
rc = init_mids();
|
|
if (rc)
|
|
@@ -1963,6 +1971,8 @@ init_cifs(void)
|
|
destroy_mids();
|
|
out_destroy_inodecache:
|
|
cifs_destroy_inodecache();
|
|
+out_destroy_cfid_put_wq:
|
|
+ destroy_workqueue(cfid_put_wq);
|
|
out_destroy_serverclose_wq:
|
|
destroy_workqueue(serverclose_wq);
|
|
out_destroy_deferredclose_wq:
|
|
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
|
|
index 111540eff66e7d..6b57b167a49d80 100644
|
|
--- a/fs/smb/client/cifsglob.h
|
|
+++ b/fs/smb/client/cifsglob.h
|
|
@@ -592,6 +592,7 @@ struct smb_version_operations {
|
|
/* Check for STATUS_NETWORK_NAME_DELETED */
|
|
bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
|
|
int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb,
|
|
+ const char *full_path,
|
|
struct kvec *rsp_iov,
|
|
struct cifs_open_info_data *data);
|
|
int (*create_reparse_symlink)(const unsigned int xid,
|
|
@@ -2022,7 +2023,7 @@ require use of the stronger protocol */
|
|
* cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once
|
|
* ->can_cache_brlcks
|
|
* cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc
|
|
- * cached_fid->fid_mutex cifs_tcon->crfid tcon_info_alloc
|
|
+ * cached_fids->cfid_list_lock cifs_tcon->cfids->entries init_cached_dirs
|
|
* cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo
|
|
* cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
|
|
* ->invalidHandle initiate_cifs_search
|
|
@@ -2111,6 +2112,7 @@ extern struct workqueue_struct *fileinfo_put_wq;
|
|
extern struct workqueue_struct *cifsoplockd_wq;
|
|
extern struct workqueue_struct *deferredclose_wq;
|
|
extern struct workqueue_struct *serverclose_wq;
|
|
+extern struct workqueue_struct *cfid_put_wq;
|
|
extern __u32 cifs_lock_secret;
|
|
|
|
extern mempool_t *cifs_sm_req_poolp;
|
|
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
|
|
index fbc358c09da3b1..fa7901ad3b80b4 100644
|
|
--- a/fs/smb/client/cifsproto.h
|
|
+++ b/fs/smb/client/cifsproto.h
|
|
@@ -679,6 +679,7 @@ char *extract_hostname(const char *unc);
|
|
char *extract_sharename(const char *unc);
|
|
int parse_reparse_point(struct reparse_data_buffer *buf,
|
|
u32 plen, struct cifs_sb_info *cifs_sb,
|
|
+ const char *full_path,
|
|
bool unicode, struct cifs_open_info_data *data);
|
|
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
|
|
struct dentry *dentry, struct cifs_tcon *tcon,
|
|
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
|
|
index 1df0a6edcc2167..7b850c40b2f320 100644
|
|
--- a/fs/smb/client/connect.c
|
|
+++ b/fs/smb/client/connect.c
|
|
@@ -1908,11 +1908,35 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
|
CIFS_MAX_USERNAME_LEN))
|
|
return 0;
|
|
if ((ctx->username && strlen(ctx->username) != 0) &&
|
|
- ses->password != NULL &&
|
|
- strncmp(ses->password,
|
|
- ctx->password ? ctx->password : "",
|
|
- CIFS_MAX_PASSWORD_LEN))
|
|
- return 0;
|
|
+ ses->password != NULL) {
|
|
+
|
|
+ /* New mount can only share sessions with an existing mount if:
|
|
+ * 1. Both password and password2 match, or
|
|
+ * 2. password2 of the old mount matches password of the new mount
|
|
+ * and password of the old mount matches password2 of the new
|
|
+ * mount
|
|
+ */
|
|
+ if (ses->password2 != NULL && ctx->password2 != NULL) {
|
|
+ if (!((strncmp(ses->password, ctx->password ?
|
|
+ ctx->password : "", CIFS_MAX_PASSWORD_LEN) == 0 &&
|
|
+ strncmp(ses->password2, ctx->password2,
|
|
+ CIFS_MAX_PASSWORD_LEN) == 0) ||
|
|
+ (strncmp(ses->password, ctx->password2,
|
|
+ CIFS_MAX_PASSWORD_LEN) == 0 &&
|
|
+ strncmp(ses->password2, ctx->password ?
|
|
+ ctx->password : "", CIFS_MAX_PASSWORD_LEN) == 0)))
|
|
+ return 0;
|
|
+
|
|
+ } else if ((ses->password2 == NULL && ctx->password2 != NULL) ||
|
|
+ (ses->password2 != NULL && ctx->password2 == NULL)) {
|
|
+ return 0;
|
|
+
|
|
+ } else {
|
|
+ if (strncmp(ses->password, ctx->password ?
|
|
+ ctx->password : "", CIFS_MAX_PASSWORD_LEN))
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
if (strcmp(ctx->local_nls->charset, ses->local_nls->charset))
|
|
@@ -2256,6 +2280,7 @@ struct cifs_ses *
|
|
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|
{
|
|
int rc = 0;
|
|
+ int retries = 0;
|
|
unsigned int xid;
|
|
struct cifs_ses *ses;
|
|
struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
|
|
@@ -2274,6 +2299,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|
cifs_dbg(FYI, "Session needs reconnect\n");
|
|
|
|
mutex_lock(&ses->session_mutex);
|
|
+
|
|
+retry_old_session:
|
|
rc = cifs_negotiate_protocol(xid, ses, server);
|
|
if (rc) {
|
|
mutex_unlock(&ses->session_mutex);
|
|
@@ -2286,6 +2313,13 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|
rc = cifs_setup_session(xid, ses, server,
|
|
ctx->local_nls);
|
|
if (rc) {
|
|
+ if (((rc == -EACCES) || (rc == -EKEYEXPIRED) ||
|
|
+ (rc == -EKEYREVOKED)) && !retries && ses->password2) {
|
|
+ retries++;
|
|
+ cifs_dbg(FYI, "Session reconnect failed, retrying with alternate password\n");
|
|
+ swap(ses->password, ses->password2);
|
|
+ goto retry_old_session;
|
|
+ }
|
|
mutex_unlock(&ses->session_mutex);
|
|
/* problem -- put our reference */
|
|
cifs_put_smb_ses(ses);
|
|
@@ -2361,6 +2395,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|
ses->chans_need_reconnect = 1;
|
|
spin_unlock(&ses->chan_lock);
|
|
|
|
+retry_new_session:
|
|
mutex_lock(&ses->session_mutex);
|
|
rc = cifs_negotiate_protocol(xid, ses, server);
|
|
if (!rc)
|
|
@@ -2373,8 +2408,16 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
|
|
sizeof(ses->smb3signingkey));
|
|
spin_unlock(&ses->chan_lock);
|
|
|
|
- if (rc)
|
|
- goto get_ses_fail;
|
|
+ if (rc) {
|
|
+ if (((rc == -EACCES) || (rc == -EKEYEXPIRED) ||
|
|
+ (rc == -EKEYREVOKED)) && !retries && ses->password2) {
|
|
+ retries++;
|
|
+ cifs_dbg(FYI, "Session setup failed, retrying with alternate password\n");
|
|
+ swap(ses->password, ses->password2);
|
|
+ goto retry_new_session;
|
|
+ } else
|
|
+ goto get_ses_fail;
|
|
+ }
|
|
|
|
/*
|
|
* success, put it on the list and add it as first channel
|
|
@@ -2558,7 +2601,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
|
|
|
if (ses->server->dialect >= SMB20_PROT_ID &&
|
|
(ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING))
|
|
- nohandlecache = ctx->nohandlecache;
|
|
+ nohandlecache = ctx->nohandlecache || !dir_cache_timeout;
|
|
else
|
|
nohandlecache = true;
|
|
tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new);
|
|
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
|
|
index 8d7484400fe8e1..4e77ba191ef87e 100644
|
|
--- a/fs/smb/client/fs_context.c
|
|
+++ b/fs/smb/client/fs_context.c
|
|
@@ -888,12 +888,37 @@ do { \
|
|
cifs_sb->ctx->field = NULL; \
|
|
} while (0)
|
|
|
|
+int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
|
|
+{
|
|
+ if (ses->password &&
|
|
+ cifs_sb->ctx->password &&
|
|
+ strcmp(ses->password, cifs_sb->ctx->password)) {
|
|
+ kfree_sensitive(cifs_sb->ctx->password);
|
|
+ cifs_sb->ctx->password = kstrdup(ses->password, GFP_KERNEL);
|
|
+ if (!cifs_sb->ctx->password)
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ if (ses->password2 &&
|
|
+ cifs_sb->ctx->password2 &&
|
|
+ strcmp(ses->password2, cifs_sb->ctx->password2)) {
|
|
+ kfree_sensitive(cifs_sb->ctx->password2);
|
|
+ cifs_sb->ctx->password2 = kstrdup(ses->password2, GFP_KERNEL);
|
|
+ if (!cifs_sb->ctx->password2) {
|
|
+ kfree_sensitive(cifs_sb->ctx->password);
|
|
+ cifs_sb->ctx->password = NULL;
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int smb3_reconfigure(struct fs_context *fc)
|
|
{
|
|
struct smb3_fs_context *ctx = smb3_fc2context(fc);
|
|
struct dentry *root = fc->root;
|
|
struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
|
|
struct cifs_ses *ses = cifs_sb_master_tcon(cifs_sb)->ses;
|
|
+ char *new_password = NULL, *new_password2 = NULL;
|
|
bool need_recon = false;
|
|
int rc;
|
|
|
|
@@ -913,21 +938,63 @@ static int smb3_reconfigure(struct fs_context *fc)
|
|
STEAL_STRING(cifs_sb, ctx, UNC);
|
|
STEAL_STRING(cifs_sb, ctx, source);
|
|
STEAL_STRING(cifs_sb, ctx, username);
|
|
+
|
|
if (need_recon == false)
|
|
STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
|
|
else {
|
|
- kfree_sensitive(ses->password);
|
|
- ses->password = kstrdup(ctx->password, GFP_KERNEL);
|
|
- if (!ses->password)
|
|
- return -ENOMEM;
|
|
- kfree_sensitive(ses->password2);
|
|
- ses->password2 = kstrdup(ctx->password2, GFP_KERNEL);
|
|
- if (!ses->password2) {
|
|
- kfree_sensitive(ses->password);
|
|
- ses->password = NULL;
|
|
+ if (ctx->password) {
|
|
+ new_password = kstrdup(ctx->password, GFP_KERNEL);
|
|
+ if (!new_password)
|
|
+ return -ENOMEM;
|
|
+ } else
|
|
+ STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * if a new password2 has been specified, then reset it's value
|
|
+ * inside the ses struct
|
|
+ */
|
|
+ if (ctx->password2) {
|
|
+ new_password2 = kstrdup(ctx->password2, GFP_KERNEL);
|
|
+ if (!new_password2) {
|
|
+ kfree_sensitive(new_password);
|
|
return -ENOMEM;
|
|
}
|
|
+ } else
|
|
+ STEAL_STRING_SENSITIVE(cifs_sb, ctx, password2);
|
|
+
|
|
+ /*
|
|
+ * we may update the passwords in the ses struct below. Make sure we do
|
|
+ * not race with smb2_reconnect
|
|
+ */
|
|
+ mutex_lock(&ses->session_mutex);
|
|
+
|
|
+ /*
|
|
+ * smb2_reconnect may swap password and password2 in case session setup
|
|
+ * failed. First get ctx passwords in sync with ses passwords. It should
|
|
+ * be okay to do this even if this function were to return an error at a
|
|
+ * later stage
|
|
+ */
|
|
+ rc = smb3_sync_session_ctx_passwords(cifs_sb, ses);
|
|
+ if (rc) {
|
|
+ mutex_unlock(&ses->session_mutex);
|
|
+ return rc;
|
|
}
|
|
+
|
|
+ /*
|
|
+ * now that allocations for passwords are done, commit them
|
|
+ */
|
|
+ if (new_password) {
|
|
+ kfree_sensitive(ses->password);
|
|
+ ses->password = new_password;
|
|
+ }
|
|
+ if (new_password2) {
|
|
+ kfree_sensitive(ses->password2);
|
|
+ ses->password2 = new_password2;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&ses->session_mutex);
|
|
+
|
|
STEAL_STRING(cifs_sb, ctx, domainname);
|
|
STEAL_STRING(cifs_sb, ctx, nodename);
|
|
STEAL_STRING(cifs_sb, ctx, iocharset);
|
|
diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
|
|
index cf577ec0dd0ac4..bbd2063ab838d3 100644
|
|
--- a/fs/smb/client/fs_context.h
|
|
+++ b/fs/smb/client/fs_context.h
|
|
@@ -298,6 +298,7 @@ static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *f
|
|
}
|
|
|
|
extern int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx);
|
|
+extern int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
|
|
extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
|
|
|
|
/*
|
|
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
|
|
index e7970cbeb86111..0f73f0dc6deb36 100644
|
|
--- a/fs/smb/client/inode.c
|
|
+++ b/fs/smb/client/inode.c
|
|
@@ -1054,6 +1054,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
|
|
rc = 0;
|
|
} else if (iov && server->ops->parse_reparse_point) {
|
|
rc = server->ops->parse_reparse_point(cifs_sb,
|
|
+ full_path,
|
|
iov, data);
|
|
}
|
|
break;
|
|
@@ -2412,13 +2413,10 @@ cifs_dentry_needs_reval(struct dentry *dentry)
|
|
return true;
|
|
|
|
if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
|
|
- spin_lock(&cfid->fid_lock);
|
|
if (cfid->time && cifs_i->time > cfid->time) {
|
|
- spin_unlock(&cfid->fid_lock);
|
|
close_cached_dir(cfid);
|
|
return false;
|
|
}
|
|
- spin_unlock(&cfid->fid_lock);
|
|
close_cached_dir(cfid);
|
|
}
|
|
/*
|
|
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
|
|
index 74abbdf5026c73..f74d0a86f44a4e 100644
|
|
--- a/fs/smb/client/reparse.c
|
|
+++ b/fs/smb/client/reparse.c
|
|
@@ -35,6 +35,9 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
|
u16 len, plen;
|
|
int rc = 0;
|
|
|
|
+ if (strlen(symname) > REPARSE_SYM_PATH_MAX)
|
|
+ return -ENAMETOOLONG;
|
|
+
|
|
sym = kstrdup(symname, GFP_KERNEL);
|
|
if (!sym)
|
|
return -ENOMEM;
|
|
@@ -64,7 +67,7 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
|
if (rc < 0)
|
|
goto out;
|
|
|
|
- plen = 2 * UniStrnlen((wchar_t *)path, PATH_MAX);
|
|
+ plen = 2 * UniStrnlen((wchar_t *)path, REPARSE_SYM_PATH_MAX);
|
|
len = sizeof(*buf) + plen * 2;
|
|
buf = kzalloc(len, GFP_KERNEL);
|
|
if (!buf) {
|
|
@@ -532,9 +535,76 @@ static int parse_reparse_posix(struct reparse_posix_data *buf,
|
|
return 0;
|
|
}
|
|
|
|
+int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len,
|
|
+ bool unicode, bool relative,
|
|
+ const char *full_path,
|
|
+ struct cifs_sb_info *cifs_sb)
|
|
+{
|
|
+ char sep = CIFS_DIR_SEP(cifs_sb);
|
|
+ char *linux_target = NULL;
|
|
+ char *smb_target = NULL;
|
|
+ int levels;
|
|
+ int rc;
|
|
+ int i;
|
|
+
|
|
+ smb_target = cifs_strndup_from_utf16(buf, len, unicode, cifs_sb->local_nls);
|
|
+ if (!smb_target) {
|
|
+ rc = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (smb_target[0] == sep && relative) {
|
|
+ /*
|
|
+ * This is a relative SMB symlink from the top of the share,
|
|
+ * which is the top level directory of the Linux mount point.
|
|
+ * Linux does not support such relative symlinks, so convert
|
|
+ * it to the relative symlink from the current directory.
|
|
+ * full_path is the SMB path to the symlink (from which is
|
|
+ * extracted current directory) and smb_target is the SMB path
|
|
+ * where symlink points, therefore full_path must always be on
|
|
+ * the SMB share.
|
|
+ */
|
|
+ int smb_target_len = strlen(smb_target)+1;
|
|
+ levels = 0;
|
|
+ for (i = 1; full_path[i]; i++) { /* i=1 to skip leading sep */
|
|
+ if (full_path[i] == sep)
|
|
+ levels++;
|
|
+ }
|
|
+ linux_target = kmalloc(levels*3 + smb_target_len, GFP_KERNEL);
|
|
+ if (!linux_target) {
|
|
+ rc = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
+ for (i = 0; i < levels; i++) {
|
|
+ linux_target[i*3 + 0] = '.';
|
|
+ linux_target[i*3 + 1] = '.';
|
|
+ linux_target[i*3 + 2] = sep;
|
|
+ }
|
|
+ memcpy(linux_target + levels*3, smb_target+1, smb_target_len); /* +1 to skip leading sep */
|
|
+ } else {
|
|
+ linux_target = smb_target;
|
|
+ smb_target = NULL;
|
|
+ }
|
|
+
|
|
+ if (sep == '\\')
|
|
+ convert_delimiter(linux_target, '/');
|
|
+
|
|
+ rc = 0;
|
|
+ *target = linux_target;
|
|
+
|
|
+ cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, *target);
|
|
+
|
|
+out:
|
|
+ if (rc != 0)
|
|
+ kfree(linux_target);
|
|
+ kfree(smb_target);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym,
|
|
u32 plen, bool unicode,
|
|
struct cifs_sb_info *cifs_sb,
|
|
+ const char *full_path,
|
|
struct cifs_open_info_data *data)
|
|
{
|
|
unsigned int len;
|
|
@@ -549,20 +619,18 @@ static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym,
|
|
return -EIO;
|
|
}
|
|
|
|
- data->symlink_target = cifs_strndup_from_utf16(sym->PathBuffer + offs,
|
|
- len, unicode,
|
|
- cifs_sb->local_nls);
|
|
- if (!data->symlink_target)
|
|
- return -ENOMEM;
|
|
-
|
|
- convert_delimiter(data->symlink_target, '/');
|
|
- cifs_dbg(FYI, "%s: target path: %s\n", __func__, data->symlink_target);
|
|
-
|
|
- return 0;
|
|
+ return smb2_parse_native_symlink(&data->symlink_target,
|
|
+ sym->PathBuffer + offs,
|
|
+ len,
|
|
+ unicode,
|
|
+ le32_to_cpu(sym->Flags) & SYMLINK_FLAG_RELATIVE,
|
|
+ full_path,
|
|
+ cifs_sb);
|
|
}
|
|
|
|
int parse_reparse_point(struct reparse_data_buffer *buf,
|
|
u32 plen, struct cifs_sb_info *cifs_sb,
|
|
+ const char *full_path,
|
|
bool unicode, struct cifs_open_info_data *data)
|
|
{
|
|
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
|
@@ -577,7 +645,7 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
|
|
case IO_REPARSE_TAG_SYMLINK:
|
|
return parse_reparse_symlink(
|
|
(struct reparse_symlink_data_buffer *)buf,
|
|
- plen, unicode, cifs_sb, data);
|
|
+ plen, unicode, cifs_sb, full_path, data);
|
|
case IO_REPARSE_TAG_LX_SYMLINK:
|
|
case IO_REPARSE_TAG_AF_UNIX:
|
|
case IO_REPARSE_TAG_LX_FIFO:
|
|
@@ -593,6 +661,7 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
|
|
}
|
|
|
|
int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
|
|
+ const char *full_path,
|
|
struct kvec *rsp_iov,
|
|
struct cifs_open_info_data *data)
|
|
{
|
|
@@ -602,7 +671,7 @@ int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
|
|
|
|
buf = (struct reparse_data_buffer *)((u8 *)io +
|
|
le32_to_cpu(io->OutputOffset));
|
|
- return parse_reparse_point(buf, plen, cifs_sb, true, data);
|
|
+ return parse_reparse_point(buf, plen, cifs_sb, full_path, true, data);
|
|
}
|
|
|
|
static void wsl_to_fattr(struct cifs_open_info_data *data,
|
|
diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
|
|
index 158e7b7aae646c..ff05b0e75c9284 100644
|
|
--- a/fs/smb/client/reparse.h
|
|
+++ b/fs/smb/client/reparse.h
|
|
@@ -12,6 +12,8 @@
|
|
#include "fs_context.h"
|
|
#include "cifsglob.h"
|
|
|
|
+#define REPARSE_SYM_PATH_MAX 4060
|
|
+
|
|
/*
|
|
* Used only by cifs.ko to ignore reparse points from files when client or
|
|
* server doesn't support FSCTL_GET_REPARSE_POINT.
|
|
@@ -115,7 +117,9 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
|
|
int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
|
|
struct dentry *dentry, struct cifs_tcon *tcon,
|
|
const char *full_path, umode_t mode, dev_t dev);
|
|
-int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, struct kvec *rsp_iov,
|
|
+int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
|
|
+ const char *full_path,
|
|
+ struct kvec *rsp_iov,
|
|
struct cifs_open_info_data *data);
|
|
|
|
#endif /* _CIFS_REPARSE_H */
|
|
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
|
|
index e3a195824b4037..b0c0572f9d1fbc 100644
|
|
--- a/fs/smb/client/smb1ops.c
|
|
+++ b/fs/smb/client/smb1ops.c
|
|
@@ -994,17 +994,17 @@ static int cifs_query_symlink(const unsigned int xid,
|
|
}
|
|
|
|
static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb,
|
|
+ const char *full_path,
|
|
struct kvec *rsp_iov,
|
|
struct cifs_open_info_data *data)
|
|
{
|
|
struct reparse_data_buffer *buf;
|
|
TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
|
|
- bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
|
|
u32 plen = le16_to_cpu(io->ByteCount);
|
|
|
|
buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
|
|
le32_to_cpu(io->DataOffset));
|
|
- return parse_reparse_point(buf, plen, cifs_sb, unicode, data);
|
|
+ return parse_reparse_point(buf, plen, cifs_sb, full_path, true, data);
|
|
}
|
|
|
|
static bool
|
|
diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c
|
|
index e0ee96d69d4952..db9c807115c605 100644
|
|
--- a/fs/smb/client/smb2file.c
|
|
+++ b/fs/smb/client/smb2file.c
|
|
@@ -63,12 +63,12 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov)
|
|
return sym;
|
|
}
|
|
|
|
-int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path)
|
|
+int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov,
|
|
+ const char *full_path, char **path)
|
|
{
|
|
struct smb2_symlink_err_rsp *sym;
|
|
unsigned int sub_offs, sub_len;
|
|
unsigned int print_offs, print_len;
|
|
- char *s;
|
|
|
|
if (!cifs_sb || !iov || !iov->iov_base || !iov->iov_len || !path)
|
|
return -EINVAL;
|
|
@@ -86,15 +86,13 @@ int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec
|
|
iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len)
|
|
return -EINVAL;
|
|
|
|
- s = cifs_strndup_from_utf16((char *)sym->PathBuffer + sub_offs, sub_len, true,
|
|
- cifs_sb->local_nls);
|
|
- if (!s)
|
|
- return -ENOMEM;
|
|
- convert_delimiter(s, '/');
|
|
- cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, s);
|
|
-
|
|
- *path = s;
|
|
- return 0;
|
|
+ return smb2_parse_native_symlink(path,
|
|
+ (char *)sym->PathBuffer + sub_offs,
|
|
+ sub_len,
|
|
+ true,
|
|
+ le32_to_cpu(sym->Flags) & SYMLINK_FLAG_RELATIVE,
|
|
+ full_path,
|
|
+ cifs_sb);
|
|
}
|
|
|
|
int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, void *buf)
|
|
@@ -126,6 +124,7 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32
|
|
goto out;
|
|
if (hdr->Status == STATUS_STOPPED_ON_SYMLINK) {
|
|
rc = smb2_parse_symlink_response(oparms->cifs_sb, &err_iov,
|
|
+ oparms->path,
|
|
&data->symlink_target);
|
|
if (!rc) {
|
|
memset(smb2_data, 0, sizeof(*smb2_data));
|
|
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
|
|
index daa841dfbadcf4..8ea476b1fe199d 100644
|
|
--- a/fs/smb/client/smb2inode.c
|
|
+++ b/fs/smb/client/smb2inode.c
|
|
@@ -828,6 +828,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
|
static int parse_create_response(struct cifs_open_info_data *data,
|
|
struct cifs_sb_info *cifs_sb,
|
|
+ const char *full_path,
|
|
const struct kvec *iov)
|
|
{
|
|
struct smb2_create_rsp *rsp = iov->iov_base;
|
|
@@ -841,6 +842,7 @@ static int parse_create_response(struct cifs_open_info_data *data,
|
|
break;
|
|
case STATUS_STOPPED_ON_SYMLINK:
|
|
rc = smb2_parse_symlink_response(cifs_sb, iov,
|
|
+ full_path,
|
|
&data->symlink_target);
|
|
if (rc)
|
|
return rc;
|
|
@@ -930,14 +932,14 @@ int smb2_query_path_info(const unsigned int xid,
|
|
|
|
switch (rc) {
|
|
case 0:
|
|
- rc = parse_create_response(data, cifs_sb, &out_iov[0]);
|
|
+ rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
|
|
break;
|
|
case -EOPNOTSUPP:
|
|
/*
|
|
* BB TODO: When support for special files added to Samba
|
|
* re-verify this path.
|
|
*/
|
|
- rc = parse_create_response(data, cifs_sb, &out_iov[0]);
|
|
+ rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
|
|
if (rc || !data->reparse_point)
|
|
goto out;
|
|
|
|
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
|
|
index ab6e79be2c15dd..6645f147d57c29 100644
|
|
--- a/fs/smb/client/smb2ops.c
|
|
+++ b/fs/smb/client/smb2ops.c
|
|
@@ -4016,7 +4016,7 @@ map_oplock_to_lease(u8 oplock)
|
|
if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE)
|
|
return SMB2_LEASE_WRITE_CACHING_LE | SMB2_LEASE_READ_CACHING_LE;
|
|
else if (oplock == SMB2_OPLOCK_LEVEL_II)
|
|
- return SMB2_LEASE_READ_CACHING_LE;
|
|
+ return SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE;
|
|
else if (oplock == SMB2_OPLOCK_LEVEL_BATCH)
|
|
return SMB2_LEASE_HANDLE_CACHING_LE | SMB2_LEASE_READ_CACHING_LE |
|
|
SMB2_LEASE_WRITE_CACHING_LE;
|
|
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
|
|
index a86a3fbfb5a49c..38b26468eb0c53 100644
|
|
--- a/fs/smb/client/smb2pdu.c
|
|
+++ b/fs/smb/client/smb2pdu.c
|
|
@@ -1228,7 +1228,9 @@ SMB2_negotiate(const unsigned int xid,
|
|
* SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
|
|
* Set the cipher type manually.
|
|
*/
|
|
- if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
|
|
+ if ((server->dialect == SMB30_PROT_ID ||
|
|
+ server->dialect == SMB302_PROT_ID) &&
|
|
+ (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
|
|
server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
|
|
|
|
security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
|
|
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
|
|
index f6fafa997e991d..613667b46c5802 100644
|
|
--- a/fs/smb/client/smb2proto.h
|
|
+++ b/fs/smb/client/smb2proto.h
|
|
@@ -113,7 +113,14 @@ extern int smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
|
struct cifs_sb_info *cifs_sb,
|
|
const unsigned char *path, char *pbuf,
|
|
unsigned int *pbytes_read);
|
|
-int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path);
|
|
+int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len,
|
|
+ bool unicode, bool relative,
|
|
+ const char *full_path,
|
|
+ struct cifs_sb_info *cifs_sb);
|
|
+int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb,
|
|
+ const struct kvec *iov,
|
|
+ const char *full_path,
|
|
+ char **path);
|
|
int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
|
|
void *buf);
|
|
extern int smb2_unlock_range(struct cifsFileInfo *cfile,
|
|
diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h
|
|
index 604e52876cd2d9..563cb4d8edf0c3 100644
|
|
--- a/fs/smb/client/trace.h
|
|
+++ b/fs/smb/client/trace.h
|
|
@@ -27,6 +27,8 @@
|
|
EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \
|
|
EM(netfs_trace_tcon_ref_free_ipc_fail, "FRE Ipc-F ") \
|
|
EM(netfs_trace_tcon_ref_free_reconnect_server, "FRE Reconn") \
|
|
+ EM(netfs_trace_tcon_ref_get_cached_laundromat, "GET Ch-Lau") \
|
|
+ EM(netfs_trace_tcon_ref_get_cached_lease_break, "GET Ch-Lea") \
|
|
EM(netfs_trace_tcon_ref_get_cancelled_close, "GET Cn-Cls") \
|
|
EM(netfs_trace_tcon_ref_get_dfs_refer, "GET DfsRef") \
|
|
EM(netfs_trace_tcon_ref_get_find, "GET Find ") \
|
|
@@ -35,6 +37,7 @@
|
|
EM(netfs_trace_tcon_ref_new, "NEW ") \
|
|
EM(netfs_trace_tcon_ref_new_ipc, "NEW Ipc ") \
|
|
EM(netfs_trace_tcon_ref_new_reconnect_server, "NEW Reconn") \
|
|
+ EM(netfs_trace_tcon_ref_put_cached_close, "PUT Ch-Cls") \
|
|
EM(netfs_trace_tcon_ref_put_cancelled_close, "PUT Cn-Cls") \
|
|
EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \
|
|
EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \
|
|
diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
|
|
index b6e0b71c281dcf..1450e007ac701d 100644
|
|
--- a/fs/smb/server/server.c
|
|
+++ b/fs/smb/server/server.c
|
|
@@ -276,8 +276,12 @@ static void handle_ksmbd_work(struct work_struct *wk)
|
|
* disconnection. waitqueue_active is safe because it
|
|
* uses atomic operation for condition.
|
|
*/
|
|
+ atomic_inc(&conn->refcnt);
|
|
if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
|
|
wake_up(&conn->r_count_q);
|
|
+
|
|
+ if (atomic_dec_and_test(&conn->refcnt))
|
|
+ kfree(conn);
|
|
}
|
|
|
|
/**
|
|
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
|
|
index b08fb28d16b55b..3409488d39ba1c 100644
|
|
--- a/fs/ubifs/super.c
|
|
+++ b/fs/ubifs/super.c
|
|
@@ -777,10 +777,10 @@ static void init_constants_master(struct ubifs_info *c)
|
|
* necessary to report something for the 'statfs()' call.
|
|
*
|
|
* Subtract the LEB reserved for GC, the LEB which is reserved for
|
|
- * deletions, minimum LEBs for the index, and assume only one journal
|
|
- * head is available.
|
|
+ * deletions, minimum LEBs for the index, the LEBs which are reserved
|
|
+ * for each journal head.
|
|
*/
|
|
- tmp64 = c->main_lebs - 1 - 1 - MIN_INDEX_LEBS - c->jhead_cnt + 1;
|
|
+ tmp64 = c->main_lebs - 1 - 1 - MIN_INDEX_LEBS - c->jhead_cnt;
|
|
tmp64 *= (long long)c->leb_size - c->leb_overhead;
|
|
tmp64 = ubifs_reported_space(c, tmp64);
|
|
c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
|
|
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
|
|
index a55e04822d16e9..7c43e0ccf6d47d 100644
|
|
--- a/fs/ubifs/tnc_commit.c
|
|
+++ b/fs/ubifs/tnc_commit.c
|
|
@@ -657,6 +657,8 @@ static int get_znodes_to_commit(struct ubifs_info *c)
|
|
znode->alt = 0;
|
|
cnext = find_next_dirty(znode);
|
|
if (!cnext) {
|
|
+ ubifs_assert(c, !znode->parent);
|
|
+ znode->cparent = NULL;
|
|
znode->cnext = c->cnext;
|
|
break;
|
|
}
|
|
diff --git a/fs/unicode/utf8-core.c b/fs/unicode/utf8-core.c
|
|
index 8395066341a437..0400824ef4936e 100644
|
|
--- a/fs/unicode/utf8-core.c
|
|
+++ b/fs/unicode/utf8-core.c
|
|
@@ -198,7 +198,7 @@ struct unicode_map *utf8_load(unsigned int version)
|
|
return um;
|
|
|
|
out_symbol_put:
|
|
- symbol_put(um->tables);
|
|
+ symbol_put(utf8_data_table);
|
|
out_free_um:
|
|
kfree(um);
|
|
return ERR_PTR(-EINVAL);
|
|
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
|
|
index 424acdd4b0fca4..50dd27b0f21577 100644
|
|
--- a/fs/xfs/libxfs/xfs_sb.c
|
|
+++ b/fs/xfs/libxfs/xfs_sb.c
|
|
@@ -260,13 +260,6 @@ xfs_validate_sb_write(
|
|
* the kernel cannot support since we checked for unsupported bits in
|
|
* the read verifier, which means that memory is corrupt.
|
|
*/
|
|
- if (xfs_sb_has_compat_feature(sbp, XFS_SB_FEAT_COMPAT_UNKNOWN)) {
|
|
- xfs_warn(mp,
|
|
-"Corruption detected in superblock compatible features (0x%x)!",
|
|
- (sbp->sb_features_compat & XFS_SB_FEAT_COMPAT_UNKNOWN));
|
|
- return -EFSCORRUPTED;
|
|
- }
|
|
-
|
|
if (!xfs_is_readonly(mp) &&
|
|
xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
|
|
xfs_alert(mp,
|
|
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
|
|
index 9f9d3abad2cf35..d11de0fa5c5f80 100644
|
|
--- a/fs/xfs/xfs_log_recover.c
|
|
+++ b/fs/xfs/xfs_log_recover.c
|
|
@@ -2456,7 +2456,10 @@ xlog_recover_process_data(
|
|
|
|
ohead = (struct xlog_op_header *)dp;
|
|
dp += sizeof(*ohead);
|
|
- ASSERT(dp <= end);
|
|
+ if (dp > end) {
|
|
+ xfs_warn(log->l_mp, "%s: op header overrun", __func__);
|
|
+ return -EFSCORRUPTED;
|
|
+ }
|
|
|
|
/* errors will abort recovery */
|
|
error = xlog_recover_process_ophdr(log, rhash, rhead, ohead,
|
|
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
|
|
index 63029bc7c9dd01..7e11ca6f86dcda 100644
|
|
--- a/include/asm-generic/vmlinux.lds.h
|
|
+++ b/include/asm-generic/vmlinux.lds.h
|
|
@@ -139,14 +139,6 @@
|
|
* often happens at runtime)
|
|
*/
|
|
|
|
-#if defined(CONFIG_MEMORY_HOTPLUG)
|
|
-#define MEM_KEEP(sec) *(.mem##sec)
|
|
-#define MEM_DISCARD(sec)
|
|
-#else
|
|
-#define MEM_KEEP(sec)
|
|
-#define MEM_DISCARD(sec) *(.mem##sec)
|
|
-#endif
|
|
-
|
|
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE
|
|
#define KEEP_PATCHABLE KEEP(*(__patchable_function_entries))
|
|
#define PATCHABLE_DISCARDS
|
|
@@ -355,10 +347,9 @@
|
|
*(.data..decrypted) \
|
|
*(.ref.data) \
|
|
*(.data..shared_aligned) /* percpu related */ \
|
|
- MEM_KEEP(init.data*) \
|
|
- *(.data.unlikely) \
|
|
+ *(.data..unlikely) \
|
|
__start_once = .; \
|
|
- *(.data.once) \
|
|
+ *(.data..once) \
|
|
__end_once = .; \
|
|
STRUCT_ALIGN(); \
|
|
*(__tracepoints) \
|
|
@@ -519,7 +510,6 @@
|
|
/* __*init sections */ \
|
|
__init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) { \
|
|
*(.ref.rodata) \
|
|
- MEM_KEEP(init.rodata) \
|
|
} \
|
|
\
|
|
/* Built-in module parameters. */ \
|
|
@@ -570,8 +560,7 @@
|
|
*(.text.unknown .text.unknown.*) \
|
|
NOINSTR_TEXT \
|
|
*(.ref.text) \
|
|
- *(.text.asan.* .text.tsan.*) \
|
|
- MEM_KEEP(init.text*) \
|
|
+ *(.text.asan.* .text.tsan.*)
|
|
|
|
|
|
/* sched.text is aling to function alignment to secure we have same
|
|
@@ -678,7 +667,6 @@
|
|
#define INIT_DATA \
|
|
KEEP(*(SORT(___kentry+*))) \
|
|
*(.init.data .init.data.*) \
|
|
- MEM_DISCARD(init.data*) \
|
|
KERNEL_CTORS() \
|
|
MCOUNT_REC() \
|
|
*(.init.rodata .init.rodata.*) \
|
|
@@ -686,7 +674,6 @@
|
|
TRACE_SYSCALLS() \
|
|
KPROBE_BLACKLIST() \
|
|
ERROR_INJECT_WHITELIST() \
|
|
- MEM_DISCARD(init.rodata) \
|
|
CLK_OF_TABLES() \
|
|
RESERVEDMEM_OF_TABLES() \
|
|
TIMER_OF_TABLES() \
|
|
@@ -704,8 +691,7 @@
|
|
|
|
#define INIT_TEXT \
|
|
*(.init.text .init.text.*) \
|
|
- *(.text.startup) \
|
|
- MEM_DISCARD(init.text*)
|
|
+ *(.text.startup)
|
|
|
|
#define EXIT_DATA \
|
|
*(.exit.data .exit.data.*) \
|
|
diff --git a/include/linux/avf/virtchnl.h b/include/linux/avf/virtchnl.h
|
|
index 6e950594215a0f..99ae7960a8d13c 100644
|
|
--- a/include/linux/avf/virtchnl.h
|
|
+++ b/include/linux/avf/virtchnl.h
|
|
@@ -245,6 +245,7 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
|
|
#define VIRTCHNL_VF_OFFLOAD_REQ_QUEUES BIT(6)
|
|
/* used to negotiate communicating link speeds in Mbps */
|
|
#define VIRTCHNL_VF_CAP_ADV_LINK_SPEED BIT(7)
|
|
+#define VIRTCHNL_VF_OFFLOAD_CRC BIT(10)
|
|
#define VIRTCHNL_VF_OFFLOAD_VLAN_V2 BIT(15)
|
|
#define VIRTCHNL_VF_OFFLOAD_VLAN BIT(16)
|
|
#define VIRTCHNL_VF_OFFLOAD_RX_POLLING BIT(17)
|
|
@@ -300,7 +301,13 @@ VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_txq_info);
|
|
/* VIRTCHNL_OP_CONFIG_RX_QUEUE
|
|
* VF sends this message to set up parameters for one RX queue.
|
|
* External data buffer contains one instance of virtchnl_rxq_info.
|
|
- * PF configures requested queue and returns a status code.
|
|
+ * PF configures requested queue and returns a status code. The
|
|
+ * crc_disable flag disables CRC stripping on the VF. Setting
|
|
+ * the crc_disable flag to 1 will disable CRC stripping for each
|
|
+ * queue in the VF where the flag is set. The VIRTCHNL_VF_OFFLOAD_CRC
|
|
+ * offload must have been set prior to sending this info or the PF
|
|
+ * will ignore the request. This flag should be set the same for
|
|
+ * all of the queues for a VF.
|
|
*/
|
|
|
|
/* Rx queue config info */
|
|
@@ -312,7 +319,7 @@ struct virtchnl_rxq_info {
|
|
u16 splithdr_enabled; /* deprecated with AVF 1.0 */
|
|
u32 databuffer_size;
|
|
u32 max_pkt_size;
|
|
- u8 pad0;
|
|
+ u8 crc_disable;
|
|
u8 rxdid;
|
|
u8 pad1[2];
|
|
u64 dma_ring_addr;
|
|
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
|
|
index a7b65d4ab616e2..ef35e9a9878c6a 100644
|
|
--- a/include/linux/blkdev.h
|
|
+++ b/include/linux/blkdev.h
|
|
@@ -1184,7 +1184,7 @@ static inline unsigned int queue_io_min(const struct request_queue *q)
|
|
return q->limits.io_min;
|
|
}
|
|
|
|
-static inline int bdev_io_min(struct block_device *bdev)
|
|
+static inline unsigned int bdev_io_min(struct block_device *bdev)
|
|
{
|
|
return queue_io_min(bdev_get_queue(bdev));
|
|
}
|
|
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
|
|
index 92919d52f7e1b2..cb8e97665eaa59 100644
|
|
--- a/include/linux/bpf_verifier.h
|
|
+++ b/include/linux/bpf_verifier.h
|
|
@@ -319,12 +319,34 @@ struct bpf_func_state {
|
|
struct bpf_stack_state *stack;
|
|
};
|
|
|
|
-struct bpf_idx_pair {
|
|
- u32 prev_idx;
|
|
+#define MAX_CALL_FRAMES 8
|
|
+
|
|
+/* instruction history flags, used in bpf_jmp_history_entry.flags field */
|
|
+enum {
|
|
+ /* instruction references stack slot through PTR_TO_STACK register;
|
|
+ * we also store stack's frame number in lower 3 bits (MAX_CALL_FRAMES is 8)
|
|
+ * and accessed stack slot's index in next 6 bits (MAX_BPF_STACK is 512,
|
|
+ * 8 bytes per slot, so slot index (spi) is [0, 63])
|
|
+ */
|
|
+ INSN_F_FRAMENO_MASK = 0x7, /* 3 bits */
|
|
+
|
|
+ INSN_F_SPI_MASK = 0x3f, /* 6 bits */
|
|
+ INSN_F_SPI_SHIFT = 3, /* shifted 3 bits to the left */
|
|
+
|
|
+ INSN_F_STACK_ACCESS = BIT(9), /* we need 10 bits total */
|
|
+};
|
|
+
|
|
+static_assert(INSN_F_FRAMENO_MASK + 1 >= MAX_CALL_FRAMES);
|
|
+static_assert(INSN_F_SPI_MASK + 1 >= MAX_BPF_STACK / 8);
|
|
+
|
|
+struct bpf_jmp_history_entry {
|
|
u32 idx;
|
|
+ /* insn idx can't be bigger than 1 million */
|
|
+ u32 prev_idx : 22;
|
|
+ /* special flags, e.g., whether insn is doing register stack spill/load */
|
|
+ u32 flags : 10;
|
|
};
|
|
|
|
-#define MAX_CALL_FRAMES 8
|
|
/* Maximum number of register states that can exist at once */
|
|
#define BPF_ID_MAP_SIZE ((MAX_BPF_REG + MAX_BPF_STACK / BPF_REG_SIZE) * MAX_CALL_FRAMES)
|
|
struct bpf_verifier_state {
|
|
@@ -407,7 +429,7 @@ struct bpf_verifier_state {
|
|
* For most states jmp_history_cnt is [0-3].
|
|
* For loops can go up to ~40.
|
|
*/
|
|
- struct bpf_idx_pair *jmp_history;
|
|
+ struct bpf_jmp_history_entry *jmp_history;
|
|
u32 jmp_history_cnt;
|
|
u32 dfs_depth;
|
|
u32 callback_unroll_depth;
|
|
@@ -640,6 +662,7 @@ struct bpf_verifier_env {
|
|
int cur_stack;
|
|
} cfg;
|
|
struct backtrack_state bt;
|
|
+ struct bpf_jmp_history_entry *cur_hist_ent;
|
|
u32 pass_cnt; /* number of times do_check() was called */
|
|
u32 subprog_cnt;
|
|
/* number of instructions analyzed by the verifier */
|
|
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
|
|
index f5859b8c68b420..7e0a2efd90ca28 100644
|
|
--- a/include/linux/compiler_attributes.h
|
|
+++ b/include/linux/compiler_attributes.h
|
|
@@ -94,19 +94,6 @@
|
|
# define __copy(symbol)
|
|
#endif
|
|
|
|
-/*
|
|
- * Optional: only supported since gcc >= 14
|
|
- * Optional: only supported since clang >= 18
|
|
- *
|
|
- * gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
|
|
- * clang: https://reviews.llvm.org/D148381
|
|
- */
|
|
-#if __has_attribute(__counted_by__)
|
|
-# define __counted_by(member) __attribute__((__counted_by__(member)))
|
|
-#else
|
|
-# define __counted_by(member)
|
|
-#endif
|
|
-
|
|
/*
|
|
* Optional: not supported by gcc
|
|
* Optional: only supported since clang >= 14.0
|
|
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
|
|
index 0a182f088c897e..02f616dfb15f4d 100644
|
|
--- a/include/linux/compiler_types.h
|
|
+++ b/include/linux/compiler_types.h
|
|
@@ -295,6 +295,25 @@ struct ftrace_likely_data {
|
|
#define __no_sanitize_or_inline __always_inline
|
|
#endif
|
|
|
|
+/*
|
|
+ * Optional: only supported since gcc >= 15
|
|
+ * Optional: only supported since clang >= 18
|
|
+ *
|
|
+ * gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
|
|
+ * clang: https://github.com/llvm/llvm-project/pull/76348
|
|
+ *
|
|
+ * __bdos on clang < 19.1.2 can erroneously return 0:
|
|
+ * https://github.com/llvm/llvm-project/pull/110497
|
|
+ *
|
|
+ * __bdos on clang < 19.1.3 can be off by 4:
|
|
+ * https://github.com/llvm/llvm-project/pull/112636
|
|
+ */
|
|
+#ifdef CONFIG_CC_HAS_COUNTED_BY
|
|
+# define __counted_by(member) __attribute__((__counted_by__(member)))
|
|
+#else
|
|
+# define __counted_by(member)
|
|
+#endif
|
|
+
|
|
/* Section for code which can't be instrumented at all */
|
|
#define __noinstr_section(section) \
|
|
noinline notrace __attribute((__section__(section))) \
|
|
diff --git a/include/linux/hisi_acc_qm.h b/include/linux/hisi_acc_qm.h
|
|
index 5c4b3a68053f51..8070bff54bfa29 100644
|
|
--- a/include/linux/hisi_acc_qm.h
|
|
+++ b/include/linux/hisi_acc_qm.h
|
|
@@ -225,6 +225,12 @@ struct hisi_qm_status {
|
|
|
|
struct hisi_qm;
|
|
|
|
+enum acc_err_result {
|
|
+ ACC_ERR_NONE,
|
|
+ ACC_ERR_NEED_RESET,
|
|
+ ACC_ERR_RECOVERED,
|
|
+};
|
|
+
|
|
struct hisi_qm_err_info {
|
|
char *acpi_rst;
|
|
u32 msi_wr_port;
|
|
@@ -253,9 +259,9 @@ struct hisi_qm_err_ini {
|
|
void (*close_axi_master_ooo)(struct hisi_qm *qm);
|
|
void (*open_sva_prefetch)(struct hisi_qm *qm);
|
|
void (*close_sva_prefetch)(struct hisi_qm *qm);
|
|
- void (*log_dev_hw_err)(struct hisi_qm *qm, u32 err_sts);
|
|
void (*show_last_dfx_regs)(struct hisi_qm *qm);
|
|
void (*err_info_init)(struct hisi_qm *qm);
|
|
+ enum acc_err_result (*get_err_result)(struct hisi_qm *qm);
|
|
};
|
|
|
|
struct hisi_qm_cap_info {
|
|
diff --git a/include/linux/init.h b/include/linux/init.h
|
|
index 01b52c9c75268f..63d2ee4f1f0e07 100644
|
|
--- a/include/linux/init.h
|
|
+++ b/include/linux/init.h
|
|
@@ -84,11 +84,15 @@
|
|
|
|
#define __exit __section(".exit.text") __exitused __cold notrace
|
|
|
|
-/* Used for MEMORY_HOTPLUG */
|
|
-#define __meminit __section(".meminit.text") __cold notrace \
|
|
- __latent_entropy
|
|
-#define __meminitdata __section(".meminit.data")
|
|
-#define __meminitconst __section(".meminit.rodata")
|
|
+#ifdef CONFIG_MEMORY_HOTPLUG
|
|
+#define __meminit
|
|
+#define __meminitdata
|
|
+#define __meminitconst
|
|
+#else
|
|
+#define __meminit __init
|
|
+#define __meminitdata __initdata
|
|
+#define __meminitconst __initconst
|
|
+#endif
|
|
|
|
/* For assembly routines */
|
|
#define __HEAD .section ".head.text","ax"
|
|
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
|
|
index e0ae2a43e0ebdd..03f38fe9b9a103 100644
|
|
--- a/include/linux/jiffies.h
|
|
+++ b/include/linux/jiffies.h
|
|
@@ -499,7 +499,7 @@ static inline unsigned long _msecs_to_jiffies(const unsigned int m)
|
|
* - all other values are converted to jiffies by either multiplying
|
|
* the input value by a factor or dividing it with a factor and
|
|
* handling any 32-bit overflows.
|
|
- * for the details see __msecs_to_jiffies()
|
|
+ * for the details see _msecs_to_jiffies()
|
|
*
|
|
* msecs_to_jiffies() checks for the passed in value being a constant
|
|
* via __builtin_constant_p() allowing gcc to eliminate most of the
|
|
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
|
|
index dc2844b071c2c2..919a5cb6368d17 100644
|
|
--- a/include/linux/lockdep.h
|
|
+++ b/include/linux/lockdep.h
|
|
@@ -230,7 +230,7 @@ static inline void lockdep_init_map(struct lockdep_map *lock, const char *name,
|
|
(lock)->dep_map.lock_type)
|
|
|
|
#define lockdep_set_subclass(lock, sub) \
|
|
- lockdep_init_map_type(&(lock)->dep_map, #lock, (lock)->dep_map.key, sub,\
|
|
+ lockdep_init_map_type(&(lock)->dep_map, (lock)->dep_map.name, (lock)->dep_map.key, sub,\
|
|
(lock)->dep_map.wait_type_inner, \
|
|
(lock)->dep_map.wait_type_outer, \
|
|
(lock)->dep_map.lock_type)
|
|
diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h
|
|
index 7c3e7b0b0e8fd6..28c21d5b25f6b7 100644
|
|
--- a/include/linux/mmdebug.h
|
|
+++ b/include/linux/mmdebug.h
|
|
@@ -46,7 +46,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
|
|
} \
|
|
} while (0)
|
|
#define VM_WARN_ON_ONCE_PAGE(cond, page) ({ \
|
|
- static bool __section(".data.once") __warned; \
|
|
+ static bool __section(".data..once") __warned; \
|
|
int __ret_warn_once = !!(cond); \
|
|
\
|
|
if (unlikely(__ret_warn_once && !__warned)) { \
|
|
@@ -66,7 +66,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
|
|
unlikely(__ret_warn); \
|
|
})
|
|
#define VM_WARN_ON_ONCE_FOLIO(cond, folio) ({ \
|
|
- static bool __section(".data.once") __warned; \
|
|
+ static bool __section(".data..once") __warned; \
|
|
int __ret_warn_once = !!(cond); \
|
|
\
|
|
if (unlikely(__ret_warn_once && !__warned)) { \
|
|
@@ -77,7 +77,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
|
|
unlikely(__ret_warn_once); \
|
|
})
|
|
#define VM_WARN_ON_ONCE_MM(cond, mm) ({ \
|
|
- static bool __section(".data.once") __warned; \
|
|
+ static bool __section(".data..once") __warned; \
|
|
int __ret_warn_once = !!(cond); \
|
|
\
|
|
if (unlikely(__ret_warn_once && !__warned)) { \
|
|
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
|
|
index bd19c4b91e3120..3ddf205b7e2c38 100644
|
|
--- a/include/linux/netpoll.h
|
|
+++ b/include/linux/netpoll.h
|
|
@@ -71,7 +71,7 @@ static inline void *netpoll_poll_lock(struct napi_struct *napi)
|
|
{
|
|
struct net_device *dev = napi->dev;
|
|
|
|
- if (dev && dev->npinfo) {
|
|
+ if (dev && rcu_access_pointer(dev->npinfo)) {
|
|
int owner = smp_processor_id();
|
|
|
|
while (cmpxchg(&napi->poll_owner, -1, owner) != -1)
|
|
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
|
|
index d69ad5bb1eb1e6..b8d6c0c208760a 100644
|
|
--- a/include/linux/of_fdt.h
|
|
+++ b/include/linux/of_fdt.h
|
|
@@ -31,6 +31,7 @@ extern void *of_fdt_unflatten_tree(const unsigned long *blob,
|
|
extern int __initdata dt_root_addr_cells;
|
|
extern int __initdata dt_root_size_cells;
|
|
extern void *initial_boot_params;
|
|
+extern phys_addr_t initial_boot_params_pa;
|
|
|
|
extern char __dtb_start[];
|
|
extern char __dtb_end[];
|
|
@@ -70,8 +71,8 @@ extern u64 dt_mem_next_cell(int s, const __be32 **cellp);
|
|
/* Early flat tree scan hooks */
|
|
extern int early_init_dt_scan_root(void);
|
|
|
|
-extern bool early_init_dt_scan(void *params);
|
|
-extern bool early_init_dt_verify(void *params);
|
|
+extern bool early_init_dt_scan(void *dt_virt, phys_addr_t dt_phys);
|
|
+extern bool early_init_dt_verify(void *dt_virt, phys_addr_t dt_phys);
|
|
extern void early_init_dt_scan_nodes(void);
|
|
|
|
extern const char *of_flat_dt_get_machine_name(void);
|
|
diff --git a/include/linux/once.h b/include/linux/once.h
|
|
index bc714d414448a7..30346fcdc7995d 100644
|
|
--- a/include/linux/once.h
|
|
+++ b/include/linux/once.h
|
|
@@ -46,7 +46,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,
|
|
#define DO_ONCE(func, ...) \
|
|
({ \
|
|
bool ___ret = false; \
|
|
- static bool __section(".data.once") ___done = false; \
|
|
+ static bool __section(".data..once") ___done = false; \
|
|
static DEFINE_STATIC_KEY_TRUE(___once_key); \
|
|
if (static_branch_unlikely(&___once_key)) { \
|
|
unsigned long ___flags; \
|
|
@@ -64,7 +64,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,
|
|
#define DO_ONCE_SLEEPABLE(func, ...) \
|
|
({ \
|
|
bool ___ret = false; \
|
|
- static bool __section(".data.once") ___done = false; \
|
|
+ static bool __section(".data..once") ___done = false; \
|
|
static DEFINE_STATIC_KEY_TRUE(___once_key); \
|
|
if (static_branch_unlikely(&___once_key)) { \
|
|
___ret = __do_once_sleepable_start(&___done); \
|
|
diff --git a/include/linux/once_lite.h b/include/linux/once_lite.h
|
|
index b7bce4983638f8..27de7bc32a0610 100644
|
|
--- a/include/linux/once_lite.h
|
|
+++ b/include/linux/once_lite.h
|
|
@@ -12,7 +12,7 @@
|
|
|
|
#define __ONCE_LITE_IF(condition) \
|
|
({ \
|
|
- static bool __section(".data.once") __already_done; \
|
|
+ static bool __section(".data..once") __already_done; \
|
|
bool __ret_cond = !!(condition); \
|
|
bool __ret_once = false; \
|
|
\
|
|
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
|
|
index 6466c2f792923c..7602d1f8a9ecb3 100644
|
|
--- a/include/linux/rcupdate.h
|
|
+++ b/include/linux/rcupdate.h
|
|
@@ -398,7 +398,7 @@ static inline int debug_lockdep_rcu_enabled(void)
|
|
*/
|
|
#define RCU_LOCKDEP_WARN(c, s) \
|
|
do { \
|
|
- static bool __section(".data.unlikely") __warned; \
|
|
+ static bool __section(".data..unlikely") __warned; \
|
|
if (debug_lockdep_rcu_enabled() && (c) && \
|
|
debug_lockdep_rcu_enabled() && !__warned) { \
|
|
__warned = true; \
|
|
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
|
|
index e9bd2f65d7f4e4..b4b4ce9a4151ec 100644
|
|
--- a/include/linux/seqlock.h
|
|
+++ b/include/linux/seqlock.h
|
|
@@ -682,6 +682,23 @@ static __always_inline unsigned raw_read_seqcount_latch(const seqcount_latch_t *
|
|
return READ_ONCE(s->seqcount.sequence);
|
|
}
|
|
|
|
+/**
|
|
+ * read_seqcount_latch() - pick even/odd latch data copy
|
|
+ * @s: Pointer to seqcount_latch_t
|
|
+ *
|
|
+ * See write_seqcount_latch() for details and a full reader/writer usage
|
|
+ * example.
|
|
+ *
|
|
+ * Return: sequence counter raw value. Use the lowest bit as an index for
|
|
+ * picking which data copy to read. The full counter must then be checked
|
|
+ * with read_seqcount_latch_retry().
|
|
+ */
|
|
+static __always_inline unsigned read_seqcount_latch(const seqcount_latch_t *s)
|
|
+{
|
|
+ kcsan_atomic_next(KCSAN_SEQLOCK_REGION_MAX);
|
|
+ return raw_read_seqcount_latch(s);
|
|
+}
|
|
+
|
|
/**
|
|
* raw_read_seqcount_latch_retry() - end a seqcount_latch_t read section
|
|
* @s: Pointer to seqcount_latch_t
|
|
@@ -696,9 +713,34 @@ raw_read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start)
|
|
return unlikely(READ_ONCE(s->seqcount.sequence) != start);
|
|
}
|
|
|
|
+/**
|
|
+ * read_seqcount_latch_retry() - end a seqcount_latch_t read section
|
|
+ * @s: Pointer to seqcount_latch_t
|
|
+ * @start: count, from read_seqcount_latch()
|
|
+ *
|
|
+ * Return: true if a read section retry is required, else false
|
|
+ */
|
|
+static __always_inline int
|
|
+read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start)
|
|
+{
|
|
+ kcsan_atomic_next(0);
|
|
+ return raw_read_seqcount_latch_retry(s, start);
|
|
+}
|
|
+
|
|
/**
|
|
* raw_write_seqcount_latch() - redirect latch readers to even/odd copy
|
|
* @s: Pointer to seqcount_latch_t
|
|
+ */
|
|
+static __always_inline void raw_write_seqcount_latch(seqcount_latch_t *s)
|
|
+{
|
|
+ smp_wmb(); /* prior stores before incrementing "sequence" */
|
|
+ s->seqcount.sequence++;
|
|
+ smp_wmb(); /* increment "sequence" before following stores */
|
|
+}
|
|
+
|
|
+/**
|
|
+ * write_seqcount_latch_begin() - redirect latch readers to odd copy
|
|
+ * @s: Pointer to seqcount_latch_t
|
|
*
|
|
* The latch technique is a multiversion concurrency control method that allows
|
|
* queries during non-atomic modifications. If you can guarantee queries never
|
|
@@ -726,17 +768,11 @@ raw_read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start)
|
|
*
|
|
* void latch_modify(struct latch_struct *latch, ...)
|
|
* {
|
|
- * smp_wmb(); // Ensure that the last data[1] update is visible
|
|
- * latch->seq.sequence++;
|
|
- * smp_wmb(); // Ensure that the seqcount update is visible
|
|
- *
|
|
+ * write_seqcount_latch_begin(&latch->seq);
|
|
* modify(latch->data[0], ...);
|
|
- *
|
|
- * smp_wmb(); // Ensure that the data[0] update is visible
|
|
- * latch->seq.sequence++;
|
|
- * smp_wmb(); // Ensure that the seqcount update is visible
|
|
- *
|
|
+ * write_seqcount_latch(&latch->seq);
|
|
* modify(latch->data[1], ...);
|
|
+ * write_seqcount_latch_end(&latch->seq);
|
|
* }
|
|
*
|
|
* The query will have a form like::
|
|
@@ -747,13 +783,13 @@ raw_read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start)
|
|
* unsigned seq, idx;
|
|
*
|
|
* do {
|
|
- * seq = raw_read_seqcount_latch(&latch->seq);
|
|
+ * seq = read_seqcount_latch(&latch->seq);
|
|
*
|
|
* idx = seq & 0x01;
|
|
* entry = data_query(latch->data[idx], ...);
|
|
*
|
|
* // This includes needed smp_rmb()
|
|
- * } while (raw_read_seqcount_latch_retry(&latch->seq, seq));
|
|
+ * } while (read_seqcount_latch_retry(&latch->seq, seq));
|
|
*
|
|
* return entry;
|
|
* }
|
|
@@ -777,11 +813,31 @@ raw_read_seqcount_latch_retry(const seqcount_latch_t *s, unsigned start)
|
|
* When data is a dynamic data structure; one should use regular RCU
|
|
* patterns to manage the lifetimes of the objects within.
|
|
*/
|
|
-static inline void raw_write_seqcount_latch(seqcount_latch_t *s)
|
|
+static __always_inline void write_seqcount_latch_begin(seqcount_latch_t *s)
|
|
{
|
|
- smp_wmb(); /* prior stores before incrementing "sequence" */
|
|
- s->seqcount.sequence++;
|
|
- smp_wmb(); /* increment "sequence" before following stores */
|
|
+ kcsan_nestable_atomic_begin();
|
|
+ raw_write_seqcount_latch(s);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * write_seqcount_latch() - redirect latch readers to even copy
|
|
+ * @s: Pointer to seqcount_latch_t
|
|
+ */
|
|
+static __always_inline void write_seqcount_latch(seqcount_latch_t *s)
|
|
+{
|
|
+ raw_write_seqcount_latch(s);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * write_seqcount_latch_end() - end a seqcount_latch_t write section
|
|
+ * @s: Pointer to seqcount_latch_t
|
|
+ *
|
|
+ * Marks the end of a seqcount_latch_t writer section, after all copies of the
|
|
+ * latch-protected data have been updated.
|
|
+ */
|
|
+static __always_inline void write_seqcount_latch_end(seqcount_latch_t *s)
|
|
+{
|
|
+ kcsan_nestable_atomic_end();
|
|
}
|
|
|
|
/*
|
|
@@ -834,11 +890,7 @@ typedef struct {
|
|
*/
|
|
static inline unsigned read_seqbegin(const seqlock_t *sl)
|
|
{
|
|
- unsigned ret = read_seqcount_begin(&sl->seqcount);
|
|
-
|
|
- kcsan_atomic_next(0); /* non-raw usage, assume closing read_seqretry() */
|
|
- kcsan_flat_atomic_begin();
|
|
- return ret;
|
|
+ return read_seqcount_begin(&sl->seqcount);
|
|
}
|
|
|
|
/**
|
|
@@ -854,12 +906,6 @@ static inline unsigned read_seqbegin(const seqlock_t *sl)
|
|
*/
|
|
static inline unsigned read_seqretry(const seqlock_t *sl, unsigned start)
|
|
{
|
|
- /*
|
|
- * Assume not nested: read_seqretry() may be called multiple times when
|
|
- * completing read critical section.
|
|
- */
|
|
- kcsan_flat_atomic_end();
|
|
-
|
|
return read_seqcount_retry(&sl->seqcount, start);
|
|
}
|
|
|
|
diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
|
|
index 0b9ecd8cf9793b..110978dc9af1b1 100644
|
|
--- a/include/linux/sock_diag.h
|
|
+++ b/include/linux/sock_diag.h
|
|
@@ -13,6 +13,7 @@ struct nlmsghdr;
|
|
struct sock;
|
|
|
|
struct sock_diag_handler {
|
|
+ struct module *owner;
|
|
__u8 family;
|
|
int (*dump)(struct sk_buff *skb, struct nlmsghdr *nlh);
|
|
int (*get_info)(struct sk_buff *skb, struct sock *sk);
|
|
@@ -22,8 +23,13 @@ struct sock_diag_handler {
|
|
int sock_diag_register(const struct sock_diag_handler *h);
|
|
void sock_diag_unregister(const struct sock_diag_handler *h);
|
|
|
|
-void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh));
|
|
-void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh));
|
|
+struct sock_diag_inet_compat {
|
|
+ struct module *owner;
|
|
+ int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh);
|
|
+};
|
|
+
|
|
+void sock_diag_register_inet_compat(const struct sock_diag_inet_compat *ptr);
|
|
+void sock_diag_unregister_inet_compat(const struct sock_diag_inet_compat *ptr);
|
|
|
|
u64 __sock_gen_cookie(struct sock *sk);
|
|
|
|
diff --git a/include/linux/util_macros.h b/include/linux/util_macros.h
|
|
index 6bb460c3e818b3..825487fb66faf9 100644
|
|
--- a/include/linux/util_macros.h
|
|
+++ b/include/linux/util_macros.h
|
|
@@ -4,19 +4,6 @@
|
|
|
|
#include <linux/math.h>
|
|
|
|
-#define __find_closest(x, a, as, op) \
|
|
-({ \
|
|
- typeof(as) __fc_i, __fc_as = (as) - 1; \
|
|
- typeof(x) __fc_x = (x); \
|
|
- typeof(*a) const *__fc_a = (a); \
|
|
- for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \
|
|
- if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] + \
|
|
- __fc_a[__fc_i + 1], 2)) \
|
|
- break; \
|
|
- } \
|
|
- (__fc_i); \
|
|
-})
|
|
-
|
|
/**
|
|
* find_closest - locate the closest element in a sorted array
|
|
* @x: The reference value.
|
|
@@ -25,8 +12,27 @@
|
|
* @as: Size of 'a'.
|
|
*
|
|
* Returns the index of the element closest to 'x'.
|
|
+ * Note: If using an array of negative numbers (or mixed positive numbers),
|
|
+ * then be sure that 'x' is of a signed-type to get good results.
|
|
*/
|
|
-#define find_closest(x, a, as) __find_closest(x, a, as, <=)
|
|
+#define find_closest(x, a, as) \
|
|
+({ \
|
|
+ typeof(as) __fc_i, __fc_as = (as) - 1; \
|
|
+ long __fc_mid_x, __fc_x = (x); \
|
|
+ long __fc_left, __fc_right; \
|
|
+ typeof(*a) const *__fc_a = (a); \
|
|
+ for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \
|
|
+ __fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i + 1]) / 2; \
|
|
+ if (__fc_x <= __fc_mid_x) { \
|
|
+ __fc_left = __fc_x - __fc_a[__fc_i]; \
|
|
+ __fc_right = __fc_a[__fc_i + 1] - __fc_x; \
|
|
+ if (__fc_right < __fc_left) \
|
|
+ __fc_i++; \
|
|
+ break; \
|
|
+ } \
|
|
+ } \
|
|
+ (__fc_i); \
|
|
+})
|
|
|
|
/**
|
|
* find_closest_descending - locate the closest element in a sorted array
|
|
@@ -36,9 +42,27 @@
|
|
* @as: Size of 'a'.
|
|
*
|
|
* Similar to find_closest() but 'a' is expected to be sorted in descending
|
|
- * order.
|
|
+ * order. The iteration is done in reverse order, so that the comparison
|
|
+ * of '__fc_right' & '__fc_left' also works for unsigned numbers.
|
|
*/
|
|
-#define find_closest_descending(x, a, as) __find_closest(x, a, as, >=)
|
|
+#define find_closest_descending(x, a, as) \
|
|
+({ \
|
|
+ typeof(as) __fc_i, __fc_as = (as) - 1; \
|
|
+ long __fc_mid_x, __fc_x = (x); \
|
|
+ long __fc_left, __fc_right; \
|
|
+ typeof(*a) const *__fc_a = (a); \
|
|
+ for (__fc_i = __fc_as; __fc_i >= 1; __fc_i--) { \
|
|
+ __fc_mid_x = (__fc_a[__fc_i] + __fc_a[__fc_i - 1]) / 2; \
|
|
+ if (__fc_x <= __fc_mid_x) { \
|
|
+ __fc_left = __fc_x - __fc_a[__fc_i]; \
|
|
+ __fc_right = __fc_a[__fc_i - 1] - __fc_x; \
|
|
+ if (__fc_right < __fc_left) \
|
|
+ __fc_i--; \
|
|
+ break; \
|
|
+ } \
|
|
+ } \
|
|
+ (__fc_i); \
|
|
+})
|
|
|
|
/**
|
|
* is_insidevar - check if the @ptr points inside the @var memory range.
|
|
diff --git a/include/media/v4l2-dv-timings.h b/include/media/v4l2-dv-timings.h
|
|
index 8fa963326bf6a2..c64096b5c78215 100644
|
|
--- a/include/media/v4l2-dv-timings.h
|
|
+++ b/include/media/v4l2-dv-timings.h
|
|
@@ -146,15 +146,18 @@ void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix,
|
|
* @polarities: the horizontal and vertical polarities (same as struct
|
|
* v4l2_bt_timings polarities).
|
|
* @interlaced: if this flag is true, it indicates interlaced format
|
|
+ * @cap: the v4l2_dv_timings_cap capabilities.
|
|
* @fmt: the resulting timings.
|
|
*
|
|
* This function will attempt to detect if the given values correspond to a
|
|
* valid CVT format. If so, then it will return true, and fmt will be filled
|
|
* in with the found CVT timings.
|
|
*/
|
|
-bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync,
|
|
- unsigned active_width, u32 polarities, bool interlaced,
|
|
- struct v4l2_dv_timings *fmt);
|
|
+bool v4l2_detect_cvt(unsigned int frame_height, unsigned int hfreq,
|
|
+ unsigned int vsync, unsigned int active_width,
|
|
+ u32 polarities, bool interlaced,
|
|
+ const struct v4l2_dv_timings_cap *cap,
|
|
+ struct v4l2_dv_timings *fmt);
|
|
|
|
/**
|
|
* v4l2_detect_gtf - detect if the given timings follow the GTF standard
|
|
@@ -170,15 +173,18 @@ bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync,
|
|
* image height, so it has to be passed explicitly. Usually
|
|
* the native screen aspect ratio is used for this. If it
|
|
* is not filled in correctly, then 16:9 will be assumed.
|
|
+ * @cap: the v4l2_dv_timings_cap capabilities.
|
|
* @fmt: the resulting timings.
|
|
*
|
|
* This function will attempt to detect if the given values correspond to a
|
|
* valid GTF format. If so, then it will return true, and fmt will be filled
|
|
* in with the found GTF timings.
|
|
*/
|
|
-bool v4l2_detect_gtf(unsigned frame_height, unsigned hfreq, unsigned vsync,
|
|
- u32 polarities, bool interlaced, struct v4l2_fract aspect,
|
|
- struct v4l2_dv_timings *fmt);
|
|
+bool v4l2_detect_gtf(unsigned int frame_height, unsigned int hfreq,
|
|
+ unsigned int vsync, u32 polarities, bool interlaced,
|
|
+ struct v4l2_fract aspect,
|
|
+ const struct v4l2_dv_timings_cap *cap,
|
|
+ struct v4l2_dv_timings *fmt);
|
|
|
|
/**
|
|
* v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes
|
|
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
|
|
index 2338f8d2a8b33b..c6cb6f64274232 100644
|
|
--- a/include/net/ieee80211_radiotap.h
|
|
+++ b/include/net/ieee80211_radiotap.h
|
|
@@ -24,25 +24,27 @@
|
|
* struct ieee80211_radiotap_header - base radiotap header
|
|
*/
|
|
struct ieee80211_radiotap_header {
|
|
- /**
|
|
- * @it_version: radiotap version, always 0
|
|
- */
|
|
- uint8_t it_version;
|
|
-
|
|
- /**
|
|
- * @it_pad: padding (or alignment)
|
|
- */
|
|
- uint8_t it_pad;
|
|
-
|
|
- /**
|
|
- * @it_len: overall radiotap header length
|
|
- */
|
|
- __le16 it_len;
|
|
-
|
|
- /**
|
|
- * @it_present: (first) present word
|
|
- */
|
|
- __le32 it_present;
|
|
+ __struct_group(ieee80211_radiotap_header_fixed, hdr, __packed,
|
|
+ /**
|
|
+ * @it_version: radiotap version, always 0
|
|
+ */
|
|
+ uint8_t it_version;
|
|
+
|
|
+ /**
|
|
+ * @it_pad: padding (or alignment)
|
|
+ */
|
|
+ uint8_t it_pad;
|
|
+
|
|
+ /**
|
|
+ * @it_len: overall radiotap header length
|
|
+ */
|
|
+ __le16 it_len;
|
|
+
|
|
+ /**
|
|
+ * @it_present: (first) present word
|
|
+ */
|
|
+ __le32 it_present;
|
|
+ );
|
|
|
|
/**
|
|
* @it_optional: all remaining presence bitmaps
|
|
@@ -50,6 +52,9 @@ struct ieee80211_radiotap_header {
|
|
__le32 it_optional[];
|
|
} __packed;
|
|
|
|
+static_assert(offsetof(struct ieee80211_radiotap_header, it_optional) == sizeof(struct ieee80211_radiotap_header_fixed),
|
|
+ "struct member likely outside of __struct_group()");
|
|
+
|
|
/* version is always 0 */
|
|
#define PKTHDR_RADIOTAP_VERSION 0
|
|
|
|
diff --git a/include/net/net_debug.h b/include/net/net_debug.h
|
|
index 1e74684cbbdbcd..4a79204c8d306e 100644
|
|
--- a/include/net/net_debug.h
|
|
+++ b/include/net/net_debug.h
|
|
@@ -27,7 +27,7 @@ void netdev_info(const struct net_device *dev, const char *format, ...);
|
|
|
|
#define netdev_level_once(level, dev, fmt, ...) \
|
|
do { \
|
|
- static bool __section(".data.once") __print_once; \
|
|
+ static bool __section(".data..once") __print_once; \
|
|
\
|
|
if (!__print_once) { \
|
|
__print_once = true; \
|
|
diff --git a/include/net/sock.h b/include/net/sock.h
|
|
index e0be8bd9839602..a6b795ec7c9cb6 100644
|
|
--- a/include/net/sock.h
|
|
+++ b/include/net/sock.h
|
|
@@ -2219,7 +2219,7 @@ sk_dst_set(struct sock *sk, struct dst_entry *dst)
|
|
|
|
sk_tx_queue_clear(sk);
|
|
WRITE_ONCE(sk->sk_dst_pending_confirm, 0);
|
|
- old_dst = xchg((__force struct dst_entry **)&sk->sk_dst_cache, dst);
|
|
+ old_dst = unrcu_pointer(xchg(&sk->sk_dst_cache, RCU_INITIALIZER(dst)));
|
|
dst_release(old_dst);
|
|
}
|
|
|
|
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
|
|
index 51c13cf9c5aee4..63a0922937e72c 100644
|
|
--- a/include/uapi/linux/rtnetlink.h
|
|
+++ b/include/uapi/linux/rtnetlink.h
|
|
@@ -174,7 +174,7 @@ enum {
|
|
#define RTM_GETLINKPROP RTM_GETLINKPROP
|
|
|
|
RTM_NEWVLAN = 112,
|
|
-#define RTM_NEWNVLAN RTM_NEWVLAN
|
|
+#define RTM_NEWVLAN RTM_NEWVLAN
|
|
RTM_DELVLAN,
|
|
#define RTM_DELVLAN RTM_DELVLAN
|
|
RTM_GETVLAN,
|
|
diff --git a/init/Kconfig b/init/Kconfig
|
|
index 6054ba684c5396..60ed7713b5ee2a 100644
|
|
--- a/init/Kconfig
|
|
+++ b/init/Kconfig
|
|
@@ -107,6 +107,15 @@ config CC_HAS_ASM_INLINE
|
|
config CC_HAS_NO_PROFILE_FN_ATTR
|
|
def_bool $(success,echo '__attribute__((no_profile_instrument_function)) int x();' | $(CC) -x c - -c -o /dev/null -Werror)
|
|
|
|
+config CC_HAS_COUNTED_BY
|
|
+ # TODO: when gcc 15 is released remove the build test and add
|
|
+ # a gcc version check
|
|
+ def_bool $(success,echo 'struct flex { int count; int array[] __attribute__((__counted_by__(count))); };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)
|
|
+ # clang needs to be at least 19.1.3 to avoid __bdos miscalculations
|
|
+ # https://github.com/llvm/llvm-project/pull/110497
|
|
+ # https://github.com/llvm/llvm-project/pull/112636
|
|
+ depends on !(CC_IS_CLANG && CLANG_VERSION < 190103)
|
|
+
|
|
config PAHOLE_VERSION
|
|
int
|
|
default $(shell,$(srctree)/scripts/pahole-version.sh $(PAHOLE))
|
|
diff --git a/init/initramfs.c b/init/initramfs.c
|
|
index efc477b905a482..148988bd8ab277 100644
|
|
--- a/init/initramfs.c
|
|
+++ b/init/initramfs.c
|
|
@@ -358,6 +358,15 @@ static int __init do_name(void)
|
|
{
|
|
state = SkipIt;
|
|
next_state = Reset;
|
|
+
|
|
+ /* name_len > 0 && name_len <= PATH_MAX checked in do_header */
|
|
+ if (collected[name_len - 1] != '\0') {
|
|
+ pr_err("initramfs name without nulterm: %.*s\n",
|
|
+ (int)name_len, collected);
|
|
+ error("malformed archive");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
if (strcmp(collected, "TRAILER!!!") == 0) {
|
|
free_hash();
|
|
return 0;
|
|
@@ -422,6 +431,12 @@ static int __init do_copy(void)
|
|
|
|
static int __init do_symlink(void)
|
|
{
|
|
+ if (collected[name_len - 1] != '\0') {
|
|
+ pr_err("initramfs symlink without nulterm: %.*s\n",
|
|
+ (int)name_len, collected);
|
|
+ error("malformed archive");
|
|
+ return 1;
|
|
+ }
|
|
collected[N_ALIGN(name_len) + body_len] = '\0';
|
|
clean_path(collected, 0);
|
|
init_symlink(collected + N_ALIGN(name_len), collected);
|
|
diff --git a/ipc/namespace.c b/ipc/namespace.c
|
|
index 6ecc30effd3ec6..4df91ceeeafe9f 100644
|
|
--- a/ipc/namespace.c
|
|
+++ b/ipc/namespace.c
|
|
@@ -83,13 +83,15 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
|
|
|
|
err = msg_init_ns(ns);
|
|
if (err)
|
|
- goto fail_put;
|
|
+ goto fail_ipc;
|
|
|
|
sem_init_ns(ns);
|
|
shm_init_ns(ns);
|
|
|
|
return ns;
|
|
|
|
+fail_ipc:
|
|
+ retire_ipc_sysctls(ns);
|
|
fail_mq:
|
|
retire_mq_sysctls(ns);
|
|
|
|
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
|
|
index 4f19a091571bb6..5ca02af3a87280 100644
|
|
--- a/kernel/bpf/verifier.c
|
|
+++ b/kernel/bpf/verifier.c
|
|
@@ -1762,8 +1762,8 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state,
|
|
int i, err;
|
|
|
|
dst_state->jmp_history = copy_array(dst_state->jmp_history, src->jmp_history,
|
|
- src->jmp_history_cnt, sizeof(struct bpf_idx_pair),
|
|
- GFP_USER);
|
|
+ src->jmp_history_cnt, sizeof(*dst_state->jmp_history),
|
|
+ GFP_USER);
|
|
if (!dst_state->jmp_history)
|
|
return -ENOMEM;
|
|
dst_state->jmp_history_cnt = src->jmp_history_cnt;
|
|
@@ -3397,6 +3397,21 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
|
|
return __check_reg_arg(env, state->regs, regno, t);
|
|
}
|
|
|
|
+static int insn_stack_access_flags(int frameno, int spi)
|
|
+{
|
|
+ return INSN_F_STACK_ACCESS | (spi << INSN_F_SPI_SHIFT) | frameno;
|
|
+}
|
|
+
|
|
+static int insn_stack_access_spi(int insn_flags)
|
|
+{
|
|
+ return (insn_flags >> INSN_F_SPI_SHIFT) & INSN_F_SPI_MASK;
|
|
+}
|
|
+
|
|
+static int insn_stack_access_frameno(int insn_flags)
|
|
+{
|
|
+ return insn_flags & INSN_F_FRAMENO_MASK;
|
|
+}
|
|
+
|
|
static void mark_jmp_point(struct bpf_verifier_env *env, int idx)
|
|
{
|
|
env->insn_aux_data[idx].jmp_point = true;
|
|
@@ -3408,28 +3423,51 @@ static bool is_jmp_point(struct bpf_verifier_env *env, int insn_idx)
|
|
}
|
|
|
|
/* for any branch, call, exit record the history of jmps in the given state */
|
|
-static int push_jmp_history(struct bpf_verifier_env *env,
|
|
- struct bpf_verifier_state *cur)
|
|
+static int push_jmp_history(struct bpf_verifier_env *env, struct bpf_verifier_state *cur,
|
|
+ int insn_flags)
|
|
{
|
|
u32 cnt = cur->jmp_history_cnt;
|
|
- struct bpf_idx_pair *p;
|
|
+ struct bpf_jmp_history_entry *p;
|
|
size_t alloc_size;
|
|
|
|
- if (!is_jmp_point(env, env->insn_idx))
|
|
+ /* combine instruction flags if we already recorded this instruction */
|
|
+ if (env->cur_hist_ent) {
|
|
+ /* atomic instructions push insn_flags twice, for READ and
|
|
+ * WRITE sides, but they should agree on stack slot
|
|
+ */
|
|
+ WARN_ONCE((env->cur_hist_ent->flags & insn_flags) &&
|
|
+ (env->cur_hist_ent->flags & insn_flags) != insn_flags,
|
|
+ "verifier insn history bug: insn_idx %d cur flags %x new flags %x\n",
|
|
+ env->insn_idx, env->cur_hist_ent->flags, insn_flags);
|
|
+ env->cur_hist_ent->flags |= insn_flags;
|
|
return 0;
|
|
+ }
|
|
|
|
cnt++;
|
|
alloc_size = kmalloc_size_roundup(size_mul(cnt, sizeof(*p)));
|
|
p = krealloc(cur->jmp_history, alloc_size, GFP_USER);
|
|
if (!p)
|
|
return -ENOMEM;
|
|
- p[cnt - 1].idx = env->insn_idx;
|
|
- p[cnt - 1].prev_idx = env->prev_insn_idx;
|
|
cur->jmp_history = p;
|
|
+
|
|
+ p = &cur->jmp_history[cnt - 1];
|
|
+ p->idx = env->insn_idx;
|
|
+ p->prev_idx = env->prev_insn_idx;
|
|
+ p->flags = insn_flags;
|
|
cur->jmp_history_cnt = cnt;
|
|
+ env->cur_hist_ent = p;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
+static struct bpf_jmp_history_entry *get_jmp_hist_entry(struct bpf_verifier_state *st,
|
|
+ u32 hist_end, int insn_idx)
|
|
+{
|
|
+ if (hist_end > 0 && st->jmp_history[hist_end - 1].idx == insn_idx)
|
|
+ return &st->jmp_history[hist_end - 1];
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
/* Backtrack one insn at a time. If idx is not at the top of recorded
|
|
* history then previous instruction came from straight line execution.
|
|
* Return -ENOENT if we exhausted all instructions within given state.
|
|
@@ -3591,9 +3629,14 @@ static inline bool bt_is_reg_set(struct backtrack_state *bt, u32 reg)
|
|
return bt->reg_masks[bt->frame] & (1 << reg);
|
|
}
|
|
|
|
+static inline bool bt_is_frame_slot_set(struct backtrack_state *bt, u32 frame, u32 slot)
|
|
+{
|
|
+ return bt->stack_masks[frame] & (1ull << slot);
|
|
+}
|
|
+
|
|
static inline bool bt_is_slot_set(struct backtrack_state *bt, u32 slot)
|
|
{
|
|
- return bt->stack_masks[bt->frame] & (1ull << slot);
|
|
+ return bt_is_frame_slot_set(bt, bt->frame, slot);
|
|
}
|
|
|
|
/* format registers bitmask, e.g., "r0,r2,r4" for 0x15 mask */
|
|
@@ -3647,7 +3690,7 @@ static bool calls_callback(struct bpf_verifier_env *env, int insn_idx);
|
|
* - *was* processed previously during backtracking.
|
|
*/
|
|
static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
- struct backtrack_state *bt)
|
|
+ struct bpf_jmp_history_entry *hist, struct backtrack_state *bt)
|
|
{
|
|
const struct bpf_insn_cbs cbs = {
|
|
.cb_call = disasm_kfunc_name,
|
|
@@ -3660,7 +3703,7 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
u8 mode = BPF_MODE(insn->code);
|
|
u32 dreg = insn->dst_reg;
|
|
u32 sreg = insn->src_reg;
|
|
- u32 spi, i;
|
|
+ u32 spi, i, fr;
|
|
|
|
if (insn->code == 0)
|
|
return 0;
|
|
@@ -3723,20 +3766,15 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
* by 'precise' mark in corresponding register of this state.
|
|
* No further tracking necessary.
|
|
*/
|
|
- if (insn->src_reg != BPF_REG_FP)
|
|
+ if (!hist || !(hist->flags & INSN_F_STACK_ACCESS))
|
|
return 0;
|
|
-
|
|
/* dreg = *(u64 *)[fp - off] was a fill from the stack.
|
|
* that [fp - off] slot contains scalar that needs to be
|
|
* tracked with precision
|
|
*/
|
|
- spi = (-insn->off - 1) / BPF_REG_SIZE;
|
|
- if (spi >= 64) {
|
|
- verbose(env, "BUG spi %d\n", spi);
|
|
- WARN_ONCE(1, "verifier backtracking bug");
|
|
- return -EFAULT;
|
|
- }
|
|
- bt_set_slot(bt, spi);
|
|
+ spi = insn_stack_access_spi(hist->flags);
|
|
+ fr = insn_stack_access_frameno(hist->flags);
|
|
+ bt_set_frame_slot(bt, fr, spi);
|
|
} else if (class == BPF_STX || class == BPF_ST) {
|
|
if (bt_is_reg_set(bt, dreg))
|
|
/* stx & st shouldn't be using _scalar_ dst_reg
|
|
@@ -3745,17 +3783,13 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
*/
|
|
return -ENOTSUPP;
|
|
/* scalars can only be spilled into stack */
|
|
- if (insn->dst_reg != BPF_REG_FP)
|
|
+ if (!hist || !(hist->flags & INSN_F_STACK_ACCESS))
|
|
return 0;
|
|
- spi = (-insn->off - 1) / BPF_REG_SIZE;
|
|
- if (spi >= 64) {
|
|
- verbose(env, "BUG spi %d\n", spi);
|
|
- WARN_ONCE(1, "verifier backtracking bug");
|
|
- return -EFAULT;
|
|
- }
|
|
- if (!bt_is_slot_set(bt, spi))
|
|
+ spi = insn_stack_access_spi(hist->flags);
|
|
+ fr = insn_stack_access_frameno(hist->flags);
|
|
+ if (!bt_is_frame_slot_set(bt, fr, spi))
|
|
return 0;
|
|
- bt_clear_slot(bt, spi);
|
|
+ bt_clear_frame_slot(bt, fr, spi);
|
|
if (class == BPF_STX)
|
|
bt_set_reg(bt, sreg);
|
|
} else if (class == BPF_JMP || class == BPF_JMP32) {
|
|
@@ -3799,10 +3833,14 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
WARN_ONCE(1, "verifier backtracking bug");
|
|
return -EFAULT;
|
|
}
|
|
- /* we don't track register spills perfectly,
|
|
- * so fallback to force-precise instead of failing */
|
|
- if (bt_stack_mask(bt) != 0)
|
|
- return -ENOTSUPP;
|
|
+ /* we are now tracking register spills correctly,
|
|
+ * so any instance of leftover slots is a bug
|
|
+ */
|
|
+ if (bt_stack_mask(bt) != 0) {
|
|
+ verbose(env, "BUG stack slots %llx\n", bt_stack_mask(bt));
|
|
+ WARN_ONCE(1, "verifier backtracking bug (subprog leftover stack slots)");
|
|
+ return -EFAULT;
|
|
+ }
|
|
/* propagate r1-r5 to the caller */
|
|
for (i = BPF_REG_1; i <= BPF_REG_5; i++) {
|
|
if (bt_is_reg_set(bt, i)) {
|
|
@@ -3827,8 +3865,11 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
|
WARN_ONCE(1, "verifier backtracking bug");
|
|
return -EFAULT;
|
|
}
|
|
- if (bt_stack_mask(bt) != 0)
|
|
- return -ENOTSUPP;
|
|
+ if (bt_stack_mask(bt) != 0) {
|
|
+ verbose(env, "BUG stack slots %llx\n", bt_stack_mask(bt));
|
|
+ WARN_ONCE(1, "verifier backtracking bug (callback leftover stack slots)");
|
|
+ return -EFAULT;
|
|
+ }
|
|
/* clear r1-r5 in callback subprog's mask */
|
|
for (i = BPF_REG_1; i <= BPF_REG_5; i++)
|
|
bt_clear_reg(bt, i);
|
|
@@ -4265,6 +4306,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
|
|
for (;;) {
|
|
DECLARE_BITMAP(mask, 64);
|
|
u32 history = st->jmp_history_cnt;
|
|
+ struct bpf_jmp_history_entry *hist;
|
|
|
|
if (env->log.level & BPF_LOG_LEVEL2) {
|
|
verbose(env, "mark_precise: frame%d: last_idx %d first_idx %d subseq_idx %d \n",
|
|
@@ -4328,7 +4370,8 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
|
|
err = 0;
|
|
skip_first = false;
|
|
} else {
|
|
- err = backtrack_insn(env, i, subseq_idx, bt);
|
|
+ hist = get_jmp_hist_entry(st, history, i);
|
|
+ err = backtrack_insn(env, i, subseq_idx, hist, bt);
|
|
}
|
|
if (err == -ENOTSUPP) {
|
|
mark_all_scalars_precise(env, env->cur_state);
|
|
@@ -4381,22 +4424,10 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno)
|
|
bitmap_from_u64(mask, bt_frame_stack_mask(bt, fr));
|
|
for_each_set_bit(i, mask, 64) {
|
|
if (i >= func->allocated_stack / BPF_REG_SIZE) {
|
|
- /* the sequence of instructions:
|
|
- * 2: (bf) r3 = r10
|
|
- * 3: (7b) *(u64 *)(r3 -8) = r0
|
|
- * 4: (79) r4 = *(u64 *)(r10 -8)
|
|
- * doesn't contain jmps. It's backtracked
|
|
- * as a single block.
|
|
- * During backtracking insn 3 is not recognized as
|
|
- * stack access, so at the end of backtracking
|
|
- * stack slot fp-8 is still marked in stack_mask.
|
|
- * However the parent state may not have accessed
|
|
- * fp-8 and it's "unallocated" stack space.
|
|
- * In such case fallback to conservative.
|
|
- */
|
|
- mark_all_scalars_precise(env, env->cur_state);
|
|
- bt_reset(bt);
|
|
- return 0;
|
|
+ verbose(env, "BUG backtracking (stack slot %d, total slots %d)\n",
|
|
+ i, func->allocated_stack / BPF_REG_SIZE);
|
|
+ WARN_ONCE(1, "verifier backtracking bug (stack slot out of bounds)");
|
|
+ return -EFAULT;
|
|
}
|
|
|
|
if (!is_spilled_scalar_reg(&func->stack[i])) {
|
|
@@ -4561,7 +4592,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
int i, slot = -off - 1, spi = slot / BPF_REG_SIZE, err;
|
|
struct bpf_insn *insn = &env->prog->insnsi[insn_idx];
|
|
struct bpf_reg_state *reg = NULL;
|
|
- u32 dst_reg = insn->dst_reg;
|
|
+ int insn_flags = insn_stack_access_flags(state->frameno, spi);
|
|
|
|
/* caller checked that off % size == 0 and -MAX_BPF_STACK <= off < 0,
|
|
* so it's aligned access and [off, off + size) are within stack limits
|
|
@@ -4599,17 +4630,6 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
mark_stack_slot_scratched(env, spi);
|
|
if (reg && !(off % BPF_REG_SIZE) && register_is_bounded(reg) &&
|
|
!register_is_null(reg) && env->bpf_capable) {
|
|
- if (dst_reg != BPF_REG_FP) {
|
|
- /* The backtracking logic can only recognize explicit
|
|
- * stack slot address like [fp - 8]. Other spill of
|
|
- * scalar via different register has to be conservative.
|
|
- * Backtrack from here and mark all registers as precise
|
|
- * that contributed into 'reg' being a constant.
|
|
- */
|
|
- err = mark_chain_precision(env, value_regno);
|
|
- if (err)
|
|
- return err;
|
|
- }
|
|
save_register_state(state, spi, reg, size);
|
|
/* Break the relation on a narrowing spill. */
|
|
if (fls64(reg->umax_value) > BITS_PER_BYTE * size)
|
|
@@ -4621,6 +4641,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
__mark_reg_known(&fake_reg, insn->imm);
|
|
fake_reg.type = SCALAR_VALUE;
|
|
save_register_state(state, spi, &fake_reg, size);
|
|
+ insn_flags = 0; /* not a register spill */
|
|
} else if (reg && is_spillable_regtype(reg->type)) {
|
|
/* register containing pointer is being spilled into stack */
|
|
if (size != BPF_REG_SIZE) {
|
|
@@ -4666,9 +4687,12 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
|
|
|
|
/* Mark slots affected by this stack write. */
|
|
for (i = 0; i < size; i++)
|
|
- state->stack[spi].slot_type[(slot - i) % BPF_REG_SIZE] =
|
|
- type;
|
|
+ state->stack[spi].slot_type[(slot - i) % BPF_REG_SIZE] = type;
|
|
+ insn_flags = 0; /* not a register spill */
|
|
}
|
|
+
|
|
+ if (insn_flags)
|
|
+ return push_jmp_history(env, env->cur_state, insn_flags);
|
|
return 0;
|
|
}
|
|
|
|
@@ -4857,6 +4881,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
|
int i, slot = -off - 1, spi = slot / BPF_REG_SIZE;
|
|
struct bpf_reg_state *reg;
|
|
u8 *stype, type;
|
|
+ int insn_flags = insn_stack_access_flags(reg_state->frameno, spi);
|
|
|
|
stype = reg_state->stack[spi].slot_type;
|
|
reg = ®_state->stack[spi].spilled_ptr;
|
|
@@ -4902,12 +4927,10 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
|
return -EACCES;
|
|
}
|
|
mark_reg_unknown(env, state->regs, dst_regno);
|
|
+ insn_flags = 0; /* not restoring original register state */
|
|
}
|
|
state->regs[dst_regno].live |= REG_LIVE_WRITTEN;
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (dst_regno >= 0) {
|
|
+ } else if (dst_regno >= 0) {
|
|
/* restore register state from stack */
|
|
copy_register_state(&state->regs[dst_regno], reg);
|
|
/* mark reg as written since spilled pointer state likely
|
|
@@ -4943,7 +4966,10 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
|
|
mark_reg_read(env, reg, reg->parent, REG_LIVE_READ64);
|
|
if (dst_regno >= 0)
|
|
mark_reg_stack_read(env, reg_state, off, off + size, dst_regno);
|
|
+ insn_flags = 0; /* we are not restoring spilled register */
|
|
}
|
|
+ if (insn_flags)
|
|
+ return push_jmp_history(env, env->cur_state, insn_flags);
|
|
return 0;
|
|
}
|
|
|
|
@@ -7027,7 +7053,6 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i
|
|
BPF_SIZE(insn->code), BPF_WRITE, -1, true, false);
|
|
if (err)
|
|
return err;
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -16773,7 +16798,8 @@ static int is_state_visited(struct bpf_verifier_env *env, int insn_idx)
|
|
* the precision needs to be propagated back in
|
|
* the current state.
|
|
*/
|
|
- err = err ? : push_jmp_history(env, cur);
|
|
+ if (is_jmp_point(env, env->insn_idx))
|
|
+ err = err ? : push_jmp_history(env, cur, 0);
|
|
err = err ? : propagate_precision(env, &sl->state);
|
|
if (err)
|
|
return err;
|
|
@@ -16997,6 +17023,9 @@ static int do_check(struct bpf_verifier_env *env)
|
|
u8 class;
|
|
int err;
|
|
|
|
+ /* reset current history entry on each new instruction */
|
|
+ env->cur_hist_ent = NULL;
|
|
+
|
|
env->prev_insn_idx = prev_insn_idx;
|
|
if (env->insn_idx >= insn_cnt) {
|
|
verbose(env, "invalid insn idx %d insn_cnt %d\n",
|
|
@@ -17036,7 +17065,7 @@ static int do_check(struct bpf_verifier_env *env)
|
|
}
|
|
|
|
if (is_jmp_point(env, env->insn_idx)) {
|
|
- err = push_jmp_history(env, state);
|
|
+ err = push_jmp_history(env, state, 0);
|
|
if (err)
|
|
return err;
|
|
}
|
|
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
|
|
index b927f0623ac774..36097e8c904fe5 100644
|
|
--- a/kernel/cgroup/cgroup.c
|
|
+++ b/kernel/cgroup/cgroup.c
|
|
@@ -2096,8 +2096,10 @@ int cgroup_setup_root(struct cgroup_root *root, u16 ss_mask)
|
|
if (ret)
|
|
goto exit_stats;
|
|
|
|
- ret = cgroup_bpf_inherit(root_cgrp);
|
|
- WARN_ON_ONCE(ret);
|
|
+ if (root == &cgrp_dfl_root) {
|
|
+ ret = cgroup_bpf_inherit(root_cgrp);
|
|
+ WARN_ON_ONCE(ret);
|
|
+ }
|
|
|
|
trace_cgroup_setup_root(root);
|
|
|
|
@@ -2270,10 +2272,8 @@ static void cgroup_kill_sb(struct super_block *sb)
|
|
* And don't kill the default root.
|
|
*/
|
|
if (list_empty(&root->cgrp.self.children) && root != &cgrp_dfl_root &&
|
|
- !percpu_ref_is_dying(&root->cgrp.self.refcnt)) {
|
|
- cgroup_bpf_offline(&root->cgrp);
|
|
+ !percpu_ref_is_dying(&root->cgrp.self.refcnt))
|
|
percpu_ref_kill(&root->cgrp.self.refcnt);
|
|
- }
|
|
cgroup_put(&root->cgrp);
|
|
kernfs_kill_sb(sb);
|
|
}
|
|
@@ -5618,9 +5618,11 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name,
|
|
if (ret)
|
|
goto out_kernfs_remove;
|
|
|
|
- ret = cgroup_bpf_inherit(cgrp);
|
|
- if (ret)
|
|
- goto out_psi_free;
|
|
+ if (cgrp->root == &cgrp_dfl_root) {
|
|
+ ret = cgroup_bpf_inherit(cgrp);
|
|
+ if (ret)
|
|
+ goto out_psi_free;
|
|
+ }
|
|
|
|
/*
|
|
* New cgroup inherits effective freeze counter, and
|
|
@@ -5938,7 +5940,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
|
|
|
|
cgroup1_check_for_release(parent);
|
|
|
|
- cgroup_bpf_offline(cgrp);
|
|
+ if (cgrp->root == &cgrp_dfl_root)
|
|
+ cgroup_bpf_offline(cgrp);
|
|
|
|
/* put the base reference */
|
|
percpu_ref_kill(&cgrp->self.refcnt);
|
|
diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c
|
|
index ed46d9e8c0e434..902575db9aec31 100644
|
|
--- a/kernel/rcu/rcuscale.c
|
|
+++ b/kernel/rcu/rcuscale.c
|
|
@@ -780,13 +780,15 @@ kfree_scale_init(void)
|
|
if (WARN_ON_ONCE(jiffies_at_lazy_cb - jif_start < 2 * HZ)) {
|
|
pr_alert("ERROR: call_rcu() CBs are not being lazy as expected!\n");
|
|
WARN_ON_ONCE(1);
|
|
- return -1;
|
|
+ firsterr = -1;
|
|
+ goto unwind;
|
|
}
|
|
|
|
if (WARN_ON_ONCE(jiffies_at_lazy_cb - jif_start > 3 * HZ)) {
|
|
pr_alert("ERROR: call_rcu() CBs are being too lazy!\n");
|
|
WARN_ON_ONCE(1);
|
|
- return -1;
|
|
+ firsterr = -1;
|
|
+ goto unwind;
|
|
}
|
|
}
|
|
|
|
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
|
|
index 3d7b119f6e2a36..fda08520c75c58 100644
|
|
--- a/kernel/rcu/tree.c
|
|
+++ b/kernel/rcu/tree.c
|
|
@@ -3150,7 +3150,7 @@ static int krc_count(struct kfree_rcu_cpu *krcp)
|
|
}
|
|
|
|
static void
|
|
-schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
|
|
+__schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
|
|
{
|
|
long delay, delay_left;
|
|
|
|
@@ -3164,6 +3164,16 @@ schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
|
|
queue_delayed_work(system_wq, &krcp->monitor_work, delay);
|
|
}
|
|
|
|
+static void
|
|
+schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
|
|
+{
|
|
+ unsigned long flags;
|
|
+
|
|
+ raw_spin_lock_irqsave(&krcp->lock, flags);
|
|
+ __schedule_delayed_monitor_work(krcp);
|
|
+ raw_spin_unlock_irqrestore(&krcp->lock, flags);
|
|
+}
|
|
+
|
|
static void
|
|
kvfree_rcu_drain_ready(struct kfree_rcu_cpu *krcp)
|
|
{
|
|
@@ -3460,7 +3470,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
|
|
|
|
// Set timer to drain after KFREE_DRAIN_JIFFIES.
|
|
if (rcu_scheduler_active == RCU_SCHEDULER_RUNNING)
|
|
- schedule_delayed_monitor_work(krcp);
|
|
+ __schedule_delayed_monitor_work(krcp);
|
|
|
|
unlock_return:
|
|
krc_this_cpu_unlock(krcp, flags);
|
|
diff --git a/kernel/signal.c b/kernel/signal.c
|
|
index 3808eaa2f49ab6..49c8c24b444d5e 100644
|
|
--- a/kernel/signal.c
|
|
+++ b/kernel/signal.c
|
|
@@ -1996,14 +1996,15 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
|
|
* into t->pending).
|
|
*
|
|
* Where type is not PIDTYPE_PID, signals must be delivered to the
|
|
- * process. In this case, prefer to deliver to current if it is in
|
|
- * the same thread group as the target process, which avoids
|
|
- * unnecessarily waking up a potentially idle task.
|
|
+ * process. In this case, prefer to deliver to current if it is in the
|
|
+ * same thread group as the target process and its sighand is stable,
|
|
+ * which avoids unnecessarily waking up a potentially idle task.
|
|
*/
|
|
t = pid_task(pid, type);
|
|
if (!t)
|
|
goto ret;
|
|
- if (type != PIDTYPE_PID && same_thread_group(t, current))
|
|
+ if (type != PIDTYPE_PID &&
|
|
+ same_thread_group(t, current) && !current->exit_state)
|
|
t = current;
|
|
if (!likely(lock_task_sighand(t, &flags)))
|
|
goto ret;
|
|
diff --git a/kernel/time/time.c b/kernel/time/time.c
|
|
index 642647f5046be0..1ad88e97b4ebcf 100644
|
|
--- a/kernel/time/time.c
|
|
+++ b/kernel/time/time.c
|
|
@@ -556,9 +556,9 @@ EXPORT_SYMBOL(ns_to_timespec64);
|
|
* - all other values are converted to jiffies by either multiplying
|
|
* the input value by a factor or dividing it with a factor and
|
|
* handling any 32-bit overflows.
|
|
- * for the details see __msecs_to_jiffies()
|
|
+ * for the details see _msecs_to_jiffies()
|
|
*
|
|
- * __msecs_to_jiffies() checks for the passed in value being a constant
|
|
+ * msecs_to_jiffies() checks for the passed in value being a constant
|
|
* via __builtin_constant_p() allowing gcc to eliminate most of the
|
|
* code, __msecs_to_jiffies() is called if the value passed does not
|
|
* allow constant folding and the actual conversion must be done at
|
|
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
|
|
index 9064f75de7e468..e8fb6ada323c1a 100644
|
|
--- a/kernel/trace/bpf_trace.c
|
|
+++ b/kernel/trace/bpf_trace.c
|
|
@@ -3098,7 +3098,6 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe,
|
|
struct bpf_prog *prog = link->link.prog;
|
|
bool sleepable = prog->aux->sleepable;
|
|
struct bpf_run_ctx *old_run_ctx;
|
|
- int err = 0;
|
|
|
|
if (link->task && current->mm != link->task->mm)
|
|
return 0;
|
|
@@ -3111,7 +3110,7 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe,
|
|
migrate_disable();
|
|
|
|
old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx);
|
|
- err = bpf_prog_run(link->link.prog, regs);
|
|
+ bpf_prog_run(link->link.prog, regs);
|
|
bpf_reset_run_ctx(old_run_ctx);
|
|
|
|
migrate_enable();
|
|
@@ -3120,7 +3119,7 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe,
|
|
rcu_read_unlock_trace();
|
|
else
|
|
rcu_read_unlock();
|
|
- return err;
|
|
+ return 0;
|
|
}
|
|
|
|
static bool
|
|
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
|
|
index 175eba24f5629a..1043936b352d12 100644
|
|
--- a/kernel/trace/ftrace.c
|
|
+++ b/kernel/trace/ftrace.c
|
|
@@ -4562,6 +4562,9 @@ ftrace_mod_callback(struct trace_array *tr, struct ftrace_hash *hash,
|
|
char *func;
|
|
int ret;
|
|
|
|
+ if (!tr)
|
|
+ return -ENODEV;
|
|
+
|
|
/* match_records() modifies func, and we need the original */
|
|
func = kstrdup(func_orig, GFP_KERNEL);
|
|
if (!func)
|
|
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
|
|
index 05e7912418126b..3ff9caa4a71bbd 100644
|
|
--- a/kernel/trace/trace_event_perf.c
|
|
+++ b/kernel/trace/trace_event_perf.c
|
|
@@ -352,10 +352,16 @@ void perf_uprobe_destroy(struct perf_event *p_event)
|
|
int perf_trace_add(struct perf_event *p_event, int flags)
|
|
{
|
|
struct trace_event_call *tp_event = p_event->tp_event;
|
|
+ struct hw_perf_event *hwc = &p_event->hw;
|
|
|
|
if (!(flags & PERF_EF_START))
|
|
p_event->hw.state = PERF_HES_STOPPED;
|
|
|
|
+ if (is_sampling_event(p_event)) {
|
|
+ hwc->last_period = hwc->sample_period;
|
|
+ perf_swevent_set_period(p_event);
|
|
+ }
|
|
+
|
|
/*
|
|
* If TRACE_REG_PERF_ADD returns false; no custom action was performed
|
|
* and we need to take the default action of enqueueing our event on
|
|
diff --git a/lib/maple_tree.c b/lib/maple_tree.c
|
|
index 4e05511c8d1eba..4eda9490636024 100644
|
|
--- a/lib/maple_tree.c
|
|
+++ b/lib/maple_tree.c
|
|
@@ -3547,9 +3547,20 @@ static inline int mas_root_expand(struct ma_state *mas, void *entry)
|
|
return slot;
|
|
}
|
|
|
|
+/*
|
|
+ * mas_store_root() - Storing value into root.
|
|
+ * @mas: The maple state
|
|
+ * @entry: The entry to store.
|
|
+ *
|
|
+ * There is no root node now and we are storing a value into the root - this
|
|
+ * function either assigns the pointer or expands into a node.
|
|
+ */
|
|
static inline void mas_store_root(struct ma_state *mas, void *entry)
|
|
{
|
|
- if (likely((mas->last != 0) || (mas->index != 0)))
|
|
+ if (!entry) {
|
|
+ if (!mas->index)
|
|
+ rcu_assign_pointer(mas->tree->ma_root, NULL);
|
|
+ } else if (likely((mas->last != 0) || (mas->index != 0)))
|
|
mas_root_expand(mas, entry);
|
|
else if (((unsigned long) (entry) & 3) == 2)
|
|
mas_root_expand(mas, entry);
|
|
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
|
|
index 9982344cca34d6..8f9f28dfdb3965 100644
|
|
--- a/lib/string_helpers.c
|
|
+++ b/lib/string_helpers.c
|
|
@@ -52,7 +52,7 @@ void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
|
|
static const unsigned int rounding[] = { 500, 50, 5 };
|
|
int i = 0, j;
|
|
u32 remainder = 0, sf_cap;
|
|
- char tmp[8];
|
|
+ char tmp[12];
|
|
const char *unit;
|
|
|
|
tmp[0] = '\0';
|
|
diff --git a/mm/internal.h b/mm/internal.h
|
|
index a0b24d00557953..f773db493a99d0 100644
|
|
--- a/mm/internal.h
|
|
+++ b/mm/internal.h
|
|
@@ -40,7 +40,7 @@ struct folio_batch;
|
|
* when we specify __GFP_NOWARN.
|
|
*/
|
|
#define WARN_ON_ONCE_GFP(cond, gfp) ({ \
|
|
- static bool __section(".data.once") __warned; \
|
|
+ static bool __section(".data..once") __warned; \
|
|
int __ret_warn_once = !!(cond); \
|
|
\
|
|
if (unlikely(!(gfp & __GFP_NOWARN) && __ret_warn_once && !__warned)) { \
|
|
diff --git a/mm/slab.h b/mm/slab.h
|
|
index 799a315695c679..62df6eeeb5ead7 100644
|
|
--- a/mm/slab.h
|
|
+++ b/mm/slab.h
|
|
@@ -78,6 +78,11 @@ struct slab {
|
|
struct {
|
|
unsigned inuse:16;
|
|
unsigned objects:15;
|
|
+ /*
|
|
+ * If slab debugging is enabled then the
|
|
+ * frozen bit can be reused to indicate
|
|
+ * that the slab was corrupted
|
|
+ */
|
|
unsigned frozen:1;
|
|
};
|
|
};
|
|
diff --git a/mm/slub.c b/mm/slub.c
|
|
index f7940048138c5a..d2544c88a5c43c 100644
|
|
--- a/mm/slub.c
|
|
+++ b/mm/slub.c
|
|
@@ -1275,6 +1275,11 @@ static int check_slab(struct kmem_cache *s, struct slab *slab)
|
|
slab->inuse, slab->objects);
|
|
return 0;
|
|
}
|
|
+ if (slab->frozen) {
|
|
+ slab_err(s, slab, "Slab disabled since SLUB metadata consistency check failed");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
/* Slab_pad_check fixes things up after itself */
|
|
slab_pad_check(s, slab);
|
|
return 1;
|
|
@@ -1463,6 +1468,7 @@ static noinline bool alloc_debug_processing(struct kmem_cache *s,
|
|
slab_fix(s, "Marking all objects used");
|
|
slab->inuse = slab->objects;
|
|
slab->freelist = NULL;
|
|
+ slab->frozen = 1; /* mark consistency-failed slab as frozen */
|
|
}
|
|
return false;
|
|
}
|
|
@@ -2162,7 +2168,8 @@ static void *alloc_single_from_partial(struct kmem_cache *s,
|
|
slab->inuse++;
|
|
|
|
if (!alloc_debug_processing(s, slab, object, orig_size)) {
|
|
- remove_partial(n, slab);
|
|
+ if (folio_test_slab(slab_folio(slab)))
|
|
+ remove_partial(n, slab);
|
|
return NULL;
|
|
}
|
|
|
|
diff --git a/mm/vmstat.c b/mm/vmstat.c
|
|
index e9616c4ca12db8..57891697846b93 100644
|
|
--- a/mm/vmstat.c
|
|
+++ b/mm/vmstat.c
|
|
@@ -1723,6 +1723,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
|
|
zone_page_state(zone, i));
|
|
|
|
#ifdef CONFIG_NUMA
|
|
+ fold_vm_zone_numa_events(zone);
|
|
for (i = 0; i < NR_VM_NUMA_EVENT_ITEMS; i++)
|
|
seq_printf(m, "\n %-12s %lu", numa_stat_name(i),
|
|
zone_numa_event_state(zone, i));
|
|
diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
|
|
index 1fffe2bed5b02f..6387ee924a2d61 100644
|
|
--- a/net/9p/trans_xen.c
|
|
+++ b/net/9p/trans_xen.c
|
|
@@ -287,7 +287,7 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
|
|
if (!priv->rings[i].intf)
|
|
break;
|
|
if (priv->rings[i].irq > 0)
|
|
- unbind_from_irqhandler(priv->rings[i].irq, priv->dev);
|
|
+ unbind_from_irqhandler(priv->rings[i].irq, ring);
|
|
if (priv->rings[i].data.in) {
|
|
for (j = 0;
|
|
j < (1 << priv->rings[i].intf->ring_order);
|
|
@@ -466,6 +466,7 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
|
|
goto error;
|
|
}
|
|
|
|
+ xenbus_switch_state(dev, XenbusStateInitialised);
|
|
return 0;
|
|
|
|
error_xenbus:
|
|
@@ -513,8 +514,10 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev,
|
|
break;
|
|
|
|
case XenbusStateInitWait:
|
|
- if (!xen_9pfs_front_init(dev))
|
|
- xenbus_switch_state(dev, XenbusStateInitialised);
|
|
+ if (dev->state != XenbusStateInitialising)
|
|
+ break;
|
|
+
|
|
+ xen_9pfs_front_init(dev);
|
|
break;
|
|
|
|
case XenbusStateConnected:
|
|
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
|
|
index 367e32fe30eb84..4b54dbbf0729a3 100644
|
|
--- a/net/bluetooth/hci_sysfs.c
|
|
+++ b/net/bluetooth/hci_sysfs.c
|
|
@@ -21,16 +21,6 @@ static const struct device_type bt_link = {
|
|
.release = bt_link_release,
|
|
};
|
|
|
|
-/*
|
|
- * The rfcomm tty device will possibly retain even when conn
|
|
- * is down, and sysfs doesn't support move zombie device,
|
|
- * so we should move the device before conn device is destroyed.
|
|
- */
|
|
-static int __match_tty(struct device *dev, void *data)
|
|
-{
|
|
- return !strncmp(dev_name(dev), "rfcomm", 6);
|
|
-}
|
|
-
|
|
void hci_conn_init_sysfs(struct hci_conn *conn)
|
|
{
|
|
struct hci_dev *hdev = conn->hdev;
|
|
@@ -73,10 +63,13 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
|
|
return;
|
|
}
|
|
|
|
+ /* If there are devices using the connection as parent reset it to NULL
|
|
+ * before unregistering the device.
|
|
+ */
|
|
while (1) {
|
|
struct device *dev;
|
|
|
|
- dev = device_find_child(&conn->dev, NULL, __match_tty);
|
|
+ dev = device_find_any_child(&conn->dev);
|
|
if (!dev)
|
|
break;
|
|
device_move(dev, NULL, DPM_ORDER_DEV_LAST);
|
|
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
|
|
index 1f3a39c20a9114..1175248e4bec4b 100644
|
|
--- a/net/bluetooth/mgmt.c
|
|
+++ b/net/bluetooth/mgmt.c
|
|
@@ -1318,7 +1318,8 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
|
|
struct mgmt_mode *cp;
|
|
|
|
/* Make sure cmd still outstanding. */
|
|
- if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
|
|
+ if (err == -ECANCELED ||
|
|
+ cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
|
|
return;
|
|
|
|
cp = cmd->param;
|
|
@@ -1351,7 +1352,13 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
|
|
static int set_powered_sync(struct hci_dev *hdev, void *data)
|
|
{
|
|
struct mgmt_pending_cmd *cmd = data;
|
|
- struct mgmt_mode *cp = cmd->param;
|
|
+ struct mgmt_mode *cp;
|
|
+
|
|
+ /* Make sure cmd still outstanding. */
|
|
+ if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
|
|
+ return -ECANCELED;
|
|
+
|
|
+ cp = cmd->param;
|
|
|
|
BT_DBG("%s", hdev->name);
|
|
|
|
@@ -1503,7 +1510,8 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
|
|
bt_dev_dbg(hdev, "err %d", err);
|
|
|
|
/* Make sure cmd still outstanding. */
|
|
- if (cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
|
|
+ if (err == -ECANCELED ||
|
|
+ cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
|
|
return;
|
|
|
|
hci_dev_lock(hdev);
|
|
@@ -1677,7 +1685,8 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
|
|
bt_dev_dbg(hdev, "err %d", err);
|
|
|
|
/* Make sure cmd still outstanding. */
|
|
- if (cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
|
|
+ if (err == -ECANCELED ||
|
|
+ cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
|
|
return;
|
|
|
|
hci_dev_lock(hdev);
|
|
@@ -1910,7 +1919,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
|
|
bool changed;
|
|
|
|
/* Make sure cmd still outstanding. */
|
|
- if (cmd != pending_find(MGMT_OP_SET_SSP, hdev))
|
|
+ if (err == -ECANCELED || cmd != pending_find(MGMT_OP_SET_SSP, hdev))
|
|
return;
|
|
|
|
if (err) {
|
|
@@ -3775,7 +3784,8 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err)
|
|
|
|
bt_dev_dbg(hdev, "err %d", err);
|
|
|
|
- if (cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev))
|
|
+ if (err == -ECANCELED ||
|
|
+ cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev))
|
|
return;
|
|
|
|
if (status) {
|
|
@@ -3950,7 +3960,8 @@ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err)
|
|
struct sk_buff *skb = cmd->skb;
|
|
u8 status = mgmt_status(err);
|
|
|
|
- if (cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev))
|
|
+ if (err == -ECANCELED ||
|
|
+ cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev))
|
|
return;
|
|
|
|
if (!status) {
|
|
@@ -5841,13 +5852,16 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
|
|
{
|
|
struct mgmt_pending_cmd *cmd = data;
|
|
|
|
+ bt_dev_dbg(hdev, "err %d", err);
|
|
+
|
|
+ if (err == -ECANCELED)
|
|
+ return;
|
|
+
|
|
if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) &&
|
|
cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) &&
|
|
cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev))
|
|
return;
|
|
|
|
- bt_dev_dbg(hdev, "err %d", err);
|
|
-
|
|
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
|
|
cmd->param, 1);
|
|
mgmt_pending_remove(cmd);
|
|
@@ -6080,7 +6094,8 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
|
|
{
|
|
struct mgmt_pending_cmd *cmd = data;
|
|
|
|
- if (cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev))
|
|
+ if (err == -ECANCELED ||
|
|
+ cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev))
|
|
return;
|
|
|
|
bt_dev_dbg(hdev, "err %d", err);
|
|
@@ -8025,7 +8040,8 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data,
|
|
u8 status = mgmt_status(err);
|
|
u16 eir_len;
|
|
|
|
- if (cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev))
|
|
+ if (err == -ECANCELED ||
|
|
+ cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev))
|
|
return;
|
|
|
|
if (!status) {
|
|
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
|
|
index cbff37b3273407..4fae82fedccaf9 100644
|
|
--- a/net/bluetooth/rfcomm/sock.c
|
|
+++ b/net/bluetooth/rfcomm/sock.c
|
|
@@ -729,7 +729,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
|
|
struct sock *l2cap_sk;
|
|
struct l2cap_conn *conn;
|
|
struct rfcomm_conninfo cinfo;
|
|
- int len, err = 0;
|
|
+ int err = 0;
|
|
+ size_t len;
|
|
u32 opt;
|
|
|
|
BT_DBG("sk %p", sk);
|
|
@@ -783,7 +784,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
|
|
cinfo.hci_handle = conn->hcon->handle;
|
|
memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
|
|
|
|
- len = min_t(unsigned int, len, sizeof(cinfo));
|
|
+ len = min(len, sizeof(cinfo));
|
|
if (copy_to_user(optval, (char *) &cinfo, len))
|
|
err = -EFAULT;
|
|
|
|
@@ -802,7 +803,8 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
|
|
{
|
|
struct sock *sk = sock->sk;
|
|
struct bt_security sec;
|
|
- int len, err = 0;
|
|
+ int err = 0;
|
|
+ size_t len;
|
|
|
|
BT_DBG("sk %p", sk);
|
|
|
|
@@ -827,7 +829,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
|
|
sec.level = rfcomm_pi(sk)->sec_level;
|
|
sec.key_size = 0;
|
|
|
|
- len = min_t(unsigned int, len, sizeof(sec));
|
|
+ len = min(len, sizeof(sec));
|
|
if (copy_to_user(optval, (char *) &sec, len))
|
|
err = -EFAULT;
|
|
|
|
diff --git a/net/core/filter.c b/net/core/filter.c
|
|
index f9d05eff80b17c..b64e7139eae19e 100644
|
|
--- a/net/core/filter.c
|
|
+++ b/net/core/filter.c
|
|
@@ -2602,18 +2602,16 @@ BPF_CALL_2(bpf_msg_cork_bytes, struct sk_msg *, msg, u32, bytes)
|
|
|
|
static void sk_msg_reset_curr(struct sk_msg *msg)
|
|
{
|
|
- u32 i = msg->sg.start;
|
|
- u32 len = 0;
|
|
-
|
|
- do {
|
|
- len += sk_msg_elem(msg, i)->length;
|
|
- sk_msg_iter_var_next(i);
|
|
- if (len >= msg->sg.size)
|
|
- break;
|
|
- } while (i != msg->sg.end);
|
|
+ if (!msg->sg.size) {
|
|
+ msg->sg.curr = msg->sg.start;
|
|
+ msg->sg.copybreak = 0;
|
|
+ } else {
|
|
+ u32 i = msg->sg.end;
|
|
|
|
- msg->sg.curr = i;
|
|
- msg->sg.copybreak = 0;
|
|
+ sk_msg_iter_var_prev(i);
|
|
+ msg->sg.curr = i;
|
|
+ msg->sg.copybreak = msg->sg.data[i].length;
|
|
+ }
|
|
}
|
|
|
|
static const struct bpf_func_proto bpf_msg_cork_bytes_proto = {
|
|
@@ -2776,7 +2774,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
|
|
sk_msg_iter_var_next(i);
|
|
} while (i != msg->sg.end);
|
|
|
|
- if (start >= offset + l)
|
|
+ if (start > offset + l)
|
|
return -EINVAL;
|
|
|
|
space = MAX_MSG_FRAGS - sk_msg_elem_used(msg);
|
|
@@ -2801,6 +2799,8 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
|
|
|
|
raw = page_address(page);
|
|
|
|
+ if (i == msg->sg.end)
|
|
+ sk_msg_iter_var_prev(i);
|
|
psge = sk_msg_elem(msg, i);
|
|
front = start - offset;
|
|
back = psge->length - front;
|
|
@@ -2817,7 +2817,13 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
|
|
}
|
|
|
|
put_page(sg_page(psge));
|
|
- } else if (start - offset) {
|
|
+ new = i;
|
|
+ goto place_new;
|
|
+ }
|
|
+
|
|
+ if (start - offset) {
|
|
+ if (i == msg->sg.end)
|
|
+ sk_msg_iter_var_prev(i);
|
|
psge = sk_msg_elem(msg, i);
|
|
rsge = sk_msg_elem_cpy(msg, i);
|
|
|
|
@@ -2828,39 +2834,44 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
|
|
sk_msg_iter_var_next(i);
|
|
sg_unmark_end(psge);
|
|
sg_unmark_end(&rsge);
|
|
- sk_msg_iter_next(msg, end);
|
|
}
|
|
|
|
/* Slot(s) to place newly allocated data */
|
|
+ sk_msg_iter_next(msg, end);
|
|
new = i;
|
|
+ sk_msg_iter_var_next(i);
|
|
+
|
|
+ if (i == msg->sg.end) {
|
|
+ if (!rsge.length)
|
|
+ goto place_new;
|
|
+ sk_msg_iter_next(msg, end);
|
|
+ goto place_new;
|
|
+ }
|
|
|
|
/* Shift one or two slots as needed */
|
|
- if (!copy) {
|
|
- sge = sk_msg_elem_cpy(msg, i);
|
|
+ sge = sk_msg_elem_cpy(msg, new);
|
|
+ sg_unmark_end(&sge);
|
|
|
|
+ nsge = sk_msg_elem_cpy(msg, i);
|
|
+ if (rsge.length) {
|
|
sk_msg_iter_var_next(i);
|
|
- sg_unmark_end(&sge);
|
|
+ nnsge = sk_msg_elem_cpy(msg, i);
|
|
sk_msg_iter_next(msg, end);
|
|
+ }
|
|
|
|
- nsge = sk_msg_elem_cpy(msg, i);
|
|
+ while (i != msg->sg.end) {
|
|
+ msg->sg.data[i] = sge;
|
|
+ sge = nsge;
|
|
+ sk_msg_iter_var_next(i);
|
|
if (rsge.length) {
|
|
- sk_msg_iter_var_next(i);
|
|
+ nsge = nnsge;
|
|
nnsge = sk_msg_elem_cpy(msg, i);
|
|
- }
|
|
-
|
|
- while (i != msg->sg.end) {
|
|
- msg->sg.data[i] = sge;
|
|
- sge = nsge;
|
|
- sk_msg_iter_var_next(i);
|
|
- if (rsge.length) {
|
|
- nsge = nnsge;
|
|
- nnsge = sk_msg_elem_cpy(msg, i);
|
|
- } else {
|
|
- nsge = sk_msg_elem_cpy(msg, i);
|
|
- }
|
|
+ } else {
|
|
+ nsge = sk_msg_elem_cpy(msg, i);
|
|
}
|
|
}
|
|
|
|
+place_new:
|
|
/* Place newly allocated data buffer */
|
|
sk_mem_charge(msg->sk, len);
|
|
msg->sg.size += len;
|
|
@@ -2889,8 +2900,10 @@ static const struct bpf_func_proto bpf_msg_push_data_proto = {
|
|
|
|
static void sk_msg_shift_left(struct sk_msg *msg, int i)
|
|
{
|
|
+ struct scatterlist *sge = sk_msg_elem(msg, i);
|
|
int prev;
|
|
|
|
+ put_page(sg_page(sge));
|
|
do {
|
|
prev = i;
|
|
sk_msg_iter_var_next(i);
|
|
@@ -2927,6 +2940,9 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
|
|
if (unlikely(flags))
|
|
return -EINVAL;
|
|
|
|
+ if (unlikely(len == 0))
|
|
+ return 0;
|
|
+
|
|
/* First find the starting scatterlist element */
|
|
i = msg->sg.start;
|
|
do {
|
|
@@ -2939,7 +2955,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
|
|
} while (i != msg->sg.end);
|
|
|
|
/* Bounds checks: start and pop must be inside message */
|
|
- if (start >= offset + l || last >= msg->sg.size)
|
|
+ if (start >= offset + l || last > msg->sg.size)
|
|
return -EINVAL;
|
|
|
|
space = MAX_MSG_FRAGS - sk_msg_elem_used(msg);
|
|
@@ -2968,12 +2984,12 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
|
|
*/
|
|
if (start != offset) {
|
|
struct scatterlist *nsge, *sge = sk_msg_elem(msg, i);
|
|
- int a = start;
|
|
+ int a = start - offset;
|
|
int b = sge->length - pop - a;
|
|
|
|
sk_msg_iter_var_next(i);
|
|
|
|
- if (pop < sge->length - a) {
|
|
+ if (b > 0) {
|
|
if (space) {
|
|
sge->length = a;
|
|
sk_msg_shift_right(msg, i);
|
|
@@ -2992,7 +3008,6 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
|
|
if (unlikely(!page))
|
|
return -ENOMEM;
|
|
|
|
- sge->length = a;
|
|
orig = sg_page(sge);
|
|
from = sg_virt(sge);
|
|
to = page_address(page);
|
|
@@ -3002,7 +3017,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
|
|
put_page(orig);
|
|
}
|
|
pop = 0;
|
|
- } else if (pop >= sge->length - a) {
|
|
+ } else {
|
|
pop -= (sge->length - a);
|
|
sge->length = a;
|
|
}
|
|
@@ -3036,7 +3051,6 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
|
|
pop -= sge->length;
|
|
sk_msg_shift_left(msg, i);
|
|
}
|
|
- sk_msg_iter_var_next(i);
|
|
}
|
|
|
|
sk_mem_uncharge(msg->sk, len - pop);
|
|
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
|
|
index fae9c4694186ea..412816076b8bc5 100644
|
|
--- a/net/core/gen_estimator.c
|
|
+++ b/net/core/gen_estimator.c
|
|
@@ -206,7 +206,7 @@ void gen_kill_estimator(struct net_rate_estimator __rcu **rate_est)
|
|
{
|
|
struct net_rate_estimator *est;
|
|
|
|
- est = xchg((__force struct net_rate_estimator **)rate_est, NULL);
|
|
+ est = unrcu_pointer(xchg(rate_est, NULL));
|
|
if (est) {
|
|
timer_shutdown_sync(&est->timer);
|
|
kfree_rcu(est, rcu);
|
|
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
|
|
index bbf40b99971382..846fd672f0e529 100644
|
|
--- a/net/core/skmsg.c
|
|
+++ b/net/core/skmsg.c
|
|
@@ -1117,9 +1117,9 @@ static void sk_psock_strp_data_ready(struct sock *sk)
|
|
if (tls_sw_has_ctx_rx(sk)) {
|
|
psock->saved_data_ready(sk);
|
|
} else {
|
|
- write_lock_bh(&sk->sk_callback_lock);
|
|
+ read_lock_bh(&sk->sk_callback_lock);
|
|
strp_data_ready(&psock->strp);
|
|
- write_unlock_bh(&sk->sk_callback_lock);
|
|
+ read_unlock_bh(&sk->sk_callback_lock);
|
|
}
|
|
}
|
|
rcu_read_unlock();
|
|
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
|
|
index c53b731f2d6728..70007fc578a136 100644
|
|
--- a/net/core/sock_diag.c
|
|
+++ b/net/core/sock_diag.c
|
|
@@ -16,9 +16,10 @@
|
|
#include <linux/inet_diag.h>
|
|
#include <linux/sock_diag.h>
|
|
|
|
-static const struct sock_diag_handler *sock_diag_handlers[AF_MAX];
|
|
-static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh);
|
|
-static DEFINE_MUTEX(sock_diag_table_mutex);
|
|
+static const struct sock_diag_handler __rcu *sock_diag_handlers[AF_MAX];
|
|
+
|
|
+static const struct sock_diag_inet_compat __rcu *inet_rcv_compat;
|
|
+
|
|
static struct workqueue_struct *broadcast_wq;
|
|
|
|
DEFINE_COOKIE(sock_cookie);
|
|
@@ -122,6 +123,24 @@ static size_t sock_diag_nlmsg_size(void)
|
|
+ nla_total_size_64bit(sizeof(struct tcp_info))); /* INET_DIAG_INFO */
|
|
}
|
|
|
|
+static const struct sock_diag_handler *sock_diag_lock_handler(int family)
|
|
+{
|
|
+ const struct sock_diag_handler *handler;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ handler = rcu_dereference(sock_diag_handlers[family]);
|
|
+ if (handler && !try_module_get(handler->owner))
|
|
+ handler = NULL;
|
|
+ rcu_read_unlock();
|
|
+
|
|
+ return handler;
|
|
+}
|
|
+
|
|
+static void sock_diag_unlock_handler(const struct sock_diag_handler *handler)
|
|
+{
|
|
+ module_put(handler->owner);
|
|
+}
|
|
+
|
|
static void sock_diag_broadcast_destroy_work(struct work_struct *work)
|
|
{
|
|
struct broadcast_sk *bsk =
|
|
@@ -138,12 +157,12 @@ static void sock_diag_broadcast_destroy_work(struct work_struct *work)
|
|
if (!skb)
|
|
goto out;
|
|
|
|
- mutex_lock(&sock_diag_table_mutex);
|
|
- hndl = sock_diag_handlers[sk->sk_family];
|
|
- if (hndl && hndl->get_info)
|
|
- err = hndl->get_info(skb, sk);
|
|
- mutex_unlock(&sock_diag_table_mutex);
|
|
-
|
|
+ hndl = sock_diag_lock_handler(sk->sk_family);
|
|
+ if (hndl) {
|
|
+ if (hndl->get_info)
|
|
+ err = hndl->get_info(skb, sk);
|
|
+ sock_diag_unlock_handler(hndl);
|
|
+ }
|
|
if (!err)
|
|
nlmsg_multicast(sock_net(sk)->diag_nlsk, skb, 0, group,
|
|
GFP_KERNEL);
|
|
@@ -166,51 +185,43 @@ void sock_diag_broadcast_destroy(struct sock *sk)
|
|
queue_work(broadcast_wq, &bsk->work);
|
|
}
|
|
|
|
-void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh))
|
|
+void sock_diag_register_inet_compat(const struct sock_diag_inet_compat *ptr)
|
|
{
|
|
- mutex_lock(&sock_diag_table_mutex);
|
|
- inet_rcv_compat = fn;
|
|
- mutex_unlock(&sock_diag_table_mutex);
|
|
+ xchg(&inet_rcv_compat, RCU_INITIALIZER(ptr));
|
|
}
|
|
EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat);
|
|
|
|
-void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh))
|
|
+void sock_diag_unregister_inet_compat(const struct sock_diag_inet_compat *ptr)
|
|
{
|
|
- mutex_lock(&sock_diag_table_mutex);
|
|
- inet_rcv_compat = NULL;
|
|
- mutex_unlock(&sock_diag_table_mutex);
|
|
+ const struct sock_diag_inet_compat *old;
|
|
+
|
|
+ old = unrcu_pointer(xchg(&inet_rcv_compat, NULL));
|
|
+ WARN_ON_ONCE(old != ptr);
|
|
}
|
|
EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat);
|
|
|
|
int sock_diag_register(const struct sock_diag_handler *hndl)
|
|
{
|
|
- int err = 0;
|
|
+ int family = hndl->family;
|
|
|
|
- if (hndl->family >= AF_MAX)
|
|
+ if (family >= AF_MAX)
|
|
return -EINVAL;
|
|
|
|
- mutex_lock(&sock_diag_table_mutex);
|
|
- if (sock_diag_handlers[hndl->family])
|
|
- err = -EBUSY;
|
|
- else
|
|
- WRITE_ONCE(sock_diag_handlers[hndl->family], hndl);
|
|
- mutex_unlock(&sock_diag_table_mutex);
|
|
-
|
|
- return err;
|
|
+ return !cmpxchg((const struct sock_diag_handler **)
|
|
+ &sock_diag_handlers[family],
|
|
+ NULL, hndl) ? 0 : -EBUSY;
|
|
}
|
|
EXPORT_SYMBOL_GPL(sock_diag_register);
|
|
|
|
-void sock_diag_unregister(const struct sock_diag_handler *hnld)
|
|
+void sock_diag_unregister(const struct sock_diag_handler *hndl)
|
|
{
|
|
- int family = hnld->family;
|
|
+ int family = hndl->family;
|
|
|
|
if (family >= AF_MAX)
|
|
return;
|
|
|
|
- mutex_lock(&sock_diag_table_mutex);
|
|
- BUG_ON(sock_diag_handlers[family] != hnld);
|
|
- WRITE_ONCE(sock_diag_handlers[family], NULL);
|
|
- mutex_unlock(&sock_diag_table_mutex);
|
|
+ xchg((const struct sock_diag_handler **)&sock_diag_handlers[family],
|
|
+ NULL);
|
|
}
|
|
EXPORT_SYMBOL_GPL(sock_diag_unregister);
|
|
|
|
@@ -227,20 +238,20 @@ static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
return -EINVAL;
|
|
req->sdiag_family = array_index_nospec(req->sdiag_family, AF_MAX);
|
|
|
|
- if (READ_ONCE(sock_diag_handlers[req->sdiag_family]) == NULL)
|
|
+ if (!rcu_access_pointer(sock_diag_handlers[req->sdiag_family]))
|
|
sock_load_diag_module(req->sdiag_family, 0);
|
|
|
|
- mutex_lock(&sock_diag_table_mutex);
|
|
- hndl = sock_diag_handlers[req->sdiag_family];
|
|
+ hndl = sock_diag_lock_handler(req->sdiag_family);
|
|
if (hndl == NULL)
|
|
- err = -ENOENT;
|
|
- else if (nlh->nlmsg_type == SOCK_DIAG_BY_FAMILY)
|
|
+ return -ENOENT;
|
|
+
|
|
+ if (nlh->nlmsg_type == SOCK_DIAG_BY_FAMILY)
|
|
err = hndl->dump(skb, nlh);
|
|
else if (nlh->nlmsg_type == SOCK_DESTROY && hndl->destroy)
|
|
err = hndl->destroy(skb, nlh);
|
|
else
|
|
err = -EOPNOTSUPP;
|
|
- mutex_unlock(&sock_diag_table_mutex);
|
|
+ sock_diag_unlock_handler(hndl);
|
|
|
|
return err;
|
|
}
|
|
@@ -248,20 +259,27 @@ static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|
static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
struct netlink_ext_ack *extack)
|
|
{
|
|
+ const struct sock_diag_inet_compat *ptr;
|
|
int ret;
|
|
|
|
switch (nlh->nlmsg_type) {
|
|
case TCPDIAG_GETSOCK:
|
|
case DCCPDIAG_GETSOCK:
|
|
- if (inet_rcv_compat == NULL)
|
|
+
|
|
+ if (!rcu_access_pointer(inet_rcv_compat))
|
|
sock_load_diag_module(AF_INET, 0);
|
|
|
|
- mutex_lock(&sock_diag_table_mutex);
|
|
- if (inet_rcv_compat != NULL)
|
|
- ret = inet_rcv_compat(skb, nlh);
|
|
- else
|
|
- ret = -EOPNOTSUPP;
|
|
- mutex_unlock(&sock_diag_table_mutex);
|
|
+ rcu_read_lock();
|
|
+ ptr = rcu_dereference(inet_rcv_compat);
|
|
+ if (ptr && !try_module_get(ptr->owner))
|
|
+ ptr = NULL;
|
|
+ rcu_read_unlock();
|
|
+
|
|
+ ret = -EOPNOTSUPP;
|
|
+ if (ptr) {
|
|
+ ret = ptr->fn(skb, nlh);
|
|
+ module_put(ptr->owner);
|
|
+ }
|
|
|
|
return ret;
|
|
case SOCK_DIAG_BY_FAMILY:
|
|
@@ -286,12 +304,12 @@ static int sock_diag_bind(struct net *net, int group)
|
|
switch (group) {
|
|
case SKNLGRP_INET_TCP_DESTROY:
|
|
case SKNLGRP_INET_UDP_DESTROY:
|
|
- if (!READ_ONCE(sock_diag_handlers[AF_INET]))
|
|
+ if (!rcu_access_pointer(sock_diag_handlers[AF_INET]))
|
|
sock_load_diag_module(AF_INET, 0);
|
|
break;
|
|
case SKNLGRP_INET6_TCP_DESTROY:
|
|
case SKNLGRP_INET6_UDP_DESTROY:
|
|
- if (!READ_ONCE(sock_diag_handlers[AF_INET6]))
|
|
+ if (!rcu_access_pointer(sock_diag_handlers[AF_INET6]))
|
|
sock_load_diag_module(AF_INET6, 0);
|
|
break;
|
|
}
|
|
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
|
|
index c5f7bd01379ce3..906c38b9d66ff3 100644
|
|
--- a/net/hsr/hsr_device.c
|
|
+++ b/net/hsr/hsr_device.c
|
|
@@ -253,6 +253,8 @@ static struct sk_buff *hsr_init_skb(struct hsr_port *master)
|
|
skb->dev = master->dev;
|
|
skb->priority = TC_PRIO_CONTROL;
|
|
|
|
+ skb_reset_network_header(skb);
|
|
+ skb_reset_transport_header(skb);
|
|
if (dev_hard_header(skb, skb->dev, ETH_P_PRP,
|
|
hsr->sup_multicast_addr,
|
|
skb->dev->dev_addr, skb->len) <= 0)
|
|
@@ -260,8 +262,6 @@ static struct sk_buff *hsr_init_skb(struct hsr_port *master)
|
|
|
|
skb_reset_mac_header(skb);
|
|
skb_reset_mac_len(skb);
|
|
- skb_reset_network_header(skb);
|
|
- skb_reset_transport_header(skb);
|
|
|
|
return skb;
|
|
out:
|
|
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
|
|
index 685474ef11c400..8daa6418e25a0d 100644
|
|
--- a/net/ipv4/cipso_ipv4.c
|
|
+++ b/net/ipv4/cipso_ipv4.c
|
|
@@ -1955,7 +1955,7 @@ int cipso_v4_req_setattr(struct request_sock *req,
|
|
buf = NULL;
|
|
|
|
req_inet = inet_rsk(req);
|
|
- opt = xchg((__force struct ip_options_rcu **)&req_inet->ireq_opt, opt);
|
|
+ opt = unrcu_pointer(xchg(&req_inet->ireq_opt, RCU_INITIALIZER(opt)));
|
|
if (opt)
|
|
kfree_rcu(opt, rcu);
|
|
|
|
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
|
|
index ca8cc0988b618c..bd032ac2376ed7 100644
|
|
--- a/net/ipv4/inet_connection_sock.c
|
|
+++ b/net/ipv4/inet_connection_sock.c
|
|
@@ -1124,7 +1124,7 @@ static void reqsk_timer_handler(struct timer_list *t)
|
|
|
|
drop:
|
|
__inet_csk_reqsk_queue_drop(sk_listener, oreq, true);
|
|
- reqsk_put(req);
|
|
+ reqsk_put(oreq);
|
|
}
|
|
|
|
static bool reqsk_queue_hash_req(struct request_sock *req,
|
|
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
|
|
index 87ecefea72398d..5d09ab3ed735e9 100644
|
|
--- a/net/ipv4/inet_diag.c
|
|
+++ b/net/ipv4/inet_diag.c
|
|
@@ -1397,6 +1397,7 @@ int inet_diag_handler_get_info(struct sk_buff *skb, struct sock *sk)
|
|
}
|
|
|
|
static const struct sock_diag_handler inet_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_INET,
|
|
.dump = inet_diag_handler_cmd,
|
|
.get_info = inet_diag_handler_get_info,
|
|
@@ -1404,6 +1405,7 @@ static const struct sock_diag_handler inet_diag_handler = {
|
|
};
|
|
|
|
static const struct sock_diag_handler inet6_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_INET6,
|
|
.dump = inet_diag_handler_cmd,
|
|
.get_info = inet_diag_handler_get_info,
|
|
@@ -1443,6 +1445,11 @@ void inet_diag_unregister(const struct inet_diag_handler *h)
|
|
}
|
|
EXPORT_SYMBOL_GPL(inet_diag_unregister);
|
|
|
|
+static const struct sock_diag_inet_compat inet_diag_compat = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .fn = inet_diag_rcv_msg_compat,
|
|
+};
|
|
+
|
|
static int __init inet_diag_init(void)
|
|
{
|
|
const int inet_diag_table_size = (IPPROTO_MAX *
|
|
@@ -1461,7 +1468,7 @@ static int __init inet_diag_init(void)
|
|
if (err)
|
|
goto out_free_inet;
|
|
|
|
- sock_diag_register_inet_compat(inet_diag_rcv_msg_compat);
|
|
+ sock_diag_register_inet_compat(&inet_diag_compat);
|
|
out:
|
|
return err;
|
|
|
|
@@ -1476,7 +1483,7 @@ static void __exit inet_diag_exit(void)
|
|
{
|
|
sock_diag_unregister(&inet6_diag_handler);
|
|
sock_diag_unregister(&inet_diag_handler);
|
|
- sock_diag_unregister_inet_compat(inet_diag_rcv_msg_compat);
|
|
+ sock_diag_unregister_inet_compat(&inet_diag_compat);
|
|
kfree(inet_diag_table);
|
|
}
|
|
|
|
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
|
|
index 66eade3fb629f1..dc0ad979a894ab 100644
|
|
--- a/net/ipv4/ipmr.c
|
|
+++ b/net/ipv4/ipmr.c
|
|
@@ -136,7 +136,7 @@ static struct mr_table *ipmr_mr_table_iter(struct net *net,
|
|
return ret;
|
|
}
|
|
|
|
-static struct mr_table *ipmr_get_table(struct net *net, u32 id)
|
|
+static struct mr_table *__ipmr_get_table(struct net *net, u32 id)
|
|
{
|
|
struct mr_table *mrt;
|
|
|
|
@@ -147,6 +147,16 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
|
|
return NULL;
|
|
}
|
|
|
|
+static struct mr_table *ipmr_get_table(struct net *net, u32 id)
|
|
+{
|
|
+ struct mr_table *mrt;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ mrt = __ipmr_get_table(net, id);
|
|
+ rcu_read_unlock();
|
|
+ return mrt;
|
|
+}
|
|
+
|
|
static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
|
|
struct mr_table **mrt)
|
|
{
|
|
@@ -188,7 +198,7 @@ static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp,
|
|
|
|
arg->table = fib_rule_get_table(rule, arg);
|
|
|
|
- mrt = ipmr_get_table(rule->fr_net, arg->table);
|
|
+ mrt = __ipmr_get_table(rule->fr_net, arg->table);
|
|
if (!mrt)
|
|
return -EAGAIN;
|
|
res->mrt = mrt;
|
|
@@ -314,6 +324,8 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
|
|
return net->ipv4.mrt;
|
|
}
|
|
|
|
+#define __ipmr_get_table ipmr_get_table
|
|
+
|
|
static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
|
|
struct mr_table **mrt)
|
|
{
|
|
@@ -402,7 +414,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
|
|
if (id != RT_TABLE_DEFAULT && id >= 1000000000)
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
- mrt = ipmr_get_table(net, id);
|
|
+ mrt = __ipmr_get_table(net, id);
|
|
if (mrt)
|
|
return mrt;
|
|
|
|
@@ -1373,7 +1385,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
|
|
goto out_unlock;
|
|
}
|
|
|
|
- mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
|
|
+ mrt = __ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
|
|
if (!mrt) {
|
|
ret = -ENOENT;
|
|
goto out_unlock;
|
|
@@ -2261,11 +2273,13 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
|
|
struct mr_table *mrt;
|
|
int err;
|
|
|
|
- mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
|
|
- if (!mrt)
|
|
+ rcu_read_lock();
|
|
+ mrt = __ipmr_get_table(net, RT_TABLE_DEFAULT);
|
|
+ if (!mrt) {
|
|
+ rcu_read_unlock();
|
|
return -ENOENT;
|
|
+ }
|
|
|
|
- rcu_read_lock();
|
|
cache = ipmr_cache_find(mrt, saddr, daddr);
|
|
if (!cache && skb->dev) {
|
|
int vif = ipmr_find_vif(mrt, skb->dev);
|
|
@@ -2550,7 +2564,7 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
|
|
grp = tb[RTA_DST] ? nla_get_in_addr(tb[RTA_DST]) : 0;
|
|
tableid = tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : 0;
|
|
|
|
- mrt = ipmr_get_table(net, tableid ? tableid : RT_TABLE_DEFAULT);
|
|
+ mrt = __ipmr_get_table(net, tableid ? tableid : RT_TABLE_DEFAULT);
|
|
if (!mrt) {
|
|
err = -ENOENT;
|
|
goto errout_free;
|
|
@@ -2602,7 +2616,7 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
|
|
if (filter.table_id) {
|
|
struct mr_table *mrt;
|
|
|
|
- mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id);
|
|
+ mrt = __ipmr_get_table(sock_net(skb->sk), filter.table_id);
|
|
if (!mrt) {
|
|
if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IPMR)
|
|
return skb->len;
|
|
@@ -2710,7 +2724,7 @@ static int rtm_to_ipmr_mfcc(struct net *net, struct nlmsghdr *nlh,
|
|
break;
|
|
}
|
|
}
|
|
- mrt = ipmr_get_table(net, tblid);
|
|
+ mrt = __ipmr_get_table(net, tblid);
|
|
if (!mrt) {
|
|
ret = -ENOENT;
|
|
goto out;
|
|
@@ -2918,13 +2932,15 @@ static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos)
|
|
struct net *net = seq_file_net(seq);
|
|
struct mr_table *mrt;
|
|
|
|
- mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
|
|
- if (!mrt)
|
|
+ rcu_read_lock();
|
|
+ mrt = __ipmr_get_table(net, RT_TABLE_DEFAULT);
|
|
+ if (!mrt) {
|
|
+ rcu_read_unlock();
|
|
return ERR_PTR(-ENOENT);
|
|
+ }
|
|
|
|
iter->mrt = mrt;
|
|
|
|
- rcu_read_lock();
|
|
return mr_vif_seq_start(seq, pos);
|
|
}
|
|
|
|
diff --git a/net/ipv4/ipmr_base.c b/net/ipv4/ipmr_base.c
|
|
index 271dc03fc6dbd9..f0af12a2f70bcd 100644
|
|
--- a/net/ipv4/ipmr_base.c
|
|
+++ b/net/ipv4/ipmr_base.c
|
|
@@ -310,7 +310,8 @@ int mr_table_dump(struct mr_table *mrt, struct sk_buff *skb,
|
|
if (filter->filter_set)
|
|
flags |= NLM_F_DUMP_FILTERED;
|
|
|
|
- list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list) {
|
|
+ list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list,
|
|
+ lockdep_rtnl_is_held()) {
|
|
if (e < s_e)
|
|
goto next_entry;
|
|
if (filter->dev &&
|
|
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
|
|
index 75371928d94f6e..5e6615f69f175d 100644
|
|
--- a/net/ipv4/tcp.c
|
|
+++ b/net/ipv4/tcp.c
|
|
@@ -3065,7 +3065,7 @@ int tcp_disconnect(struct sock *sk, int flags)
|
|
icsk->icsk_ack.rcv_mss = TCP_MIN_MSS;
|
|
memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
|
|
__sk_dst_reset(sk);
|
|
- dst_release(xchg((__force struct dst_entry **)&sk->sk_rx_dst, NULL));
|
|
+ dst_release(unrcu_pointer(xchg(&sk->sk_rx_dst, NULL)));
|
|
tcp_saved_syn_free(tp);
|
|
tp->compressed_ack = 0;
|
|
tp->segs_in = 0;
|
|
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
|
|
index fe6178715ba05f..915286c3615a27 100644
|
|
--- a/net/ipv4/tcp_bpf.c
|
|
+++ b/net/ipv4/tcp_bpf.c
|
|
@@ -221,11 +221,11 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
|
|
int flags,
|
|
int *addr_len)
|
|
{
|
|
- struct tcp_sock *tcp = tcp_sk(sk);
|
|
int peek = flags & MSG_PEEK;
|
|
- u32 seq = tcp->copied_seq;
|
|
struct sk_psock *psock;
|
|
+ struct tcp_sock *tcp;
|
|
int copied = 0;
|
|
+ u32 seq;
|
|
|
|
if (unlikely(flags & MSG_ERRQUEUE))
|
|
return inet_recv_error(sk, msg, len, addr_len);
|
|
@@ -238,7 +238,8 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
|
|
return tcp_recvmsg(sk, msg, len, flags, addr_len);
|
|
|
|
lock_sock(sk);
|
|
-
|
|
+ tcp = tcp_sk(sk);
|
|
+ seq = tcp->copied_seq;
|
|
/* We may have received data on the sk_receive_queue pre-accept and
|
|
* then we can not use read_skb in this context because we haven't
|
|
* assigned a sk_socket yet so have no link to the ops. The work-around
|
|
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
|
|
index 8ed54e7334a9c6..0f523cbfe329ef 100644
|
|
--- a/net/ipv4/tcp_fastopen.c
|
|
+++ b/net/ipv4/tcp_fastopen.c
|
|
@@ -49,7 +49,7 @@ void tcp_fastopen_ctx_destroy(struct net *net)
|
|
{
|
|
struct tcp_fastopen_context *ctxt;
|
|
|
|
- ctxt = xchg((__force struct tcp_fastopen_context **)&net->ipv4.tcp_fastopen_ctx, NULL);
|
|
+ ctxt = unrcu_pointer(xchg(&net->ipv4.tcp_fastopen_ctx, NULL));
|
|
|
|
if (ctxt)
|
|
call_rcu(&ctxt->rcu, tcp_fastopen_ctx_free);
|
|
@@ -80,9 +80,10 @@ int tcp_fastopen_reset_cipher(struct net *net, struct sock *sk,
|
|
|
|
if (sk) {
|
|
q = &inet_csk(sk)->icsk_accept_queue.fastopenq;
|
|
- octx = xchg((__force struct tcp_fastopen_context **)&q->ctx, ctx);
|
|
+ octx = unrcu_pointer(xchg(&q->ctx, RCU_INITIALIZER(ctx)));
|
|
} else {
|
|
- octx = xchg((__force struct tcp_fastopen_context **)&net->ipv4.tcp_fastopen_ctx, ctx);
|
|
+ octx = unrcu_pointer(xchg(&net->ipv4.tcp_fastopen_ctx,
|
|
+ RCU_INITIALIZER(ctx)));
|
|
}
|
|
|
|
if (octx)
|
|
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
|
|
index 73fb814460b6b7..2e4e5356039480 100644
|
|
--- a/net/ipv4/udp.c
|
|
+++ b/net/ipv4/udp.c
|
|
@@ -2232,7 +2232,7 @@ bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
|
|
struct dst_entry *old;
|
|
|
|
if (dst_hold_safe(dst)) {
|
|
- old = xchg((__force struct dst_entry **)&sk->sk_rx_dst, dst);
|
|
+ old = unrcu_pointer(xchg(&sk->sk_rx_dst, RCU_INITIALIZER(dst)));
|
|
dst_release(old);
|
|
return old != dst;
|
|
}
|
|
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
|
|
index a9358c796a8150..8360939acf85ad 100644
|
|
--- a/net/ipv6/addrconf.c
|
|
+++ b/net/ipv6/addrconf.c
|
|
@@ -2535,6 +2535,24 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
|
|
return idev;
|
|
}
|
|
|
|
+static void delete_tempaddrs(struct inet6_dev *idev,
|
|
+ struct inet6_ifaddr *ifp)
|
|
+{
|
|
+ struct inet6_ifaddr *ift, *tmp;
|
|
+
|
|
+ write_lock_bh(&idev->lock);
|
|
+ list_for_each_entry_safe(ift, tmp, &idev->tempaddr_list, tmp_list) {
|
|
+ if (ift->ifpub != ifp)
|
|
+ continue;
|
|
+
|
|
+ in6_ifa_hold(ift);
|
|
+ write_unlock_bh(&idev->lock);
|
|
+ ipv6_del_addr(ift);
|
|
+ write_lock_bh(&idev->lock);
|
|
+ }
|
|
+ write_unlock_bh(&idev->lock);
|
|
+}
|
|
+
|
|
static void manage_tempaddrs(struct inet6_dev *idev,
|
|
struct inet6_ifaddr *ifp,
|
|
__u32 valid_lft, __u32 prefered_lft,
|
|
@@ -3076,11 +3094,12 @@ static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
|
|
in6_ifa_hold(ifp);
|
|
read_unlock_bh(&idev->lock);
|
|
|
|
- if (!(ifp->flags & IFA_F_TEMPORARY) &&
|
|
- (ifa_flags & IFA_F_MANAGETEMPADDR))
|
|
- manage_tempaddrs(idev, ifp, 0, 0, false,
|
|
- jiffies);
|
|
ipv6_del_addr(ifp);
|
|
+
|
|
+ if (!(ifp->flags & IFA_F_TEMPORARY) &&
|
|
+ (ifp->flags & IFA_F_MANAGETEMPADDR))
|
|
+ delete_tempaddrs(idev, ifp);
|
|
+
|
|
addrconf_verify_rtnl(net);
|
|
if (ipv6_addr_is_multicast(pfx)) {
|
|
ipv6_mc_config(net->ipv6.mc_autojoin_sk,
|
|
@@ -4891,14 +4910,12 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
|
|
}
|
|
|
|
if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
|
|
- if (was_managetempaddr &&
|
|
- !(ifp->flags & IFA_F_MANAGETEMPADDR)) {
|
|
- cfg->valid_lft = 0;
|
|
- cfg->preferred_lft = 0;
|
|
- }
|
|
- manage_tempaddrs(ifp->idev, ifp, cfg->valid_lft,
|
|
- cfg->preferred_lft, !was_managetempaddr,
|
|
- jiffies);
|
|
+ if (was_managetempaddr && !(ifp->flags & IFA_F_MANAGETEMPADDR))
|
|
+ delete_tempaddrs(ifp->idev, ifp);
|
|
+ else
|
|
+ manage_tempaddrs(ifp->idev, ifp, cfg->valid_lft,
|
|
+ cfg->preferred_lft, !was_managetempaddr,
|
|
+ jiffies);
|
|
}
|
|
|
|
addrconf_verify_rtnl(net);
|
|
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
|
|
index b9c50cceba568c..99843eb4d49b9a 100644
|
|
--- a/net/ipv6/af_inet6.c
|
|
+++ b/net/ipv6/af_inet6.c
|
|
@@ -507,7 +507,7 @@ void inet6_cleanup_sock(struct sock *sk)
|
|
|
|
/* Free tx options */
|
|
|
|
- opt = xchg((__force struct ipv6_txoptions **)&np->opt, NULL);
|
|
+ opt = unrcu_pointer(xchg(&np->opt, NULL));
|
|
if (opt) {
|
|
atomic_sub(opt->tot_len, &sk->sk_omem_alloc);
|
|
txopt_put(opt);
|
|
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
|
|
index 4356806b52bd51..afa9073567dc40 100644
|
|
--- a/net/ipv6/ip6_fib.c
|
|
+++ b/net/ipv6/ip6_fib.c
|
|
@@ -982,7 +982,7 @@ static void __fib6_drop_pcpu_from(struct fib6_nh *fib6_nh,
|
|
if (pcpu_rt && rcu_access_pointer(pcpu_rt->from) == match) {
|
|
struct fib6_info *from;
|
|
|
|
- from = xchg((__force struct fib6_info **)&pcpu_rt->from, NULL);
|
|
+ from = unrcu_pointer(xchg(&pcpu_rt->from, NULL));
|
|
fib6_info_release(from);
|
|
}
|
|
}
|
|
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
|
|
index 30ca064b76ef17..e24fa0843c7d11 100644
|
|
--- a/net/ipv6/ip6mr.c
|
|
+++ b/net/ipv6/ip6mr.c
|
|
@@ -125,7 +125,7 @@ static struct mr_table *ip6mr_mr_table_iter(struct net *net,
|
|
return ret;
|
|
}
|
|
|
|
-static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
|
|
+static struct mr_table *__ip6mr_get_table(struct net *net, u32 id)
|
|
{
|
|
struct mr_table *mrt;
|
|
|
|
@@ -136,6 +136,16 @@ static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
|
|
return NULL;
|
|
}
|
|
|
|
+static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
|
|
+{
|
|
+ struct mr_table *mrt;
|
|
+
|
|
+ rcu_read_lock();
|
|
+ mrt = __ip6mr_get_table(net, id);
|
|
+ rcu_read_unlock();
|
|
+ return mrt;
|
|
+}
|
|
+
|
|
static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
|
|
struct mr_table **mrt)
|
|
{
|
|
@@ -177,7 +187,7 @@ static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp,
|
|
|
|
arg->table = fib_rule_get_table(rule, arg);
|
|
|
|
- mrt = ip6mr_get_table(rule->fr_net, arg->table);
|
|
+ mrt = __ip6mr_get_table(rule->fr_net, arg->table);
|
|
if (!mrt)
|
|
return -EAGAIN;
|
|
res->mrt = mrt;
|
|
@@ -304,6 +314,8 @@ static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
|
|
return net->ipv6.mrt6;
|
|
}
|
|
|
|
+#define __ip6mr_get_table ip6mr_get_table
|
|
+
|
|
static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
|
|
struct mr_table **mrt)
|
|
{
|
|
@@ -382,7 +394,7 @@ static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
|
|
{
|
|
struct mr_table *mrt;
|
|
|
|
- mrt = ip6mr_get_table(net, id);
|
|
+ mrt = __ip6mr_get_table(net, id);
|
|
if (mrt)
|
|
return mrt;
|
|
|
|
@@ -411,13 +423,15 @@ static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
|
|
struct net *net = seq_file_net(seq);
|
|
struct mr_table *mrt;
|
|
|
|
- mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
|
|
- if (!mrt)
|
|
+ rcu_read_lock();
|
|
+ mrt = __ip6mr_get_table(net, RT6_TABLE_DFLT);
|
|
+ if (!mrt) {
|
|
+ rcu_read_unlock();
|
|
return ERR_PTR(-ENOENT);
|
|
+ }
|
|
|
|
iter->mrt = mrt;
|
|
|
|
- rcu_read_lock();
|
|
return mr_vif_seq_start(seq, pos);
|
|
}
|
|
|
|
@@ -2278,11 +2292,13 @@ int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
|
|
struct mfc6_cache *cache;
|
|
struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
|
|
|
|
- mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
|
|
- if (!mrt)
|
|
+ rcu_read_lock();
|
|
+ mrt = __ip6mr_get_table(net, RT6_TABLE_DFLT);
|
|
+ if (!mrt) {
|
|
+ rcu_read_unlock();
|
|
return -ENOENT;
|
|
+ }
|
|
|
|
- rcu_read_lock();
|
|
cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
|
|
if (!cache && skb->dev) {
|
|
int vif = ip6mr_find_vif(mrt, skb->dev);
|
|
@@ -2563,7 +2579,7 @@ static int ip6mr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
|
|
grp = nla_get_in6_addr(tb[RTA_DST]);
|
|
tableid = tb[RTA_TABLE] ? nla_get_u32(tb[RTA_TABLE]) : 0;
|
|
|
|
- mrt = ip6mr_get_table(net, tableid ?: RT_TABLE_DEFAULT);
|
|
+ mrt = __ip6mr_get_table(net, tableid ?: RT_TABLE_DEFAULT);
|
|
if (!mrt) {
|
|
NL_SET_ERR_MSG_MOD(extack, "MR table does not exist");
|
|
return -ENOENT;
|
|
@@ -2608,7 +2624,7 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
|
|
if (filter.table_id) {
|
|
struct mr_table *mrt;
|
|
|
|
- mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id);
|
|
+ mrt = __ip6mr_get_table(sock_net(skb->sk), filter.table_id);
|
|
if (!mrt) {
|
|
if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IP6MR)
|
|
return skb->len;
|
|
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
|
|
index 0e2a0847b387f0..f106b19b74dd79 100644
|
|
--- a/net/ipv6/ipv6_sockglue.c
|
|
+++ b/net/ipv6/ipv6_sockglue.c
|
|
@@ -111,8 +111,7 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
|
|
icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
|
|
}
|
|
}
|
|
- opt = xchg((__force struct ipv6_txoptions **)&inet6_sk(sk)->opt,
|
|
- opt);
|
|
+ opt = unrcu_pointer(xchg(&inet6_sk(sk)->opt, RCU_INITIALIZER(opt)));
|
|
sk_dst_reset(sk);
|
|
|
|
return opt;
|
|
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
|
|
index a9104c4c1c02d9..e320dfa7fe7fc7 100644
|
|
--- a/net/ipv6/route.c
|
|
+++ b/net/ipv6/route.c
|
|
@@ -368,7 +368,7 @@ static void ip6_dst_destroy(struct dst_entry *dst)
|
|
in6_dev_put(idev);
|
|
}
|
|
|
|
- from = xchg((__force struct fib6_info **)&rt->from, NULL);
|
|
+ from = unrcu_pointer(xchg(&rt->from, NULL));
|
|
fib6_info_release(from);
|
|
}
|
|
|
|
@@ -376,6 +376,7 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
|
|
{
|
|
struct rt6_info *rt = (struct rt6_info *)dst;
|
|
struct inet6_dev *idev = rt->rt6i_idev;
|
|
+ struct fib6_info *from;
|
|
|
|
if (idev && idev->dev != blackhole_netdev) {
|
|
struct inet6_dev *blackhole_idev = in6_dev_get(blackhole_netdev);
|
|
@@ -385,6 +386,8 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
|
|
in6_dev_put(idev);
|
|
}
|
|
}
|
|
+ from = unrcu_pointer(xchg(&rt->from, NULL));
|
|
+ fib6_info_release(from);
|
|
}
|
|
|
|
static bool __rt6_check_expired(const struct rt6_info *rt)
|
|
@@ -1430,7 +1433,7 @@ static struct rt6_info *rt6_make_pcpu_route(struct net *net,
|
|
if (res->f6i->fib6_destroying) {
|
|
struct fib6_info *from;
|
|
|
|
- from = xchg((__force struct fib6_info **)&pcpu_rt->from, NULL);
|
|
+ from = unrcu_pointer(xchg(&pcpu_rt->from, NULL));
|
|
fib6_info_release(from);
|
|
}
|
|
|
|
@@ -1447,7 +1450,6 @@ static DEFINE_SPINLOCK(rt6_exception_lock);
|
|
static void rt6_remove_exception(struct rt6_exception_bucket *bucket,
|
|
struct rt6_exception *rt6_ex)
|
|
{
|
|
- struct fib6_info *from;
|
|
struct net *net;
|
|
|
|
if (!bucket || !rt6_ex)
|
|
@@ -1459,8 +1461,6 @@ static void rt6_remove_exception(struct rt6_exception_bucket *bucket,
|
|
/* purge completely the exception to allow releasing the held resources:
|
|
* some [sk] cache may keep the dst around for unlimited time
|
|
*/
|
|
- from = xchg((__force struct fib6_info **)&rt6_ex->rt6i->from, NULL);
|
|
- fib6_info_release(from);
|
|
dst_dev_put(&rt6_ex->rt6i->dst);
|
|
|
|
hlist_del_rcu(&rt6_ex->hlist);
|
|
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
|
|
index 815b1df0b2d194..0f660b1d3bd51c 100644
|
|
--- a/net/iucv/af_iucv.c
|
|
+++ b/net/iucv/af_iucv.c
|
|
@@ -1238,7 +1238,9 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|
return -EOPNOTSUPP;
|
|
|
|
/* receive/dequeue next skb:
|
|
- * the function understands MSG_PEEK and, thus, does not dequeue skb */
|
|
+ * the function understands MSG_PEEK and, thus, does not dequeue skb
|
|
+ * only refcount is increased.
|
|
+ */
|
|
skb = skb_recv_datagram(sk, flags, &err);
|
|
if (!skb) {
|
|
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
|
@@ -1254,9 +1256,8 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|
|
|
cskb = skb;
|
|
if (skb_copy_datagram_msg(cskb, offset, msg, copied)) {
|
|
- if (!(flags & MSG_PEEK))
|
|
- skb_queue_head(&sk->sk_receive_queue, skb);
|
|
- return -EFAULT;
|
|
+ err = -EFAULT;
|
|
+ goto err_out;
|
|
}
|
|
|
|
/* SOCK_SEQPACKET: set MSG_TRUNC if recv buf size is too small */
|
|
@@ -1273,11 +1274,8 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|
err = put_cmsg(msg, SOL_IUCV, SCM_IUCV_TRGCLS,
|
|
sizeof(IUCV_SKB_CB(skb)->class),
|
|
(void *)&IUCV_SKB_CB(skb)->class);
|
|
- if (err) {
|
|
- if (!(flags & MSG_PEEK))
|
|
- skb_queue_head(&sk->sk_receive_queue, skb);
|
|
- return err;
|
|
- }
|
|
+ if (err)
|
|
+ goto err_out;
|
|
|
|
/* Mark read part of skb as used */
|
|
if (!(flags & MSG_PEEK)) {
|
|
@@ -1333,8 +1331,18 @@ static int iucv_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|
/* SOCK_SEQPACKET: return real length if MSG_TRUNC is set */
|
|
if (sk->sk_type == SOCK_SEQPACKET && (flags & MSG_TRUNC))
|
|
copied = rlen;
|
|
+ if (flags & MSG_PEEK)
|
|
+ skb_unref(skb);
|
|
|
|
return copied;
|
|
+
|
|
+err_out:
|
|
+ if (!(flags & MSG_PEEK))
|
|
+ skb_queue_head(&sk->sk_receive_queue, skb);
|
|
+ else
|
|
+ skb_unref(skb);
|
|
+
|
|
+ return err;
|
|
}
|
|
|
|
static inline __poll_t iucv_accept_poll(struct sock *parent)
|
|
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
|
|
index fde1140d899efc..cc25fec44f8502 100644
|
|
--- a/net/llc/af_llc.c
|
|
+++ b/net/llc/af_llc.c
|
|
@@ -1099,7 +1099,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
|
|
lock_sock(sk);
|
|
if (unlikely(level != SOL_LLC || optlen != sizeof(int)))
|
|
goto out;
|
|
- rc = copy_from_sockptr(&opt, optval, sizeof(opt));
|
|
+ rc = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
|
|
if (rc)
|
|
goto out;
|
|
rc = -EINVAL;
|
|
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
|
|
index 71d60f57a886ce..d1046f495e63ff 100644
|
|
--- a/net/mac80211/main.c
|
|
+++ b/net/mac80211/main.c
|
|
@@ -145,6 +145,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
|
|
}
|
|
|
|
power = ieee80211_chandef_max_power(&chandef);
|
|
+ if (local->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
|
|
+ power = min(local->user_power_level, power);
|
|
|
|
rcu_read_lock();
|
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
|
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
|
|
index b8357d7c6b3a10..01f6ce970918c5 100644
|
|
--- a/net/mptcp/protocol.c
|
|
+++ b/net/mptcp/protocol.c
|
|
@@ -2691,8 +2691,8 @@ void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout)
|
|
if (!fail_tout && !inet_csk(sk)->icsk_mtup.probe_timestamp)
|
|
return;
|
|
|
|
- close_timeout = inet_csk(sk)->icsk_mtup.probe_timestamp - tcp_jiffies32 + jiffies +
|
|
- TCP_TIMEWAIT_LEN;
|
|
+ close_timeout = (unsigned long)inet_csk(sk)->icsk_mtup.probe_timestamp -
|
|
+ tcp_jiffies32 + jiffies + TCP_TIMEWAIT_LEN;
|
|
|
|
/* the close timeout takes precedence on the fail one, and here at least one of
|
|
* them is active
|
|
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
|
|
index e4fa00abde6a2a..5988b9bb9029dc 100644
|
|
--- a/net/netfilter/ipset/ip_set_bitmap_ip.c
|
|
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
|
|
@@ -163,11 +163,8 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
|
|
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
|
|
if (ret)
|
|
return ret;
|
|
- if (ip > ip_to) {
|
|
+ if (ip > ip_to)
|
|
swap(ip, ip_to);
|
|
- if (ip < map->first_ip)
|
|
- return -IPSET_ERR_BITMAP_RANGE;
|
|
- }
|
|
} else if (tb[IPSET_ATTR_CIDR]) {
|
|
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
|
|
|
@@ -178,7 +175,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
|
|
ip_to = ip;
|
|
}
|
|
|
|
- if (ip_to > map->last_ip)
|
|
+ if (ip < map->first_ip || ip_to > map->last_ip)
|
|
return -IPSET_ERR_BITMAP_RANGE;
|
|
|
|
for (; !before(ip_to, ip); ip += map->hosts) {
|
|
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
|
|
index 8a583e8f3c136a..eee7997048fb97 100644
|
|
--- a/net/netfilter/nf_tables_api.c
|
|
+++ b/net/netfilter/nf_tables_api.c
|
|
@@ -3231,25 +3231,37 @@ int nft_expr_inner_parse(const struct nft_ctx *ctx, const struct nlattr *nla,
|
|
if (!tb[NFTA_EXPR_DATA] || !tb[NFTA_EXPR_NAME])
|
|
return -EINVAL;
|
|
|
|
+ rcu_read_lock();
|
|
+
|
|
type = __nft_expr_type_get(ctx->family, tb[NFTA_EXPR_NAME]);
|
|
- if (!type)
|
|
- return -ENOENT;
|
|
+ if (!type) {
|
|
+ err = -ENOENT;
|
|
+ goto out_unlock;
|
|
+ }
|
|
|
|
- if (!type->inner_ops)
|
|
- return -EOPNOTSUPP;
|
|
+ if (!type->inner_ops) {
|
|
+ err = -EOPNOTSUPP;
|
|
+ goto out_unlock;
|
|
+ }
|
|
|
|
err = nla_parse_nested_deprecated(info->tb, type->maxattr,
|
|
tb[NFTA_EXPR_DATA],
|
|
type->policy, NULL);
|
|
if (err < 0)
|
|
- goto err_nla_parse;
|
|
+ goto out_unlock;
|
|
|
|
info->attr = nla;
|
|
info->ops = type->inner_ops;
|
|
|
|
+ /* No module reference will be taken on type->owner.
|
|
+ * Presence of type->inner_ops implies that the expression
|
|
+ * is builtin, so it cannot go away.
|
|
+ */
|
|
+ rcu_read_unlock();
|
|
return 0;
|
|
|
|
-err_nla_parse:
|
|
+out_unlock:
|
|
+ rcu_read_unlock();
|
|
return err;
|
|
}
|
|
|
|
@@ -3349,13 +3361,15 @@ void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr)
|
|
* Rules
|
|
*/
|
|
|
|
-static struct nft_rule *__nft_rule_lookup(const struct nft_chain *chain,
|
|
+static struct nft_rule *__nft_rule_lookup(const struct net *net,
|
|
+ const struct nft_chain *chain,
|
|
u64 handle)
|
|
{
|
|
struct nft_rule *rule;
|
|
|
|
// FIXME: this sucks
|
|
- list_for_each_entry_rcu(rule, &chain->rules, list) {
|
|
+ list_for_each_entry_rcu(rule, &chain->rules, list,
|
|
+ lockdep_commit_lock_is_held(net)) {
|
|
if (handle == rule->handle)
|
|
return rule;
|
|
}
|
|
@@ -3363,13 +3377,14 @@ static struct nft_rule *__nft_rule_lookup(const struct nft_chain *chain,
|
|
return ERR_PTR(-ENOENT);
|
|
}
|
|
|
|
-static struct nft_rule *nft_rule_lookup(const struct nft_chain *chain,
|
|
+static struct nft_rule *nft_rule_lookup(const struct net *net,
|
|
+ const struct nft_chain *chain,
|
|
const struct nlattr *nla)
|
|
{
|
|
if (nla == NULL)
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
- return __nft_rule_lookup(chain, be64_to_cpu(nla_get_be64(nla)));
|
|
+ return __nft_rule_lookup(net, chain, be64_to_cpu(nla_get_be64(nla)));
|
|
}
|
|
|
|
static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
|
|
@@ -3661,9 +3676,10 @@ static int nf_tables_dump_rules_done(struct netlink_callback *cb)
|
|
return 0;
|
|
}
|
|
|
|
-/* called with rcu_read_lock held */
|
|
-static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
- const struct nlattr * const nla[])
|
|
+/* Caller must hold rcu read lock or transaction mutex */
|
|
+static struct sk_buff *
|
|
+nf_tables_getrule_single(u32 portid, const struct nfnl_info *info,
|
|
+ const struct nlattr * const nla[], bool reset)
|
|
{
|
|
struct netlink_ext_ack *extack = info->extack;
|
|
u8 genmask = nft_genmask_cur(info->net);
|
|
@@ -3673,60 +3689,82 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
struct net *net = info->net;
|
|
struct nft_table *table;
|
|
struct sk_buff *skb2;
|
|
- bool reset = false;
|
|
int err;
|
|
|
|
- if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
- struct netlink_dump_control c = {
|
|
- .start= nf_tables_dump_rules_start,
|
|
- .dump = nf_tables_dump_rules,
|
|
- .done = nf_tables_dump_rules_done,
|
|
- .module = THIS_MODULE,
|
|
- .data = (void *)nla,
|
|
- };
|
|
-
|
|
- return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
|
|
- }
|
|
-
|
|
table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask, 0);
|
|
if (IS_ERR(table)) {
|
|
NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]);
|
|
- return PTR_ERR(table);
|
|
+ return ERR_CAST(table);
|
|
}
|
|
|
|
chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN], genmask);
|
|
if (IS_ERR(chain)) {
|
|
NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
|
|
- return PTR_ERR(chain);
|
|
+ return ERR_CAST(chain);
|
|
}
|
|
|
|
- rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
|
|
+ rule = nft_rule_lookup(net, chain, nla[NFTA_RULE_HANDLE]);
|
|
if (IS_ERR(rule)) {
|
|
NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
|
|
- return PTR_ERR(rule);
|
|
+ return ERR_CAST(rule);
|
|
}
|
|
|
|
skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
|
|
if (!skb2)
|
|
- return -ENOMEM;
|
|
+ return ERR_PTR(-ENOMEM);
|
|
+
|
|
+ err = nf_tables_fill_rule_info(skb2, net, portid,
|
|
+ info->nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
|
|
+ family, table, chain, rule, 0, reset);
|
|
+ if (err < 0) {
|
|
+ kfree_skb(skb2);
|
|
+ return ERR_PTR(err);
|
|
+ }
|
|
+
|
|
+ return skb2;
|
|
+}
|
|
+
|
|
+static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
+ const struct nlattr * const nla[])
|
|
+{
|
|
+ struct nftables_pernet *nft_net = nft_pernet(info->net);
|
|
+ u32 portid = NETLINK_CB(skb).portid;
|
|
+ struct net *net = info->net;
|
|
+ struct sk_buff *skb2;
|
|
+ bool reset = false;
|
|
+ char *buf;
|
|
+
|
|
+ if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
+ struct netlink_dump_control c = {
|
|
+ .start= nf_tables_dump_rules_start,
|
|
+ .dump = nf_tables_dump_rules,
|
|
+ .done = nf_tables_dump_rules_done,
|
|
+ .module = THIS_MODULE,
|
|
+ .data = (void *)nla,
|
|
+ };
|
|
+
|
|
+ return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
|
|
+ }
|
|
|
|
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
|
|
reset = true;
|
|
|
|
- err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
|
|
- info->nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
|
|
- family, table, chain, rule, 0, reset);
|
|
- if (err < 0)
|
|
- goto err_fill_rule_info;
|
|
+ skb2 = nf_tables_getrule_single(portid, info, nla, reset);
|
|
+ if (IS_ERR(skb2))
|
|
+ return PTR_ERR(skb2);
|
|
|
|
- if (reset)
|
|
- audit_log_rule_reset(table, nft_pernet(net)->base_seq, 1);
|
|
+ if (!reset)
|
|
+ return nfnetlink_unicast(skb2, net, portid);
|
|
|
|
- return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
|
+ buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
|
|
+ nla_len(nla[NFTA_RULE_TABLE]),
|
|
+ (char *)nla_data(nla[NFTA_RULE_TABLE]),
|
|
+ nft_net->base_seq);
|
|
+ audit_log_nfcfg(buf, info->nfmsg->nfgen_family, 1,
|
|
+ AUDIT_NFT_OP_RULE_RESET, GFP_ATOMIC);
|
|
+ kfree(buf);
|
|
|
|
-err_fill_rule_info:
|
|
- kfree_skb(skb2);
|
|
- return err;
|
|
+ return nfnetlink_unicast(skb2, net, portid);
|
|
}
|
|
|
|
void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
|
|
@@ -3938,7 +3976,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
if (nla[NFTA_RULE_HANDLE]) {
|
|
handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE]));
|
|
- rule = __nft_rule_lookup(chain, handle);
|
|
+ rule = __nft_rule_lookup(net, chain, handle);
|
|
if (IS_ERR(rule)) {
|
|
NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
|
|
return PTR_ERR(rule);
|
|
@@ -3960,7 +3998,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
if (nla[NFTA_RULE_POSITION]) {
|
|
pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
|
|
- old_rule = __nft_rule_lookup(chain, pos_handle);
|
|
+ old_rule = __nft_rule_lookup(net, chain, pos_handle);
|
|
if (IS_ERR(old_rule)) {
|
|
NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION]);
|
|
return PTR_ERR(old_rule);
|
|
@@ -4177,7 +4215,7 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|
|
|
if (chain) {
|
|
if (nla[NFTA_RULE_HANDLE]) {
|
|
- rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
|
|
+ rule = nft_rule_lookup(info->net, chain, nla[NFTA_RULE_HANDLE]);
|
|
if (IS_ERR(rule)) {
|
|
if (PTR_ERR(rule) == -ENOENT &&
|
|
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYRULE)
|
|
@@ -7577,9 +7615,7 @@ static int nf_tables_updobj(const struct nft_ctx *ctx,
|
|
struct nft_trans *trans;
|
|
int err = -ENOMEM;
|
|
|
|
- if (!try_module_get(type->owner))
|
|
- return -ENOENT;
|
|
-
|
|
+ /* caller must have obtained type->owner reference. */
|
|
trans = nft_trans_alloc(ctx, NFT_MSG_NEWOBJ,
|
|
sizeof(struct nft_trans_obj));
|
|
if (!trans)
|
|
@@ -7647,12 +7683,16 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
|
|
if (info->nlh->nlmsg_flags & NLM_F_REPLACE)
|
|
return -EOPNOTSUPP;
|
|
|
|
- type = __nft_obj_type_get(objtype, family);
|
|
- if (WARN_ON_ONCE(!type))
|
|
- return -ENOENT;
|
|
+ if (!obj->ops->update)
|
|
+ return 0;
|
|
+
|
|
+ type = nft_obj_type_get(net, objtype, family);
|
|
+ if (WARN_ON_ONCE(IS_ERR(type)))
|
|
+ return PTR_ERR(type);
|
|
|
|
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
|
|
|
|
+ /* type->owner reference is put when transaction object is released. */
|
|
return nf_tables_updobj(&ctx, type, nla[NFTA_OBJ_DATA], obj);
|
|
}
|
|
|
|
@@ -7888,7 +7928,7 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb)
|
|
return 0;
|
|
}
|
|
|
|
-/* called with rcu_read_lock held */
|
|
+/* Caller must hold rcu read lock or transaction mutex */
|
|
static struct sk_buff *
|
|
nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,
|
|
const struct nlattr * const nla[], bool reset)
|
|
@@ -9394,9 +9434,10 @@ static void nft_obj_commit_update(struct nft_trans *trans)
|
|
obj = nft_trans_obj(trans);
|
|
newobj = nft_trans_obj_newobj(trans);
|
|
|
|
- if (obj->ops->update)
|
|
- obj->ops->update(obj, newobj);
|
|
+ if (WARN_ON_ONCE(!obj->ops->update))
|
|
+ return;
|
|
|
|
+ obj->ops->update(obj, newobj);
|
|
nft_obj_destroy(&trans->ctx, newobj);
|
|
}
|
|
|
|
diff --git a/net/netlink/diag.c b/net/netlink/diag.c
|
|
index 9c4f231be27572..7b15aa5f7bc20b 100644
|
|
--- a/net/netlink/diag.c
|
|
+++ b/net/netlink/diag.c
|
|
@@ -241,6 +241,7 @@ static int netlink_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
|
|
}
|
|
|
|
static const struct sock_diag_handler netlink_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_NETLINK,
|
|
.dump = netlink_diag_handler_dump,
|
|
};
|
|
diff --git a/net/packet/diag.c b/net/packet/diag.c
|
|
index f6b200cb3c0668..d4142636aa2b71 100644
|
|
--- a/net/packet/diag.c
|
|
+++ b/net/packet/diag.c
|
|
@@ -245,6 +245,7 @@ static int packet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
|
|
}
|
|
|
|
static const struct sock_diag_handler packet_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_PACKET,
|
|
.dump = packet_diag_handler_dump,
|
|
};
|
|
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
|
|
index 4e32d659524e0d..b12edbe0ef45c1 100644
|
|
--- a/net/rfkill/rfkill-gpio.c
|
|
+++ b/net/rfkill/rfkill-gpio.c
|
|
@@ -31,8 +31,12 @@ static int rfkill_gpio_set_power(void *data, bool blocked)
|
|
{
|
|
struct rfkill_gpio_data *rfkill = data;
|
|
|
|
- if (!blocked && !IS_ERR(rfkill->clk) && !rfkill->clk_enabled)
|
|
- clk_enable(rfkill->clk);
|
|
+ if (!blocked && !IS_ERR(rfkill->clk) && !rfkill->clk_enabled) {
|
|
+ int ret = clk_enable(rfkill->clk);
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
|
|
gpiod_set_value_cansleep(rfkill->shutdown_gpio, !blocked);
|
|
gpiod_set_value_cansleep(rfkill->reset_gpio, !blocked);
|
|
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
|
|
index fa8aec78f63d70..205e0d4d048ea2 100644
|
|
--- a/net/rxrpc/af_rxrpc.c
|
|
+++ b/net/rxrpc/af_rxrpc.c
|
|
@@ -661,9 +661,10 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
|
|
ret = -EISCONN;
|
|
if (rx->sk.sk_state != RXRPC_UNBOUND)
|
|
goto error;
|
|
- ret = copy_from_sockptr(&min_sec_level, optval,
|
|
- sizeof(unsigned int));
|
|
- if (ret < 0)
|
|
+ ret = copy_safe_from_sockptr(&min_sec_level,
|
|
+ sizeof(min_sec_level),
|
|
+ optval, optlen);
|
|
+ if (ret)
|
|
goto error;
|
|
ret = -EINVAL;
|
|
if (min_sec_level > RXRPC_SECURITY_MAX)
|
|
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
|
|
index 4572aa6e0273f8..e509ac28c49299 100644
|
|
--- a/net/sched/act_api.c
|
|
+++ b/net/sched/act_api.c
|
|
@@ -62,7 +62,7 @@ static void tcf_set_action_cookie(struct tc_cookie __rcu **old_cookie,
|
|
{
|
|
struct tc_cookie *old;
|
|
|
|
- old = xchg((__force struct tc_cookie **)old_cookie, new_cookie);
|
|
+ old = unrcu_pointer(xchg(old_cookie, RCU_INITIALIZER(new_cookie)));
|
|
if (old)
|
|
call_rcu(&old->rcu, tcf_free_cookie_rcu);
|
|
}
|
|
diff --git a/net/smc/smc_diag.c b/net/smc/smc_diag.c
|
|
index 37833b96b508ef..d58c699b5328ae 100644
|
|
--- a/net/smc/smc_diag.c
|
|
+++ b/net/smc/smc_diag.c
|
|
@@ -250,6 +250,7 @@ static int smc_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
|
|
}
|
|
|
|
static const struct sock_diag_handler smc_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_SMC,
|
|
.dump = smc_diag_handler_dump,
|
|
};
|
|
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
|
|
index 95ff747061046c..3298da2e37e43d 100644
|
|
--- a/net/sunrpc/cache.c
|
|
+++ b/net/sunrpc/cache.c
|
|
@@ -1431,7 +1431,9 @@ static int c_show(struct seq_file *m, void *p)
|
|
seq_printf(m, "# expiry=%lld refcnt=%d flags=%lx\n",
|
|
convert_to_wallclock(cp->expiry_time),
|
|
kref_read(&cp->ref), cp->flags);
|
|
- cache_get(cp);
|
|
+ if (!cache_get_rcu(cp))
|
|
+ return 0;
|
|
+
|
|
if (cache_check(cd, cp, NULL))
|
|
/* cache_check does a cache_put on failure */
|
|
seq_puts(m, "# ");
|
|
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
|
|
index 933e12e3a55c75..83996eea100626 100644
|
|
--- a/net/sunrpc/svcsock.c
|
|
+++ b/net/sunrpc/svcsock.c
|
|
@@ -1562,6 +1562,10 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
|
|
newlen = error;
|
|
|
|
if (protocol == IPPROTO_TCP) {
|
|
+ __netns_tracker_free(net, &sock->sk->ns_tracker, false);
|
|
+ sock->sk->sk_net_refcnt = 1;
|
|
+ get_net_track(net, &sock->sk->ns_tracker, GFP_KERNEL);
|
|
+ sock_inuse_add(net, 1);
|
|
if ((error = kernel_listen(sock, 64)) < 0)
|
|
goto bummer;
|
|
}
|
|
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c
|
|
index f0d5eeed4c886f..e1d4e426b21fa9 100644
|
|
--- a/net/sunrpc/xprtrdma/svc_rdma.c
|
|
+++ b/net/sunrpc/xprtrdma/svc_rdma.c
|
|
@@ -234,25 +234,34 @@ static int svc_rdma_proc_init(void)
|
|
|
|
rc = percpu_counter_init(&svcrdma_stat_read, 0, GFP_KERNEL);
|
|
if (rc)
|
|
- goto out_err;
|
|
+ goto err;
|
|
rc = percpu_counter_init(&svcrdma_stat_recv, 0, GFP_KERNEL);
|
|
if (rc)
|
|
- goto out_err;
|
|
+ goto err_read;
|
|
rc = percpu_counter_init(&svcrdma_stat_sq_starve, 0, GFP_KERNEL);
|
|
if (rc)
|
|
- goto out_err;
|
|
+ goto err_recv;
|
|
rc = percpu_counter_init(&svcrdma_stat_write, 0, GFP_KERNEL);
|
|
if (rc)
|
|
- goto out_err;
|
|
+ goto err_sq;
|
|
|
|
svcrdma_table_header = register_sysctl("sunrpc/svc_rdma",
|
|
svcrdma_parm_table);
|
|
+ if (!svcrdma_table_header)
|
|
+ goto err_write;
|
|
+
|
|
return 0;
|
|
|
|
-out_err:
|
|
+err_write:
|
|
+ rc = -ENOMEM;
|
|
+ percpu_counter_destroy(&svcrdma_stat_write);
|
|
+err_sq:
|
|
percpu_counter_destroy(&svcrdma_stat_sq_starve);
|
|
+err_recv:
|
|
percpu_counter_destroy(&svcrdma_stat_recv);
|
|
+err_read:
|
|
percpu_counter_destroy(&svcrdma_stat_read);
|
|
+err:
|
|
return rc;
|
|
}
|
|
|
|
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
|
|
index 3b05f90a3e50dd..9cec7bcb8a9768 100644
|
|
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
|
|
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
|
|
@@ -478,7 +478,13 @@ static bool xdr_check_write_chunk(struct svc_rdma_recv_ctxt *rctxt)
|
|
if (xdr_stream_decode_u32(&rctxt->rc_stream, &segcount))
|
|
return false;
|
|
|
|
- /* A bogus segcount causes this buffer overflow check to fail. */
|
|
+ /* Before trusting the segcount value enough to use it in
|
|
+ * a computation, perform a simple range check. This is an
|
|
+ * arbitrary but sensible limit (ie, not architectural).
|
|
+ */
|
|
+ if (unlikely(segcount > RPCSVC_MAXPAGES))
|
|
+ return false;
|
|
+
|
|
p = xdr_inline_decode(&rctxt->rc_stream,
|
|
segcount * rpcrdma_segment_maxsz * sizeof(*p));
|
|
return p != NULL;
|
|
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
|
|
index 50490b1e8a0d09..1c4bc8234ea875 100644
|
|
--- a/net/sunrpc/xprtsock.c
|
|
+++ b/net/sunrpc/xprtsock.c
|
|
@@ -1186,6 +1186,7 @@ static void xs_sock_reset_state_flags(struct rpc_xprt *xprt)
|
|
clear_bit(XPRT_SOCK_WAKE_WRITE, &transport->sock_state);
|
|
clear_bit(XPRT_SOCK_WAKE_DISCONNECT, &transport->sock_state);
|
|
clear_bit(XPRT_SOCK_NOSPACE, &transport->sock_state);
|
|
+ clear_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state);
|
|
}
|
|
|
|
static void xs_run_error_worker(struct sock_xprt *transport, unsigned int nr)
|
|
@@ -1920,6 +1921,13 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt,
|
|
goto out;
|
|
}
|
|
|
|
+ if (protocol == IPPROTO_TCP) {
|
|
+ __netns_tracker_free(xprt->xprt_net, &sock->sk->ns_tracker, false);
|
|
+ sock->sk->sk_net_refcnt = 1;
|
|
+ get_net_track(xprt->xprt_net, &sock->sk->ns_tracker, GFP_KERNEL);
|
|
+ sock_inuse_add(xprt->xprt_net, 1);
|
|
+ }
|
|
+
|
|
filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
|
|
if (IS_ERR(filp))
|
|
return ERR_CAST(filp);
|
|
@@ -2595,11 +2603,10 @@ static int xs_tls_handshake_sync(struct rpc_xprt *lower_xprt, struct xprtsec_par
|
|
rc = wait_for_completion_interruptible_timeout(&lower_transport->handshake_done,
|
|
XS_TLS_HANDSHAKE_TO);
|
|
if (rc <= 0) {
|
|
- if (!tls_handshake_cancel(sk)) {
|
|
- if (rc == 0)
|
|
- rc = -ETIMEDOUT;
|
|
- goto out_put_xprt;
|
|
- }
|
|
+ tls_handshake_cancel(sk);
|
|
+ if (rc == 0)
|
|
+ rc = -ETIMEDOUT;
|
|
+ goto out_put_xprt;
|
|
}
|
|
|
|
rc = lower_transport->xprt_err;
|
|
diff --git a/net/tipc/diag.c b/net/tipc/diag.c
|
|
index 73137f4aeb68f9..11da9d2ebbf699 100644
|
|
--- a/net/tipc/diag.c
|
|
+++ b/net/tipc/diag.c
|
|
@@ -95,6 +95,7 @@ static int tipc_sock_diag_handler_dump(struct sk_buff *skb,
|
|
}
|
|
|
|
static const struct sock_diag_handler tipc_sock_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_TIPC,
|
|
.dump = tipc_sock_diag_handler_dump,
|
|
};
|
|
diff --git a/net/unix/diag.c b/net/unix/diag.c
|
|
index 1de7500b41b616..a6bd861314df08 100644
|
|
--- a/net/unix/diag.c
|
|
+++ b/net/unix/diag.c
|
|
@@ -322,6 +322,7 @@ static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
|
|
}
|
|
|
|
static const struct sock_diag_handler unix_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_UNIX,
|
|
.dump = unix_diag_handler_dump,
|
|
};
|
|
diff --git a/net/vmw_vsock/diag.c b/net/vmw_vsock/diag.c
|
|
index a2823b1c5e28b1..6efa9eb93336f2 100644
|
|
--- a/net/vmw_vsock/diag.c
|
|
+++ b/net/vmw_vsock/diag.c
|
|
@@ -157,6 +157,7 @@ static int vsock_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h)
|
|
}
|
|
|
|
static const struct sock_diag_handler vsock_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_VSOCK,
|
|
.dump = vsock_diag_handler_dump,
|
|
};
|
|
diff --git a/net/xdp/xsk_diag.c b/net/xdp/xsk_diag.c
|
|
index 22b36c8143cfd5..e1012bfec72079 100644
|
|
--- a/net/xdp/xsk_diag.c
|
|
+++ b/net/xdp/xsk_diag.c
|
|
@@ -194,6 +194,7 @@ static int xsk_diag_handler_dump(struct sk_buff *nlskb, struct nlmsghdr *hdr)
|
|
}
|
|
|
|
static const struct sock_diag_handler xsk_diag_handler = {
|
|
+ .owner = THIS_MODULE,
|
|
.family = AF_XDP,
|
|
.dump = xsk_diag_handler_dump,
|
|
};
|
|
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
|
|
index 34ae73f5db068a..7bdb3a5a18a064 100644
|
|
--- a/rust/macros/lib.rs
|
|
+++ b/rust/macros/lib.rs
|
|
@@ -298,7 +298,7 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
/// macro_rules! pub_no_prefix {
|
|
/// ($prefix:ident, $($newname:ident),+) => {
|
|
/// kernel::macros::paste! {
|
|
-/// $(pub(crate) const fn [<$newname:lower:span>]: u32 = [<$prefix $newname:span>];)+
|
|
+/// $(pub(crate) const fn [<$newname:lower:span>]() -> u32 { [<$prefix $newname:span>] })+
|
|
/// }
|
|
/// };
|
|
/// }
|
|
diff --git a/samples/bpf/xdp_adjust_tail_kern.c b/samples/bpf/xdp_adjust_tail_kern.c
|
|
index ffdd548627f0a4..da67bcad1c6381 100644
|
|
--- a/samples/bpf/xdp_adjust_tail_kern.c
|
|
+++ b/samples/bpf/xdp_adjust_tail_kern.c
|
|
@@ -57,6 +57,7 @@ static __always_inline void swap_mac(void *data, struct ethhdr *orig_eth)
|
|
|
|
static __always_inline __u16 csum_fold_helper(__u32 csum)
|
|
{
|
|
+ csum = (csum & 0xffff) + (csum >> 16);
|
|
return ~((csum & 0xffff) + (csum >> 16));
|
|
}
|
|
|
|
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
|
|
index 7d16f863edf1c7..6744b58c35083f 100755
|
|
--- a/scripts/checkpatch.pl
|
|
+++ b/scripts/checkpatch.pl
|
|
@@ -28,6 +28,7 @@ my %verbose_messages = ();
|
|
my %verbose_emitted = ();
|
|
my $tree = 1;
|
|
my $chk_signoff = 1;
|
|
+my $chk_fixes_tag = 1;
|
|
my $chk_patch = 1;
|
|
my $tst_only;
|
|
my $emacs = 0;
|
|
@@ -88,6 +89,7 @@ Options:
|
|
-v, --verbose verbose mode
|
|
--no-tree run without a kernel tree
|
|
--no-signoff do not check for 'Signed-off-by' line
|
|
+ --no-fixes-tag do not check for 'Fixes:' tag
|
|
--patch treat FILE as patchfile (default)
|
|
--emacs emacs compile window format
|
|
--terse one line per report
|
|
@@ -295,6 +297,7 @@ GetOptions(
|
|
'v|verbose!' => \$verbose,
|
|
'tree!' => \$tree,
|
|
'signoff!' => \$chk_signoff,
|
|
+ 'fixes-tag!' => \$chk_fixes_tag,
|
|
'patch!' => \$chk_patch,
|
|
'emacs!' => \$emacs,
|
|
'terse!' => \$terse,
|
|
@@ -1256,6 +1259,7 @@ sub git_commit_info {
|
|
}
|
|
|
|
$chk_signoff = 0 if ($file);
|
|
+$chk_fixes_tag = 0 if ($file);
|
|
|
|
my @rawlines = ();
|
|
my @lines = ();
|
|
@@ -2635,6 +2639,9 @@ sub process {
|
|
|
|
our $clean = 1;
|
|
my $signoff = 0;
|
|
+ my $fixes_tag = 0;
|
|
+ my $is_revert = 0;
|
|
+ my $needs_fixes_tag = "";
|
|
my $author = '';
|
|
my $authorsignoff = 0;
|
|
my $author_sob = '';
|
|
@@ -3188,38 +3195,44 @@ sub process {
|
|
}
|
|
}
|
|
|
|
+# These indicate a bug fix
|
|
+ if (!$in_header_lines && !$is_patch &&
|
|
+ $line =~ /^This reverts commit/) {
|
|
+ $is_revert = 1;
|
|
+ }
|
|
+
|
|
+ if (!$in_header_lines && !$is_patch &&
|
|
+ $line =~ /((?:(?:BUG: K.|UB)SAN: |Call Trace:|stable\@|syzkaller))/) {
|
|
+ $needs_fixes_tag = $1;
|
|
+ }
|
|
|
|
# Check Fixes: styles is correct
|
|
if (!$in_header_lines &&
|
|
- $line =~ /^\s*fixes:?\s*(?:commit\s*)?[0-9a-f]{5,}\b/i) {
|
|
- my $orig_commit = "";
|
|
- my $id = "0123456789ab";
|
|
- my $title = "commit title";
|
|
- my $tag_case = 1;
|
|
- my $tag_space = 1;
|
|
- my $id_length = 1;
|
|
- my $id_case = 1;
|
|
+ $line =~ /^\s*(fixes:?)\s*(?:commit\s*)?([0-9a-f]{5,40})(?:\s*($balanced_parens))?/i) {
|
|
+ my $tag = $1;
|
|
+ my $orig_commit = $2;
|
|
+ my $title;
|
|
my $title_has_quotes = 0;
|
|
-
|
|
- if ($line =~ /(\s*fixes:?)\s+([0-9a-f]{5,})\s+($balanced_parens)/i) {
|
|
- my $tag = $1;
|
|
- $orig_commit = $2;
|
|
- $title = $3;
|
|
-
|
|
- $tag_case = 0 if $tag eq "Fixes:";
|
|
- $tag_space = 0 if ($line =~ /^fixes:? [0-9a-f]{5,} ($balanced_parens)/i);
|
|
-
|
|
- $id_length = 0 if ($orig_commit =~ /^[0-9a-f]{12}$/i);
|
|
- $id_case = 0 if ($orig_commit !~ /[A-F]/);
|
|
-
|
|
+ $fixes_tag = 1;
|
|
+ if (defined $3) {
|
|
# Always strip leading/trailing parens then double quotes if existing
|
|
- $title = substr($title, 1, -1);
|
|
+ $title = substr($3, 1, -1);
|
|
if ($title =~ /^".*"$/) {
|
|
$title = substr($title, 1, -1);
|
|
$title_has_quotes = 1;
|
|
}
|
|
+ } else {
|
|
+ $title = "commit title"
|
|
}
|
|
|
|
+
|
|
+ my $tag_case = not ($tag eq "Fixes:");
|
|
+ my $tag_space = not ($line =~ /^fixes:? [0-9a-f]{5,40} ($balanced_parens)/i);
|
|
+
|
|
+ my $id_length = not ($orig_commit =~ /^[0-9a-f]{12}$/i);
|
|
+ my $id_case = not ($orig_commit !~ /[A-F]/);
|
|
+
|
|
+ my $id = "0123456789ab";
|
|
my ($cid, $ctitle) = git_commit_info($orig_commit, $id,
|
|
$title);
|
|
|
|
@@ -7680,6 +7693,12 @@ sub process {
|
|
ERROR("NOT_UNIFIED_DIFF",
|
|
"Does not appear to be a unified-diff format patch\n");
|
|
}
|
|
+ if ($is_patch && $has_commit_log && $chk_fixes_tag) {
|
|
+ if ($needs_fixes_tag ne "" && !$is_revert && !$fixes_tag) {
|
|
+ WARN("MISSING_FIXES_TAG",
|
|
+ "The commit message has '$needs_fixes_tag', perhaps it also needs a 'Fixes:' tag?\n");
|
|
+ }
|
|
+ }
|
|
if ($is_patch && $has_commit_log && $chk_signoff) {
|
|
if ($signoff == 0) {
|
|
ERROR("MISSING_SIGN_OFF",
|
|
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
|
|
index 6583b36dbe6948..efbb4836ec668f 100644
|
|
--- a/scripts/mod/file2alias.c
|
|
+++ b/scripts/mod/file2alias.c
|
|
@@ -809,10 +809,7 @@ static int do_eisa_entry(const char *filename, void *symval,
|
|
char *alias)
|
|
{
|
|
DEF_FIELD_ADDR(symval, eisa_device_id, sig);
|
|
- if (sig[0])
|
|
- sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
|
|
- else
|
|
- strcat(alias, "*");
|
|
+ sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
|
|
return 1;
|
|
}
|
|
|
|
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
|
|
index 828d5cc367169f..4110d559ed6881 100644
|
|
--- a/scripts/mod/modpost.c
|
|
+++ b/scripts/mod/modpost.c
|
|
@@ -792,25 +792,15 @@ static void check_section(const char *modname, struct elf_info *elf,
|
|
|
|
|
|
#define ALL_INIT_DATA_SECTIONS \
|
|
- ".init.setup", ".init.rodata", ".meminit.rodata", \
|
|
- ".init.data", ".meminit.data"
|
|
-#define ALL_EXIT_DATA_SECTIONS \
|
|
- ".exit.data", ".memexit.data"
|
|
-
|
|
-#define ALL_INIT_TEXT_SECTIONS \
|
|
- ".init.text", ".meminit.text"
|
|
-#define ALL_EXIT_TEXT_SECTIONS \
|
|
- ".exit.text"
|
|
+ ".init.setup", ".init.rodata", ".init.data"
|
|
|
|
#define ALL_PCI_INIT_SECTIONS \
|
|
".pci_fixup_early", ".pci_fixup_header", ".pci_fixup_final", \
|
|
".pci_fixup_enable", ".pci_fixup_resume", \
|
|
".pci_fixup_resume_early", ".pci_fixup_suspend"
|
|
|
|
-#define ALL_XXXINIT_SECTIONS MEM_INIT_SECTIONS
|
|
-
|
|
-#define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS
|
|
-#define ALL_EXIT_SECTIONS EXIT_SECTIONS
|
|
+#define ALL_INIT_SECTIONS ".init.*"
|
|
+#define ALL_EXIT_SECTIONS ".exit.*"
|
|
|
|
#define DATA_SECTIONS ".data", ".data.rel"
|
|
#define TEXT_SECTIONS ".text", ".text.*", ".sched.text", \
|
|
@@ -820,12 +810,7 @@ static void check_section(const char *modname, struct elf_info *elf,
|
|
".fixup", ".entry.text", ".exception.text", \
|
|
".coldtext", ".softirqentry.text"
|
|
|
|
-#define INIT_SECTIONS ".init.*"
|
|
-#define MEM_INIT_SECTIONS ".meminit.*"
|
|
-
|
|
-#define EXIT_SECTIONS ".exit.*"
|
|
-
|
|
-#define ALL_TEXT_SECTIONS ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \
|
|
+#define ALL_TEXT_SECTIONS ".init.text", ".exit.text", \
|
|
TEXT_SECTIONS, OTHER_TEXT_SECTIONS
|
|
|
|
enum mismatch {
|
|
@@ -869,7 +854,7 @@ static const struct sectioncheck sectioncheck[] = {
|
|
},
|
|
{
|
|
.fromsec = { DATA_SECTIONS, NULL },
|
|
- .bad_tosec = { ALL_XXXINIT_SECTIONS, INIT_SECTIONS, NULL },
|
|
+ .bad_tosec = { ALL_INIT_SECTIONS, NULL },
|
|
.mismatch = DATA_TO_ANY_INIT,
|
|
},
|
|
{
|
|
@@ -877,12 +862,6 @@ static const struct sectioncheck sectioncheck[] = {
|
|
.bad_tosec = { ALL_EXIT_SECTIONS, NULL },
|
|
.mismatch = TEXTDATA_TO_ANY_EXIT,
|
|
},
|
|
-/* Do not reference init code/data from meminit code/data */
|
|
-{
|
|
- .fromsec = { ALL_XXXINIT_SECTIONS, NULL },
|
|
- .bad_tosec = { INIT_SECTIONS, NULL },
|
|
- .mismatch = XXXINIT_TO_SOME_INIT,
|
|
-},
|
|
/* Do not use exit code/data from init code */
|
|
{
|
|
.fromsec = { ALL_INIT_SECTIONS, NULL },
|
|
@@ -897,7 +876,7 @@ static const struct sectioncheck sectioncheck[] = {
|
|
},
|
|
{
|
|
.fromsec = { ALL_PCI_INIT_SECTIONS, NULL },
|
|
- .bad_tosec = { INIT_SECTIONS, NULL },
|
|
+ .bad_tosec = { ALL_INIT_SECTIONS, NULL },
|
|
.mismatch = ANY_INIT_TO_ANY_EXIT,
|
|
},
|
|
{
|
|
@@ -1009,12 +988,6 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
|
|
"*_console")))
|
|
return 0;
|
|
|
|
- /* symbols in data sections that may refer to meminit sections */
|
|
- if (match(fromsec, PATTERNS(DATA_SECTIONS)) &&
|
|
- match(tosec, PATTERNS(ALL_XXXINIT_SECTIONS)) &&
|
|
- match(fromsym, PATTERNS("*driver")))
|
|
- return 0;
|
|
-
|
|
/*
|
|
* symbols in data sections must not refer to .exit.*, but there are
|
|
* quite a few offenders, so hide these unless for W=1 builds until
|
|
@@ -1022,7 +995,7 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
|
|
*/
|
|
if (!extra_warn &&
|
|
match(fromsec, PATTERNS(DATA_SECTIONS)) &&
|
|
- match(tosec, PATTERNS(EXIT_SECTIONS)) &&
|
|
+ match(tosec, PATTERNS(ALL_EXIT_SECTIONS)) &&
|
|
match(fromsym, PATTERNS("*driver")))
|
|
return 0;
|
|
|
|
@@ -1187,10 +1160,10 @@ static void check_export_symbol(struct module *mod, struct elf_info *elf,
|
|
ELF_ST_TYPE(sym->st_info) == STT_LOPROC)
|
|
s->is_func = true;
|
|
|
|
- if (match(secname, PATTERNS(INIT_SECTIONS)))
|
|
+ if (match(secname, PATTERNS(ALL_INIT_SECTIONS)))
|
|
warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n",
|
|
mod->name, name);
|
|
- else if (match(secname, PATTERNS(EXIT_SECTIONS)))
|
|
+ else if (match(secname, PATTERNS(ALL_EXIT_SECTIONS)))
|
|
warn("%s: %s: EXPORT_SYMBOL used for exit symbol. Remove __exit or EXPORT_SYMBOL.\n",
|
|
mod->name, name);
|
|
}
|
|
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
|
|
index 2fb6a2ea0b998c..82485972006238 100644
|
|
--- a/security/apparmor/capability.c
|
|
+++ b/security/apparmor/capability.c
|
|
@@ -96,6 +96,8 @@ static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile
|
|
return error;
|
|
} else {
|
|
aa_put_profile(ent->profile);
|
|
+ if (profile != ent->profile)
|
|
+ cap_clear(ent->caps);
|
|
ent->profile = aa_get_profile(profile);
|
|
cap_raise(ent->caps, cap);
|
|
}
|
|
diff --git a/security/apparmor/policy_unpack_test.c b/security/apparmor/policy_unpack_test.c
|
|
index 2b8003eb4f463a..dd551587fe4ac7 100644
|
|
--- a/security/apparmor/policy_unpack_test.c
|
|
+++ b/security/apparmor/policy_unpack_test.c
|
|
@@ -281,6 +281,8 @@ static void policy_unpack_test_unpack_strdup_with_null_name(struct kunit *test)
|
|
((uintptr_t)puf->e->start <= (uintptr_t)string)
|
|
&& ((uintptr_t)string <= (uintptr_t)puf->e->end));
|
|
KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA);
|
|
+
|
|
+ kfree(string);
|
|
}
|
|
|
|
static void policy_unpack_test_unpack_strdup_with_name(struct kunit *test)
|
|
@@ -296,6 +298,8 @@ static void policy_unpack_test_unpack_strdup_with_name(struct kunit *test)
|
|
((uintptr_t)puf->e->start <= (uintptr_t)string)
|
|
&& ((uintptr_t)string <= (uintptr_t)puf->e->end));
|
|
KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA);
|
|
+
|
|
+ kfree(string);
|
|
}
|
|
|
|
static void policy_unpack_test_unpack_strdup_out_of_bounds(struct kunit *test)
|
|
@@ -313,6 +317,8 @@ static void policy_unpack_test_unpack_strdup_out_of_bounds(struct kunit *test)
|
|
KUNIT_EXPECT_EQ(test, size, 0);
|
|
KUNIT_EXPECT_NULL(test, string);
|
|
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start);
|
|
+
|
|
+ kfree(string);
|
|
}
|
|
|
|
static void policy_unpack_test_unpack_nameX_with_null_name(struct kunit *test)
|
|
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
|
|
index cc21c483c4a579..e40de64ec85cb5 100644
|
|
--- a/sound/core/pcm_native.c
|
|
+++ b/sound/core/pcm_native.c
|
|
@@ -3794,9 +3794,11 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
|
|
return VM_FAULT_SIGBUS;
|
|
if (substream->ops->page)
|
|
page = substream->ops->page(substream, offset);
|
|
- else if (!snd_pcm_get_dma_buf(substream))
|
|
+ else if (!snd_pcm_get_dma_buf(substream)) {
|
|
+ if (WARN_ON_ONCE(!runtime->dma_area))
|
|
+ return VM_FAULT_SIGBUS;
|
|
page = virt_to_page(runtime->dma_area + offset);
|
|
- else
|
|
+ } else
|
|
page = snd_sgbuf_get_page(snd_pcm_get_dma_buf(substream), offset);
|
|
if (!page)
|
|
return VM_FAULT_SIGBUS;
|
|
diff --git a/sound/core/ump.c b/sound/core/ump.c
|
|
index 8a7ecec74b5d61..b1ce4756961a54 100644
|
|
--- a/sound/core/ump.c
|
|
+++ b/sound/core/ump.c
|
|
@@ -724,7 +724,10 @@ static void fill_fb_info(struct snd_ump_endpoint *ump,
|
|
info->ui_hint = buf->fb_info.ui_hint;
|
|
info->first_group = buf->fb_info.first_group;
|
|
info->num_groups = buf->fb_info.num_groups;
|
|
- info->flags = buf->fb_info.midi_10;
|
|
+ if (buf->fb_info.midi_10 < 2)
|
|
+ info->flags = buf->fb_info.midi_10;
|
|
+ else
|
|
+ info->flags = SNDRV_UMP_BLOCK_IS_MIDI1 | SNDRV_UMP_BLOCK_IS_LOWSPEED;
|
|
info->active = buf->fb_info.active;
|
|
info->midi_ci_version = buf->fb_info.midi_ci_version;
|
|
info->sysex8_streams = buf->fb_info.sysex8_streams;
|
|
diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
|
|
index e7c2ef6c6b4cb0..16a3e478e50b94 100644
|
|
--- a/sound/hda/intel-dsp-config.c
|
|
+++ b/sound/hda/intel-dsp-config.c
|
|
@@ -721,6 +721,10 @@ static const struct config_entry acpi_config_table[] = {
|
|
#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \
|
|
IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
|
|
/* BayTrail */
|
|
+ {
|
|
+ .flags = FLAG_SST_OR_SOF_BYT,
|
|
+ .acpi_hid = "LPE0F28",
|
|
+ },
|
|
{
|
|
.flags = FLAG_SST_OR_SOF_BYT,
|
|
.acpi_hid = "80860F28",
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index ffe298eb7b369b..92299bab251572 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -471,6 +471,8 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
|
break;
|
|
case 0x10ec0234:
|
|
case 0x10ec0274:
|
|
+ alc_write_coef_idx(codec, 0x6e, 0x0c25);
|
|
+ fallthrough;
|
|
case 0x10ec0294:
|
|
case 0x10ec0700:
|
|
case 0x10ec0701:
|
|
@@ -3602,25 +3604,22 @@ static void alc256_init(struct hda_codec *codec)
|
|
|
|
hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
|
|
|
|
- if (hp_pin_sense)
|
|
+ if (hp_pin_sense) {
|
|
msleep(2);
|
|
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
|
|
|
|
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
|
|
-
|
|
- snd_hda_codec_write(codec, hp_pin, 0,
|
|
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
|
-
|
|
- if (hp_pin_sense || spec->ultra_low_power)
|
|
- msleep(85);
|
|
-
|
|
- snd_hda_codec_write(codec, hp_pin, 0,
|
|
+ snd_hda_codec_write(codec, hp_pin, 0,
|
|
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
|
|
|
- if (hp_pin_sense || spec->ultra_low_power)
|
|
- msleep(100);
|
|
+ msleep(75);
|
|
+
|
|
+ snd_hda_codec_write(codec, hp_pin, 0,
|
|
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
|
|
|
|
+ msleep(75);
|
|
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
|
|
+ }
|
|
alc_update_coef_idx(codec, 0x46, 3 << 12, 0);
|
|
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
|
|
alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */
|
|
alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15);
|
|
/*
|
|
@@ -3644,29 +3643,28 @@ static void alc256_shutup(struct hda_codec *codec)
|
|
alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
|
|
hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
|
|
|
|
- if (hp_pin_sense)
|
|
+ if (hp_pin_sense) {
|
|
msleep(2);
|
|
|
|
- snd_hda_codec_write(codec, hp_pin, 0,
|
|
+ snd_hda_codec_write(codec, hp_pin, 0,
|
|
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
|
|
|
- if (hp_pin_sense || spec->ultra_low_power)
|
|
- msleep(85);
|
|
+ msleep(75);
|
|
|
|
/* 3k pull low control for Headset jack. */
|
|
/* NOTE: call this before clearing the pin, otherwise codec stalls */
|
|
/* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
|
|
* when booting with headset plugged. So skip setting it for the codec alc257
|
|
*/
|
|
- if (spec->en_3kpull_low)
|
|
- alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
|
|
+ if (spec->en_3kpull_low)
|
|
+ alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
|
|
|
|
- if (!spec->no_shutup_pins)
|
|
- snd_hda_codec_write(codec, hp_pin, 0,
|
|
+ if (!spec->no_shutup_pins)
|
|
+ snd_hda_codec_write(codec, hp_pin, 0,
|
|
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
|
|
|
- if (hp_pin_sense || spec->ultra_low_power)
|
|
- msleep(100);
|
|
+ msleep(75);
|
|
+ }
|
|
|
|
alc_auto_setup_eapd(codec, false);
|
|
alc_shutup_pins(codec);
|
|
@@ -3761,33 +3759,28 @@ static void alc225_init(struct hda_codec *codec)
|
|
hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin);
|
|
hp2_pin_sense = snd_hda_jack_detect(codec, 0x16);
|
|
|
|
- if (hp1_pin_sense || hp2_pin_sense)
|
|
+ if (hp1_pin_sense || hp2_pin_sense) {
|
|
msleep(2);
|
|
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
|
|
|
|
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
|
|
-
|
|
- if (hp1_pin_sense || spec->ultra_low_power)
|
|
- snd_hda_codec_write(codec, hp_pin, 0,
|
|
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
|
- if (hp2_pin_sense)
|
|
- snd_hda_codec_write(codec, 0x16, 0,
|
|
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
|
-
|
|
- if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power)
|
|
- msleep(85);
|
|
-
|
|
- if (hp1_pin_sense || spec->ultra_low_power)
|
|
- snd_hda_codec_write(codec, hp_pin, 0,
|
|
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
|
- if (hp2_pin_sense)
|
|
- snd_hda_codec_write(codec, 0x16, 0,
|
|
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
|
+ if (hp1_pin_sense)
|
|
+ snd_hda_codec_write(codec, hp_pin, 0,
|
|
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
|
+ if (hp2_pin_sense)
|
|
+ snd_hda_codec_write(codec, 0x16, 0,
|
|
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
|
+ msleep(75);
|
|
|
|
- if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power)
|
|
- msleep(100);
|
|
+ if (hp1_pin_sense)
|
|
+ snd_hda_codec_write(codec, hp_pin, 0,
|
|
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
|
|
+ if (hp2_pin_sense)
|
|
+ snd_hda_codec_write(codec, 0x16, 0,
|
|
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
|
|
|
|
- alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
|
|
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
|
|
+ msleep(75);
|
|
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
|
|
+ }
|
|
}
|
|
|
|
static void alc225_shutup(struct hda_codec *codec)
|
|
@@ -3799,36 +3792,35 @@ static void alc225_shutup(struct hda_codec *codec)
|
|
if (!hp_pin)
|
|
hp_pin = 0x21;
|
|
|
|
- alc_disable_headset_jack_key(codec);
|
|
- /* 3k pull low control for Headset jack. */
|
|
- alc_update_coef_idx(codec, 0x4a, 0, 3 << 10);
|
|
-
|
|
hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin);
|
|
hp2_pin_sense = snd_hda_jack_detect(codec, 0x16);
|
|
|
|
- if (hp1_pin_sense || hp2_pin_sense)
|
|
+ if (hp1_pin_sense || hp2_pin_sense) {
|
|
+ alc_disable_headset_jack_key(codec);
|
|
+ /* 3k pull low control for Headset jack. */
|
|
+ alc_update_coef_idx(codec, 0x4a, 0, 3 << 10);
|
|
msleep(2);
|
|
|
|
- if (hp1_pin_sense || spec->ultra_low_power)
|
|
- snd_hda_codec_write(codec, hp_pin, 0,
|
|
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
|
- if (hp2_pin_sense)
|
|
- snd_hda_codec_write(codec, 0x16, 0,
|
|
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
|
-
|
|
- if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power)
|
|
- msleep(85);
|
|
+ if (hp1_pin_sense)
|
|
+ snd_hda_codec_write(codec, hp_pin, 0,
|
|
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
|
+ if (hp2_pin_sense)
|
|
+ snd_hda_codec_write(codec, 0x16, 0,
|
|
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
|
|
|
|
- if (hp1_pin_sense || spec->ultra_low_power)
|
|
- snd_hda_codec_write(codec, hp_pin, 0,
|
|
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
|
- if (hp2_pin_sense)
|
|
- snd_hda_codec_write(codec, 0x16, 0,
|
|
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
|
+ msleep(75);
|
|
|
|
- if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power)
|
|
- msleep(100);
|
|
+ if (hp1_pin_sense)
|
|
+ snd_hda_codec_write(codec, hp_pin, 0,
|
|
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
|
+ if (hp2_pin_sense)
|
|
+ snd_hda_codec_write(codec, 0x16, 0,
|
|
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
|
|
|
|
+ msleep(75);
|
|
+ alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
|
|
+ alc_enable_headset_jack_key(codec);
|
|
+ }
|
|
alc_auto_setup_eapd(codec, false);
|
|
alc_shutup_pins(codec);
|
|
if (spec->ultra_low_power) {
|
|
@@ -3839,9 +3831,6 @@ static void alc225_shutup(struct hda_codec *codec)
|
|
alc_update_coef_idx(codec, 0x4a, 3<<4, 2<<4);
|
|
msleep(30);
|
|
}
|
|
-
|
|
- alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
|
|
- alc_enable_headset_jack_key(codec);
|
|
}
|
|
|
|
static void alc_default_init(struct hda_codec *codec)
|
|
@@ -7265,6 +7254,8 @@ enum {
|
|
ALC290_FIXUP_SUBWOOFER_HSJACK,
|
|
ALC269_FIXUP_THINKPAD_ACPI,
|
|
ALC269_FIXUP_DMIC_THINKPAD_ACPI,
|
|
+ ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13,
|
|
+ ALC269VC_FIXUP_INFINIX_Y4_MAX,
|
|
ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO,
|
|
ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
|
|
ALC255_FIXUP_ASUS_MIC_NO_PRESENCE,
|
|
@@ -7644,6 +7635,25 @@ static const struct hda_fixup alc269_fixups[] = {
|
|
.type = HDA_FIXUP_FUNC,
|
|
.v.func = alc269_fixup_pincfg_U7x7_headset_mic,
|
|
},
|
|
+ [ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13] = {
|
|
+ .type = HDA_FIXUP_PINS,
|
|
+ .v.pins = (const struct hda_pintbl[]) {
|
|
+ { 0x14, 0x90170151 }, /* use as internal speaker (LFE) */
|
|
+ { 0x1b, 0x90170152 }, /* use as internal speaker (back) */
|
|
+ { }
|
|
+ },
|
|
+ .chained = true,
|
|
+ .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
|
|
+ },
|
|
+ [ALC269VC_FIXUP_INFINIX_Y4_MAX] = {
|
|
+ .type = HDA_FIXUP_PINS,
|
|
+ .v.pins = (const struct hda_pintbl[]) {
|
|
+ { 0x1b, 0x90170150 }, /* use as internal speaker */
|
|
+ { }
|
|
+ },
|
|
+ .chained = true,
|
|
+ .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
|
|
+ },
|
|
[ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO] = {
|
|
.type = HDA_FIXUP_PINS,
|
|
.v.pins = (const struct hda_pintbl[]) {
|
|
@@ -10412,7 +10422,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
|
|
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
|
|
SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
|
+ SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13),
|
|
SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
|
|
+ SND_PCI_QUIRK(0x2782, 0x1701, "Infinix Y4 Max", ALC269VC_FIXUP_INFINIX_Y4_MAX),
|
|
+ SND_PCI_QUIRK(0x2782, 0x1705, "MEDION E15433", ALC269VC_FIXUP_INFINIX_Y4_MAX),
|
|
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
|
|
SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC),
|
|
SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED),
|
|
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
|
|
index 08f823cd886999..a00933df9168ae 100644
|
|
--- a/sound/soc/amd/yc/acp6x-mach.c
|
|
+++ b/sound/soc/amd/yc/acp6x-mach.c
|
|
@@ -227,6 +227,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "21M3"),
|
|
}
|
|
},
|
|
+ {
|
|
+ .driver_data = &acp6x_card,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M4"),
|
|
+ }
|
|
+ },
|
|
{
|
|
.driver_data = &acp6x_card,
|
|
.matches = {
|
|
@@ -234,6 +241,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "21M5"),
|
|
}
|
|
},
|
|
+ {
|
|
+ .driver_data = &acp6x_card,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "21ME"),
|
|
+ }
|
|
+ },
|
|
{
|
|
.driver_data = &acp6x_card,
|
|
.matches = {
|
|
@@ -530,8 +544,14 @@ static int acp6x_probe(struct platform_device *pdev)
|
|
struct acp6x_pdm *machine = NULL;
|
|
struct snd_soc_card *card;
|
|
struct acpi_device *adev;
|
|
+ acpi_handle handle;
|
|
+ acpi_integer dmic_status;
|
|
int ret;
|
|
+ bool is_dmic_enable, wov_en;
|
|
|
|
+ /* IF WOV entry not found, enable dmic based on AcpDmicConnected entry*/
|
|
+ is_dmic_enable = false;
|
|
+ wov_en = true;
|
|
/* check the parent device's firmware node has _DSD or not */
|
|
adev = ACPI_COMPANION(pdev->dev.parent);
|
|
if (adev) {
|
|
@@ -539,9 +559,19 @@ static int acp6x_probe(struct platform_device *pdev)
|
|
|
|
if (!acpi_dev_get_property(adev, "AcpDmicConnected", ACPI_TYPE_INTEGER, &obj) &&
|
|
obj->integer.value == 1)
|
|
- platform_set_drvdata(pdev, &acp6x_card);
|
|
+ is_dmic_enable = true;
|
|
}
|
|
|
|
+ handle = ACPI_HANDLE(pdev->dev.parent);
|
|
+ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
|
|
+ if (!ACPI_FAILURE(ret))
|
|
+ wov_en = dmic_status;
|
|
+
|
|
+ if (is_dmic_enable && wov_en)
|
|
+ platform_set_drvdata(pdev, &acp6x_card);
|
|
+ else
|
|
+ return 0;
|
|
+
|
|
/* check for any DMI overrides */
|
|
dmi_id = dmi_first_match(yc_acp_quirk_table);
|
|
if (dmi_id)
|
|
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
|
|
index 600c2db587568d..dd86033b707738 100644
|
|
--- a/sound/soc/codecs/da7219.c
|
|
+++ b/sound/soc/codecs/da7219.c
|
|
@@ -1167,17 +1167,20 @@ static int da7219_set_dai_sysclk(struct snd_soc_dai *codec_dai,
|
|
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
|
|
int ret = 0;
|
|
|
|
- if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq))
|
|
+ mutex_lock(&da7219->pll_lock);
|
|
+
|
|
+ if ((da7219->clk_src == clk_id) && (da7219->mclk_rate == freq)) {
|
|
+ mutex_unlock(&da7219->pll_lock);
|
|
return 0;
|
|
+ }
|
|
|
|
if ((freq < 2000000) || (freq > 54000000)) {
|
|
+ mutex_unlock(&da7219->pll_lock);
|
|
dev_err(codec_dai->dev, "Unsupported MCLK value %d\n",
|
|
freq);
|
|
return -EINVAL;
|
|
}
|
|
|
|
- mutex_lock(&da7219->pll_lock);
|
|
-
|
|
switch (clk_id) {
|
|
case DA7219_CLKSRC_MCLK_SQR:
|
|
snd_soc_component_update_bits(component, DA7219_PLL_CTRL,
|
|
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
|
|
index e8cdc166bdaa99..1955d77cffd996 100644
|
|
--- a/sound/soc/codecs/rt5640.c
|
|
+++ b/sound/soc/codecs/rt5640.c
|
|
@@ -2422,10 +2422,20 @@ static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data)
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
-static void rt5640_cancel_work(void *data)
|
|
+static void rt5640_disable_irq_and_cancel_work(void *data)
|
|
{
|
|
struct rt5640_priv *rt5640 = data;
|
|
|
|
+ if (rt5640->jd_gpio_irq_requested) {
|
|
+ free_irq(rt5640->jd_gpio_irq, rt5640);
|
|
+ rt5640->jd_gpio_irq_requested = false;
|
|
+ }
|
|
+
|
|
+ if (rt5640->irq_requested) {
|
|
+ free_irq(rt5640->irq, rt5640);
|
|
+ rt5640->irq_requested = false;
|
|
+ }
|
|
+
|
|
cancel_delayed_work_sync(&rt5640->jack_work);
|
|
cancel_delayed_work_sync(&rt5640->bp_work);
|
|
}
|
|
@@ -2466,13 +2476,7 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
|
|
if (!rt5640->jack)
|
|
return;
|
|
|
|
- if (rt5640->jd_gpio_irq_requested)
|
|
- free_irq(rt5640->jd_gpio_irq, rt5640);
|
|
-
|
|
- if (rt5640->irq_requested)
|
|
- free_irq(rt5640->irq, rt5640);
|
|
-
|
|
- rt5640_cancel_work(rt5640);
|
|
+ rt5640_disable_irq_and_cancel_work(rt5640);
|
|
|
|
if (rt5640->jack->status & SND_JACK_MICROPHONE) {
|
|
rt5640_disable_micbias1_ovcd_irq(component);
|
|
@@ -2480,8 +2484,6 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
|
|
snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
|
|
}
|
|
|
|
- rt5640->jd_gpio_irq_requested = false;
|
|
- rt5640->irq_requested = false;
|
|
rt5640->jd_gpio = NULL;
|
|
rt5640->jack = NULL;
|
|
}
|
|
@@ -2801,7 +2803,8 @@ static int rt5640_suspend(struct snd_soc_component *component)
|
|
if (rt5640->jack) {
|
|
/* disable jack interrupts during system suspend */
|
|
disable_irq(rt5640->irq);
|
|
- rt5640_cancel_work(rt5640);
|
|
+ cancel_delayed_work_sync(&rt5640->jack_work);
|
|
+ cancel_delayed_work_sync(&rt5640->bp_work);
|
|
}
|
|
|
|
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
|
|
@@ -3035,7 +3038,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c)
|
|
INIT_DELAYED_WORK(&rt5640->jack_work, rt5640_jack_work);
|
|
|
|
/* Make sure work is stopped on probe-error / remove */
|
|
- ret = devm_add_action_or_reset(&i2c->dev, rt5640_cancel_work, rt5640);
|
|
+ ret = devm_add_action_or_reset(&i2c->dev, rt5640_disable_irq_and_cancel_work, rt5640);
|
|
if (ret)
|
|
return ret;
|
|
|
|
diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c
|
|
index 9ff607984ea193..b9b330375addab 100644
|
|
--- a/sound/soc/codecs/rt722-sdca.c
|
|
+++ b/sound/soc/codecs/rt722-sdca.c
|
|
@@ -607,12 +607,8 @@ static int rt722_sdca_dmic_set_gain_get(struct snd_kcontrol *kcontrol,
|
|
|
|
if (!adc_vol_flag) /* boost gain */
|
|
ctl = regvalue / boost_step;
|
|
- else { /* ADC gain */
|
|
- if (adc_vol_flag)
|
|
- ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset);
|
|
- else
|
|
- ctl = p->max - (((0 - regvalue) & 0xffff) / interval_offset);
|
|
- }
|
|
+ else /* ADC gain */
|
|
+ ctl = p->max - (((vol_max - regvalue) & 0xffff) / interval_offset);
|
|
|
|
ucontrol->value.integer.value[i] = ctl;
|
|
}
|
|
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
|
|
index 629e2195a890b2..1cc64ed8de6da8 100644
|
|
--- a/sound/soc/codecs/tas2781-fmwlib.c
|
|
+++ b/sound/soc/codecs/tas2781-fmwlib.c
|
|
@@ -2022,6 +2022,7 @@ static int tasdevice_dspfw_ready(const struct firmware *fmw,
|
|
break;
|
|
case 0x202:
|
|
case 0x400:
|
|
+ case 0x401:
|
|
tas_priv->fw_parse_variable_header =
|
|
fw_parse_variable_header_git;
|
|
tas_priv->fw_parse_program_data =
|
|
diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
|
|
index 8478a4ac59f9dd..f57f0ab8a1add1 100644
|
|
--- a/sound/soc/fsl/fsl_micfil.c
|
|
+++ b/sound/soc/fsl/fsl_micfil.c
|
|
@@ -1051,7 +1051,7 @@ static irqreturn_t micfil_isr(int irq, void *devid)
|
|
regmap_write_bits(micfil->regmap,
|
|
REG_MICFIL_STAT,
|
|
MICFIL_STAT_CHXF(i),
|
|
- 1);
|
|
+ MICFIL_STAT_CHXF(i));
|
|
}
|
|
|
|
for (i = 0; i < MICFIL_FIFO_NUM; i++) {
|
|
@@ -1086,7 +1086,7 @@ static irqreturn_t micfil_err_isr(int irq, void *devid)
|
|
if (stat_reg & MICFIL_STAT_LOWFREQF) {
|
|
dev_dbg(&pdev->dev, "isr: ipg_clk_app is too low\n");
|
|
regmap_write_bits(micfil->regmap, REG_MICFIL_STAT,
|
|
- MICFIL_STAT_LOWFREQF, 1);
|
|
+ MICFIL_STAT_LOWFREQF, MICFIL_STAT_LOWFREQF);
|
|
}
|
|
|
|
return IRQ_HANDLED;
|
|
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
|
|
index b1c675c6b6db62..686e0dea2bc752 100644
|
|
--- a/sound/soc/generic/audio-graph-card2.c
|
|
+++ b/sound/soc/generic/audio-graph-card2.c
|
|
@@ -261,16 +261,19 @@ static enum graph_type __graph_get_type(struct device_node *lnk)
|
|
|
|
if (of_node_name_eq(np, GRAPH_NODENAME_MULTI)) {
|
|
ret = GRAPH_MULTI;
|
|
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
|
|
goto out_put;
|
|
}
|
|
|
|
if (of_node_name_eq(np, GRAPH_NODENAME_DPCM)) {
|
|
ret = GRAPH_DPCM;
|
|
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
|
|
goto out_put;
|
|
}
|
|
|
|
if (of_node_name_eq(np, GRAPH_NODENAME_C2C)) {
|
|
ret = GRAPH_C2C;
|
|
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
|
|
goto out_put;
|
|
}
|
|
|
|
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
|
|
index 29d44c989e5fc2..cfa1632ae4f03f 100644
|
|
--- a/sound/soc/intel/atom/sst/sst_acpi.c
|
|
+++ b/sound/soc/intel/atom/sst/sst_acpi.c
|
|
@@ -125,6 +125,28 @@ static const struct sst_res_info bytcr_res_info = {
|
|
.acpi_ipc_irq_index = 0
|
|
};
|
|
|
|
+/* For "LPE0F28" ACPI device found on some Android factory OS models */
|
|
+static const struct sst_res_info lpe8086_res_info = {
|
|
+ .shim_offset = 0x140000,
|
|
+ .shim_size = 0x000100,
|
|
+ .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
|
|
+ .ssp0_offset = 0xa0000,
|
|
+ .ssp0_size = 0x1000,
|
|
+ .dma0_offset = 0x98000,
|
|
+ .dma0_size = 0x4000,
|
|
+ .dma1_offset = 0x9c000,
|
|
+ .dma1_size = 0x4000,
|
|
+ .iram_offset = 0x0c0000,
|
|
+ .iram_size = 0x14000,
|
|
+ .dram_offset = 0x100000,
|
|
+ .dram_size = 0x28000,
|
|
+ .mbox_offset = 0x144000,
|
|
+ .mbox_size = 0x1000,
|
|
+ .acpi_lpe_res_index = 1,
|
|
+ .acpi_ddr_index = 0,
|
|
+ .acpi_ipc_irq_index = 0
|
|
+};
|
|
+
|
|
static struct sst_platform_info byt_rvp_platform_data = {
|
|
.probe_data = &byt_fwparse_info,
|
|
.ipc_info = &byt_ipc_info,
|
|
@@ -268,10 +290,38 @@ static int sst_acpi_probe(struct platform_device *pdev)
|
|
mach->pdata = &chv_platform_data;
|
|
pdata = mach->pdata;
|
|
|
|
- ret = kstrtouint(id->id, 16, &dev_id);
|
|
- if (ret < 0) {
|
|
- dev_err(dev, "Unique device id conversion error: %d\n", ret);
|
|
- return ret;
|
|
+ if (!strcmp(id->id, "LPE0F28")) {
|
|
+ struct resource *rsrc;
|
|
+
|
|
+ /* Use regular BYT SST PCI VID:PID */
|
|
+ dev_id = 0x80860F28;
|
|
+ byt_rvp_platform_data.res_info = &lpe8086_res_info;
|
|
+
|
|
+ /*
|
|
+ * The "LPE0F28" ACPI device has separate IO-mem resources for:
|
|
+ * DDR, SHIM, MBOX, IRAM, DRAM, CFG
|
|
+ * None of which covers the entire LPE base address range.
|
|
+ * lpe8086_res_info.acpi_lpe_res_index points to the SHIM.
|
|
+ * Patch this to cover the entire base address range as expected
|
|
+ * by sst_platform_get_resources().
|
|
+ */
|
|
+ rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
|
|
+ pdata->res_info->acpi_lpe_res_index);
|
|
+ if (!rsrc) {
|
|
+ dev_err(dev, "Invalid SHIM base\n");
|
|
+ return -EIO;
|
|
+ }
|
|
+ rsrc->start -= pdata->res_info->shim_offset;
|
|
+ rsrc->end = rsrc->start + 0x200000 - 1;
|
|
+ } else {
|
|
+ ret = kstrtouint(id->id, 16, &dev_id);
|
|
+ if (ret < 0) {
|
|
+ dev_err(dev, "Unique device id conversion error: %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ if (soc_intel_is_byt_cr(pdev))
|
|
+ byt_rvp_platform_data.res_info = &bytcr_res_info;
|
|
}
|
|
|
|
dev_dbg(dev, "ACPI device id: %x\n", dev_id);
|
|
@@ -280,11 +330,6 @@ static int sst_acpi_probe(struct platform_device *pdev)
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- if (soc_intel_is_byt_cr(pdev)) {
|
|
- /* override resource info */
|
|
- byt_rvp_platform_data.res_info = &bytcr_res_info;
|
|
- }
|
|
-
|
|
/* update machine parameters */
|
|
mach->mach_params.acpi_ipc_irq_index =
|
|
pdata->res_info->acpi_ipc_irq_index;
|
|
@@ -344,6 +389,7 @@ static void sst_acpi_remove(struct platform_device *pdev)
|
|
}
|
|
|
|
static const struct acpi_device_id sst_acpi_ids[] = {
|
|
+ { "LPE0F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
|
|
{ "80860F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
|
|
{ "808622A8", (unsigned long)&snd_soc_acpi_intel_cherrytrail_machines},
|
|
{ },
|
|
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
|
|
index 5b8b21ade9cfed..ddf68be0af14a5 100644
|
|
--- a/sound/soc/intel/boards/bytcr_rt5640.c
|
|
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
|
|
@@ -17,6 +17,7 @@
|
|
#include <linux/acpi.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/device.h>
|
|
+#include <linux/device/bus.h>
|
|
#include <linux/dmi.h>
|
|
#include <linux/gpio/consumer.h>
|
|
#include <linux/gpio/machine.h>
|
|
@@ -32,6 +33,8 @@
|
|
#include "../atom/sst-atom-controls.h"
|
|
#include "../common/soc-intel-quirks.h"
|
|
|
|
+#define BYT_RT5640_FALLBACK_CODEC_DEV_NAME "i2c-rt5640"
|
|
+
|
|
enum {
|
|
BYT_RT5640_DMIC1_MAP,
|
|
BYT_RT5640_DMIC2_MAP,
|
|
@@ -1129,6 +1132,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
|
BYT_RT5640_SSP0_AIF2 |
|
|
BYT_RT5640_MCLK_EN),
|
|
},
|
|
+ { /* Vexia Edu Atla 10 tablet */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
|
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
|
|
+ /* Above strings are too generic, also match on BIOS date */
|
|
+ DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
|
|
+ },
|
|
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
|
|
+ BYT_RT5640_JD_SRC_JD2_IN4N |
|
|
+ BYT_RT5640_OVCD_TH_2000UA |
|
|
+ BYT_RT5640_OVCD_SF_0P75 |
|
|
+ BYT_RT5640_DIFF_MIC |
|
|
+ BYT_RT5640_SSP0_AIF2 |
|
|
+ BYT_RT5640_MCLK_EN),
|
|
+ },
|
|
{ /* Voyo Winpad A15 */
|
|
.matches = {
|
|
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
|
@@ -1697,9 +1715,33 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
|
|
|
|
codec_dev = acpi_get_first_physical_node(adev);
|
|
acpi_dev_put(adev);
|
|
- if (!codec_dev)
|
|
- return -EPROBE_DEFER;
|
|
- priv->codec_dev = get_device(codec_dev);
|
|
+
|
|
+ if (codec_dev) {
|
|
+ priv->codec_dev = get_device(codec_dev);
|
|
+ } else {
|
|
+ /*
|
|
+ * Special case for Android tablets where the codec i2c_client
|
|
+ * has been manually instantiated by x86_android_tablets.ko due
|
|
+ * to a broken DSDT.
|
|
+ */
|
|
+ codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
|
|
+ BYT_RT5640_FALLBACK_CODEC_DEV_NAME);
|
|
+ if (!codec_dev)
|
|
+ return -EPROBE_DEFER;
|
|
+
|
|
+ if (!i2c_verify_client(codec_dev)) {
|
|
+ dev_err(dev, "Error '%s' is not an i2c_client\n",
|
|
+ BYT_RT5640_FALLBACK_CODEC_DEV_NAME);
|
|
+ put_device(codec_dev);
|
|
+ }
|
|
+
|
|
+ /* fixup codec name */
|
|
+ strscpy(byt_rt5640_codec_name, BYT_RT5640_FALLBACK_CODEC_DEV_NAME,
|
|
+ sizeof(byt_rt5640_codec_name));
|
|
+
|
|
+ /* bus_find_device() returns a reference no need to get() */
|
|
+ priv->codec_dev = codec_dev;
|
|
+ }
|
|
|
|
/*
|
|
* swap SSP0 if bytcr is detected
|
|
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
|
|
index 0acc848c1f004d..dcbcd1a59a3aae 100644
|
|
--- a/sound/soc/stm/stm32_sai_sub.c
|
|
+++ b/sound/soc/stm/stm32_sai_sub.c
|
|
@@ -317,7 +317,7 @@ static int stm32_sai_get_clk_div(struct stm32_sai_sub_data *sai,
|
|
int div;
|
|
|
|
div = DIV_ROUND_CLOSEST(input_rate, output_rate);
|
|
- if (div > SAI_XCR1_MCKDIV_MAX(version)) {
|
|
+ if (div > SAI_XCR1_MCKDIV_MAX(version) || div <= 0) {
|
|
dev_err(&sai->pdev->dev, "Divider %d out of range\n", div);
|
|
return -EINVAL;
|
|
}
|
|
@@ -378,8 +378,8 @@ static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
|
|
int div;
|
|
|
|
div = stm32_sai_get_clk_div(sai, *prate, rate);
|
|
- if (div < 0)
|
|
- return div;
|
|
+ if (div <= 0)
|
|
+ return -EINVAL;
|
|
|
|
mclk->freq = *prate / div;
|
|
|
|
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
|
|
index 33e962178c9363..d562a30b087f01 100644
|
|
--- a/sound/usb/6fire/chip.c
|
|
+++ b/sound/usb/6fire/chip.c
|
|
@@ -61,8 +61,10 @@ static void usb6fire_chip_abort(struct sfire_chip *chip)
|
|
}
|
|
}
|
|
|
|
-static void usb6fire_chip_destroy(struct sfire_chip *chip)
|
|
+static void usb6fire_card_free(struct snd_card *card)
|
|
{
|
|
+ struct sfire_chip *chip = card->private_data;
|
|
+
|
|
if (chip) {
|
|
if (chip->pcm)
|
|
usb6fire_pcm_destroy(chip);
|
|
@@ -72,8 +74,6 @@ static void usb6fire_chip_destroy(struct sfire_chip *chip)
|
|
usb6fire_comm_destroy(chip);
|
|
if (chip->control)
|
|
usb6fire_control_destroy(chip);
|
|
- if (chip->card)
|
|
- snd_card_free(chip->card);
|
|
}
|
|
}
|
|
|
|
@@ -136,6 +136,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
|
|
chip->regidx = regidx;
|
|
chip->intf_count = 1;
|
|
chip->card = card;
|
|
+ card->private_free = usb6fire_card_free;
|
|
|
|
ret = usb6fire_comm_init(chip);
|
|
if (ret < 0)
|
|
@@ -162,7 +163,7 @@ static int usb6fire_chip_probe(struct usb_interface *intf,
|
|
return 0;
|
|
|
|
destroy_chip:
|
|
- usb6fire_chip_destroy(chip);
|
|
+ snd_card_free(card);
|
|
return ret;
|
|
}
|
|
|
|
@@ -181,7 +182,6 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf)
|
|
|
|
chip->shutdown = true;
|
|
usb6fire_chip_abort(chip);
|
|
- usb6fire_chip_destroy(chip);
|
|
}
|
|
}
|
|
}
|
|
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
|
|
index 4981753652a7fe..7a89872aa0cbd6 100644
|
|
--- a/sound/usb/caiaq/audio.c
|
|
+++ b/sound/usb/caiaq/audio.c
|
|
@@ -869,14 +869,20 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
|
|
return 0;
|
|
}
|
|
|
|
-void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
|
|
+void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev)
|
|
{
|
|
struct device *dev = caiaqdev_to_dev(cdev);
|
|
|
|
dev_dbg(dev, "%s(%p)\n", __func__, cdev);
|
|
stream_stop(cdev);
|
|
+}
|
|
+
|
|
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev)
|
|
+{
|
|
+ struct device *dev = caiaqdev_to_dev(cdev);
|
|
+
|
|
+ dev_dbg(dev, "%s(%p)\n", __func__, cdev);
|
|
free_urbs(cdev->data_urbs_in);
|
|
free_urbs(cdev->data_urbs_out);
|
|
kfree(cdev->data_cb_info);
|
|
}
|
|
-
|
|
diff --git a/sound/usb/caiaq/audio.h b/sound/usb/caiaq/audio.h
|
|
index 869bf6264d6a09..07f5d064456cf7 100644
|
|
--- a/sound/usb/caiaq/audio.h
|
|
+++ b/sound/usb/caiaq/audio.h
|
|
@@ -3,6 +3,7 @@
|
|
#define CAIAQ_AUDIO_H
|
|
|
|
int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev);
|
|
+void snd_usb_caiaq_audio_disconnect(struct snd_usb_caiaqdev *cdev);
|
|
void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *cdev);
|
|
|
|
#endif /* CAIAQ_AUDIO_H */
|
|
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
|
|
index b5cbf1f195c48c..dfd820483849eb 100644
|
|
--- a/sound/usb/caiaq/device.c
|
|
+++ b/sound/usb/caiaq/device.c
|
|
@@ -376,6 +376,17 @@ static void setup_card(struct snd_usb_caiaqdev *cdev)
|
|
dev_err(dev, "Unable to set up control system (ret=%d)\n", ret);
|
|
}
|
|
|
|
+static void card_free(struct snd_card *card)
|
|
+{
|
|
+ struct snd_usb_caiaqdev *cdev = caiaqdev(card);
|
|
+
|
|
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
|
|
+ snd_usb_caiaq_input_free(cdev);
|
|
+#endif
|
|
+ snd_usb_caiaq_audio_free(cdev);
|
|
+ usb_reset_device(cdev->chip.dev);
|
|
+}
|
|
+
|
|
static int create_card(struct usb_device *usb_dev,
|
|
struct usb_interface *intf,
|
|
struct snd_card **cardp)
|
|
@@ -489,6 +500,7 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
|
|
cdev->vendor_name, cdev->product_name, usbpath);
|
|
|
|
setup_card(cdev);
|
|
+ card->private_free = card_free;
|
|
return 0;
|
|
|
|
err_kill_urb:
|
|
@@ -534,15 +546,14 @@ static void snd_disconnect(struct usb_interface *intf)
|
|
snd_card_disconnect(card);
|
|
|
|
#ifdef CONFIG_SND_USB_CAIAQ_INPUT
|
|
- snd_usb_caiaq_input_free(cdev);
|
|
+ snd_usb_caiaq_input_disconnect(cdev);
|
|
#endif
|
|
- snd_usb_caiaq_audio_free(cdev);
|
|
+ snd_usb_caiaq_audio_disconnect(cdev);
|
|
|
|
usb_kill_urb(&cdev->ep1_in_urb);
|
|
usb_kill_urb(&cdev->midi_out_urb);
|
|
|
|
- snd_card_free(card);
|
|
- usb_reset_device(interface_to_usbdev(intf));
|
|
+ snd_card_free_when_closed(card);
|
|
}
|
|
|
|
|
|
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
|
|
index 84f26dce7f5d03..a9130891bb696d 100644
|
|
--- a/sound/usb/caiaq/input.c
|
|
+++ b/sound/usb/caiaq/input.c
|
|
@@ -829,15 +829,21 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev)
|
|
return ret;
|
|
}
|
|
|
|
-void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev)
|
|
+void snd_usb_caiaq_input_disconnect(struct snd_usb_caiaqdev *cdev)
|
|
{
|
|
if (!cdev || !cdev->input_dev)
|
|
return;
|
|
|
|
usb_kill_urb(cdev->ep4_in_urb);
|
|
+ input_unregister_device(cdev->input_dev);
|
|
+}
|
|
+
|
|
+void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev)
|
|
+{
|
|
+ if (!cdev || !cdev->input_dev)
|
|
+ return;
|
|
+
|
|
usb_free_urb(cdev->ep4_in_urb);
|
|
cdev->ep4_in_urb = NULL;
|
|
-
|
|
- input_unregister_device(cdev->input_dev);
|
|
cdev->input_dev = NULL;
|
|
}
|
|
diff --git a/sound/usb/caiaq/input.h b/sound/usb/caiaq/input.h
|
|
index c42891e7be884d..fbe267f85d025f 100644
|
|
--- a/sound/usb/caiaq/input.h
|
|
+++ b/sound/usb/caiaq/input.h
|
|
@@ -4,6 +4,7 @@
|
|
|
|
void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *cdev, char *buf, unsigned int len);
|
|
int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev);
|
|
+void snd_usb_caiaq_input_disconnect(struct snd_usb_caiaqdev *cdev);
|
|
void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev);
|
|
|
|
#endif
|
|
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
|
|
index a676ad093d1897..f0f1e445cc5676 100644
|
|
--- a/sound/usb/clock.c
|
|
+++ b/sound/usb/clock.c
|
|
@@ -36,6 +36,12 @@ union uac23_clock_multiplier_desc {
|
|
struct uac_clock_multiplier_descriptor v3;
|
|
};
|
|
|
|
+/* check whether the descriptor bLength has the minimal length */
|
|
+#define DESC_LENGTH_CHECK(p, proto) \
|
|
+ ((proto) == UAC_VERSION_3 ? \
|
|
+ ((p)->v3.bLength >= sizeof((p)->v3)) : \
|
|
+ ((p)->v2.bLength >= sizeof((p)->v2)))
|
|
+
|
|
#define GET_VAL(p, proto, field) \
|
|
((proto) == UAC_VERSION_3 ? (p)->v3.field : (p)->v2.field)
|
|
|
|
@@ -58,6 +64,8 @@ static bool validate_clock_source(void *p, int id, int proto)
|
|
{
|
|
union uac23_clock_source_desc *cs = p;
|
|
|
|
+ if (!DESC_LENGTH_CHECK(cs, proto))
|
|
+ return false;
|
|
return GET_VAL(cs, proto, bClockID) == id;
|
|
}
|
|
|
|
@@ -65,13 +73,27 @@ static bool validate_clock_selector(void *p, int id, int proto)
|
|
{
|
|
union uac23_clock_selector_desc *cs = p;
|
|
|
|
- return GET_VAL(cs, proto, bClockID) == id;
|
|
+ if (!DESC_LENGTH_CHECK(cs, proto))
|
|
+ return false;
|
|
+ if (GET_VAL(cs, proto, bClockID) != id)
|
|
+ return false;
|
|
+ /* additional length check for baCSourceID array (in bNrInPins size)
|
|
+ * and two more fields (which sizes depend on the protocol)
|
|
+ */
|
|
+ if (proto == UAC_VERSION_3)
|
|
+ return cs->v3.bLength >= sizeof(cs->v3) + cs->v3.bNrInPins +
|
|
+ 4 /* bmControls */ + 2 /* wCSelectorDescrStr */;
|
|
+ else
|
|
+ return cs->v2.bLength >= sizeof(cs->v2) + cs->v2.bNrInPins +
|
|
+ 1 /* bmControls */ + 1 /* iClockSelector */;
|
|
}
|
|
|
|
static bool validate_clock_multiplier(void *p, int id, int proto)
|
|
{
|
|
union uac23_clock_multiplier_desc *cs = p;
|
|
|
|
+ if (!DESC_LENGTH_CHECK(cs, proto))
|
|
+ return false;
|
|
return GET_VAL(cs, proto, bClockID) == id;
|
|
}
|
|
|
|
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
|
|
index 75cde5779f38d5..d1bd8e0d602525 100644
|
|
--- a/sound/usb/quirks-table.h
|
|
+++ b/sound/usb/quirks-table.h
|
|
@@ -324,7 +324,6 @@ YAMAHA_DEVICE(0x105a, NULL),
|
|
YAMAHA_DEVICE(0x105b, NULL),
|
|
YAMAHA_DEVICE(0x105c, NULL),
|
|
YAMAHA_DEVICE(0x105d, NULL),
|
|
-YAMAHA_DEVICE(0x1718, "P-125"),
|
|
{
|
|
USB_DEVICE(0x0499, 0x1503),
|
|
QUIRK_DRIVER_INFO {
|
|
@@ -391,6 +390,19 @@ YAMAHA_DEVICE(0x1718, "P-125"),
|
|
}
|
|
}
|
|
},
|
|
+{
|
|
+ USB_DEVICE(0x0499, 0x1718),
|
|
+ QUIRK_DRIVER_INFO {
|
|
+ /* .vendor_name = "Yamaha", */
|
|
+ /* .product_name = "P-125", */
|
|
+ QUIRK_DATA_COMPOSITE {
|
|
+ { QUIRK_DATA_STANDARD_AUDIO(1) },
|
|
+ { QUIRK_DATA_STANDARD_AUDIO(2) },
|
|
+ { QUIRK_DATA_MIDI_YAMAHA(3) },
|
|
+ QUIRK_COMPOSITE_END
|
|
+ }
|
|
+ }
|
|
+},
|
|
YAMAHA_DEVICE(0x2000, "DGP-7"),
|
|
YAMAHA_DEVICE(0x2001, "DGP-5"),
|
|
YAMAHA_DEVICE(0x2002, NULL),
|
|
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
|
|
index 37211ad31ec894..30a4d2deefdab5 100644
|
|
--- a/sound/usb/quirks.c
|
|
+++ b/sound/usb/quirks.c
|
|
@@ -555,6 +555,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
|
|
static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interface *intf)
|
|
{
|
|
struct usb_host_config *config = dev->actconfig;
|
|
+ struct usb_device_descriptor new_device_descriptor;
|
|
int err;
|
|
|
|
if (le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_OLD ||
|
|
@@ -566,10 +567,14 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
|
|
if (err < 0)
|
|
dev_dbg(&dev->dev, "error sending boot message: %d\n", err);
|
|
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
|
|
- &dev->descriptor, sizeof(dev->descriptor));
|
|
- config = dev->actconfig;
|
|
+ &new_device_descriptor, sizeof(new_device_descriptor));
|
|
if (err < 0)
|
|
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
|
|
+ if (new_device_descriptor.bNumConfigurations > dev->descriptor.bNumConfigurations)
|
|
+ dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n",
|
|
+ new_device_descriptor.bNumConfigurations);
|
|
+ else
|
|
+ memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor));
|
|
err = usb_reset_configuration(dev);
|
|
if (err < 0)
|
|
dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
|
|
@@ -901,6 +906,7 @@ static void mbox2_setup_48_24_magic(struct usb_device *dev)
|
|
static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
|
|
{
|
|
struct usb_host_config *config = dev->actconfig;
|
|
+ struct usb_device_descriptor new_device_descriptor;
|
|
int err;
|
|
u8 bootresponse[0x12];
|
|
int fwsize;
|
|
@@ -936,10 +942,14 @@ static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
|
|
dev_dbg(&dev->dev, "device initialised!\n");
|
|
|
|
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
|
|
- &dev->descriptor, sizeof(dev->descriptor));
|
|
- config = dev->actconfig;
|
|
+ &new_device_descriptor, sizeof(new_device_descriptor));
|
|
if (err < 0)
|
|
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
|
|
+ if (new_device_descriptor.bNumConfigurations > dev->descriptor.bNumConfigurations)
|
|
+ dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n",
|
|
+ new_device_descriptor.bNumConfigurations);
|
|
+ else
|
|
+ memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor));
|
|
|
|
err = usb_reset_configuration(dev);
|
|
if (err < 0)
|
|
@@ -1253,6 +1263,7 @@ static void mbox3_setup_48_24_magic(struct usb_device *dev)
|
|
static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
|
|
{
|
|
struct usb_host_config *config = dev->actconfig;
|
|
+ struct usb_device_descriptor new_device_descriptor;
|
|
int err;
|
|
int descriptor_size;
|
|
|
|
@@ -1266,10 +1277,14 @@ static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
|
|
dev_dbg(&dev->dev, "device initialised!\n");
|
|
|
|
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
|
|
- &dev->descriptor, sizeof(dev->descriptor));
|
|
- config = dev->actconfig;
|
|
+ &new_device_descriptor, sizeof(new_device_descriptor));
|
|
if (err < 0)
|
|
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
|
|
+ if (new_device_descriptor.bNumConfigurations > dev->descriptor.bNumConfigurations)
|
|
+ dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n",
|
|
+ new_device_descriptor.bNumConfigurations);
|
|
+ else
|
|
+ memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor));
|
|
|
|
err = usb_reset_configuration(dev);
|
|
if (err < 0)
|
|
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
|
|
index 709ccad972e2ff..612047ca5fe7ac 100644
|
|
--- a/sound/usb/usx2y/us122l.c
|
|
+++ b/sound/usb/usx2y/us122l.c
|
|
@@ -617,10 +617,7 @@ static void snd_us122l_disconnect(struct usb_interface *intf)
|
|
usb_put_intf(usb_ifnum_to_if(us122l->dev, 1));
|
|
usb_put_dev(us122l->dev);
|
|
|
|
- while (atomic_read(&us122l->mmap_count))
|
|
- msleep(500);
|
|
-
|
|
- snd_card_free(card);
|
|
+ snd_card_free_when_closed(card);
|
|
}
|
|
|
|
static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message)
|
|
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
|
|
index 52f4e6652407d5..4c4ce0319d624d 100644
|
|
--- a/sound/usb/usx2y/usbusx2y.c
|
|
+++ b/sound/usb/usx2y/usbusx2y.c
|
|
@@ -423,7 +423,7 @@ static void snd_usx2y_disconnect(struct usb_interface *intf)
|
|
}
|
|
if (usx2y->us428ctls_sharedmem)
|
|
wake_up(&usx2y->us428ctls_wait_queue_head);
|
|
- snd_card_free(card);
|
|
+ snd_card_free_when_closed(card);
|
|
}
|
|
|
|
static int snd_usx2y_probe(struct usb_interface *intf,
|
|
diff --git a/tools/bpf/bpftool/jit_disasm.c b/tools/bpf/bpftool/jit_disasm.c
|
|
index 7b8d9ec89ebd35..c032d2c6ab6d55 100644
|
|
--- a/tools/bpf/bpftool/jit_disasm.c
|
|
+++ b/tools/bpf/bpftool/jit_disasm.c
|
|
@@ -80,7 +80,8 @@ symbol_lookup_callback(__maybe_unused void *disasm_info,
|
|
static int
|
|
init_context(disasm_ctx_t *ctx, const char *arch,
|
|
__maybe_unused const char *disassembler_options,
|
|
- __maybe_unused unsigned char *image, __maybe_unused ssize_t len)
|
|
+ __maybe_unused unsigned char *image, __maybe_unused ssize_t len,
|
|
+ __maybe_unused __u64 func_ksym)
|
|
{
|
|
char *triple;
|
|
|
|
@@ -109,12 +110,13 @@ static void destroy_context(disasm_ctx_t *ctx)
|
|
}
|
|
|
|
static int
|
|
-disassemble_insn(disasm_ctx_t *ctx, unsigned char *image, ssize_t len, int pc)
|
|
+disassemble_insn(disasm_ctx_t *ctx, unsigned char *image, ssize_t len, int pc,
|
|
+ __u64 func_ksym)
|
|
{
|
|
char buf[256];
|
|
int count;
|
|
|
|
- count = LLVMDisasmInstruction(*ctx, image + pc, len - pc, pc,
|
|
+ count = LLVMDisasmInstruction(*ctx, image + pc, len - pc, func_ksym + pc,
|
|
buf, sizeof(buf));
|
|
if (json_output)
|
|
printf_json(buf);
|
|
@@ -136,8 +138,21 @@ int disasm_init(void)
|
|
#ifdef HAVE_LIBBFD_SUPPORT
|
|
#define DISASM_SPACER "\t"
|
|
|
|
+struct disasm_info {
|
|
+ struct disassemble_info info;
|
|
+ __u64 func_ksym;
|
|
+};
|
|
+
|
|
+static void disasm_print_addr(bfd_vma addr, struct disassemble_info *info)
|
|
+{
|
|
+ struct disasm_info *dinfo = container_of(info, struct disasm_info, info);
|
|
+
|
|
+ addr += dinfo->func_ksym;
|
|
+ generic_print_address(addr, info);
|
|
+}
|
|
+
|
|
typedef struct {
|
|
- struct disassemble_info *info;
|
|
+ struct disasm_info *info;
|
|
disassembler_ftype disassemble;
|
|
bfd *bfdf;
|
|
} disasm_ctx_t;
|
|
@@ -215,7 +230,7 @@ static int fprintf_json_styled(void *out,
|
|
|
|
static int init_context(disasm_ctx_t *ctx, const char *arch,
|
|
const char *disassembler_options,
|
|
- unsigned char *image, ssize_t len)
|
|
+ unsigned char *image, ssize_t len, __u64 func_ksym)
|
|
{
|
|
struct disassemble_info *info;
|
|
char tpath[PATH_MAX];
|
|
@@ -238,12 +253,13 @@ static int init_context(disasm_ctx_t *ctx, const char *arch,
|
|
}
|
|
bfdf = ctx->bfdf;
|
|
|
|
- ctx->info = malloc(sizeof(struct disassemble_info));
|
|
+ ctx->info = malloc(sizeof(struct disasm_info));
|
|
if (!ctx->info) {
|
|
p_err("mem alloc failed");
|
|
goto err_close;
|
|
}
|
|
- info = ctx->info;
|
|
+ ctx->info->func_ksym = func_ksym;
|
|
+ info = &ctx->info->info;
|
|
|
|
if (json_output)
|
|
init_disassemble_info_compat(info, stdout,
|
|
@@ -272,6 +288,7 @@ static int init_context(disasm_ctx_t *ctx, const char *arch,
|
|
info->disassembler_options = disassembler_options;
|
|
info->buffer = image;
|
|
info->buffer_length = len;
|
|
+ info->print_address_func = disasm_print_addr;
|
|
|
|
disassemble_init_for_target(info);
|
|
|
|
@@ -304,9 +321,10 @@ static void destroy_context(disasm_ctx_t *ctx)
|
|
|
|
static int
|
|
disassemble_insn(disasm_ctx_t *ctx, __maybe_unused unsigned char *image,
|
|
- __maybe_unused ssize_t len, int pc)
|
|
+ __maybe_unused ssize_t len, int pc,
|
|
+ __maybe_unused __u64 func_ksym)
|
|
{
|
|
- return ctx->disassemble(pc, ctx->info);
|
|
+ return ctx->disassemble(pc, &ctx->info->info);
|
|
}
|
|
|
|
int disasm_init(void)
|
|
@@ -331,7 +349,7 @@ int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
|
|
if (!len)
|
|
return -1;
|
|
|
|
- if (init_context(&ctx, arch, disassembler_options, image, len))
|
|
+ if (init_context(&ctx, arch, disassembler_options, image, len, func_ksym))
|
|
return -1;
|
|
|
|
if (json_output)
|
|
@@ -360,7 +378,7 @@ int disasm_print_insn(unsigned char *image, ssize_t len, int opcodes,
|
|
printf("%4x:" DISASM_SPACER, pc);
|
|
}
|
|
|
|
- count = disassemble_insn(&ctx, image, len, pc);
|
|
+ count = disassemble_insn(&ctx, image, len, pc, func_ksym);
|
|
|
|
if (json_output) {
|
|
/* Operand array, was started in fprintf_json. Before
|
|
diff --git a/tools/include/nolibc/arch-s390.h b/tools/include/nolibc/arch-s390.h
|
|
index 5d60fd43f88309..f72df614db3a24 100644
|
|
--- a/tools/include/nolibc/arch-s390.h
|
|
+++ b/tools/include/nolibc/arch-s390.h
|
|
@@ -10,6 +10,7 @@
|
|
|
|
#include "compiler.h"
|
|
#include "crt.h"
|
|
+#include "std.h"
|
|
|
|
/* Syscalls for s390:
|
|
* - registers are 64-bit
|
|
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
|
|
index ceed16a10285ab..2fad178949efe9 100644
|
|
--- a/tools/lib/bpf/libbpf.c
|
|
+++ b/tools/lib/bpf/libbpf.c
|
|
@@ -3586,7 +3586,7 @@ static bool sym_is_subprog(const Elf64_Sym *sym, int text_shndx)
|
|
return true;
|
|
|
|
/* global function */
|
|
- return bind == STB_GLOBAL && type == STT_FUNC;
|
|
+ return (bind == STB_GLOBAL || bind == STB_WEAK) && type == STT_FUNC;
|
|
}
|
|
|
|
static int find_extern_btf_id(const struct btf *btf, const char *ext_name)
|
|
@@ -3990,7 +3990,7 @@ static int bpf_object__collect_externs(struct bpf_object *obj)
|
|
|
|
static bool prog_is_subprog(const struct bpf_object *obj, const struct bpf_program *prog)
|
|
{
|
|
- return prog->sec_idx == obj->efile.text_shndx && obj->nr_programs > 1;
|
|
+ return prog->sec_idx == obj->efile.text_shndx;
|
|
}
|
|
|
|
struct bpf_program *
|
|
@@ -6837,8 +6837,14 @@ static int libbpf_prepare_prog_load(struct bpf_program *prog,
|
|
opts->prog_flags |= BPF_F_XDP_HAS_FRAGS;
|
|
|
|
/* special check for usdt to use uprobe_multi link */
|
|
- if ((def & SEC_USDT) && kernel_supports(prog->obj, FEAT_UPROBE_MULTI_LINK))
|
|
+ if ((def & SEC_USDT) && kernel_supports(prog->obj, FEAT_UPROBE_MULTI_LINK)) {
|
|
+ /* for BPF_TRACE_UPROBE_MULTI, user might want to query expected_attach_type
|
|
+ * in prog, and expected_attach_type we set in kernel is from opts, so we
|
|
+ * update both.
|
|
+ */
|
|
prog->expected_attach_type = BPF_TRACE_UPROBE_MULTI;
|
|
+ opts->expected_attach_type = BPF_TRACE_UPROBE_MULTI;
|
|
+ }
|
|
|
|
if ((def & SEC_ATTACH_BTF) && !prog->attach_btf_id) {
|
|
int btf_obj_fd = 0, btf_type_id = 0, err;
|
|
@@ -6915,6 +6921,7 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
|
|
load_attr.attach_btf_id = prog->attach_btf_id;
|
|
load_attr.kern_version = kern_version;
|
|
load_attr.prog_ifindex = prog->prog_ifindex;
|
|
+ load_attr.expected_attach_type = prog->expected_attach_type;
|
|
|
|
/* specify func_info/line_info only if kernel supports them */
|
|
btf_fd = bpf_object__btf_fd(obj);
|
|
@@ -6943,9 +6950,6 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
|
|
insns_cnt = prog->insns_cnt;
|
|
}
|
|
|
|
- /* allow prog_prepare_load_fn to change expected_attach_type */
|
|
- load_attr.expected_attach_type = prog->expected_attach_type;
|
|
-
|
|
if (obj->gen_loader) {
|
|
bpf_gen__prog_load(obj->gen_loader, prog->type, prog->name,
|
|
license, insns, insns_cnt, &load_attr,
|
|
diff --git a/tools/lib/bpf/linker.c b/tools/lib/bpf/linker.c
|
|
index b311bb91f672e5..88cc7236f12202 100644
|
|
--- a/tools/lib/bpf/linker.c
|
|
+++ b/tools/lib/bpf/linker.c
|
|
@@ -396,6 +396,8 @@ static int init_output_elf(struct bpf_linker *linker, const char *file)
|
|
pr_warn_elf("failed to create SYMTAB data");
|
|
return -EINVAL;
|
|
}
|
|
+ /* Ensure libelf translates byte-order of symbol records */
|
|
+ sec->data->d_type = ELF_T_SYM;
|
|
|
|
str_off = strset__add_str(linker->strtab_strs, sec->sec_name);
|
|
if (str_off < 0)
|
|
diff --git a/tools/lib/thermal/Makefile b/tools/lib/thermal/Makefile
|
|
index 2d0d255fd0e1c4..8890fd57b110cc 100644
|
|
--- a/tools/lib/thermal/Makefile
|
|
+++ b/tools/lib/thermal/Makefile
|
|
@@ -121,7 +121,9 @@ all: fixdep
|
|
|
|
clean:
|
|
$(call QUIET_CLEAN, libthermal) $(RM) $(LIBTHERMAL_A) \
|
|
- *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBTHERMAL_VERSION) .*.d .*.cmd LIBTHERMAL-CFLAGS $(LIBTHERMAL_PC)
|
|
+ *.o *~ *.a *.so *.so.$(VERSION) *.so.$(LIBTHERMAL_VERSION) \
|
|
+ .*.d .*.cmd LIBTHERMAL-CFLAGS $(LIBTHERMAL_PC) \
|
|
+ $(srctree)/tools/$(THERMAL_UAPI)
|
|
|
|
$(LIBTHERMAL_PC):
|
|
$(QUIET_GEN)sed -e "s|@PREFIX@|$(prefix)|" \
|
|
diff --git a/tools/lib/thermal/commands.c b/tools/lib/thermal/commands.c
|
|
index 73d4d4e8d6ec0b..27b4442f0e347a 100644
|
|
--- a/tools/lib/thermal/commands.c
|
|
+++ b/tools/lib/thermal/commands.c
|
|
@@ -261,9 +261,25 @@ static struct genl_ops thermal_cmd_ops = {
|
|
.o_ncmds = ARRAY_SIZE(thermal_cmds),
|
|
};
|
|
|
|
-static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int cmd,
|
|
- int flags, void *arg)
|
|
+struct cmd_param {
|
|
+ int tz_id;
|
|
+};
|
|
+
|
|
+typedef int (*cmd_cb_t)(struct nl_msg *, struct cmd_param *);
|
|
+
|
|
+static int thermal_genl_tz_id_encode(struct nl_msg *msg, struct cmd_param *p)
|
|
+{
|
|
+ if (p->tz_id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id))
|
|
+ return -1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static thermal_error_t thermal_genl_auto(struct thermal_handler *th, cmd_cb_t cmd_cb,
|
|
+ struct cmd_param *param,
|
|
+ int cmd, int flags, void *arg)
|
|
{
|
|
+ thermal_error_t ret = THERMAL_ERROR;
|
|
struct nl_msg *msg;
|
|
void *hdr;
|
|
|
|
@@ -274,45 +290,55 @@ static thermal_error_t thermal_genl_auto(struct thermal_handler *th, int id, int
|
|
hdr = genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, thermal_cmd_ops.o_id,
|
|
0, flags, cmd, THERMAL_GENL_VERSION);
|
|
if (!hdr)
|
|
- return THERMAL_ERROR;
|
|
+ goto out;
|
|
|
|
- if (id >= 0 && nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id))
|
|
- return THERMAL_ERROR;
|
|
+ if (cmd_cb && cmd_cb(msg, param))
|
|
+ goto out;
|
|
|
|
if (nl_send_msg(th->sk_cmd, th->cb_cmd, msg, genl_handle_msg, arg))
|
|
- return THERMAL_ERROR;
|
|
+ goto out;
|
|
|
|
+ ret = THERMAL_SUCCESS;
|
|
+out:
|
|
nlmsg_free(msg);
|
|
|
|
- return THERMAL_SUCCESS;
|
|
+ return ret;
|
|
}
|
|
|
|
thermal_error_t thermal_cmd_get_tz(struct thermal_handler *th, struct thermal_zone **tz)
|
|
{
|
|
- return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_TZ_GET_ID,
|
|
+ return thermal_genl_auto(th, NULL, NULL, THERMAL_GENL_CMD_TZ_GET_ID,
|
|
NLM_F_DUMP | NLM_F_ACK, tz);
|
|
}
|
|
|
|
thermal_error_t thermal_cmd_get_cdev(struct thermal_handler *th, struct thermal_cdev **tc)
|
|
{
|
|
- return thermal_genl_auto(th, -1, THERMAL_GENL_CMD_CDEV_GET,
|
|
+ return thermal_genl_auto(th, NULL, NULL, THERMAL_GENL_CMD_CDEV_GET,
|
|
NLM_F_DUMP | NLM_F_ACK, tc);
|
|
}
|
|
|
|
thermal_error_t thermal_cmd_get_trip(struct thermal_handler *th, struct thermal_zone *tz)
|
|
{
|
|
- return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TRIP,
|
|
- 0, tz);
|
|
+ struct cmd_param p = { .tz_id = tz->id };
|
|
+
|
|
+ return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p,
|
|
+ THERMAL_GENL_CMD_TZ_GET_TRIP, 0, tz);
|
|
}
|
|
|
|
thermal_error_t thermal_cmd_get_governor(struct thermal_handler *th, struct thermal_zone *tz)
|
|
{
|
|
- return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz);
|
|
+ struct cmd_param p = { .tz_id = tz->id };
|
|
+
|
|
+ return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p,
|
|
+ THERMAL_GENL_CMD_TZ_GET_GOV, 0, tz);
|
|
}
|
|
|
|
thermal_error_t thermal_cmd_get_temp(struct thermal_handler *th, struct thermal_zone *tz)
|
|
{
|
|
- return thermal_genl_auto(th, tz->id, THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz);
|
|
+ struct cmd_param p = { .tz_id = tz->id };
|
|
+
|
|
+ return thermal_genl_auto(th, thermal_genl_tz_id_encode, &p,
|
|
+ THERMAL_GENL_CMD_TZ_GET_TEMP, 0, tz);
|
|
}
|
|
|
|
thermal_error_t thermal_cmd_exit(struct thermal_handler *th)
|
|
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
|
|
index ac2e6c75f91201..a1971703e49cb8 100644
|
|
--- a/tools/perf/builtin-ftrace.c
|
|
+++ b/tools/perf/builtin-ftrace.c
|
|
@@ -771,7 +771,7 @@ static void display_histogram(int buckets[], bool use_nsec)
|
|
|
|
bar_len = buckets[0] * bar_total / total;
|
|
printf(" %4d - %-4d %s | %10d | %.*s%*s |\n",
|
|
- 0, 1, "us", buckets[0], bar_len, bar, bar_total - bar_len, "");
|
|
+ 0, 1, use_nsec ? "ns" : "us", buckets[0], bar_len, bar, bar_total - bar_len, "");
|
|
|
|
for (i = 1; i < NUM_BUCKET - 1; i++) {
|
|
int start = (1 << (i - 1));
|
|
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
|
|
index 61c2c96cc0701b..c8c72fcf37e116 100644
|
|
--- a/tools/perf/builtin-list.c
|
|
+++ b/tools/perf/builtin-list.c
|
|
@@ -95,7 +95,7 @@ static void wordwrap(const char *s, int start, int max, int corr)
|
|
}
|
|
}
|
|
|
|
-static void default_print_event(void *ps, const char *pmu_name, const char *topic,
|
|
+static void default_print_event(void *ps, const char *topic, const char *pmu_name,
|
|
const char *event_name, const char *event_alias,
|
|
const char *scale_unit __maybe_unused,
|
|
bool deprecated, const char *event_type_desc,
|
|
@@ -321,7 +321,7 @@ static void fix_escape_printf(struct strbuf *buf, const char *fmt, ...)
|
|
fputs(buf->buf, stdout);
|
|
}
|
|
|
|
-static void json_print_event(void *ps, const char *pmu_name, const char *topic,
|
|
+static void json_print_event(void *ps, const char *topic, const char *pmu_name,
|
|
const char *event_name, const char *event_alias,
|
|
const char *scale_unit,
|
|
bool deprecated, const char *event_type_desc,
|
|
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
|
|
index 78c10492218102..9692ebdd7f11e9 100644
|
|
--- a/tools/perf/builtin-stat.c
|
|
+++ b/tools/perf/builtin-stat.c
|
|
@@ -712,15 +712,19 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
}
|
|
|
|
if (!cpu_map__is_dummy(evsel_list->core.user_requested_cpus)) {
|
|
- if (affinity__setup(&saved_affinity) < 0)
|
|
- return -1;
|
|
+ if (affinity__setup(&saved_affinity) < 0) {
|
|
+ err = -1;
|
|
+ goto err_out;
|
|
+ }
|
|
affinity = &saved_affinity;
|
|
}
|
|
|
|
evlist__for_each_entry(evsel_list, counter) {
|
|
counter->reset_group = false;
|
|
- if (bpf_counter__load(counter, &target))
|
|
- return -1;
|
|
+ if (bpf_counter__load(counter, &target)) {
|
|
+ err = -1;
|
|
+ goto err_out;
|
|
+ }
|
|
if (!(evsel__is_bperf(counter)))
|
|
all_counters_use_bpf = false;
|
|
}
|
|
@@ -763,7 +767,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
|
|
switch (stat_handle_error(counter)) {
|
|
case COUNTER_FATAL:
|
|
- return -1;
|
|
+ err = -1;
|
|
+ goto err_out;
|
|
case COUNTER_RETRY:
|
|
goto try_again;
|
|
case COUNTER_SKIP:
|
|
@@ -804,7 +809,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
|
|
switch (stat_handle_error(counter)) {
|
|
case COUNTER_FATAL:
|
|
- return -1;
|
|
+ err = -1;
|
|
+ goto err_out;
|
|
case COUNTER_RETRY:
|
|
goto try_again_reset;
|
|
case COUNTER_SKIP:
|
|
@@ -817,6 +823,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
}
|
|
}
|
|
affinity__cleanup(affinity);
|
|
+ affinity = NULL;
|
|
|
|
evlist__for_each_entry(evsel_list, counter) {
|
|
if (!counter->supported) {
|
|
@@ -829,8 +836,10 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
stat_config.unit_width = l;
|
|
|
|
if (evsel__should_store_id(counter) &&
|
|
- evsel__store_ids(counter, evsel_list))
|
|
- return -1;
|
|
+ evsel__store_ids(counter, evsel_list)) {
|
|
+ err = -1;
|
|
+ goto err_out;
|
|
+ }
|
|
}
|
|
|
|
if (evlist__apply_filters(evsel_list, &counter)) {
|
|
@@ -851,20 +860,23 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
}
|
|
|
|
if (err < 0)
|
|
- return err;
|
|
+ goto err_out;
|
|
|
|
err = perf_event__synthesize_stat_events(&stat_config, NULL, evsel_list,
|
|
process_synthesized_event, is_pipe);
|
|
if (err < 0)
|
|
- return err;
|
|
+ goto err_out;
|
|
+
|
|
}
|
|
|
|
if (target.initial_delay) {
|
|
pr_info(EVLIST_DISABLED_MSG);
|
|
} else {
|
|
err = enable_counters();
|
|
- if (err)
|
|
- return -1;
|
|
+ if (err) {
|
|
+ err = -1;
|
|
+ goto err_out;
|
|
+ }
|
|
}
|
|
|
|
/* Exec the command, if any */
|
|
@@ -874,8 +886,10 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
if (target.initial_delay > 0) {
|
|
usleep(target.initial_delay * USEC_PER_MSEC);
|
|
err = enable_counters();
|
|
- if (err)
|
|
- return -1;
|
|
+ if (err) {
|
|
+ err = -1;
|
|
+ goto err_out;
|
|
+ }
|
|
|
|
pr_info(EVLIST_ENABLED_MSG);
|
|
}
|
|
@@ -895,7 +909,8 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
if (workload_exec_errno) {
|
|
const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
|
|
pr_err("Workload failed: %s\n", emsg);
|
|
- return -1;
|
|
+ err = -1;
|
|
+ goto err_out;
|
|
}
|
|
|
|
if (WIFSIGNALED(status))
|
|
@@ -942,6 +957,13 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
|
|
evlist__close(evsel_list);
|
|
|
|
return WEXITSTATUS(status);
|
|
+
|
|
+err_out:
|
|
+ if (forks)
|
|
+ evlist__cancel_workload(evsel_list);
|
|
+
|
|
+ affinity__cleanup(affinity);
|
|
+ return err;
|
|
}
|
|
|
|
static int run_perf_stat(int argc, const char **argv, int run_idx)
|
|
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
|
|
index e541d0e2777ab9..3ecd6868be2d6d 100644
|
|
--- a/tools/perf/builtin-trace.c
|
|
+++ b/tools/perf/builtin-trace.c
|
|
@@ -2414,6 +2414,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
|
|
char msg[1024];
|
|
void *args, *augmented_args = NULL;
|
|
int augmented_args_size;
|
|
+ size_t printed = 0;
|
|
|
|
if (sc == NULL)
|
|
return -1;
|
|
@@ -2429,8 +2430,8 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
|
|
|
|
args = perf_evsel__sc_tp_ptr(evsel, args, sample);
|
|
augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size);
|
|
- syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread);
|
|
- fprintf(trace->output, "%s", msg);
|
|
+ printed += syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread);
|
|
+ fprintf(trace->output, "%.*s", (int)printed, msg);
|
|
err = 0;
|
|
out_put:
|
|
thread__put(thread);
|
|
@@ -2803,7 +2804,7 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel,
|
|
printed += syscall_arg_fmt__scnprintf_val(arg, bf + printed, size - printed, &syscall_arg, val);
|
|
}
|
|
|
|
- return printed + fprintf(trace->output, "%s", bf);
|
|
+ return printed + fprintf(trace->output, "%.*s", (int)printed, bf);
|
|
}
|
|
|
|
static int trace__event_handler(struct trace *trace, struct evsel *evsel,
|
|
@@ -2812,13 +2813,8 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
|
|
{
|
|
struct thread *thread;
|
|
int callchain_ret = 0;
|
|
- /*
|
|
- * Check if we called perf_evsel__disable(evsel) due to, for instance,
|
|
- * this event's max_events having been hit and this is an entry coming
|
|
- * from the ring buffer that we should discard, since the max events
|
|
- * have already been considered/printed.
|
|
- */
|
|
- if (evsel->disabled)
|
|
+
|
|
+ if (evsel->nr_events_printed >= evsel->max_events)
|
|
return 0;
|
|
|
|
thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
|
|
@@ -3923,6 +3919,9 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
|
|
sizeof(__u32), BPF_ANY);
|
|
}
|
|
}
|
|
+
|
|
+ if (trace->skel)
|
|
+ trace->filter_pids.map = trace->skel->maps.pids_filtered;
|
|
#endif
|
|
err = trace__set_filter_pids(trace);
|
|
if (err < 0)
|
|
@@ -5031,6 +5030,10 @@ int cmd_trace(int argc, const char **argv)
|
|
if (trace.summary_only)
|
|
trace.summary = trace.summary_only;
|
|
|
|
+ /* Keep exited threads, otherwise information might be lost for summary */
|
|
+ if (trace.summary)
|
|
+ symbol_conf.keep_exited_threads = true;
|
|
+
|
|
if (output_name != NULL) {
|
|
err = trace__open_output(&trace, output_name);
|
|
if (err < 0) {
|
|
diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default
|
|
index a1e2da0a9a6ddb..e47fb49446799b 100644
|
|
--- a/tools/perf/tests/attr/test-stat-default
|
|
+++ b/tools/perf/tests/attr/test-stat-default
|
|
@@ -88,98 +88,142 @@ enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
|
|
+# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
|
|
[event13:base-stat]
|
|
fd=13
|
|
group_fd=11
|
|
type=4
|
|
-config=33280
|
|
+config=33024
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-be-bound (0x8300)
|
|
+# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
|
|
[event14:base-stat]
|
|
fd=14
|
|
group_fd=11
|
|
type=4
|
|
-config=33536
|
|
+config=33280
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
|
|
+# PERF_TYPE_RAW / topdown-be-bound (0x8300)
|
|
[event15:base-stat]
|
|
fd=15
|
|
group_fd=11
|
|
type=4
|
|
-config=33024
|
|
+config=33536
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
|
|
+# PERF_TYPE_RAW / topdown-heavy-ops (0x8400)
|
|
[event16:base-stat]
|
|
fd=16
|
|
+group_fd=11
|
|
type=4
|
|
-config=4109
|
|
+config=33792
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
|
|
+# PERF_TYPE_RAW / topdown-br-mispredict (0x8500)
|
|
[event17:base-stat]
|
|
fd=17
|
|
+group_fd=11
|
|
type=4
|
|
-config=17039629
|
|
+config=34048
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
|
|
+# PERF_TYPE_RAW / topdown-fetch-lat (0x8600)
|
|
[event18:base-stat]
|
|
fd=18
|
|
+group_fd=11
|
|
type=4
|
|
-config=60
|
|
+config=34304
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
|
|
+# PERF_TYPE_RAW / topdown-mem-bound (0x8700)
|
|
[event19:base-stat]
|
|
fd=19
|
|
+group_fd=11
|
|
type=4
|
|
-config=2097421
|
|
+config=34560
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
|
|
+# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
|
|
[event20:base-stat]
|
|
fd=20
|
|
type=4
|
|
-config=316
|
|
+config=4109
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
|
|
+# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
|
|
[event21:base-stat]
|
|
fd=21
|
|
type=4
|
|
-config=412
|
|
+config=17039629
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
|
|
[event22:base-stat]
|
|
fd=22
|
|
type=4
|
|
-config=572
|
|
+config=60
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
|
|
+# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
|
|
[event23:base-stat]
|
|
fd=23
|
|
type=4
|
|
-config=706
|
|
+config=2097421
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / UOPS_ISSUED.ANY
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
|
|
[event24:base-stat]
|
|
fd=24
|
|
type=4
|
|
+config=316
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
|
|
+[event25:base-stat]
|
|
+fd=25
|
|
+type=4
|
|
+config=412
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
|
|
+[event26:base-stat]
|
|
+fd=26
|
|
+type=4
|
|
+config=572
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
|
|
+[event27:base-stat]
|
|
+fd=27
|
|
+type=4
|
|
+config=706
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / UOPS_ISSUED.ANY
|
|
+[event28:base-stat]
|
|
+fd=28
|
|
+type=4
|
|
config=270
|
|
optional=1
|
|
diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1
|
|
index 1c52cb05c900d7..3d500d3e0c5c8a 100644
|
|
--- a/tools/perf/tests/attr/test-stat-detailed-1
|
|
+++ b/tools/perf/tests/attr/test-stat-detailed-1
|
|
@@ -90,99 +90,143 @@ enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
|
|
+# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
|
|
[event13:base-stat]
|
|
fd=13
|
|
group_fd=11
|
|
type=4
|
|
-config=33280
|
|
+config=33024
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-be-bound (0x8300)
|
|
+# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
|
|
[event14:base-stat]
|
|
fd=14
|
|
group_fd=11
|
|
type=4
|
|
-config=33536
|
|
+config=33280
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
|
|
+# PERF_TYPE_RAW / topdown-be-bound (0x8300)
|
|
[event15:base-stat]
|
|
fd=15
|
|
group_fd=11
|
|
type=4
|
|
-config=33024
|
|
+config=33536
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
|
|
+# PERF_TYPE_RAW / topdown-heavy-ops (0x8400)
|
|
[event16:base-stat]
|
|
fd=16
|
|
+group_fd=11
|
|
type=4
|
|
-config=4109
|
|
+config=33792
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
|
|
+# PERF_TYPE_RAW / topdown-br-mispredict (0x8500)
|
|
[event17:base-stat]
|
|
fd=17
|
|
+group_fd=11
|
|
type=4
|
|
-config=17039629
|
|
+config=34048
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
|
|
+# PERF_TYPE_RAW / topdown-fetch-lat (0x8600)
|
|
[event18:base-stat]
|
|
fd=18
|
|
+group_fd=11
|
|
type=4
|
|
-config=60
|
|
+config=34304
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
|
|
+# PERF_TYPE_RAW / topdown-mem-bound (0x8700)
|
|
[event19:base-stat]
|
|
fd=19
|
|
+group_fd=11
|
|
type=4
|
|
-config=2097421
|
|
+config=34560
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
|
|
+# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
|
|
[event20:base-stat]
|
|
fd=20
|
|
type=4
|
|
-config=316
|
|
+config=4109
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
|
|
+# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
|
|
[event21:base-stat]
|
|
fd=21
|
|
type=4
|
|
-config=412
|
|
+config=17039629
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
|
|
[event22:base-stat]
|
|
fd=22
|
|
type=4
|
|
-config=572
|
|
+config=60
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
|
|
+# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
|
|
[event23:base-stat]
|
|
fd=23
|
|
type=4
|
|
-config=706
|
|
+config=2097421
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / UOPS_ISSUED.ANY
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
|
|
[event24:base-stat]
|
|
fd=24
|
|
type=4
|
|
+config=316
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
|
|
+[event25:base-stat]
|
|
+fd=25
|
|
+type=4
|
|
+config=412
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
|
|
+[event26:base-stat]
|
|
+fd=26
|
|
+type=4
|
|
+config=572
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
|
|
+[event27:base-stat]
|
|
+fd=27
|
|
+type=4
|
|
+config=706
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / UOPS_ISSUED.ANY
|
|
+[event28:base-stat]
|
|
+fd=28
|
|
+type=4
|
|
config=270
|
|
optional=1
|
|
|
|
@@ -190,8 +234,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1D << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event25:base-stat]
|
|
-fd=25
|
|
+[event29:base-stat]
|
|
+fd=29
|
|
type=3
|
|
config=0
|
|
optional=1
|
|
@@ -200,8 +244,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1D << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event26:base-stat]
|
|
-fd=26
|
|
+[event30:base-stat]
|
|
+fd=30
|
|
type=3
|
|
config=65536
|
|
optional=1
|
|
@@ -210,8 +254,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_LL << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event27:base-stat]
|
|
-fd=27
|
|
+[event31:base-stat]
|
|
+fd=31
|
|
type=3
|
|
config=2
|
|
optional=1
|
|
@@ -220,8 +264,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_LL << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event28:base-stat]
|
|
-fd=28
|
|
+[event32:base-stat]
|
|
+fd=32
|
|
type=3
|
|
config=65538
|
|
optional=1
|
|
diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2
|
|
index 7e961d24a885a7..01777a63752fe6 100644
|
|
--- a/tools/perf/tests/attr/test-stat-detailed-2
|
|
+++ b/tools/perf/tests/attr/test-stat-detailed-2
|
|
@@ -90,99 +90,143 @@ enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
|
|
+# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
|
|
[event13:base-stat]
|
|
fd=13
|
|
group_fd=11
|
|
type=4
|
|
-config=33280
|
|
+config=33024
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-be-bound (0x8300)
|
|
+# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
|
|
[event14:base-stat]
|
|
fd=14
|
|
group_fd=11
|
|
type=4
|
|
-config=33536
|
|
+config=33280
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
|
|
+# PERF_TYPE_RAW / topdown-be-bound (0x8300)
|
|
[event15:base-stat]
|
|
fd=15
|
|
group_fd=11
|
|
type=4
|
|
-config=33024
|
|
+config=33536
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
|
|
+# PERF_TYPE_RAW / topdown-heavy-ops (0x8400)
|
|
[event16:base-stat]
|
|
fd=16
|
|
+group_fd=11
|
|
type=4
|
|
-config=4109
|
|
+config=33792
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
|
|
+# PERF_TYPE_RAW / topdown-br-mispredict (0x8500)
|
|
[event17:base-stat]
|
|
fd=17
|
|
+group_fd=11
|
|
type=4
|
|
-config=17039629
|
|
+config=34048
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
|
|
+# PERF_TYPE_RAW / topdown-fetch-lat (0x8600)
|
|
[event18:base-stat]
|
|
fd=18
|
|
+group_fd=11
|
|
type=4
|
|
-config=60
|
|
+config=34304
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
|
|
+# PERF_TYPE_RAW / topdown-mem-bound (0x8700)
|
|
[event19:base-stat]
|
|
fd=19
|
|
+group_fd=11
|
|
type=4
|
|
-config=2097421
|
|
+config=34560
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
|
|
+# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
|
|
[event20:base-stat]
|
|
fd=20
|
|
type=4
|
|
-config=316
|
|
+config=4109
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
|
|
+# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
|
|
[event21:base-stat]
|
|
fd=21
|
|
type=4
|
|
-config=412
|
|
+config=17039629
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
|
|
[event22:base-stat]
|
|
fd=22
|
|
type=4
|
|
-config=572
|
|
+config=60
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
|
|
+# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
|
|
[event23:base-stat]
|
|
fd=23
|
|
type=4
|
|
-config=706
|
|
+config=2097421
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / UOPS_ISSUED.ANY
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
|
|
[event24:base-stat]
|
|
fd=24
|
|
type=4
|
|
+config=316
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
|
|
+[event25:base-stat]
|
|
+fd=25
|
|
+type=4
|
|
+config=412
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
|
|
+[event26:base-stat]
|
|
+fd=26
|
|
+type=4
|
|
+config=572
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
|
|
+[event27:base-stat]
|
|
+fd=27
|
|
+type=4
|
|
+config=706
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / UOPS_ISSUED.ANY
|
|
+[event28:base-stat]
|
|
+fd=28
|
|
+type=4
|
|
config=270
|
|
optional=1
|
|
|
|
@@ -190,8 +234,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1D << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event25:base-stat]
|
|
-fd=25
|
|
+[event29:base-stat]
|
|
+fd=29
|
|
type=3
|
|
config=0
|
|
optional=1
|
|
@@ -200,8 +244,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1D << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event26:base-stat]
|
|
-fd=26
|
|
+[event30:base-stat]
|
|
+fd=30
|
|
type=3
|
|
config=65536
|
|
optional=1
|
|
@@ -210,8 +254,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_LL << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event27:base-stat]
|
|
-fd=27
|
|
+[event31:base-stat]
|
|
+fd=31
|
|
type=3
|
|
config=2
|
|
optional=1
|
|
@@ -220,8 +264,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_LL << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event28:base-stat]
|
|
-fd=28
|
|
+[event32:base-stat]
|
|
+fd=32
|
|
type=3
|
|
config=65538
|
|
optional=1
|
|
@@ -230,8 +274,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1I << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event29:base-stat]
|
|
-fd=29
|
|
+[event33:base-stat]
|
|
+fd=33
|
|
type=3
|
|
config=1
|
|
optional=1
|
|
@@ -240,8 +284,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1I << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event30:base-stat]
|
|
-fd=30
|
|
+[event34:base-stat]
|
|
+fd=34
|
|
type=3
|
|
config=65537
|
|
optional=1
|
|
@@ -250,8 +294,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_DTLB << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event31:base-stat]
|
|
-fd=31
|
|
+[event35:base-stat]
|
|
+fd=35
|
|
type=3
|
|
config=3
|
|
optional=1
|
|
@@ -260,8 +304,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_DTLB << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event32:base-stat]
|
|
-fd=32
|
|
+[event36:base-stat]
|
|
+fd=36
|
|
type=3
|
|
config=65539
|
|
optional=1
|
|
@@ -270,8 +314,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_ITLB << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event33:base-stat]
|
|
-fd=33
|
|
+[event37:base-stat]
|
|
+fd=37
|
|
type=3
|
|
config=4
|
|
optional=1
|
|
@@ -280,8 +324,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_ITLB << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event34:base-stat]
|
|
-fd=34
|
|
+[event38:base-stat]
|
|
+fd=38
|
|
type=3
|
|
config=65540
|
|
optional=1
|
|
diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3
|
|
index e50535f45977c6..8400abd7e1e488 100644
|
|
--- a/tools/perf/tests/attr/test-stat-detailed-3
|
|
+++ b/tools/perf/tests/attr/test-stat-detailed-3
|
|
@@ -90,99 +90,143 @@ enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
|
|
+# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
|
|
[event13:base-stat]
|
|
fd=13
|
|
group_fd=11
|
|
type=4
|
|
-config=33280
|
|
+config=33024
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-be-bound (0x8300)
|
|
+# PERF_TYPE_RAW / topdown-fe-bound (0x8200)
|
|
[event14:base-stat]
|
|
fd=14
|
|
group_fd=11
|
|
type=4
|
|
-config=33536
|
|
+config=33280
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / topdown-bad-spec (0x8100)
|
|
+# PERF_TYPE_RAW / topdown-be-bound (0x8300)
|
|
[event15:base-stat]
|
|
fd=15
|
|
group_fd=11
|
|
type=4
|
|
-config=33024
|
|
+config=33536
|
|
disabled=0
|
|
enable_on_exec=0
|
|
read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
|
|
+# PERF_TYPE_RAW / topdown-heavy-ops (0x8400)
|
|
[event16:base-stat]
|
|
fd=16
|
|
+group_fd=11
|
|
type=4
|
|
-config=4109
|
|
+config=33792
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
|
|
+# PERF_TYPE_RAW / topdown-br-mispredict (0x8500)
|
|
[event17:base-stat]
|
|
fd=17
|
|
+group_fd=11
|
|
type=4
|
|
-config=17039629
|
|
+config=34048
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
|
|
+# PERF_TYPE_RAW / topdown-fetch-lat (0x8600)
|
|
[event18:base-stat]
|
|
fd=18
|
|
+group_fd=11
|
|
type=4
|
|
-config=60
|
|
+config=34304
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
|
|
+# PERF_TYPE_RAW / topdown-mem-bound (0x8700)
|
|
[event19:base-stat]
|
|
fd=19
|
|
+group_fd=11
|
|
type=4
|
|
-config=2097421
|
|
+config=34560
|
|
+disabled=0
|
|
+enable_on_exec=0
|
|
+read_format=15
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
|
|
+# PERF_TYPE_RAW / INT_MISC.UOP_DROPPING
|
|
[event20:base-stat]
|
|
fd=20
|
|
type=4
|
|
-config=316
|
|
+config=4109
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
|
|
+# PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/
|
|
[event21:base-stat]
|
|
fd=21
|
|
type=4
|
|
-config=412
|
|
+config=17039629
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD
|
|
[event22:base-stat]
|
|
fd=22
|
|
type=4
|
|
-config=572
|
|
+config=60
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
|
|
+# PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY
|
|
[event23:base-stat]
|
|
fd=23
|
|
type=4
|
|
-config=706
|
|
+config=2097421
|
|
optional=1
|
|
|
|
-# PERF_TYPE_RAW / UOPS_ISSUED.ANY
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK
|
|
[event24:base-stat]
|
|
fd=24
|
|
type=4
|
|
+config=316
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE
|
|
+[event25:base-stat]
|
|
+fd=25
|
|
+type=4
|
|
+config=412
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE
|
|
+[event26:base-stat]
|
|
+fd=26
|
|
+type=4
|
|
+config=572
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS
|
|
+[event27:base-stat]
|
|
+fd=27
|
|
+type=4
|
|
+config=706
|
|
+optional=1
|
|
+
|
|
+# PERF_TYPE_RAW / UOPS_ISSUED.ANY
|
|
+[event28:base-stat]
|
|
+fd=28
|
|
+type=4
|
|
config=270
|
|
optional=1
|
|
|
|
@@ -190,8 +234,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1D << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event25:base-stat]
|
|
-fd=25
|
|
+[event29:base-stat]
|
|
+fd=29
|
|
type=3
|
|
config=0
|
|
optional=1
|
|
@@ -200,8 +244,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1D << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event26:base-stat]
|
|
-fd=26
|
|
+[event30:base-stat]
|
|
+fd=30
|
|
type=3
|
|
config=65536
|
|
optional=1
|
|
@@ -210,8 +254,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_LL << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event27:base-stat]
|
|
-fd=27
|
|
+[event31:base-stat]
|
|
+fd=31
|
|
type=3
|
|
config=2
|
|
optional=1
|
|
@@ -220,8 +264,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_LL << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event28:base-stat]
|
|
-fd=28
|
|
+[event32:base-stat]
|
|
+fd=32
|
|
type=3
|
|
config=65538
|
|
optional=1
|
|
@@ -230,8 +274,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1I << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event29:base-stat]
|
|
-fd=29
|
|
+[event33:base-stat]
|
|
+fd=33
|
|
type=3
|
|
config=1
|
|
optional=1
|
|
@@ -240,8 +284,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1I << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event30:base-stat]
|
|
-fd=30
|
|
+[event34:base-stat]
|
|
+fd=34
|
|
type=3
|
|
config=65537
|
|
optional=1
|
|
@@ -250,8 +294,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_DTLB << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event31:base-stat]
|
|
-fd=31
|
|
+[event35:base-stat]
|
|
+fd=35
|
|
type=3
|
|
config=3
|
|
optional=1
|
|
@@ -260,8 +304,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_DTLB << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event32:base-stat]
|
|
-fd=32
|
|
+[event36:base-stat]
|
|
+fd=36
|
|
type=3
|
|
config=65539
|
|
optional=1
|
|
@@ -270,8 +314,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_ITLB << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event33:base-stat]
|
|
-fd=33
|
|
+[event37:base-stat]
|
|
+fd=37
|
|
type=3
|
|
config=4
|
|
optional=1
|
|
@@ -280,8 +324,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_ITLB << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event34:base-stat]
|
|
-fd=34
|
|
+[event38:base-stat]
|
|
+fd=38
|
|
type=3
|
|
config=65540
|
|
optional=1
|
|
@@ -290,8 +334,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1D << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
|
|
-[event35:base-stat]
|
|
-fd=35
|
|
+[event39:base-stat]
|
|
+fd=39
|
|
type=3
|
|
config=512
|
|
optional=1
|
|
@@ -300,8 +344,8 @@ optional=1
|
|
# PERF_COUNT_HW_CACHE_L1D << 0 |
|
|
# (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
|
|
# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
|
|
-[event36:base-stat]
|
|
-fd=36
|
|
+[event40:base-stat]
|
|
+fd=40
|
|
type=3
|
|
config=66048
|
|
optional=1
|
|
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
|
|
index 9729d006550d98..799c104901b4ff 100644
|
|
--- a/tools/perf/util/cs-etm.c
|
|
+++ b/tools/perf/util/cs-etm.c
|
|
@@ -2412,12 +2412,6 @@ static void cs_etm__clear_all_traceid_queues(struct cs_etm_queue *etmq)
|
|
|
|
/* Ignore return value */
|
|
cs_etm__process_traceid_queue(etmq, tidq);
|
|
-
|
|
- /*
|
|
- * Generate an instruction sample with the remaining
|
|
- * branchstack entries.
|
|
- */
|
|
- cs_etm__flush(etmq, tidq);
|
|
}
|
|
}
|
|
|
|
@@ -2560,7 +2554,7 @@ static int cs_etm__process_timestamped_queues(struct cs_etm_auxtrace *etm)
|
|
|
|
while (1) {
|
|
if (!etm->heap.heap_cnt)
|
|
- goto out;
|
|
+ break;
|
|
|
|
/* Take the entry at the top of the min heap */
|
|
cs_queue_nr = etm->heap.heap_array[0].queue_nr;
|
|
@@ -2643,6 +2637,23 @@ static int cs_etm__process_timestamped_queues(struct cs_etm_auxtrace *etm)
|
|
ret = auxtrace_heap__add(&etm->heap, cs_queue_nr, cs_timestamp);
|
|
}
|
|
|
|
+ for (i = 0; i < etm->queues.nr_queues; i++) {
|
|
+ struct int_node *inode;
|
|
+
|
|
+ etmq = etm->queues.queue_array[i].priv;
|
|
+ if (!etmq)
|
|
+ continue;
|
|
+
|
|
+ intlist__for_each_entry(inode, etmq->traceid_queues_list) {
|
|
+ int idx = (int)(intptr_t)inode->priv;
|
|
+
|
|
+ /* Flush any remaining branch stack entries */
|
|
+ tidq = etmq->traceid_queues[idx];
|
|
+ ret = cs_etm__end_block(etmq, tidq);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
out:
|
|
return ret;
|
|
}
|
|
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
|
|
index eb1dd29c538d5c..1eadb4f7c1b9dc 100644
|
|
--- a/tools/perf/util/evlist.c
|
|
+++ b/tools/perf/util/evlist.c
|
|
@@ -46,6 +46,7 @@
|
|
#include <sys/mman.h>
|
|
#include <sys/prctl.h>
|
|
#include <sys/timerfd.h>
|
|
+#include <sys/wait.h>
|
|
|
|
#include <linux/bitops.h>
|
|
#include <linux/hash.h>
|
|
@@ -1412,6 +1413,8 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, const
|
|
int child_ready_pipe[2], go_pipe[2];
|
|
char bf;
|
|
|
|
+ evlist->workload.cork_fd = -1;
|
|
+
|
|
if (pipe(child_ready_pipe) < 0) {
|
|
perror("failed to create 'ready' pipe");
|
|
return -1;
|
|
@@ -1464,7 +1467,7 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, const
|
|
* For cancelling the workload without actually running it,
|
|
* the parent will just close workload.cork_fd, without writing
|
|
* anything, i.e. read will return zero and we just exit()
|
|
- * here.
|
|
+ * here (See evlist__cancel_workload()).
|
|
*/
|
|
if (ret != 1) {
|
|
if (ret == -1)
|
|
@@ -1528,7 +1531,7 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, const
|
|
|
|
int evlist__start_workload(struct evlist *evlist)
|
|
{
|
|
- if (evlist->workload.cork_fd > 0) {
|
|
+ if (evlist->workload.cork_fd >= 0) {
|
|
char bf = 0;
|
|
int ret;
|
|
/*
|
|
@@ -1539,12 +1542,24 @@ int evlist__start_workload(struct evlist *evlist)
|
|
perror("unable to write to pipe");
|
|
|
|
close(evlist->workload.cork_fd);
|
|
+ evlist->workload.cork_fd = -1;
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
+void evlist__cancel_workload(struct evlist *evlist)
|
|
+{
|
|
+ int status;
|
|
+
|
|
+ if (evlist->workload.cork_fd >= 0) {
|
|
+ close(evlist->workload.cork_fd);
|
|
+ evlist->workload.cork_fd = -1;
|
|
+ waitpid(evlist->workload.pid, &status, WNOHANG);
|
|
+ }
|
|
+}
|
|
+
|
|
int evlist__parse_sample(struct evlist *evlist, union perf_event *event, struct perf_sample *sample)
|
|
{
|
|
struct evsel *evsel = evlist__event2evsel(evlist, event);
|
|
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
|
|
index cb91dc9117a272..12f929ffdf920d 100644
|
|
--- a/tools/perf/util/evlist.h
|
|
+++ b/tools/perf/util/evlist.h
|
|
@@ -184,6 +184,7 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target,
|
|
const char *argv[], bool pipe_output,
|
|
void (*exec_error)(int signo, siginfo_t *info, void *ucontext));
|
|
int evlist__start_workload(struct evlist *evlist);
|
|
+void evlist__cancel_workload(struct evlist *evlist);
|
|
|
|
struct option;
|
|
|
|
diff --git a/tools/perf/util/pfm.c b/tools/perf/util/pfm.c
|
|
index 862e4a689868b6..54421fceef5c7f 100644
|
|
--- a/tools/perf/util/pfm.c
|
|
+++ b/tools/perf/util/pfm.c
|
|
@@ -220,7 +220,7 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state,
|
|
}
|
|
|
|
if (is_libpfm_event_supported(name, cpus, threads)) {
|
|
- print_cb->print_event(print_state, pinfo->name, topic,
|
|
+ print_cb->print_event(print_state, topic, pinfo->name,
|
|
name, info->equiv,
|
|
/*scale_unit=*/NULL,
|
|
/*deprecated=*/NULL, "PFM event",
|
|
@@ -254,8 +254,8 @@ print_libpfm_event(const struct print_callbacks *print_cb, void *print_state,
|
|
continue;
|
|
|
|
print_cb->print_event(print_state,
|
|
- pinfo->name,
|
|
topic,
|
|
+ pinfo->name,
|
|
name, /*alias=*/NULL,
|
|
/*scale_unit=*/NULL,
|
|
/*deprecated=*/NULL, "PFM event",
|
|
diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c
|
|
index 54a237b2b85386..f0577aa7eca885 100644
|
|
--- a/tools/perf/util/pmus.c
|
|
+++ b/tools/perf/util/pmus.c
|
|
@@ -474,8 +474,8 @@ void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *p
|
|
goto free;
|
|
|
|
print_cb->print_event(print_state,
|
|
- aliases[j].pmu_name,
|
|
aliases[j].topic,
|
|
+ aliases[j].pmu_name,
|
|
aliases[j].name,
|
|
aliases[j].alias,
|
|
aliases[j].scale_unit,
|
|
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
|
|
index f171360b0ef4db..c0c8d7f9514b04 100644
|
|
--- a/tools/perf/util/probe-finder.c
|
|
+++ b/tools/perf/util/probe-finder.c
|
|
@@ -1499,6 +1499,10 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
|
|
if (ret >= 0 && tf.pf.skip_empty_arg)
|
|
ret = fill_empty_trace_arg(pev, tf.tevs, tf.ntevs);
|
|
|
|
+#if _ELFUTILS_PREREQ(0, 142)
|
|
+ dwarf_cfi_end(tf.pf.cfi_eh);
|
|
+#endif
|
|
+
|
|
if (ret < 0 || tf.ntevs == 0) {
|
|
for (i = 0; i < tf.ntevs; i++)
|
|
clear_probe_trace_event(&tf.tevs[i]);
|
|
@@ -1741,8 +1745,21 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr,
|
|
|
|
/* Find a corresponding function (name, baseline and baseaddr) */
|
|
if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
|
|
- /* Get function entry information */
|
|
- func = basefunc = dwarf_diename(&spdie);
|
|
+ /*
|
|
+ * Get function entry information.
|
|
+ *
|
|
+ * As described in the document DWARF Debugging Information
|
|
+ * Format Version 5, section 2.22 Linkage Names, "mangled names,
|
|
+ * are used in various ways, ... to distinguish multiple
|
|
+ * entities that have the same name".
|
|
+ *
|
|
+ * Firstly try to get distinct linkage name, if fail then
|
|
+ * rollback to get associated name in DIE.
|
|
+ */
|
|
+ func = basefunc = die_get_linkage_name(&spdie);
|
|
+ if (!func)
|
|
+ func = basefunc = dwarf_diename(&spdie);
|
|
+
|
|
if (!func ||
|
|
die_entrypc(&spdie, &baseaddr) != 0 ||
|
|
dwarf_decl_line(&spdie, &baseline) != 0) {
|
|
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
|
|
index 8bc1c80d3c1c0b..1f4650b955094f 100644
|
|
--- a/tools/perf/util/probe-finder.h
|
|
+++ b/tools/perf/util/probe-finder.h
|
|
@@ -81,9 +81,9 @@ struct probe_finder {
|
|
|
|
/* For variable searching */
|
|
#if _ELFUTILS_PREREQ(0, 142)
|
|
- /* Call Frame Information from .eh_frame */
|
|
+ /* Call Frame Information from .eh_frame. Owned by this struct. */
|
|
Dwarf_CFI *cfi_eh;
|
|
- /* Call Frame Information from .debug_frame */
|
|
+ /* Call Frame Information from .debug_frame. Not owned. */
|
|
Dwarf_CFI *cfi_dbg;
|
|
#endif
|
|
Dwarf_Op *fb_ops; /* Frame base attribute */
|
|
diff --git a/tools/testing/selftests/arm64/mte/check_tags_inclusion.c b/tools/testing/selftests/arm64/mte/check_tags_inclusion.c
|
|
index 2b1425b92b6991..a3d1e23fe02aff 100644
|
|
--- a/tools/testing/selftests/arm64/mte/check_tags_inclusion.c
|
|
+++ b/tools/testing/selftests/arm64/mte/check_tags_inclusion.c
|
|
@@ -65,7 +65,7 @@ static int check_single_included_tags(int mem_type, int mode)
|
|
ptr = mte_insert_tags(ptr, BUFFER_SIZE);
|
|
/* Check tag value */
|
|
if (MT_FETCH_TAG((uintptr_t)ptr) == tag) {
|
|
- ksft_print_msg("FAIL: wrong tag = 0x%x with include mask=0x%x\n",
|
|
+ ksft_print_msg("FAIL: wrong tag = 0x%lx with include mask=0x%x\n",
|
|
MT_FETCH_TAG((uintptr_t)ptr),
|
|
MT_INCLUDE_VALID_TAG(tag));
|
|
result = KSFT_FAIL;
|
|
@@ -97,7 +97,7 @@ static int check_multiple_included_tags(int mem_type, int mode)
|
|
ptr = mte_insert_tags(ptr, BUFFER_SIZE);
|
|
/* Check tag value */
|
|
if (MT_FETCH_TAG((uintptr_t)ptr) < tag) {
|
|
- ksft_print_msg("FAIL: wrong tag = 0x%x with include mask=0x%x\n",
|
|
+ ksft_print_msg("FAIL: wrong tag = 0x%lx with include mask=0x%lx\n",
|
|
MT_FETCH_TAG((uintptr_t)ptr),
|
|
MT_INCLUDE_VALID_TAGS(excl_mask));
|
|
result = KSFT_FAIL;
|
|
diff --git a/tools/testing/selftests/arm64/mte/mte_common_util.c b/tools/testing/selftests/arm64/mte/mte_common_util.c
|
|
index 00ffd34c66d301..1120f5aa76550f 100644
|
|
--- a/tools/testing/selftests/arm64/mte/mte_common_util.c
|
|
+++ b/tools/testing/selftests/arm64/mte/mte_common_util.c
|
|
@@ -38,7 +38,7 @@ void mte_default_handler(int signum, siginfo_t *si, void *uc)
|
|
if (cur_mte_cxt.trig_si_code == si->si_code)
|
|
cur_mte_cxt.fault_valid = true;
|
|
else
|
|
- ksft_print_msg("Got unexpected SEGV_MTEAERR at pc=$lx, fault addr=%lx\n",
|
|
+ ksft_print_msg("Got unexpected SEGV_MTEAERR at pc=%llx, fault addr=%lx\n",
|
|
((ucontext_t *)uc)->uc_mcontext.pc,
|
|
addr);
|
|
return;
|
|
@@ -64,7 +64,7 @@ void mte_default_handler(int signum, siginfo_t *si, void *uc)
|
|
exit(1);
|
|
}
|
|
} else if (signum == SIGBUS) {
|
|
- ksft_print_msg("INFO: SIGBUS signal at pc=%lx, fault addr=%lx, si_code=%lx\n",
|
|
+ ksft_print_msg("INFO: SIGBUS signal at pc=%llx, fault addr=%lx, si_code=%x\n",
|
|
((ucontext_t *)uc)->uc_mcontext.pc, addr, si->si_code);
|
|
if ((cur_mte_cxt.trig_range >= 0 &&
|
|
addr >= MT_CLEAR_TAG(cur_mte_cxt.trig_addr) &&
|
|
diff --git a/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c b/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c
|
|
index 86cd183ef6dc8a..293ac1049d3889 100644
|
|
--- a/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c
|
|
+++ b/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c
|
|
@@ -28,8 +28,8 @@ struct {
|
|
},
|
|
};
|
|
|
|
-SEC(".data.A") struct bpf_spin_lock lockA;
|
|
-SEC(".data.B") struct bpf_spin_lock lockB;
|
|
+static struct bpf_spin_lock lockA SEC(".data.A");
|
|
+static struct bpf_spin_lock lockB SEC(".data.B");
|
|
|
|
SEC("?tc")
|
|
int lock_id_kptr_preserve(void *ctx)
|
|
diff --git a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
|
|
index f61d623b1ce8df..f87365f7599bf7 100644
|
|
--- a/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
|
|
+++ b/tools/testing/selftests/bpf/progs/verifier_subprog_precision.c
|
|
@@ -541,11 +541,24 @@ static __u64 subprog_spill_reg_precise(void)
|
|
|
|
SEC("?raw_tp")
|
|
__success __log_level(2)
|
|
-/* precision backtracking can't currently handle stack access not through r10,
|
|
- * so we won't be able to mark stack slot fp-8 as precise, and so will
|
|
- * fallback to forcing all as precise
|
|
- */
|
|
-__msg("mark_precise: frame0: falling back to forcing all scalars precise")
|
|
+__msg("10: (0f) r1 += r7")
|
|
+__msg("mark_precise: frame0: last_idx 10 first_idx 7 subseq_idx -1")
|
|
+__msg("mark_precise: frame0: regs=r7 stack= before 9: (bf) r1 = r8")
|
|
+__msg("mark_precise: frame0: regs=r7 stack= before 8: (27) r7 *= 4")
|
|
+__msg("mark_precise: frame0: regs=r7 stack= before 7: (79) r7 = *(u64 *)(r10 -8)")
|
|
+__msg("mark_precise: frame0: parent state regs= stack=-8: R0_w=2 R6_w=1 R8_rw=map_value(map=.data.vals,ks=4,vs=16) R10=fp0 fp-8_rw=P1")
|
|
+__msg("mark_precise: frame0: last_idx 18 first_idx 0 subseq_idx 7")
|
|
+__msg("mark_precise: frame0: regs= stack=-8 before 18: (95) exit")
|
|
+__msg("mark_precise: frame1: regs= stack= before 17: (0f) r0 += r2")
|
|
+__msg("mark_precise: frame1: regs= stack= before 16: (79) r2 = *(u64 *)(r1 +0)")
|
|
+__msg("mark_precise: frame1: regs= stack= before 15: (79) r0 = *(u64 *)(r10 -16)")
|
|
+__msg("mark_precise: frame1: regs= stack= before 14: (7b) *(u64 *)(r10 -16) = r2")
|
|
+__msg("mark_precise: frame1: regs= stack= before 13: (7b) *(u64 *)(r1 +0) = r2")
|
|
+__msg("mark_precise: frame1: regs=r2 stack= before 6: (85) call pc+6")
|
|
+__msg("mark_precise: frame0: regs=r2 stack= before 5: (bf) r2 = r6")
|
|
+__msg("mark_precise: frame0: regs=r6 stack= before 4: (07) r1 += -8")
|
|
+__msg("mark_precise: frame0: regs=r6 stack= before 3: (bf) r1 = r10")
|
|
+__msg("mark_precise: frame0: regs=r6 stack= before 2: (b7) r6 = 1")
|
|
__naked int subprog_spill_into_parent_stack_slot_precise(void)
|
|
{
|
|
asm volatile (
|
|
diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
|
|
index a181c0ccf98b2a..dccaf9b8cb900b 100644
|
|
--- a/tools/testing/selftests/bpf/test_sockmap.c
|
|
+++ b/tools/testing/selftests/bpf/test_sockmap.c
|
|
@@ -56,6 +56,8 @@ static void running_handler(int a);
|
|
#define BPF_SOCKHASH_FILENAME "test_sockhash_kern.bpf.o"
|
|
#define CG_PATH "/sockmap"
|
|
|
|
+#define EDATAINTEGRITY 2001
|
|
+
|
|
/* global sockets */
|
|
int s1, s2, c1, c2, p1, p2;
|
|
int test_cnt;
|
|
@@ -85,6 +87,10 @@ int ktls;
|
|
int peek_flag;
|
|
int skb_use_parser;
|
|
int txmsg_omit_skb_parser;
|
|
+int verify_push_start;
|
|
+int verify_push_len;
|
|
+int verify_pop_start;
|
|
+int verify_pop_len;
|
|
|
|
static const struct option long_options[] = {
|
|
{"help", no_argument, NULL, 'h' },
|
|
@@ -417,16 +423,18 @@ static int msg_loop_sendpage(int fd, int iov_length, int cnt,
|
|
{
|
|
bool drop = opt->drop_expected;
|
|
unsigned char k = 0;
|
|
+ int i, j, fp;
|
|
FILE *file;
|
|
- int i, fp;
|
|
|
|
file = tmpfile();
|
|
if (!file) {
|
|
perror("create file for sendpage");
|
|
return 1;
|
|
}
|
|
- for (i = 0; i < iov_length * cnt; i++, k++)
|
|
- fwrite(&k, sizeof(char), 1, file);
|
|
+ for (i = 0; i < cnt; i++, k = 0) {
|
|
+ for (j = 0; j < iov_length; j++, k++)
|
|
+ fwrite(&k, sizeof(char), 1, file);
|
|
+ }
|
|
fflush(file);
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
@@ -509,42 +517,111 @@ static int msg_alloc_iov(struct msghdr *msg,
|
|
return -ENOMEM;
|
|
}
|
|
|
|
-static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz)
|
|
+/* In push or pop test, we need to do some calculations for msg_verify_data */
|
|
+static void msg_verify_date_prep(void)
|
|
{
|
|
- int i, j = 0, bytes_cnt = 0;
|
|
- unsigned char k = 0;
|
|
+ int push_range_end = txmsg_start_push + txmsg_end_push - 1;
|
|
+ int pop_range_end = txmsg_start_pop + txmsg_pop - 1;
|
|
+
|
|
+ if (txmsg_end_push && txmsg_pop &&
|
|
+ txmsg_start_push <= pop_range_end && txmsg_start_pop <= push_range_end) {
|
|
+ /* The push range and the pop range overlap */
|
|
+ int overlap_len;
|
|
+
|
|
+ verify_push_start = txmsg_start_push;
|
|
+ verify_pop_start = txmsg_start_pop;
|
|
+ if (txmsg_start_push < txmsg_start_pop)
|
|
+ overlap_len = min(push_range_end - txmsg_start_pop + 1, txmsg_pop);
|
|
+ else
|
|
+ overlap_len = min(pop_range_end - txmsg_start_push + 1, txmsg_end_push);
|
|
+ verify_push_len = max(txmsg_end_push - overlap_len, 0);
|
|
+ verify_pop_len = max(txmsg_pop - overlap_len, 0);
|
|
+ } else {
|
|
+ /* Otherwise */
|
|
+ verify_push_start = txmsg_start_push;
|
|
+ verify_pop_start = txmsg_start_pop;
|
|
+ verify_push_len = txmsg_end_push;
|
|
+ verify_pop_len = txmsg_pop;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz,
|
|
+ unsigned char *k_p, int *bytes_cnt_p,
|
|
+ int *check_cnt_p, int *push_p)
|
|
+{
|
|
+ int bytes_cnt = *bytes_cnt_p, check_cnt = *check_cnt_p, push = *push_p;
|
|
+ unsigned char k = *k_p;
|
|
+ int i, j;
|
|
|
|
- for (i = 0; i < msg->msg_iovlen; i++) {
|
|
+ for (i = 0, j = 0; i < msg->msg_iovlen && size; i++, j = 0) {
|
|
unsigned char *d = msg->msg_iov[i].iov_base;
|
|
|
|
/* Special case test for skb ingress + ktls */
|
|
if (i == 0 && txmsg_ktls_skb) {
|
|
if (msg->msg_iov[i].iov_len < 4)
|
|
- return -EIO;
|
|
+ return -EDATAINTEGRITY;
|
|
if (memcmp(d, "PASS", 4) != 0) {
|
|
fprintf(stderr,
|
|
"detected skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n",
|
|
i, 0, d[0], d[1], d[2], d[3]);
|
|
- return -EIO;
|
|
+ return -EDATAINTEGRITY;
|
|
}
|
|
j = 4; /* advance index past PASS header */
|
|
}
|
|
|
|
for (; j < msg->msg_iov[i].iov_len && size; j++) {
|
|
+ if (push > 0 &&
|
|
+ check_cnt == verify_push_start + verify_push_len - push) {
|
|
+ int skipped;
|
|
+revisit_push:
|
|
+ skipped = push;
|
|
+ if (j + push >= msg->msg_iov[i].iov_len)
|
|
+ skipped = msg->msg_iov[i].iov_len - j;
|
|
+ push -= skipped;
|
|
+ size -= skipped;
|
|
+ j += skipped - 1;
|
|
+ check_cnt += skipped;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (verify_pop_len > 0 && check_cnt == verify_pop_start) {
|
|
+ bytes_cnt += verify_pop_len;
|
|
+ check_cnt += verify_pop_len;
|
|
+ k += verify_pop_len;
|
|
+
|
|
+ if (bytes_cnt == chunk_sz) {
|
|
+ k = 0;
|
|
+ bytes_cnt = 0;
|
|
+ check_cnt = 0;
|
|
+ push = verify_push_len;
|
|
+ }
|
|
+
|
|
+ if (push > 0 &&
|
|
+ check_cnt == verify_push_start + verify_push_len - push)
|
|
+ goto revisit_push;
|
|
+ }
|
|
+
|
|
if (d[j] != k++) {
|
|
fprintf(stderr,
|
|
"detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
|
|
i, j, d[j], k - 1, d[j+1], k);
|
|
- return -EIO;
|
|
+ return -EDATAINTEGRITY;
|
|
}
|
|
bytes_cnt++;
|
|
+ check_cnt++;
|
|
if (bytes_cnt == chunk_sz) {
|
|
k = 0;
|
|
bytes_cnt = 0;
|
|
+ check_cnt = 0;
|
|
+ push = verify_push_len;
|
|
}
|
|
size--;
|
|
}
|
|
}
|
|
+ *k_p = k;
|
|
+ *bytes_cnt_p = bytes_cnt;
|
|
+ *check_cnt_p = check_cnt;
|
|
+ *push_p = push;
|
|
return 0;
|
|
}
|
|
|
|
@@ -597,10 +674,14 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
|
|
}
|
|
clock_gettime(CLOCK_MONOTONIC, &s->end);
|
|
} else {
|
|
+ float total_bytes, txmsg_pop_total, txmsg_push_total;
|
|
int slct, recvp = 0, recv, max_fd = fd;
|
|
- float total_bytes, txmsg_pop_total;
|
|
int fd_flags = O_NONBLOCK;
|
|
struct timeval timeout;
|
|
+ unsigned char k = 0;
|
|
+ int bytes_cnt = 0;
|
|
+ int check_cnt = 0;
|
|
+ int push = 0;
|
|
fd_set w;
|
|
|
|
fcntl(fd, fd_flags);
|
|
@@ -614,12 +695,22 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
|
|
* This is really only useful for testing edge cases in code
|
|
* paths.
|
|
*/
|
|
- total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
|
|
- if (txmsg_apply)
|
|
+ total_bytes = (float)iov_length * (float)cnt;
|
|
+ if (!opt->sendpage)
|
|
+ total_bytes *= (float)iov_count;
|
|
+ if (txmsg_apply) {
|
|
+ txmsg_push_total = txmsg_end_push * (total_bytes / txmsg_apply);
|
|
txmsg_pop_total = txmsg_pop * (total_bytes / txmsg_apply);
|
|
- else
|
|
+ } else {
|
|
+ txmsg_push_total = txmsg_end_push * cnt;
|
|
txmsg_pop_total = txmsg_pop * cnt;
|
|
+ }
|
|
+ total_bytes += txmsg_push_total;
|
|
total_bytes -= txmsg_pop_total;
|
|
+ if (data) {
|
|
+ msg_verify_date_prep();
|
|
+ push = verify_push_len;
|
|
+ }
|
|
err = clock_gettime(CLOCK_MONOTONIC, &s->start);
|
|
if (err < 0)
|
|
perror("recv start time");
|
|
@@ -692,10 +783,11 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
|
|
|
|
if (data) {
|
|
int chunk_sz = opt->sendpage ?
|
|
- iov_length * cnt :
|
|
+ iov_length :
|
|
iov_length * iov_count;
|
|
|
|
- errno = msg_verify_data(&msg, recv, chunk_sz);
|
|
+ errno = msg_verify_data(&msg, recv, chunk_sz, &k, &bytes_cnt,
|
|
+ &check_cnt, &push);
|
|
if (errno) {
|
|
perror("data verify msg failed");
|
|
goto out_errno;
|
|
@@ -703,7 +795,11 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
|
|
if (recvp) {
|
|
errno = msg_verify_data(&msg_peek,
|
|
recvp,
|
|
- chunk_sz);
|
|
+ chunk_sz,
|
|
+ &k,
|
|
+ &bytes_cnt,
|
|
+ &check_cnt,
|
|
+ &push);
|
|
if (errno) {
|
|
perror("data verify msg_peek failed");
|
|
goto out_errno;
|
|
@@ -785,8 +881,6 @@ static int sendmsg_test(struct sockmap_options *opt)
|
|
|
|
rxpid = fork();
|
|
if (rxpid == 0) {
|
|
- if (txmsg_pop || txmsg_start_pop)
|
|
- iov_buf -= (txmsg_pop - txmsg_start_pop + 1);
|
|
if (opt->drop_expected || txmsg_ktls_skb_drop)
|
|
_exit(0);
|
|
|
|
@@ -811,7 +905,7 @@ static int sendmsg_test(struct sockmap_options *opt)
|
|
s.bytes_sent, sent_Bps, sent_Bps/giga,
|
|
s.bytes_recvd, recvd_Bps, recvd_Bps/giga,
|
|
peek_flag ? "(peek_msg)" : "");
|
|
- if (err && txmsg_cork)
|
|
+ if (err && err != -EDATAINTEGRITY && txmsg_cork)
|
|
err = 0;
|
|
exit(err ? 1 : 0);
|
|
} else if (rxpid == -1) {
|
|
@@ -1459,8 +1553,8 @@ static void test_send_many(struct sockmap_options *opt, int cgrp)
|
|
|
|
static void test_send_large(struct sockmap_options *opt, int cgrp)
|
|
{
|
|
- opt->iov_length = 256;
|
|
- opt->iov_count = 1024;
|
|
+ opt->iov_length = 8192;
|
|
+ opt->iov_count = 32;
|
|
opt->rate = 2;
|
|
test_exec(cgrp, opt);
|
|
}
|
|
@@ -1589,17 +1683,19 @@ static void test_txmsg_cork_hangs(int cgrp, struct sockmap_options *opt)
|
|
static void test_txmsg_pull(int cgrp, struct sockmap_options *opt)
|
|
{
|
|
/* Test basic start/end */
|
|
+ txmsg_pass = 1;
|
|
txmsg_start = 1;
|
|
txmsg_end = 2;
|
|
test_send(opt, cgrp);
|
|
|
|
/* Test >4k pull */
|
|
+ txmsg_pass = 1;
|
|
txmsg_start = 4096;
|
|
txmsg_end = 9182;
|
|
test_send_large(opt, cgrp);
|
|
|
|
/* Test pull + redirect */
|
|
- txmsg_redir = 0;
|
|
+ txmsg_redir = 1;
|
|
txmsg_start = 1;
|
|
txmsg_end = 2;
|
|
test_send(opt, cgrp);
|
|
@@ -1621,12 +1717,16 @@ static void test_txmsg_pull(int cgrp, struct sockmap_options *opt)
|
|
|
|
static void test_txmsg_pop(int cgrp, struct sockmap_options *opt)
|
|
{
|
|
+ bool data = opt->data_test;
|
|
+
|
|
/* Test basic pop */
|
|
+ txmsg_pass = 1;
|
|
txmsg_start_pop = 1;
|
|
txmsg_pop = 2;
|
|
test_send_many(opt, cgrp);
|
|
|
|
/* Test pop with >4k */
|
|
+ txmsg_pass = 1;
|
|
txmsg_start_pop = 4096;
|
|
txmsg_pop = 4096;
|
|
test_send_large(opt, cgrp);
|
|
@@ -1637,6 +1737,12 @@ static void test_txmsg_pop(int cgrp, struct sockmap_options *opt)
|
|
txmsg_pop = 2;
|
|
test_send_many(opt, cgrp);
|
|
|
|
+ /* TODO: Test for pop + cork should be different,
|
|
+ * - It makes the layout of the received data difficult
|
|
+ * - It makes it hard to calculate the total_bytes in the recvmsg
|
|
+ * Temporarily skip the data integrity test for this case now.
|
|
+ */
|
|
+ opt->data_test = false;
|
|
/* Test pop + cork */
|
|
txmsg_redir = 0;
|
|
txmsg_cork = 512;
|
|
@@ -1650,16 +1756,21 @@ static void test_txmsg_pop(int cgrp, struct sockmap_options *opt)
|
|
txmsg_start_pop = 1;
|
|
txmsg_pop = 2;
|
|
test_send_many(opt, cgrp);
|
|
+ opt->data_test = data;
|
|
}
|
|
|
|
static void test_txmsg_push(int cgrp, struct sockmap_options *opt)
|
|
{
|
|
+ bool data = opt->data_test;
|
|
+
|
|
/* Test basic push */
|
|
+ txmsg_pass = 1;
|
|
txmsg_start_push = 1;
|
|
txmsg_end_push = 1;
|
|
test_send(opt, cgrp);
|
|
|
|
/* Test push 4kB >4k */
|
|
+ txmsg_pass = 1;
|
|
txmsg_start_push = 4096;
|
|
txmsg_end_push = 4096;
|
|
test_send_large(opt, cgrp);
|
|
@@ -1670,16 +1781,24 @@ static void test_txmsg_push(int cgrp, struct sockmap_options *opt)
|
|
txmsg_end_push = 2;
|
|
test_send_many(opt, cgrp);
|
|
|
|
+ /* TODO: Test for push + cork should be different,
|
|
+ * - It makes the layout of the received data difficult
|
|
+ * - It makes it hard to calculate the total_bytes in the recvmsg
|
|
+ * Temporarily skip the data integrity test for this case now.
|
|
+ */
|
|
+ opt->data_test = false;
|
|
/* Test push + cork */
|
|
txmsg_redir = 0;
|
|
txmsg_cork = 512;
|
|
txmsg_start_push = 1;
|
|
txmsg_end_push = 2;
|
|
test_send_many(opt, cgrp);
|
|
+ opt->data_test = data;
|
|
}
|
|
|
|
static void test_txmsg_push_pop(int cgrp, struct sockmap_options *opt)
|
|
{
|
|
+ txmsg_pass = 1;
|
|
txmsg_start_push = 1;
|
|
txmsg_end_push = 10;
|
|
txmsg_start_pop = 5;
|
|
diff --git a/tools/testing/selftests/bpf/verifier/precise.c b/tools/testing/selftests/bpf/verifier/precise.c
|
|
index 0d84dd1f38b6b0..8a2ff81d835088 100644
|
|
--- a/tools/testing/selftests/bpf/verifier/precise.c
|
|
+++ b/tools/testing/selftests/bpf/verifier/precise.c
|
|
@@ -140,10 +140,11 @@
|
|
.result = REJECT,
|
|
},
|
|
{
|
|
- "precise: ST insn causing spi > allocated_stack",
|
|
+ "precise: ST zero to stack insn is supported",
|
|
.insns = {
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
|
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_3, 123, 0),
|
|
+ /* not a register spill, so we stop precision propagation for R4 here */
|
|
BPF_ST_MEM(BPF_DW, BPF_REG_3, -8, 0),
|
|
BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_10, -8),
|
|
BPF_MOV64_IMM(BPF_REG_0, -1),
|
|
@@ -157,11 +158,11 @@
|
|
mark_precise: frame0: last_idx 4 first_idx 2\
|
|
mark_precise: frame0: regs=r4 stack= before 4\
|
|
mark_precise: frame0: regs=r4 stack= before 3\
|
|
- mark_precise: frame0: regs= stack=-8 before 2\
|
|
- mark_precise: frame0: falling back to forcing all scalars precise\
|
|
- force_precise: frame0: forcing r0 to be precise\
|
|
mark_precise: frame0: last_idx 5 first_idx 5\
|
|
- mark_precise: frame0: parent state regs= stack=:",
|
|
+ mark_precise: frame0: parent state regs=r0 stack=:\
|
|
+ mark_precise: frame0: last_idx 4 first_idx 2\
|
|
+ mark_precise: frame0: regs=r0 stack= before 4\
|
|
+ 5: R0=-1 R4=0",
|
|
.result = VERBOSE_ACCEPT,
|
|
.retval = -1,
|
|
},
|
|
@@ -169,6 +170,8 @@
|
|
"precise: STX insn causing spi > allocated_stack",
|
|
.insns = {
|
|
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_get_prandom_u32),
|
|
+ /* make later reg spill more interesting by having somewhat known scalar */
|
|
+ BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xff),
|
|
BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
|
|
BPF_JMP_IMM(BPF_JNE, BPF_REG_3, 123, 0),
|
|
BPF_STX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, -8),
|
|
@@ -179,18 +182,21 @@
|
|
},
|
|
.prog_type = BPF_PROG_TYPE_XDP,
|
|
.flags = BPF_F_TEST_STATE_FREQ,
|
|
- .errstr = "mark_precise: frame0: last_idx 6 first_idx 6\
|
|
+ .errstr = "mark_precise: frame0: last_idx 7 first_idx 7\
|
|
mark_precise: frame0: parent state regs=r4 stack=:\
|
|
- mark_precise: frame0: last_idx 5 first_idx 3\
|
|
- mark_precise: frame0: regs=r4 stack= before 5\
|
|
- mark_precise: frame0: regs=r4 stack= before 4\
|
|
- mark_precise: frame0: regs= stack=-8 before 3\
|
|
- mark_precise: frame0: falling back to forcing all scalars precise\
|
|
- force_precise: frame0: forcing r0 to be precise\
|
|
- force_precise: frame0: forcing r0 to be precise\
|
|
- force_precise: frame0: forcing r0 to be precise\
|
|
- force_precise: frame0: forcing r0 to be precise\
|
|
- mark_precise: frame0: last_idx 6 first_idx 6\
|
|
+ mark_precise: frame0: last_idx 6 first_idx 4\
|
|
+ mark_precise: frame0: regs=r4 stack= before 6: (b7) r0 = -1\
|
|
+ mark_precise: frame0: regs=r4 stack= before 5: (79) r4 = *(u64 *)(r10 -8)\
|
|
+ mark_precise: frame0: regs= stack=-8 before 4: (7b) *(u64 *)(r3 -8) = r0\
|
|
+ mark_precise: frame0: parent state regs=r0 stack=:\
|
|
+ mark_precise: frame0: last_idx 3 first_idx 3\
|
|
+ mark_precise: frame0: regs=r0 stack= before 3: (55) if r3 != 0x7b goto pc+0\
|
|
+ mark_precise: frame0: regs=r0 stack= before 2: (bf) r3 = r10\
|
|
+ mark_precise: frame0: regs=r0 stack= before 1: (57) r0 &= 255\
|
|
+ mark_precise: frame0: parent state regs=r0 stack=:\
|
|
+ mark_precise: frame0: last_idx 0 first_idx 0\
|
|
+ mark_precise: frame0: regs=r0 stack= before 0: (85) call bpf_get_prandom_u32#7\
|
|
+ mark_precise: frame0: last_idx 7 first_idx 7\
|
|
mark_precise: frame0: parent state regs= stack=:",
|
|
.result = VERBOSE_ACCEPT,
|
|
.retval = -1,
|
|
diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c
|
|
index c6a8c732b80217..304e6422a1f1ce 100644
|
|
--- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c
|
|
+++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c
|
|
@@ -1026,7 +1026,7 @@ FIXTURE_SETUP(mount_setattr_idmapped)
|
|
"size=100000,mode=700"), 0);
|
|
|
|
ASSERT_EQ(mount("testing", "/mnt", "tmpfs", MS_NOATIME | MS_NODEV,
|
|
- "size=100000,mode=700"), 0);
|
|
+ "size=2m,mode=700"), 0);
|
|
|
|
ASSERT_EQ(mkdir("/mnt/A", 0777), 0);
|
|
|
|
diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh
|
|
index d65fdd407d73f9..1c0dd2f7816782 100755
|
|
--- a/tools/testing/selftests/net/pmtu.sh
|
|
+++ b/tools/testing/selftests/net/pmtu.sh
|
|
@@ -1961,7 +1961,7 @@ check_running() {
|
|
pid=${1}
|
|
cmd=${2}
|
|
|
|
- [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "{cmd}" ]
|
|
+ [ "$(cat /proc/${pid}/cmdline 2>/dev/null | tr -d '\0')" = "${cmd}" ]
|
|
}
|
|
|
|
test_cleanup_vxlanX_exception() {
|
|
diff --git a/tools/testing/selftests/resctrl/fill_buf.c b/tools/testing/selftests/resctrl/fill_buf.c
|
|
index 0f6cca61ec94ba..a85ae8148db84e 100644
|
|
--- a/tools/testing/selftests/resctrl/fill_buf.c
|
|
+++ b/tools/testing/selftests/resctrl/fill_buf.c
|
|
@@ -51,29 +51,6 @@ static void mem_flush(unsigned char *buf, size_t buf_size)
|
|
sb();
|
|
}
|
|
|
|
-static void *malloc_and_init_memory(size_t buf_size)
|
|
-{
|
|
- void *p = NULL;
|
|
- uint64_t *p64;
|
|
- size_t s64;
|
|
- int ret;
|
|
-
|
|
- ret = posix_memalign(&p, PAGE_SIZE, buf_size);
|
|
- if (ret < 0)
|
|
- return NULL;
|
|
-
|
|
- p64 = (uint64_t *)p;
|
|
- s64 = buf_size / sizeof(uint64_t);
|
|
-
|
|
- while (s64 > 0) {
|
|
- *p64 = (uint64_t)rand();
|
|
- p64 += (CL_SIZE / sizeof(uint64_t));
|
|
- s64 -= (CL_SIZE / sizeof(uint64_t));
|
|
- }
|
|
-
|
|
- return p;
|
|
-}
|
|
-
|
|
static int fill_one_span_read(unsigned char *buf, size_t buf_size)
|
|
{
|
|
unsigned char *end_ptr = buf + buf_size;
|
|
@@ -135,41 +112,48 @@ static int fill_cache_write(unsigned char *buf, size_t buf_size, bool once)
|
|
return 0;
|
|
}
|
|
|
|
-static int fill_cache(size_t buf_size, int memflush, int op, bool once)
|
|
+static unsigned char *alloc_buffer(size_t buf_size, int memflush)
|
|
{
|
|
- unsigned char *buf;
|
|
+ void *buf = NULL;
|
|
+ uint64_t *p64;
|
|
+ ssize_t s64;
|
|
int ret;
|
|
|
|
- buf = malloc_and_init_memory(buf_size);
|
|
- if (!buf)
|
|
- return -1;
|
|
-
|
|
- /* Flush the memory before using to avoid "cache hot pages" effect */
|
|
- if (memflush)
|
|
- mem_flush(buf, buf_size);
|
|
-
|
|
- if (op == 0)
|
|
- ret = fill_cache_read(buf, buf_size, once);
|
|
- else
|
|
- ret = fill_cache_write(buf, buf_size, once);
|
|
+ ret = posix_memalign(&buf, PAGE_SIZE, buf_size);
|
|
+ if (ret < 0)
|
|
+ return NULL;
|
|
|
|
- free(buf);
|
|
+ /* Initialize the buffer */
|
|
+ p64 = buf;
|
|
+ s64 = buf_size / sizeof(uint64_t);
|
|
|
|
- if (ret) {
|
|
- printf("\n Error in fill cache read/write...\n");
|
|
- return -1;
|
|
+ while (s64 > 0) {
|
|
+ *p64 = (uint64_t)rand();
|
|
+ p64 += (CL_SIZE / sizeof(uint64_t));
|
|
+ s64 -= (CL_SIZE / sizeof(uint64_t));
|
|
}
|
|
|
|
+ /* Flush the memory before using to avoid "cache hot pages" effect */
|
|
+ if (memflush)
|
|
+ mem_flush(buf, buf_size);
|
|
|
|
- return 0;
|
|
+ return buf;
|
|
}
|
|
|
|
-int run_fill_buf(size_t span, int memflush, int op, bool once)
|
|
+int run_fill_buf(size_t buf_size, int memflush, int op, bool once)
|
|
{
|
|
- size_t cache_size = span;
|
|
+ unsigned char *buf;
|
|
int ret;
|
|
|
|
- ret = fill_cache(cache_size, memflush, op, once);
|
|
+ buf = alloc_buffer(buf_size, memflush);
|
|
+ if (!buf)
|
|
+ return -1;
|
|
+
|
|
+ if (op == 0)
|
|
+ ret = fill_cache_read(buf, buf_size, once);
|
|
+ else
|
|
+ ret = fill_cache_write(buf, buf_size, once);
|
|
+ free(buf);
|
|
if (ret) {
|
|
printf("\n Error in fill cache\n");
|
|
return -1;
|
|
diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h
|
|
index dd3546655657a9..a848e9c755787c 100644
|
|
--- a/tools/testing/selftests/resctrl/resctrl.h
|
|
+++ b/tools/testing/selftests/resctrl/resctrl.h
|
|
@@ -91,7 +91,7 @@ int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
|
|
char *resctrl_val);
|
|
int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
|
|
int group_fd, unsigned long flags);
|
|
-int run_fill_buf(size_t span, int memflush, int op, bool once);
|
|
+int run_fill_buf(size_t buf_size, int memflush, int op, bool once);
|
|
int resctrl_val(const char * const *benchmark_cmd, struct resctrl_val_param *param);
|
|
int mbm_bw_change(int cpu_no, const char * const *benchmark_cmd);
|
|
void tests_cleanup(void);
|
|
diff --git a/tools/testing/selftests/resctrl/resctrl_val.c b/tools/testing/selftests/resctrl/resctrl_val.c
|
|
index 45439e726e79c5..d77fdf356e98eb 100644
|
|
--- a/tools/testing/selftests/resctrl/resctrl_val.c
|
|
+++ b/tools/testing/selftests/resctrl/resctrl_val.c
|
|
@@ -102,13 +102,12 @@ void get_event_and_umask(char *cas_count_cfg, int count, bool op)
|
|
char *token[MAX_TOKENS];
|
|
int i = 0;
|
|
|
|
- strcat(cas_count_cfg, ",");
|
|
token[0] = strtok(cas_count_cfg, "=,");
|
|
|
|
for (i = 1; i < MAX_TOKENS; i++)
|
|
token[i] = strtok(NULL, "=,");
|
|
|
|
- for (i = 0; i < MAX_TOKENS; i++) {
|
|
+ for (i = 0; i < MAX_TOKENS - 1; i++) {
|
|
if (!token[i])
|
|
break;
|
|
if (strcmp(token[i], "event") == 0) {
|
|
diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c
|
|
index 7dd5668ea8a6e3..28f35620c49919 100644
|
|
--- a/tools/testing/selftests/vDSO/parse_vdso.c
|
|
+++ b/tools/testing/selftests/vDSO/parse_vdso.c
|
|
@@ -222,8 +222,7 @@ void *vdso_sym(const char *version, const char *name)
|
|
ELF(Sym) *sym = &vdso_info.symtab[chain];
|
|
|
|
/* Check for a defined global or weak function w/ right name. */
|
|
- if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC &&
|
|
- ELF64_ST_TYPE(sym->st_info) != STT_NOTYPE)
|
|
+ if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
|
|
continue;
|
|
if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
|
|
ELF64_ST_BIND(sym->st_info) != STB_WEAK)
|
|
diff --git a/tools/testing/selftests/watchdog/watchdog-test.c b/tools/testing/selftests/watchdog/watchdog-test.c
|
|
index bc71cbca0dde70..a1f506ba557864 100644
|
|
--- a/tools/testing/selftests/watchdog/watchdog-test.c
|
|
+++ b/tools/testing/selftests/watchdog/watchdog-test.c
|
|
@@ -334,7 +334,13 @@ int main(int argc, char *argv[])
|
|
|
|
printf("Watchdog Ticking Away!\n");
|
|
|
|
+ /*
|
|
+ * Register the signals
|
|
+ */
|
|
signal(SIGINT, term);
|
|
+ signal(SIGTERM, term);
|
|
+ signal(SIGKILL, term);
|
|
+ signal(SIGQUIT, term);
|
|
|
|
while (1) {
|
|
keep_alive();
|
|
diff --git a/tools/testing/selftests/wireguard/netns.sh b/tools/testing/selftests/wireguard/netns.sh
|
|
index 405ff262ca93d4..55500f901fbc36 100755
|
|
--- a/tools/testing/selftests/wireguard/netns.sh
|
|
+++ b/tools/testing/selftests/wireguard/netns.sh
|
|
@@ -332,6 +332,7 @@ waitiface $netns1 vethc
|
|
waitiface $netns2 veths
|
|
|
|
n0 bash -c 'printf 1 > /proc/sys/net/ipv4/ip_forward'
|
|
+[[ -e /proc/sys/net/netfilter/nf_conntrack_udp_timeout ]] || modprobe nf_conntrack
|
|
n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout'
|
|
n0 bash -c 'printf 2 > /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream'
|
|
n0 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 10.0.0.0/24 -j SNAT --to 10.0.0.1
|