diff options
535 files changed, 5134 insertions, 3570 deletions
@@ -426,6 +426,9 @@ Krzysztof Wilczyński <kwilczynski@kernel.org> <krzysztof.wilczynski@linux.com> Krzysztof Wilczyński <kwilczynski@kernel.org> <kw@linux.com> Kshitiz Godara <quic_kgodara@quicinc.com> <kgodara@codeaurora.org> Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Kuniyuki Iwashima <kuniyu@google.com> <kuniyu@amazon.com> +Kuniyuki Iwashima <kuniyu@google.com> <kuniyu@amazon.co.jp> +Kuniyuki Iwashima <kuniyu@google.com> <kuni1840@gmail.com> Kuogee Hsieh <quic_khsieh@quicinc.com> <khsieh@codeaurora.org> Lee Jones <lee@kernel.org> <joneslee@google.com> Lee Jones <lee@kernel.org> <lee.jones@canonical.com> @@ -719,6 +722,7 @@ Srinivas Ramana <quic_sramana@quicinc.com> <sramana@codeaurora.org> Sriram R <quic_srirrama@quicinc.com> <srirrama@codeaurora.org> Sriram Yagnaraman <sriram.yagnaraman@ericsson.com> <sriram.yagnaraman@est.tech> Stanislav Fomichev <sdf@fomichev.me> <sdf@google.com> +Stanislav Fomichev <sdf@fomichev.me> <stfomichev@gmail.com> Stefan Wahren <wahrenst@gmx.net> <stefan.wahren@i2se.com> Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr> Stephen Hemminger <stephen@networkplumber.org> <shemminger@linux-foundation.org> diff --git a/Documentation/admin-guide/cifs/usage.rst b/Documentation/admin-guide/cifs/usage.rst index c09674a75a9e..d989ae5778ba 100644 --- a/Documentation/admin-guide/cifs/usage.rst +++ b/Documentation/admin-guide/cifs/usage.rst @@ -270,6 +270,8 @@ configured for Unix Extensions (and the client has not disabled illegal Windows/NTFS/SMB characters to a remap range (this mount parameter is the default for SMB3). This remap (``mapposix``) range is also compatible with Mac (and "Services for Mac" on some older Windows). +When POSIX Extensions for SMB 3.1.1 are negotiated, remapping is automatically +disabled. CIFS VFS Mount Options ====================== diff --git a/Documentation/block/ublk.rst b/Documentation/block/ublk.rst index c368e1081b41..8c4030bcabb6 100644 --- a/Documentation/block/ublk.rst +++ b/Documentation/block/ublk.rst @@ -352,6 +352,83 @@ For reaching best IO performance, ublk server should align its segment parameter of `struct ublk_param_segment` with backend for avoiding unnecessary IO split, which usually hurts io_uring performance. +Auto Buffer Registration +------------------------ + +The ``UBLK_F_AUTO_BUF_REG`` feature automatically handles buffer registration +and unregistration for I/O requests, which simplifies the buffer management +process and reduces overhead in the ublk server implementation. + +This is another feature flag for using zero copy, and it is compatible with +``UBLK_F_SUPPORT_ZERO_COPY``. + +Feature Overview +~~~~~~~~~~~~~~~~ + +This feature automatically registers request buffers to the io_uring context +before delivering I/O commands to the ublk server and unregisters them when +completing I/O commands. This eliminates the need for manual buffer +registration/unregistration via ``UBLK_IO_REGISTER_IO_BUF`` and +``UBLK_IO_UNREGISTER_IO_BUF`` commands, then IO handling in ublk server +can avoid dependency on the two uring_cmd operations. + +IOs can't be issued concurrently to io_uring if there is any dependency +among these IOs. So this way not only simplifies ublk server implementation, +but also makes concurrent IO handling becomes possible by removing the +dependency on buffer registration & unregistration commands. + +Usage Requirements +~~~~~~~~~~~~~~~~~~ + +1. The ublk server must create a sparse buffer table on the same ``io_ring_ctx`` + used for ``UBLK_IO_FETCH_REQ`` and ``UBLK_IO_COMMIT_AND_FETCH_REQ``. If + uring_cmd is issued on a different ``io_ring_ctx``, manual buffer + unregistration is required. + +2. Buffer registration data must be passed via uring_cmd's ``sqe->addr`` with the + following structure:: + + struct ublk_auto_buf_reg { + __u16 index; /* Buffer index for registration */ + __u8 flags; /* Registration flags */ + __u8 reserved0; /* Reserved for future use */ + __u32 reserved1; /* Reserved for future use */ + }; + + ublk_auto_buf_reg_to_sqe_addr() is for converting the above structure into + ``sqe->addr``. + +3. All reserved fields in ``ublk_auto_buf_reg`` must be zeroed. + +4. Optional flags can be passed via ``ublk_auto_buf_reg.flags``. + +Fallback Behavior +~~~~~~~~~~~~~~~~~ + +If auto buffer registration fails: + +1. When ``UBLK_AUTO_BUF_REG_FALLBACK`` is enabled: + + - The uring_cmd is completed + - ``UBLK_IO_F_NEED_REG_BUF`` is set in ``ublksrv_io_desc.op_flags`` + - The ublk server must manually deal with the failure, such as, register + the buffer manually, or using user copy feature for retrieving the data + for handling ublk IO + +2. If fallback is not enabled: + + - The ublk I/O request fails silently + - The uring_cmd won't be completed + +Limitations +~~~~~~~~~~~ + +- Requires same ``io_ring_ctx`` for all operations +- May require manual buffer management in fallback cases +- io_ring_ctx buffer table has a max size of 16K, which may not be enough + in case that too many ublk devices are handled by this single io_ring_ctx + and each one has very large queue depth + References ========== diff --git a/Documentation/devicetree/bindings/clock/alphascale,acc.txt b/Documentation/devicetree/bindings/clock/alphascale,acc.txt deleted file mode 100644 index c9fb9324c634..000000000000 --- a/Documentation/devicetree/bindings/clock/alphascale,acc.txt +++ /dev/null @@ -1,114 +0,0 @@ -Alphascale Clock Controller - -The ACC (Alphascale Clock Controller) is responsible for choosing proper -clock source, setting dividers and clock gates. - -Required properties for the ACC node: - - compatible: must be "alphascale,asm9260-clock-controller" - - reg: must contain the ACC register base and size - - #clock-cells : shall be set to 1. - -Simple one-cell clock specifier format is used, where the only cell is used -as an index of the clock inside the provider. -It is encouraged to use dt-binding for clock index definitions. SoC specific -dt-binding should be included to the device tree descriptor. For example -Alphascale ASM9260: -#include <dt-bindings/clock/alphascale,asm9260.h> - -This binding contains two types of clock providers: - _AHB_ - AHB gate; - _SYS_ - adjustable clock source. Not all peripheral have _SYS_ clock provider. -All clock specific details can be found in the SoC documentation. -CLKID_AHB_ROM 0 -CLKID_AHB_RAM 1 -CLKID_AHB_GPIO 2 -CLKID_AHB_MAC 3 -CLKID_AHB_EMI 4 -CLKID_AHB_USB0 5 -CLKID_AHB_USB1 6 -CLKID_AHB_DMA0 7 -CLKID_AHB_DMA1 8 -CLKID_AHB_UART0 9 -CLKID_AHB_UART1 10 -CLKID_AHB_UART2 11 -CLKID_AHB_UART3 12 -CLKID_AHB_UART4 13 -CLKID_AHB_UART5 14 -CLKID_AHB_UART6 15 -CLKID_AHB_UART7 16 -CLKID_AHB_UART8 17 -CLKID_AHB_UART9 18 -CLKID_AHB_I2S0 19 -CLKID_AHB_I2C0 20 -CLKID_AHB_I2C1 21 -CLKID_AHB_SSP0 22 -CLKID_AHB_IOCONFIG 23 -CLKID_AHB_WDT 24 -CLKID_AHB_CAN0 25 -CLKID_AHB_CAN1 26 -CLKID_AHB_MPWM 27 -CLKID_AHB_SPI0 28 -CLKID_AHB_SPI1 29 -CLKID_AHB_QEI 30 -CLKID_AHB_QUADSPI0 31 -CLKID_AHB_CAMIF 32 -CLKID_AHB_LCDIF 33 -CLKID_AHB_TIMER0 34 -CLKID_AHB_TIMER1 35 -CLKID_AHB_TIMER2 36 -CLKID_AHB_TIMER3 37 -CLKID_AHB_IRQ 38 -CLKID_AHB_RTC 39 -CLKID_AHB_NAND 40 -CLKID_AHB_ADC0 41 -CLKID_AHB_LED 42 -CLKID_AHB_DAC0 43 -CLKID_AHB_LCD 44 -CLKID_AHB_I2S1 45 -CLKID_AHB_MAC1 46 - -CLKID_SYS_CPU 47 -CLKID_SYS_AHB 48 -CLKID_SYS_I2S0M 49 -CLKID_SYS_I2S0S 50 -CLKID_SYS_I2S1M 51 -CLKID_SYS_I2S1S 52 -CLKID_SYS_UART0 53 -CLKID_SYS_UART1 54 -CLKID_SYS_UART2 55 -CLKID_SYS_UART3 56 -CLKID_SYS_UART4 56 -CLKID_SYS_UART5 57 -CLKID_SYS_UART6 58 -CLKID_SYS_UART7 59 -CLKID_SYS_UART8 60 -CLKID_SYS_UART9 61 -CLKID_SYS_SPI0 62 -CLKID_SYS_SPI1 63 -CLKID_SYS_QUADSPI 64 -CLKID_SYS_SSP0 65 -CLKID_SYS_NAND 66 -CLKID_SYS_TRACE 67 -CLKID_SYS_CAMM 68 -CLKID_SYS_WDT 69 -CLKID_SYS_CLKOUT 70 -CLKID_SYS_MAC 71 -CLKID_SYS_LCD 72 -CLKID_SYS_ADCANA 73 - -Example of clock consumer with _SYS_ and _AHB_ sinks. -uart4: serial@80010000 { - compatible = "alphascale,asm9260-uart"; - reg = <0x80010000 0x4000>; - clocks = <&acc CLKID_SYS_UART4>, <&acc CLKID_AHB_UART4>; - interrupts = <19>; -}; - -Clock consumer with only one, _AHB_ sink. -timer0: timer@80088000 { - compatible = "alphascale,asm9260-timer"; - reg = <0x80088000 0x4000>; - clocks = <&acc CLKID_AHB_TIMER0>; - interrupts = <29>; -}; - diff --git a/Documentation/devicetree/bindings/clock/alphascale,asm9260-clock-controller.yaml b/Documentation/devicetree/bindings/clock/alphascale,asm9260-clock-controller.yaml new file mode 100644 index 000000000000..1caad419ce9d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/alphascale,asm9260-clock-controller.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/alphascale,asm9260-clock-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Alphascale Clock Controller + +maintainers: + - Oleksij Rempel <linux@rempel-privat.de> + +description: | + The ACC (Alphascale Clock Controller) is responsible for choosing proper + clock source, setting dividers and clock gates. + + Simple one-cell clock specifier format is used, where the only cell is used + as an index of the clock inside the provider. + It is encouraged to use dt-binding for clock index definitions. SoC specific + dt-binding should be included to the device tree descriptor. For example + Alphascale ASM9260: + + #include <dt-bindings/clock/alphascale,asm9260.h> + + This binding contains two types of clock providers: + + _AHB_ - AHB gate; + _SYS_ - adjustable clock source. Not all peripheral have _SYS_ clock provider. + + All clock specific details can be found in the SoC documentation. + +properties: + compatible: + const: alphascale,asm9260-clock-controller + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/clock/apm,xgene-device-clock.yaml b/Documentation/devicetree/bindings/clock/apm,xgene-device-clock.yaml new file mode 100644 index 000000000000..b27bcb2a9ee0 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/apm,xgene-device-clock.yaml @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/apm,xgene-device-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: APM X-Gene SoC device clocks + +maintainers: + - Khuong Dinh <khuong@os.amperecomputing.com> + +properties: + compatible: + const: apm,xgene-device-clock + + reg: + minItems: 1 + maxItems: 2 + + reg-names: + items: + - enum: [ csr-reg, div-reg ] + - const: div-reg + minItems: 1 + + clocks: + maxItems: 1 + + "#clock-cells": + const: 1 + + clock-output-names: + maxItems: 1 + + clock-names: + maxItems: 1 + + csr-offset: + description: Offset to the CSR reset register + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + + csr-mask: + description: CSR reset mask bit + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0xf + + enable-offset: + description: Offset to the enable register + $ref: /schemas/types.yaml#/definitions/uint32 + default: 8 + + enable-mask: + description: CSR enable mask bit + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0xf + + divider-offset: + description: Offset to the divider register + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + + divider-width: + description: Width of the divider register + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + + divider-shift: + description: Bit shift of the divider register + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + +required: + - compatible + - reg + - clocks + - '#clock-cells' + - clock-output-names + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/clock/apm,xgene-socpll-clock.yaml b/Documentation/devicetree/bindings/clock/apm,xgene-socpll-clock.yaml new file mode 100644 index 000000000000..bdd4a6b92bbd --- /dev/null +++ b/Documentation/devicetree/bindings/clock/apm,xgene-socpll-clock.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/apm,xgene-socpll-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: APM X-Gene SoC PLL, PCPPLL, and PMD clocks + +maintainers: + - Khuong Dinh <khuong@os.amperecomputing.com> + +properties: + compatible: + items: + - enum: + - apm,xgene-pcppll-clock + - apm,xgene-pcppll-v2-clock + - apm,xgene-pmd-clock + - apm,xgene-socpll-clock + - apm,xgene-socpll-v2-clock + + reg: + maxItems: 1 + + reg-names: + items: + - enum: [ csr-reg, div-reg ] + - const: div-reg + minItems: 1 + + clocks: + maxItems: 1 + + clock-names: + enum: [ pcppll, socpll ] + + "#clock-cells": + const: 1 + + clock-output-names: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - '#clock-cells' + - clock-output-names + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/clock/armada3700-periph-clock.txt b/Documentation/devicetree/bindings/clock/armada3700-periph-clock.txt deleted file mode 100644 index fbf58c443c04..000000000000 --- a/Documentation/devicetree/bindings/clock/armada3700-periph-clock.txt +++ /dev/null @@ -1,71 +0,0 @@ -* Peripheral Clock bindings for Marvell Armada 37xx SoCs - -Marvell Armada 37xx SoCs provide peripheral clocks which are -used as clock source for the peripheral of the SoC. - -There are two different blocks associated to north bridge and south -bridge. - -The peripheral clock consumer should specify the desired clock by -having the clock ID in its "clocks" phandle cell. - -The following is a list of provided IDs for Armada 3700 North bridge clocks: -ID Clock name Description ------------------------------------ -0 mmc MMC controller -1 sata_host Sata Host -2 sec_at Security AT -3 sac_dap Security DAP -4 tsecm Security Engine -5 setm_tmx Serial Embedded Trace Module -6 avs Adaptive Voltage Scaling -7 sqf SPI -8 pwm PWM -9 i2c_2 I2C 2 -10 i2c_1 I2C 1 -11 ddr_phy DDR PHY -12 ddr_fclk DDR F clock -13 trace Trace -14 counter Counter -15 eip97 EIP 97 -16 cpu CPU - -The following is a list of provided IDs for Armada 3700 South bridge clocks: -ID Clock name Description ------------------------------------ -0 gbe-50 50 MHz parent clock for Gigabit Ethernet -1 gbe-core parent clock for Gigabit Ethernet core -2 gbe-125 125 MHz parent clock for Gigabit Ethernet -3 gbe1-50 50 MHz clock for Gigabit Ethernet port 1 -4 gbe0-50 50 MHz clock for Gigabit Ethernet port 0 -5 gbe1-125 125 MHz clock for Gigabit Ethernet port 1 -6 gbe0-125 125 MHz clock for Gigabit Ethernet port 0 -7 gbe1-core Gigabit Ethernet core port 1 -8 gbe0-core Gigabit Ethernet core port 0 -9 gbe-bm Gigabit Ethernet Buffer Manager -10 sdio SDIO -11 usb32-sub2-sys USB 2 clock -12 usb32-ss-sys USB 3 clock -13 pcie PCIe controller - -Required properties: - -- compatible : shall be "marvell,armada-3700-periph-clock-nb" for the - north bridge block, or - "marvell,armada-3700-periph-clock-sb" for the south bridge block -- reg : must be the register address of North/South Bridge Clock register -- #clock-cells : from common clock binding; shall be set to 1 - -- clocks : list of the parent clock phandle in the following order: - TBG-A P, TBG-B P, TBG-A S, TBG-B S and finally the xtal clock. - - -Example: - -nb_perih_clk: nb-periph-clk@13000{ - compatible = "marvell,armada-3700-periph-clock-nb"; - reg = <0x13000 0x1000>; - clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, - <&tbg 3>, <&xtalclk>; - #clock-cells = <1>; -}; diff --git a/Documentation/devicetree/bindings/clock/armada3700-tbg-clock.txt b/Documentation/devicetree/bindings/clock/armada3700-tbg-clock.txt deleted file mode 100644 index ed1df32c577a..000000000000 --- a/Documentation/devicetree/bindings/clock/armada3700-tbg-clock.txt +++ /dev/null @@ -1,27 +0,0 @@ -* Time Base Generator Clock bindings for Marvell Armada 37xx SoCs - -Marvell Armada 37xx SoCs provide Time Base Generator clocks which are -used as parent clocks for the peripheral clocks. - -The TBG clock consumer should specify the desired clock by having the -clock ID in its "clocks" phandle cell. - -The following is a list of provided IDs and clock names on Armada 3700: - 0 = TBG A P - 1 = TBG B P - 2 = TBG A S - 3 = TBG B S - -Required properties: -- compatible : shall be "marvell,armada-3700-tbg-clock" -- reg : must be the register address of North Bridge PLL register -- #clock-cells : from common clock binding; shall be set to 1 - -Example: - -tbg: tbg@13200 { - compatible = "marvell,armada-3700-tbg-clock"; - reg = <0x13200 0x1000>; - clocks = <&xtalclk>; - #clock-cells = <1>; -}; diff --git a/Documentation/devicetree/bindings/clock/artpec6.txt b/Documentation/devicetree/bindings/clock/artpec6.txt deleted file mode 100644 index dff9cdf0009c..000000000000 --- a/Documentation/devicetree/bindings/clock/artpec6.txt +++ /dev/null @@ -1,41 +0,0 @@ -* Clock bindings for Axis ARTPEC-6 chip - -The bindings are based on the clock provider binding in -Documentation/devicetree/bindings/clock/clock-bindings.txt - -External clocks: ----------------- - -There are two external inputs to the main clock controller which should be -provided using the common clock bindings. -- "sys_refclk": External 50 Mhz oscillator (required) -- "i2s_refclk": Alternate audio reference clock (optional). - -Main clock controller ---------------------- - -Required properties: -- #clock-cells: Should be <1> - See dt-bindings/clock/axis,artpec6-clkctrl.h for the list of valid identifiers. -- compatible: Should be "axis,artpec6-clkctrl" -- reg: Must contain the base address and length of the system controller -- clocks: Must contain a phandle entry for each clock in clock-names -- clock-names: Must include the external oscillator ("sys_refclk"). Optional - ones are the audio reference clock ("i2s_refclk") and the audio fractional - dividers ("frac_clk0" and "frac_clk1"). - -Examples: - -ext_clk: ext_clk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <50000000>; -}; - -clkctrl: clkctrl@f8000000 { - #clock-cells = <1>; - compatible = "axis,artpec6-clkctrl"; - reg = <0xf8000000 0x48>; - clocks = <&ext_clk>; - clock-names = "sys_refclk"; -}; diff --git a/Documentation/devicetree/bindings/clock/axis,artpec6-clkctrl.yaml b/Documentation/devicetree/bindings/clock/axis,artpec6-clkctrl.yaml new file mode 100644 index 000000000000..a78269369df8 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/axis,artpec6-clkctrl.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/axis,artpec6-clkctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Axis ARTPEC-6 clock controller + +maintainers: + - Lars Persson <lars.persson@axis.com> + +properties: + compatible: + const: axis,artpec6-clkctrl + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + clocks: + minItems: 1 + items: + - description: external 50 MHz oscillator. + - description: optional audio reference clock. + - description: fractional audio clock divider 0. + - description: fractional audio clock divider 1. + + clock-names: + minItems: 1 + items: + - const: sys_refclk + - const: i2s_refclk + - const: frac_clk0 + - const: frac_clk1 + +required: + - compatible + - reg + - "#clock-cells" + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + clock-controller@f8000000 { + compatible = "axis,artpec6-clkctrl"; + reg = <0xf8000000 0x48>; + #clock-cells = <1>; + clocks = <&ext_clk>; + clock-names = "sys_refclk"; + }; diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt deleted file mode 100644 index 9e0b03a6519b..000000000000 --- a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt +++ /dev/null @@ -1,60 +0,0 @@ -Broadcom BCM2835 CPRMAN clocks - -This binding uses the common clock binding: - Documentation/devicetree/bindings/clock/clock-bindings.txt - -The CPRMAN clock controller generates clocks in the audio power domain -of the BCM2835. There is a level of PLLs deriving from an external -oscillator, a level of PLL dividers that produce channels off of the -few PLLs, and a level of mostly-generic clock generators sourcing from -the PLL channels. Most other hardware components source from the -clock generators, but a few (like the ARM or HDMI) will source from -the PLL dividers directly. - -Required properties: -- compatible: should be one of the following, - "brcm,bcm2711-cprman" - "brcm,bcm2835-cprman" -- #clock-cells: Should be <1>. The permitted clock-specifier values can be - found in include/dt-bindings/clock/bcm2835.h -- reg: Specifies base physical address and size of the registers -- clocks: phandles to the parent clocks used as input to the module, in - the following order: - - - External oscillator - - DSI0 byte clock - - DSI0 DDR2 clock - - DSI0 DDR clock - - DSI1 byte clock - - DSI1 DDR2 clock - - DSI1 DDR clock - - Only external oscillator is required. The DSI clocks may - not be present, in which case their children will be - unusable. - -Example: - - clk_osc: clock@3 { - compatible = "fixed-clock"; - reg = <3>; - #clock-cells = <0>; - clock-output-names = "osc"; - clock-frequency = <19200000>; - }; - - clocks: cprman@7e101000 { - compatible = "brcm,bcm2835-cprman"; - #clock-cells = <1>; - reg = <0x7e101000 0x2000>; - clocks = <&clk_osc>; - }; - - i2c0: i2c@7e205000 { - compatible = "brcm,bcm2835-i2c"; - reg = <0x7e205000 0x1000>; - interrupts = <2 21>; - clocks = <&clocks BCM2835_CLOCK_VPU>; - #address-cells = <1>; - #size-cells = <0>; - }; diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.yaml b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.yaml new file mode 100644 index 000000000000..b0cf76c74bc7 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/brcm,bcm2835-cprman.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM2835 CPRMAN clocks + +maintainers: + - Stefan Wahren <wahrenst@gmx.net> + - Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com> + +description: + The CPRMAN clock controller generates clocks in the audio power domain of the + BCM2835. There is a level of PLLs deriving from an external oscillator, a + level of PLL dividers that produce channels off of the few PLLs, and a level + of mostly-generic clock generators sourcing from the PLL channels. Most other + hardware components source from the clock generators, but a few (like the ARM + or HDMI) will source from the PLL dividers directly. + +properties: + compatible: + enum: + - brcm,bcm2711-cprman + - brcm,bcm2835-cprman + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + minItems: 1 + items: + - description: External oscillator clock. + - description: DSI0 byte clock. + - description: DSI0 DDR2 clock. + - description: DSI0 DDR clock. + - description: DSI1 byte clock. + - description: DSI1 DDR2 clock. + - description: DSI1 DDR clock. + +additionalProperties: false + +required: + - compatible + - '#clock-cells' + - reg + - clocks + +examples: + - | + clock-controller@7e101000 { + compatible = "brcm,bcm2835-cprman"; + reg = <0x7e101000 0x2000>; + #clock-cells = <1>; + clocks = <&clk_osc>; + }; diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm53573-ilp.txt b/Documentation/devicetree/bindings/clock/brcm,bcm53573-ilp.txt deleted file mode 100644 index 2ebb107331dd..000000000000 --- a/Documentation/devicetree/bindings/clock/brcm,bcm53573-ilp.txt +++ /dev/null @@ -1,36 +0,0 @@ -Broadcom BCM53573 ILP clock -=========================== - -This binding uses the common clock binding: - Documentation/devicetree/bindings/clock/clock-bindings.txt - -This binding is used for ILP clock (sometimes referred as "slow clock") -on Broadcom BCM53573 devices using Cortex-A7 CPU. - -ILP's rate has to be calculated on runtime and it depends on ALP clock -which has to be referenced. - -This clock is part of PMU (Power Management Unit), a Broadcom's device -handing power-related aspects. Its node must be sub-node of the PMU -device. - -Required properties: -- compatible: "brcm,bcm53573-ilp" -- clocks: has to reference an ALP clock -- #clock-cells: should be <0> -- clock-output-names: from common clock bindings, should contain clock - name - -Example: - -pmu@18012000 { - compatible = "simple-mfd", "syscon"; - reg = <0x18012000 0x00001000>; - - ilp { - compatible = "brcm,bcm53573-ilp"; - clocks = <&alp>; - #clock-cells = <0>; - clock-output-names = "ilp"; - }; -}; diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm53573-ilp.yaml b/Documentation/devicetree/bindings/clock/brcm,bcm53573-ilp.yaml new file mode 100644 index 000000000000..cd291f428a8d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/brcm,bcm53573-ilp.yaml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/brcm,bcm53573-ilp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM53573 ILP clock + +maintainers: + - Rafał Miłecki <rafal@milecki.pl> + +description: > + ILP clock (sometimes referred as "slow clock") on Broadcom BCM53573 devices + using Cortex-A7 CPU. + + ILP's rate has to be calculated on runtime and it depends on ALP clock which + has to be referenced. + + This clock is part of PMU (Power Management Unit), a Broadcom device handling + power-related aspects. Its node must be sub-node of the PMU device. + +properties: + compatible: + items: + - const: brcm,bcm53573-ilp + + clocks: + maxItems: 1 + + '#clock-cells': + const: 0 + + clock-output-names: + items: + - const: ilp + +additionalProperties: false + +examples: + - | + ilp { + compatible = "brcm,bcm53573-ilp"; + clocks = <&alp>; + #clock-cells = <0>; + clock-output-names = "ilp"; + }; diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.txt b/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.txt deleted file mode 100644 index 3e7ca5530775..000000000000 --- a/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.txt +++ /dev/null @@ -1,24 +0,0 @@ -Gated Clock Controller Bindings for MIPS based BCM63XX SoCs - -Required properties: -- compatible: must be one of: - "brcm,bcm3368-clocks" - "brcm,bcm6318-clocks" - "brcm,bcm6318-ubus-clocks" - "brcm,bcm6328-clocks" - "brcm,bcm6358-clocks" - "brcm,bcm6362-clocks" - "brcm,bcm6368-clocks" - "brcm,bcm63268-clocks" - -- reg: Address and length of the register set -- #clock-cells: must be <1> - - -Example: - -clkctl: clock-controller@10000004 { - compatible = "brcm,bcm6328-clocks"; - reg = <0x10000004 0x4>; - #clock-cells = <1>; -}; diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.yaml b/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.yaml new file mode 100644 index 000000000000..56909ea499a2 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/brcm,bcm63xx-clocks.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MIPS based BCM63XX SoCs Gated Clock Controller + +maintainers: + - Álvaro Fernández Rojas <noltari@gmail.com> + - Jonas Gorski <jonas.gorski@gmail.com> + +properties: + compatible: + enum: + - brcm,bcm3368-clocks + - brcm,bcm6318-clocks + - brcm,bcm6318-ubus-clocks + - brcm,bcm6328-clocks + - brcm,bcm6358-clocks + - brcm,bcm6362-clocks + - brcm,bcm6368-clocks + - brcm,bcm63268-clocks + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@10000004 { + compatible = "brcm,bcm6328-clocks"; + reg = <0x10000004 0x4>; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/cirrus,ep7209-clk.yaml b/Documentation/devicetree/bindings/clock/cirrus,ep7209-clk.yaml new file mode 100644 index 000000000000..fbd0d50d46a8 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/cirrus,ep7209-clk.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/cirrus,ep7209-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cirrus Logic CLPS711X Clock Controller + +maintainers: + - Alexander Shiyan <shc_work@mail.ru> + +description: + See include/dt-bindings/clock/clps711x-clock.h for the full list of CLPS711X + clock IDs. + +properties: + compatible: + items: + - const: cirrus,ep7312-clk + - const: cirrus,ep7209-clk + + reg: + maxItems: 1 + + startup-frequency: + description: Factory set CPU startup frequency in HZ. + $ref: /schemas/types.yaml#/definitions/uint32 + + "#clock-cells": + const: 1 + +required: + - compatible + - reg + - startup-frequency + - "#clock-cells" + +additionalProperties: false + +examples: + - | + clock-controller@80000000 { + compatible = "cirrus,ep7312-clk", "cirrus,ep7209-clk"; + reg = <0x80000000 0xc000>; + #clock-cells = <1>; + startup-frequency = <73728000>; + }; diff --git a/Documentation/devicetree/bindings/clock/clps711x-clock.txt b/Documentation/devicetree/bindings/clock/clps711x-clock.txt deleted file mode 100644 index f1bd53f79d91..000000000000 --- a/Documentation/devicetree/bindings/clock/clps711x-clock.txt +++ /dev/null @@ -1,19 +0,0 @@ -* Clock bindings for the Cirrus Logic CLPS711X CPUs - -Required properties: -- compatible : Shall contain "cirrus,ep7209-clk". -- reg : Address of the internal register set. -- startup-frequency: Factory set CPU startup frequency in HZ. -- #clock-cells : Should be <1>. - -The clock consumer should specify the desired clock by having the clock -ID in its "clocks" phandle cell. See include/dt-bindings/clock/clps711x-clock.h -for the full list of CLPS711X clock IDs. - -Example: - clks: clks@80000000 { - #clock-cells = <1>; - compatible = "cirrus,ep7312-clk", "cirrus,ep7209-clk"; - reg = <0x80000000 0xc000>; - startup-frequency = <73728000>; - }; diff --git a/Documentation/devicetree/bindings/clock/dove-divider-clock.txt b/Documentation/devicetree/bindings/clock/dove-divider-clock.txt deleted file mode 100644 index 217871f483c0..000000000000 --- a/Documentation/devicetree/bindings/clock/dove-divider-clock.txt +++ /dev/null @@ -1,28 +0,0 @@ -PLL divider based Dove clocks - -Marvell Dove has a 2GHz PLL, which feeds into a set of dividers to provide -high speed clocks for a number of peripherals. These dividers are part of -the PMU, and thus this node should be a child of the PMU node. - -The following clocks are provided: - -ID Clock -------------- -0 AXI bus clock -1 GPU clock -2 VMeta clock -3 LCD clock - -Required properties: -- compatible : shall be "marvell,dove-divider-clock" -- reg : shall be the register address of the Core PLL and Clock Divider - Control 0 register. This will cover that register, as well as the - Core PLL and Clock Divider Control 1 register. Thus, it will have - a size of 8. -- #clock-cells : from common clock binding; shall be set to 1 - -divider_clk: core-clock@64 { - compatible = "marvell,dove-divider-clock"; - reg = <0x0064 0x8>; - #clock-cells = <1>; -}; diff --git a/Documentation/devicetree/bindings/clock/img,pistachio-clk.yaml b/Documentation/devicetree/bindings/clock/img,pistachio-clk.yaml new file mode 100644 index 000000000000..e70feee8e894 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/img,pistachio-clk.yaml @@ -0,0 +1,136 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/img,pistachio-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Imagination Technologies Pistachio SoC clock controllers + +maintainers: + - Andrew Bresticker <abrestic@chromium.org> + +description: | + Pistachio has four clock controllers (core clock, peripheral clock, peripheral + general control, and top general control) which are instantiated individually + from the device-tree. + + Core clock controller: + + The core clock controller generates clocks for the CPU, RPU (WiFi + BT + co-processor), audio, and several peripherals. + + Peripheral clock controller: + + The peripheral clock controller generates clocks for the DDR, ROM, and other + peripherals. The peripheral system clock ("periph_sys") generated by the core + clock controller is the input clock to the peripheral clock controller. + + Peripheral general control: + + The peripheral general control block generates system interface clocks and + resets for various peripherals. It also contains miscellaneous peripheral + control registers. + + Top-level general control: + + The top-level general control block contains miscellaneous control registers + and gates for the external clocks "audio_clk_in" and "enet_clk_in". + +properties: + compatible: + items: + - enum: + - img,pistachio-clk + - img,pistachio-clk-periph + - img,pistachio-cr-periph + - img,pistachio-cr-top + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + minItems: 1 + maxItems: 3 + + clock-names: + minItems: 1 + maxItems: 3 + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +allOf: + - if: + properties: + compatible: + contains: + const: img,pistachio-clk + then: + properties: + clocks: + items: + - description: External 52Mhz oscillator + - description: Alternate audio reference clock + - description: Alternate ethernet PHY clock + + clock-names: + items: + - const: xtal + - const: audio_refclk_ext_gate + - const: ext_enet_in_gate + + - if: + properties: + compatible: + contains: + const: img,pistachio-clk-periph + then: + properties: + clocks: + items: + - description: Peripheral system clock + + clock-names: + items: + - const: periph_sys_core + + - if: + properties: + compatible: + contains: + const: img,pistachio-cr-periph + then: + properties: + clocks: + items: + - description: System interface clock + + clock-names: + items: + - const: sys + + - if: + properties: + compatible: + contains: + const: img,pistachio-cr-top + then: + properties: + clocks: + items: + - description: External audio reference clock + - description: External ethernet PHY clock + + clock-names: + items: + - const: audio_clk_in + - const: enet_clk_in + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt deleted file mode 100644 index 8cf8f0ecdd16..000000000000 --- a/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt +++ /dev/null @@ -1,77 +0,0 @@ -* NXP LPC1850 Clock Control Unit (CCU) - -Each CGU base clock has several clock branches which can be turned on -or off independently by the Clock Control Units CCU1 or CCU2. The -branch clocks are distributed between CCU1 and CCU2. - - - Above text taken from NXP LPC1850 User Manual. - -This binding uses the common clock binding: - Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible: - Should be "nxp,lpc1850-ccu" -- reg: - Shall define the base and range of the address space - containing clock control registers -- #clock-cells: - Shall have value <1>. The permitted clock-specifier values - are the branch clock names defined in table below. -- clocks: - Shall contain a list of phandles for the base clocks routed - from the CGU to the specific CCU. See mapping of base clocks - and CCU in table below. -- clock-names: - Shall contain a list of names for the base clock routed - from the CGU to the specific CCU. Valid CCU clock names: - "base_usb0_clk", "base_periph_clk", "base_usb1_clk", - "base_cpu_clk", "base_spifi_clk", "base_spi_clk", - "base_apb1_clk", "base_apb3_clk", "base_adchs_clk", - "base_sdio_clk", "base_ssp0_clk", "base_ssp1_clk", - "base_uart0_clk", "base_uart1_clk", "base_uart2_clk", - "base_uart3_clk", "base_audio_clk" - -Which branch clocks that are available on the CCU depends on the -specific LPC part. Check the user manual for your specific part. - -A list of CCU clocks can be found in dt-bindings/clock/lpc18xx-ccu.h. - -Example board file: - -soc { - ccu1: clock-controller@40051000 { - compatible = "nxp,lpc1850-ccu"; - reg = <0x40051000 0x1000>; - #clock-cells = <1>; - clocks = <&cgu BASE_APB3_CLK>, <&cgu BASE_APB1_CLK>, - <&cgu BASE_SPIFI_CLK>, <&cgu BASE_CPU_CLK>, - <&cgu BASE_PERIPH_CLK>, <&cgu BASE_USB0_CLK>, - <&cgu BASE_USB1_CLK>, <&cgu BASE_SPI_CLK>; - clock-names = "base_apb3_clk", "base_apb1_clk", - "base_spifi_clk", "base_cpu_clk", - "base_periph_clk", "base_usb0_clk", - "base_usb1_clk", "base_spi_clk"; - }; - - ccu2: clock-controller@40052000 { - compatible = "nxp,lpc1850-ccu"; - reg = <0x40052000 0x1000>; - #clock-cells = <1>; - clocks = <&cgu BASE_AUDIO_CLK>, <&cgu BASE_UART3_CLK>, - <&cgu BASE_UART2_CLK>, <&cgu BASE_UART1_CLK>, - <&cgu BASE_UART0_CLK>, <&cgu BASE_SSP1_CLK>, - <&cgu BASE_SSP0_CLK>, <&cgu BASE_SDIO_CLK>; - clock-names = "base_audio_clk", "base_uart3_clk", - "base_uart2_clk", "base_uart1_clk", - "base_uart0_clk", "base_ssp1_clk", - "base_ssp0_clk", "base_sdio_clk"; - }; - - /* A user of CCU branch clocks */ - uart1: serial@40082000 { - ... - clocks = <&ccu2 CLK_APB0_UART1>, <&ccu1 CLK_CPU_UART1>; - ... - }; -}; diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt deleted file mode 100644 index 2cc32a9a945a..000000000000 --- a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt +++ /dev/null @@ -1,131 +0,0 @@ -* NXP LPC1850 Clock Generation Unit (CGU) - -The CGU generates multiple independent clocks for the core and the -peripheral blocks of the LPC18xx. Each independent clock is called -a base clock and itself is one of the inputs to the two Clock -Control Units (CCUs) which control the branch clocks to the -individual peripherals. - -The CGU selects the inputs to the clock generators from multiple -clock sources, controls the clock generation, and routes the outputs -of the clock generators through the clock source bus to the output -stages. Each output stage provides an independent clock source and -corresponds to one of the base clocks for the LPC18xx. - - - Above text taken from NXP LPC1850 User Manual. - - -This binding uses the common clock binding: - Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible: - Should be "nxp,lpc1850-cgu" -- reg: - Shall define the base and range of the address space - containing clock control registers -- #clock-cells: - Shall have value <1>. The permitted clock-specifier values - are the base clock numbers defined below. -- clocks: - Shall contain a list of phandles for the external input - sources to the CGU. The list shall be in the following - order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin. -- clock-indices: - Shall be an ordered list of numbers defining the base clock - number provided by the CGU. -- clock-output-names: - Shall be an ordered list of strings defining the names of - the clocks provided by the CGU. - -Which base clocks that are available on the CGU depends on the -specific LPC part. Base clocks are numbered from 0 to 27. - -Number: Name: Description: - 0 BASE_SAFE_CLK Base safe clock (always on) for WWDT - 1 BASE_USB0_CLK Base clock for USB0 - 2 BASE_PERIPH_CLK Base clock for Cortex-M0SUB subsystem, - SPI, and SGPIO - 3 BASE_USB1_CLK Base clock for USB1 - 4 BASE_CPU_CLK System base clock for ARM Cortex-M core - and APB peripheral blocks #0 and #2 - 5 BASE_SPIFI_CLK Base clock for SPIFI - 6 BASE_SPI_CLK Base clock for SPI - 7 BASE_PHY_RX_CLK Base clock for Ethernet PHY Receive clock - 8 BASE_PHY_TX_CLK Base clock for Ethernet PHY Transmit clock - 9 BASE_APB1_CLK Base clock for APB peripheral block # 1 -10 BASE_APB3_CLK Base clock for APB peripheral block # 3 -11 BASE_LCD_CLK Base clock for LCD -12 BASE_ADCHS_CLK Base clock for ADCHS -13 BASE_SDIO_CLK Base clock for SD/MMC -14 BASE_SSP0_CLK Base clock for SSP0 -15 BASE_SSP1_CLK Base clock for SSP1 -16 BASE_UART0_CLK Base clock for UART0 -17 BASE_UART1_CLK Base clock for UART1 -18 BASE_UART2_CLK Base clock for UART2 -19 BASE_UART3_CLK Base clock for UART3 -20 BASE_OUT_CLK Base clock for CLKOUT pin -24-21 - Reserved -25 BASE_AUDIO_CLK Base clock for audio system (I2S) -26 BASE_CGU_OUT0_CLK Base clock for CGU_OUT0 clock output -27 BASE_CGU_OUT1_CLK Base clock for CGU_OUT1 clock output - -BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx. -BASE_ADCHS_CLK is only available on LPC4370. - - -Example board file: - -/ { - clocks { - xtal: xtal { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <12000000>; - }; - - xtal32: xtal32 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <32768>; - }; - - enet_rx_clk: enet_rx_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <0>; - clock-output-names = "enet_rx_clk"; - }; - - enet_tx_clk: enet_tx_clk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <0>; - clock-output-names = "enet_tx_clk"; - }; - - gp_clkin: gp_clkin { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <0>; - clock-output-names = "gp_clkin"; - }; - }; - - soc { - cgu: clock-controller@40050000 { - compatible = "nxp,lpc1850-cgu"; - reg = <0x40050000 0x1000>; - #clock-cells = <1>; - clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>; - }; - - /* A CGU and CCU clock consumer */ - lcdc: lcdc@40008000 { - ... - clocks = <&cgu BASE_LCD_CLK>, <&ccu1 CLK_CPU_LCD>; - clock-names = "clcdclk", "apb_pclk"; - ... - }; - }; -}; diff --git a/Documentation/devicetree/bindings/clock/lsi,axm5516-clks.txt b/Documentation/devicetree/bindings/clock/lsi,axm5516-clks.txt deleted file mode 100644 index 3ce97cfe999b..000000000000 --- a/Documentation/devicetree/bindings/clock/lsi,axm5516-clks.txt +++ /dev/null @@ -1,29 +0,0 @@ -AXM5516 clock driver bindings ------------------------------ - -Required properties : -- compatible : shall contain "lsi,axm5516-clks" -- reg : shall contain base register location and length -- #clock-cells : shall contain 1 - -The consumer specifies the desired clock by having the clock ID in its "clocks" -phandle cell. See <dt-bindings/clock/lsi,axxia-clock.h> for the list of -supported clock IDs. - -Example: - - clks: clock-controller@2010020000 { - compatible = "lsi,axm5516-clks"; - #clock-cells = <1>; - reg = <0x20 0x10020000 0 0x20000>; - }; - - serial0: uart@2010080000 { - compatible = "arm,pl011", "arm,primecell"; - reg = <0x20 0x10080000 0 0x1000>; - interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks AXXIA_CLK_PER>; - clock-names = "apb_pclk"; - }; - }; - diff --git a/Documentation/devicetree/bindings/clock/lsi,axm5516-clks.yaml b/Documentation/devicetree/bindings/clock/lsi,axm5516-clks.yaml new file mode 100644 index 000000000000..7a792dbeffb3 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/lsi,axm5516-clks.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright 2025 LSI +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/lsi,axm5516-clks.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LSI AXM5516 Clock Controller + +maintainers: + - Anders Berg <anders.berg@lsi.com> + +description: + See <dt-bindings/clock/lsi,axxia-clock.h> for the list of supported clock IDs. + +properties: + compatible: + const: lsi,axm5516-clks + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + - | + bus { + #address-cells = <2>; + #size-cells = <1>; + clock-controller@2010020000 { + compatible = "lsi,axm5516-clks"; + #clock-cells = <1>; + reg = <0x20 0x10020000 0x20000>; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/lsi,nspire-cx-clock.yaml b/Documentation/devicetree/bindings/clock/lsi,nspire-cx-clock.yaml new file mode 100644 index 000000000000..52c217d210d0 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/lsi,nspire-cx-clock.yaml @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/lsi,nspire-cx-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI-NSPIRE Clocks + +maintainers: + - Daniel Tang <dt.tangr@gmail.com> + +properties: + compatible: + enum: + - lsi,nspire-cx-ahb-divider + - lsi,nspire-classic-ahb-divider + - lsi,nspire-cx-clock + - lsi,nspire-classic-clock + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + '#clock-cells': + const: 0 + +additionalProperties: false + +required: + - compatible + - reg diff --git a/Documentation/devicetree/bindings/clock/marvell,armada-370-corediv-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,armada-370-corediv-clock.yaml new file mode 100644 index 000000000000..9d766558cdb9 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,armada-370-corediv-clock.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/marvell,armada-370-corediv-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell MVEBU Core Divider Clock + +maintainers: + - Andrew Lunn <andrew@lunn.ch> + - Gregory Clement <gregory.clement@bootlin.com> + +properties: + compatible: + oneOf: + - enum: + - marvell,armada-370-corediv-clock + - marvell,armada-375-corediv-clock + - marvell,armada-380-corediv-clock + - marvell,mv98dx3236-corediv-clock + - items: + - const: marvell,armada-390-corediv-clock + - const: marvell,armada-380-corediv-clock + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + +required: + - compatible + - reg + - "#clock-cells" + - clocks + +additionalProperties: false + +examples: + - | + clock-controller@18740 { + compatible = "marvell,armada-370-corediv-clock"; + reg = <0x18740 0xc>; + #clock-cells = <1>; + clocks = <&pll>; + }; diff --git a/Documentation/devicetree/bindings/clock/marvell,armada-3700-periph-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,armada-3700-periph-clock.yaml new file mode 100644 index 000000000000..87e8e4ca111a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,armada-3700-periph-clock.yaml @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/marvell,armada-3700-periph-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell Armada 37xx SoCs Peripheral Clocks + +maintainers: + - Andrew Lunn <andrew@lunn.ch> + - Gregory Clement <gregory.clement@bootlin.com> + +description: > + Marvell Armada 37xx SoCs provide peripheral clocks which are used as clock + source for the peripheral of the SoC. + + There are two different blocks associated to north bridge and south bridge. + + The following is a list of provided IDs for Armada 3700 North bridge clocks: + + ID Clock name Description + ----------------------------------- + 0 mmc MMC controller + 1 sata_host Sata Host + 2 sec_at Security AT + 3 sac_dap Security DAP + 4 tsecm Security Engine + 5 setm_tmx Serial Embedded Trace Module + 6 avs Adaptive Voltage Scaling + 7 sqf SPI + 8 pwm PWM + 9 i2c_2 I2C 2 + 10 i2c_1 I2C 1 + 11 ddr_phy DDR PHY + 12 ddr_fclk DDR F clock + 13 trace Trace + 14 counter Counter + 15 eip97 EIP 97 + 16 cpu CPU + + The following is a list of provided IDs for Armada 3700 South bridge clocks: + + ID Clock name Description + ----------------------------------- + 0 gbe-50 50 MHz parent clock for Gigabit Ethernet + 1 gbe-core parent clock for Gigabit Ethernet core + 2 gbe-125 125 MHz parent clock for Gigabit Ethernet + 3 gbe1-50 50 MHz clock for Gigabit Ethernet port 1 + 4 gbe0-50 50 MHz clock for Gigabit Ethernet port 0 + 5 gbe1-125 125 MHz clock for Gigabit Ethernet port 1 + 6 gbe0-125 125 MHz clock for Gigabit Ethernet port 0 + 7 gbe1-core Gigabit Ethernet core port 1 + 8 gbe0-core Gigabit Ethernet core port 0 + 9 gbe-bm Gigabit Ethernet Buffer Manager + 10 sdio SDIO + 11 usb32-sub2-sys USB 2 clock + 12 usb32-ss-sys USB 3 clock + 13 pcie PCIe controller + +properties: + compatible: + oneOf: + - const: marvell,armada-3700-periph-clock-sb + - items: + - const: marvell,armada-3700-periph-clock-nb + - const: syscon + reg: + maxItems: 1 + + clocks: + items: + - description: TBG-A P clock and specifier + - description: TBG-B P clock and specifier + - description: TBG-A S clock and specifier + - description: TBG-B S clock and specifier + - description: Xtal clock and specifier + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + - clocks + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@13000{ + compatible = "marvell,armada-3700-periph-clock-sb"; + reg = <0x13000 0x1000>; + clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, <&tbg 3>, <&xtalclk>; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/marvell,armada-3700-tbg-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,armada-3700-tbg-clock.yaml new file mode 100644 index 000000000000..7fd1d758f794 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,armada-3700-tbg-clock.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/marvell,armada-3700-tbg-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell Armada 3700 Time Base Generator Clock + +maintainers: + - Andrew Lunn <andrew@lunn.ch> + - Gregory Clement <gregory.clement@bootlin.com> + +description: > + Marvell Armada 37xx SoCs provide Time Base Generator clocks which are used as + parent clocks for the peripheral clocks. + + The TBG clock consumer should specify the desired clock by having the clock ID + in its "clocks" phandle cell. + + The following is a list of provided IDs and clock names on Armada 3700: + + 0 = TBG A P + 1 = TBG B P + 2 = TBG A S + 3 = TBG B S + +properties: + compatible: + const: marvell,armada-3700-tbg-clock + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@13200 { + compatible = "marvell,armada-3700-tbg-clock"; + reg = <0x13200 0x1000>; + clocks = <&xtalclk>; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/marvell,armada-xp-cpu-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,armada-xp-cpu-clock.yaml new file mode 100644 index 000000000000..f2ac6741da9a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,armada-xp-cpu-clock.yaml @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +--- +$schema: http://devicetree.org/meta-schemas/core.yaml# +$id: http://devicetree.org/schemas/clock/marvell,armada-xp-cpu-clock.yaml# + +title: Marvell EBU CPU Clock + +maintainers: + - Andrew Lunn <andrew@lunn.ch> + - Gregory Clement <gregory.clement@bootlin.com> + +properties: + compatible: + enum: + - marvell,armada-xp-cpu-clock + - marvell,mv98dx3236-cpu-clock + + reg: + items: + - description: Clock complex registers + - description: PMU DFS registers + + '#clock-cells': + const: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - '#clock-cells' + - clocks + +additionalProperties: false + +examples: + - | + clock-controller@d0018700 { + #clock-cells = <1>; + compatible = "marvell,armada-xp-cpu-clock"; + reg = <0xd0018700 0xa0>, <0x1c054 0x10>; + clocks = <&coreclk 1>; + }; diff --git a/Documentation/devicetree/bindings/clock/marvell,berlin.txt b/Documentation/devicetree/bindings/clock/marvell,berlin.txt deleted file mode 100644 index c611c495f3ff..000000000000 --- a/Documentation/devicetree/bindings/clock/marvell,berlin.txt +++ /dev/null @@ -1,31 +0,0 @@ -Device Tree Clock bindings for Marvell Berlin - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Clock related registers are spread among the chip control registers. Berlin -clock node should be a sub-node of the chip controller node. Marvell Berlin2 -(BG2, BG2CD, BG2Q) SoCs share the same IP for PLLs and clocks, with some -minor differences in features and register layout. - -Required properties: -- compatible: must be "marvell,berlin2-clk" or "marvell,berlin2q-clk" -- #clock-cells: must be 1 -- clocks: must be the input parent clock phandle -- clock-names: name of the input parent clock - Allowed clock-names for the reference clocks are - "refclk" for the SoCs oscillator input on all SoCs, - and SoC-specific input clocks for - BG2/BG2CD: "video_ext0" for the external video clock input - - -Example: - -chip_clk: clock { - compatible = "marvell,berlin2q-clk"; - - #clock-cells = <1>; - clocks = <&refclk>; - clock-names = "refclk"; -}; diff --git a/Documentation/devicetree/bindings/clock/marvell,berlin2-clk.yaml b/Documentation/devicetree/bindings/clock/marvell,berlin2-clk.yaml new file mode 100644 index 000000000000..8d48a2c7e381 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,berlin2-clk.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/marvell,berlin2-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell Berlin Clock Controller + +maintainers: + - Jisheng Zhang <jszhang@kernel.org> + +description: + Clock related registers are spread among the chip control registers. Berlin + clock node should be a sub-node of the chip controller node. Marvell Berlin2 + (BG2, BG2CD, BG2Q) SoCs share the same IP for PLLs and clocks, with some minor + differences in features and register layout. + +properties: + compatible: + enum: + - marvell,berlin2-clk + - marvell,berlin2q-clk + + '#clock-cells': + const: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - enum: + - refclk + - video_ext0 + +required: + - compatible + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + clock-controller { + compatible = "marvell,berlin2q-clk"; + #clock-cells = <1>; + clocks = <&refclk>; + clock-names = "refclk"; + }; diff --git a/Documentation/devicetree/bindings/clock/marvell,dove-divider-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,dove-divider-clock.yaml new file mode 100644 index 000000000000..7a8e0e281b63 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,dove-divider-clock.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/marvell,dove-divider-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell Dove PLL Divider Clock + +maintainers: + - Andrew Lunn <andrew@lunn.ch> + - Gregory Clement <gregory.clement@bootlin.com> + +description: > + Marvell Dove has a 2GHz PLL, which feeds into a set of dividers to provide + high speed clocks for a number of peripherals. These dividers are part of the + PMU, and thus this node should be a child of the PMU node. + + The following clocks are provided: + + ID Clock + ------------- + 0 AXI bus clock + 1 GPU clock + 2 VMeta clock + 3 LCD clock + +properties: + compatible: + const: marvell,dove-divider-clock + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@64 { + compatible = "marvell,dove-divider-clock"; + reg = <0x0064 0x8>; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/marvell,mvebu-core-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,mvebu-core-clock.yaml new file mode 100644 index 000000000000..215bcd9080c3 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell,mvebu-core-clock.yaml @@ -0,0 +1,94 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/marvell,mvebu-core-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell MVEBU SoC core clock + +maintainers: + - Andrew Lunn <andrew@lunn.ch> + - Gregory Clement <gregory.clement@bootlin.com> + +description: > + Marvell MVEBU SoCs usually allow to determine core clock frequencies by + reading the Sample-At-Reset (SAR) register. The core clock consumer should + specify the desired clock by having the clock ID in its "clocks" phandle cell. + + The following is a list of provided IDs and clock names on Armada 370/XP: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU clock) + 2 = nbclk (L2 Cache clock) + 3 = hclk (DRAM control clock) + 4 = dramclk (DDR clock) + + The following is a list of provided IDs and clock names on Armada 375: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU clock) + 2 = l2clk (L2 Cache clock) + 3 = ddrclk (DDR clock) + + The following is a list of provided IDs and clock names on Armada 380/385: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU clock) + 2 = l2clk (L2 Cache clock) + 3 = ddrclk (DDR clock) + + The following is a list of provided IDs and clock names on Armada 39x: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU clock) + 2 = nbclk (Coherent Fabric clock) + 3 = hclk (SDRAM Controller Internal Clock) + 4 = dclk (SDRAM Interface Clock) + 5 = refclk (Reference Clock) + + The following is a list of provided IDs and clock names on 98dx3236: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU clock) + 2 = ddrclk (DDR clock) + 3 = mpll (MPLL Clock) + + The following is a list of provided IDs and clock names on Kirkwood and Dove: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU0 clock) + 2 = l2clk (L2 Cache clock derived from CPU0 clock) + 3 = ddrclk (DDR controller clock derived from CPU0 clock) + + The following is a list of provided IDs and clock names on Orion5x: + 0 = tclk (Internal Bus clock) + 1 = cpuclk (CPU0 clock) + 2 = ddrclk (DDR controller clock derived from CPU0 clock) + +properties: + compatible: + enum: + - marvell,armada-370-core-clock + - marvell,armada-375-core-clock + - marvell,armada-380-core-clock + - marvell,armada-390-core-clock + - marvell,armada-xp-core-clock + - marvell,dove-core-clock + - marvell,kirkwood-core-clock + - marvell,mv88f5181-core-clock + - marvell,mv88f5182-core-clock + - marvell,mv88f5281-core-clock + - marvell,mv88f6180-core-clock + - marvell,mv88f6183-core-clock + - marvell,mv98dx1135-core-clock + - marvell,mv98dx3236-core-clock + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clock-output-names: + description: Overwrite default clock output names. + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/clock/marvell-armada-370-gating-clock.yaml b/Documentation/devicetree/bindings/clock/marvell-armada-370-gating-clock.yaml new file mode 100644 index 000000000000..0475360d2b6a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/marvell-armada-370-gating-clock.yaml @@ -0,0 +1,227 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +--- +$id: http://devicetree.org/schemas/clock/marvell-armada-370-gating-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Marvell EBU SoC gating-clock + +maintainers: + - Andrew Lunn <andrew@lunn.ch> + - Gregory Clement <gregory.clement@bootlin.com> + +description: > + Marvell Armada 370/375/380/385/39x/XP, Dove and Kirkwood allow some peripheral + clocks to be gated to save some power. The clock ID is directly mapped to the + corresponding clock gating control bit in HW to ease manual clock lookup in + datasheet. + + The following is a list of provided IDs for Armada 370: + + ID Clock Peripheral + ----------------------------------- + 0 Audio AC97 Cntrl + 1 pex0_en PCIe 0 Clock out + 2 pex1_en PCIe 1 Clock out + 3 ge1 Gigabit Ethernet 1 + 4 ge0 Gigabit Ethernet 0 + 5 pex0 PCIe Cntrl 0 + 9 pex1 PCIe Cntrl 1 + 15 sata0 SATA Host 0 + 17 sdio SDHCI Host + 23 crypto CESA (crypto engine) + 25 tdm Time Division Mplx + 28 ddr DDR Cntrl + 30 sata1 SATA Host 0 + + The following is a list of provided IDs for Armada 375: + + ID Clock Peripheral + ----------------------------------- + 2 mu Management Unit + 3 pp Packet Processor + 4 ptp PTP + 5 pex0 PCIe 0 Clock out + 6 pex1 PCIe 1 Clock out + 8 audio Audio Cntrl + 11 nd_clk Nand Flash Cntrl + 14 sata0_link SATA 0 Link + 15 sata0_core SATA 0 Core + 16 usb3 USB3 Host + 17 sdio SDHCI Host + 18 usb USB Host + 19 gop Gigabit Ethernet MAC + 20 sata1_link SATA 1 Link + 21 sata1_core SATA 1 Core + 22 xor0 XOR DMA 0 + 23 xor1 XOR DMA 0 + 24 copro Coprocessor + 25 tdm Time Division Mplx + 28 crypto0_enc Cryptographic Unit Port 0 Encryption + 29 crypto0_core Cryptographic Unit Port 0 Core + 30 crypto1_enc Cryptographic Unit Port 1 Encryption + 31 crypto1_core Cryptographic Unit Port 1 Core + + The following is a list of provided IDs for Armada 380/385: + + ID Clock Peripheral + ----------------------------------- + 0 audio Audio + 2 ge2 Gigabit Ethernet 2 + 3 ge1 Gigabit Ethernet 1 + 4 ge0 Gigabit Ethernet 0 + 5 pex1 PCIe 1 + 6 pex2 PCIe 2 + 7 pex3 PCIe 3 + 8 pex0 PCIe 0 + 9 usb3h0 USB3 Host 0 + 10 usb3h1 USB3 Host 1 + 11 usb3d USB3 Device + 13 bm Buffer Management + 14 crypto0z Cryptographic 0 Z + 15 sata0 SATA 0 + 16 crypto1z Cryptographic 1 Z + 17 sdio SDIO + 18 usb2 USB 2 + 21 crypto1 Cryptographic 1 + 22 xor0 XOR 0 + 23 crypto0 Cryptographic 0 + 25 tdm Time Division Multiplexing + 28 xor1 XOR 1 + 30 sata1 SATA 1 + + The following is a list of provided IDs for Armada 39x: + + ID Clock Peripheral + ----------------------------------- + 5 pex1 PCIe 1 + 6 pex2 PCIe 2 + 7 pex3 PCIe 3 + 8 pex0 PCIe 0 + 9 usb3h0 USB3 Host 0 + 10 usb3h1 USB3 Host 1 + 15 sata0 SATA 0 + 17 sdio SDIO + 22 xor0 XOR 0 + 28 xor1 XOR 1 + + The following is a list of provided IDs for Armada XP: + + ID Clock Peripheral + ----------------------------------- + 0 audio Audio Cntrl + 1 ge3 Gigabit Ethernet 3 + 2 ge2 Gigabit Ethernet 2 + 3 ge1 Gigabit Ethernet 1 + 4 ge0 Gigabit Ethernet 0 + 5 pex0 PCIe Cntrl 0 + 6 pex1 PCIe Cntrl 1 + 7 pex2 PCIe Cntrl 2 + 8 pex3 PCIe Cntrl 3 + 13 bp + 14 sata0lnk + 15 sata0 SATA Host 0 + 16 lcd LCD Cntrl + 17 sdio SDHCI Host + 18 usb0 USB Host 0 + 19 usb1 USB Host 1 + 20 usb2 USB Host 2 + 22 xor0 XOR DMA 0 + 23 crypto CESA engine + 25 tdm Time Division Mplx + 28 xor1 XOR DMA 1 + 29 sata1lnk + 30 sata1 SATA Host 1 + + The following is a list of provided IDs for 98dx3236: + + ID Clock Peripheral + ----------------------------------- + 3 ge1 Gigabit Ethernet 1 + 4 ge0 Gigabit Ethernet 0 + 5 pex0 PCIe Cntrl 0 + 17 sdio SDHCI Host + 18 usb0 USB Host 0 + 22 xor0 XOR DMA 0 + + The following is a list of provided IDs for Dove: + + ID Clock Peripheral + ----------------------------------- + 0 usb0 USB Host 0 + 1 usb1 USB Host 1 + 2 ge Gigabit Ethernet + 3 sata SATA Host + 4 pex0 PCIe Cntrl 0 + 5 pex1 PCIe Cntrl 1 + 8 sdio0 SDHCI Host 0 + 9 sdio1 SDHCI Host 1 + 10 nand NAND Cntrl + 11 camera Camera Cntrl + 12 i2s0 I2S Cntrl 0 + 13 i2s1 I2S Cntrl 1 + 15 crypto CESA engine + 21 ac97 AC97 Cntrl + 22 pdma Peripheral DMA + 23 xor0 XOR DMA 0 + 24 xor1 XOR DMA 1 + 30 gephy Gigabit Ethernet PHY + Note: gephy(30) is implemented as a parent clock of ge(2) + + The following is a list of provided IDs for Kirkwood: + + ID Clock Peripheral + ----------------------------------- + 0 ge0 Gigabit Ethernet 0 + 2 pex0 PCIe Cntrl 0 + 3 usb0 USB Host 0 + 4 sdio SDIO Cntrl + 5 tsu Transp. Stream Unit + 6 dunit SDRAM Cntrl + 7 runit Runit + 8 xor0 XOR DMA 0 + 9 audio I2S Cntrl 0 + 14 sata0 SATA Host 0 + 15 sata1 SATA Host 1 + 16 xor1 XOR DMA 1 + 17 crypto CESA engine + 18 pex1 PCIe Cntrl 1 + 19 ge1 Gigabit Ethernet 1 + 20 tdm Time Division Mplx + +properties: + compatible: + enum: + - marvell,armada-370-gating-clock + - marvell,armada-375-gating-clock + - marvell,armada-380-gating-clock + - marvell,armada-390-gating-clock + - marvell,armada-xp-gating-clock + - marvell,mv98dx3236-gating-clock + - marvell,dove-gating-clock + - marvell,kirkwood-gating-clock + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@d0038 { + compatible = "marvell,dove-gating-clock"; + reg = <0xd0038 0x4>; + /* default parent clock is tclk */ + clocks = <&core_clk 0>; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/maxim,max9485.txt b/Documentation/devicetree/bindings/clock/maxim,max9485.txt deleted file mode 100644 index b8f5c3bbf12b..000000000000 --- a/Documentation/devicetree/bindings/clock/maxim,max9485.txt +++ /dev/null @@ -1,59 +0,0 @@ -Devicetree bindings for Maxim MAX9485 Programmable Audio Clock Generator - -This device exposes 4 clocks in total: - -- MAX9485_MCLKOUT: A gated, buffered output of the input clock of 27 MHz -- MAX9485_CLKOUT: A PLL that can be configured to 16 different discrete - frequencies -- MAX9485_CLKOUT[1,2]: Two gated outputs for MAX9485_CLKOUT - -MAX9485_CLKOUT[1,2] are children of MAX9485_CLKOUT which upchain all rate set -requests. - -Required properties: -- compatible: "maxim,max9485" -- clocks: Input clock, must provide 27.000 MHz -- clock-names: Must be set to "xclk" -- #clock-cells: From common clock binding; shall be set to 1 - -Optional properties: -- reset-gpios: GPIO descriptor connected to the #RESET input pin -- vdd-supply: A regulator node for Vdd -- clock-output-names: Name of output clocks, as defined in common clock - bindings - -If not explicitly set, the output names are "mclkout", "clkout", "clkout1" -and "clkout2". - -Clocks are defined as preprocessor macros in the dt-binding header. - -Example: - - #include <dt-bindings/clock/maxim,max9485.h> - - xo-27mhz: xo-27mhz { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <27000000>; - }; - - &i2c0 { - max9485: audio-clock@63 { - reg = <0x63>; - compatible = "maxim,max9485"; - clock-names = "xclk"; - clocks = <&xo-27mhz>; - reset-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; - vdd-supply = <&3v3-reg>; - #clock-cells = <1>; - }; - }; - - // Clock consumer node - - foo@0 { - compatible = "bar,foo"; - /* ... */ - clock-names = "foo-input-clk"; - clocks = <&max9485 MAX9485_CLKOUT1>; - }; diff --git a/Documentation/devicetree/bindings/clock/maxim,max9485.yaml b/Documentation/devicetree/bindings/clock/maxim,max9485.yaml new file mode 100644 index 000000000000..f9d8941c7235 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/maxim,max9485.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/maxim,max9485.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim MAX9485 Programmable Audio Clock Generator + +maintainers: + - Daniel Mack <daniel@zonque.org> + +description: > + Maxim MAX9485 Programmable Audio Clock Generator exposes 4 clocks in total: + + - MAX9485_MCLKOUT: A gated, buffered output of the input clock of 27 MHz + - MAX9485_CLKOUT: A PLL that can be configured to 16 different discrete + frequencies + - MAX9485_CLKOUT[1,2]: Two gated outputs for MAX9485_CLKOUT + + MAX9485_CLKOUT[1,2] are children of MAX9485_CLKOUT which upchain all rate set + requests. + +properties: + compatible: + const: maxim,max9485 + + reg: + maxItems: 1 + + clocks: + description: Input clock. Must provide 27 MHz + maxItems: 1 + + clock-names: + items: + - const: xclk + + '#clock-cells': + const: 1 + + reset-gpios: + description: > + GPIO descriptor connected to the #RESET input pin + + vdd-supply: + description: A regulator node for Vdd + + clock-output-names: + description: Name of output clocks, as defined in common clock bindings + items: + - const: mclkout + - const: clkout + - const: clkout1 + - const: clkout2 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + clock-controller@63 { + compatible = "maxim,max9485"; + reg = <0x63>; + #clock-cells = <1>; + clock-names = "xclk"; + clocks = <&xo_27mhz>; + reset-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + vdd-supply = <®_3v3>; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/microchip,pic32.txt b/Documentation/devicetree/bindings/clock/microchip,pic32.txt deleted file mode 100644 index c93d88fdd858..000000000000 --- a/Documentation/devicetree/bindings/clock/microchip,pic32.txt +++ /dev/null @@ -1,39 +0,0 @@ -Microchip PIC32 Clock Controller Binding ----------------------------------------- -Microchip clock controller is consists of few oscillators, PLL, multiplexer -and few divider modules. - -This binding uses common clock bindings. -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible: shall be "microchip,pic32mzda-clk". -- reg: shall contain base address and length of clock registers. -- #clock-cells: shall be 1. - -Optional properties: -- microchip,pic32mzda-sosc: shall be added only if platform has - secondary oscillator connected. - -Example: - rootclk: clock-controller@1f801200 { - compatible = "microchip,pic32mzda-clk"; - reg = <0x1f801200 0x200>; - #clock-cells = <1>; - /* optional */ - microchip,pic32mzda-sosc; - }; - - -The clock consumer shall specify the desired clock-output of the clock -controller (as defined in [2]) by specifying output-id in its "clock" -phandle cell. -[2] include/dt-bindings/clock/microchip,pic32-clock.h - -For example for UART2: -uart2: serial@2 { - compatible = "microchip,pic32mzda-uart"; - reg = <>; - interrupts = <>; - clocks = <&rootclk PB2CLK>; -}; diff --git a/Documentation/devicetree/bindings/clock/microchip,pic32mzda-clk.yaml b/Documentation/devicetree/bindings/clock/microchip,pic32mzda-clk.yaml new file mode 100644 index 000000000000..a14a838140f1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/microchip,pic32mzda-clk.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/microchip,pic32mzda-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip PIC32MZDA Clock Controller + +maintainers: + - Purna Chandra Mandal <purna.mandal@microchip.com> + +description: + Microchip clock controller consists of a few oscillators, PLL, multiplexer + and divider modules. + +properties: + compatible: + const: microchip,pic32mzda-clk + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + microchip,pic32mzda-sosc: + description: Presence of secondary oscillator. + type: boolean + +required: + - compatible + - reg + - "#clock-cells" + +additionalProperties: false + +examples: + - | + clock-controller@1f801200 { + compatible = "microchip,pic32mzda-clk"; + reg = <0x1f801200 0x200>; + #clock-cells = <1>; + /* optional */ + microchip,pic32mzda-sosc; + }; diff --git a/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt deleted file mode 100644 index fedea84314a1..000000000000 --- a/Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt +++ /dev/null @@ -1,48 +0,0 @@ -Device Tree Clock bindings for arch-moxart - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -MOXA ART SoCs allow to determine PLL output and APB frequencies -by reading registers holding multiplier and divisor information. - - -PLL: - -Required properties: -- compatible : Must be "moxa,moxart-pll-clock" -- #clock-cells : Should be 0 -- reg : Should contain registers location and length -- clocks : Should contain phandle + clock-specifier for the parent clock - -Optional properties: -- clock-output-names : Should contain clock name - - -APB: - -Required properties: -- compatible : Must be "moxa,moxart-apb-clock" -- #clock-cells : Should be 0 -- reg : Should contain registers location and length -- clocks : Should contain phandle + clock-specifier for the parent clock - -Optional properties: -- clock-output-names : Should contain clock name - - -For example: - - clk_pll: clk_pll@98100000 { - compatible = "moxa,moxart-pll-clock"; - #clock-cells = <0>; - reg = <0x98100000 0x34>; - }; - - clk_apb: clk_apb@98100000 { - compatible = "moxa,moxart-apb-clock"; - #clock-cells = <0>; - reg = <0x98100000 0x34>; - clocks = <&clk_pll>; - }; diff --git a/Documentation/devicetree/bindings/clock/moxa,moxart-clock.yaml b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.yaml new file mode 100644 index 000000000000..bcf7cc240eba --- /dev/null +++ b/Documentation/devicetree/bindings/clock/moxa,moxart-clock.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/moxa,moxart-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MOXA ART Clock Controllers + +maintainers: + - Krzysztof Kozlowski <krzk@kernel.org> + +description: + MOXA ART SoCs allow to determine PLL output and APB frequencies by reading + registers holding multiplier and divisor information. + +properties: + compatible: + enum: + - moxa,moxart-apb-clock + - moxa,moxart-pll-clock + + "#clock-cells": + const: 0 + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: true + +additionalProperties: false + +required: + - compatible + - "#clock-cells" + - reg diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt deleted file mode 100644 index d8f5c490f893..000000000000 --- a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt +++ /dev/null @@ -1,87 +0,0 @@ -* Core Clock bindings for Marvell MVEBU SoCs - -Marvell MVEBU SoCs usually allow to determine core clock frequencies by -reading the Sample-At-Reset (SAR) register. The core clock consumer should -specify the desired clock by having the clock ID in its "clocks" phandle cell. - -The following is a list of provided IDs and clock names on Armada 370/XP: - 0 = tclk (Internal Bus clock) - 1 = cpuclk (CPU clock) - 2 = nbclk (L2 Cache clock) - 3 = hclk (DRAM control clock) - 4 = dramclk (DDR clock) - -The following is a list of provided IDs and clock names on Armada 375: - 0 = tclk (Internal Bus clock) - 1 = cpuclk (CPU clock) - 2 = l2clk (L2 Cache clock) - 3 = ddrclk (DDR clock) - -The following is a list of provided IDs and clock names on Armada 380/385: - 0 = tclk (Internal Bus clock) - 1 = cpuclk (CPU clock) - 2 = l2clk (L2 Cache clock) - 3 = ddrclk (DDR clock) - -The following is a list of provided IDs and clock names on Armada 39x: - 0 = tclk (Internal Bus clock) - 1 = cpuclk (CPU clock) - 2 = nbclk (Coherent Fabric clock) - 3 = hclk (SDRAM Controller Internal Clock) - 4 = dclk (SDRAM Interface Clock) - 5 = refclk (Reference Clock) - -The following is a list of provided IDs and clock names on 98dx3236: - 0 = tclk (Internal Bus clock) - 1 = cpuclk (CPU clock) - 2 = ddrclk (DDR clock) - 3 = mpll (MPLL Clock) - -The following is a list of provided IDs and clock names on Kirkwood and Dove: - 0 = tclk (Internal Bus clock) - 1 = cpuclk (CPU0 clock) - 2 = l2clk (L2 Cache clock derived from CPU0 clock) - 3 = ddrclk (DDR controller clock derived from CPU0 clock) - -The following is a list of provided IDs and clock names on Orion5x: - 0 = tclk (Internal Bus clock) - 1 = cpuclk (CPU0 clock) - 2 = ddrclk (DDR controller clock derived from CPU0 clock) - -Required properties: -- compatible : shall be one of the following: - "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks - "marvell,armada-375-core-clock" - For Armada 375 SoC core clocks - "marvell,armada-380-core-clock" - For Armada 380/385 SoC core clocks - "marvell,armada-390-core-clock" - For Armada 39x SoC core clocks - "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks - "marvell,mv98dx3236-core-clock" - For 98dx3236 family SoC core clocks - "marvell,dove-core-clock" - for Dove SoC core clocks - "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180) - "marvell,mv88f6180-core-clock" - for Kirkwood MV88f6180 SoC - "marvell,mv98dx1135-core-clock" - for Kirkwood 98dx1135 SoC - "marvell,mv88f5181-core-clock" - for Orion MV88F5181 SoC - "marvell,mv88f5182-core-clock" - for Orion MV88F5182 SoC - "marvell,mv88f5281-core-clock" - for Orion MV88F5281 SoC - "marvell,mv88f6183-core-clock" - for Orion MV88F6183 SoC -- reg : shall be the register address of the Sample-At-Reset (SAR) register -- #clock-cells : from common clock binding; shall be set to 1 - -Optional properties: -- clock-output-names : from common clock binding; allows overwrite default clock - output names ("tclk", "cpuclk", "l2clk", "ddrclk") - -Example: - -core_clk: core-clocks@d0214 { - compatible = "marvell,dove-core-clock"; - reg = <0xd0214 0x4>; - #clock-cells = <1>; -}; - -spi0: spi@10600 { - compatible = "marvell,orion-spi"; - /* ... */ - /* get tclk from core clock provider */ - clocks = <&core_clk 0>; -}; diff --git a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt deleted file mode 100644 index c7b4e3a6b2c6..000000000000 --- a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt +++ /dev/null @@ -1,23 +0,0 @@ -* Core Divider Clock bindings for Marvell MVEBU SoCs - -The following is a list of provided IDs and clock names on Armada 370/XP: - 0 = nand (NAND clock) - -Required properties: -- compatible : must be "marvell,armada-370-corediv-clock", - "marvell,armada-375-corediv-clock", - "marvell,armada-380-corediv-clock", - "marvell,mv98dx3236-corediv-clock", - -- reg : must be the register address of Core Divider control register -- #clock-cells : from common clock binding; shall be set to 1 -- clocks : must be set to the parent's phandle - -Example: - -corediv_clk: corediv-clocks@18740 { - compatible = "marvell,armada-370-corediv-clock"; - reg = <0x18740 0xc>; - #clock-cells = <1>; - clocks = <&pll>; -}; diff --git a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt deleted file mode 100644 index 7f28506eaee7..000000000000 --- a/Documentation/devicetree/bindings/clock/mvebu-cpu-clock.txt +++ /dev/null @@ -1,23 +0,0 @@ -Device Tree Clock bindings for cpu clock of Marvell EBU platforms - -Required properties: -- compatible : shall be one of the following: - "marvell,armada-xp-cpu-clock" - cpu clocks for Armada XP - "marvell,mv98dx3236-cpu-clock" - cpu clocks for 98DX3236 SoC -- reg : Address and length of the clock complex register set, followed - by address and length of the PMU DFS registers -- #clock-cells : should be set to 1. -- clocks : shall be the input parent clock phandle for the clock. - -cpuclk: clock-complex@d0018700 { - #clock-cells = <1>; - compatible = "marvell,armada-xp-cpu-clock"; - reg = <0xd0018700 0xA0>, <0x1c054 0x10>; - clocks = <&coreclk 1>; -} - -cpu@0 { - compatible = "marvell,sheeva-v7"; - reg = <0>; - clocks = <&cpuclk 0>; -}; diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt deleted file mode 100644 index de562da2ae77..000000000000 --- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt +++ /dev/null @@ -1,205 +0,0 @@ -* Gated Clock bindings for Marvell EBU SoCs - -Marvell Armada 370/375/380/385/39x/XP, Dove and Kirkwood allow some -peripheral clocks to be gated to save some power. The clock consumer -should specify the desired clock by having the clock ID in its -"clocks" phandle cell. The clock ID is directly mapped to the -corresponding clock gating control bit in HW to ease manual clock -lookup in datasheet. - -The following is a list of provided IDs for Armada 370: -ID Clock Peripheral ------------------------------------ -0 Audio AC97 Cntrl -1 pex0_en PCIe 0 Clock out -2 pex1_en PCIe 1 Clock out -3 ge1 Gigabit Ethernet 1 -4 ge0 Gigabit Ethernet 0 -5 pex0 PCIe Cntrl 0 -9 pex1 PCIe Cntrl 1 -15 sata0 SATA Host 0 -17 sdio SDHCI Host -23 crypto CESA (crypto engine) -25 tdm Time Division Mplx -28 ddr DDR Cntrl -30 sata1 SATA Host 0 - -The following is a list of provided IDs for Armada 375: -ID Clock Peripheral ------------------------------------ -2 mu Management Unit -3 pp Packet Processor -4 ptp PTP -5 pex0 PCIe 0 Clock out -6 pex1 PCIe 1 Clock out -8 audio Audio Cntrl -11 nd_clk Nand Flash Cntrl -14 sata0_link SATA 0 Link -15 sata0_core SATA 0 Core -16 usb3 USB3 Host -17 sdio SDHCI Host -18 usb USB Host -19 gop Gigabit Ethernet MAC -20 sata1_link SATA 1 Link -21 sata1_core SATA 1 Core -22 xor0 XOR DMA 0 -23 xor1 XOR DMA 0 -24 copro Coprocessor -25 tdm Time Division Mplx -28 crypto0_enc Cryptographic Unit Port 0 Encryption -29 crypto0_core Cryptographic Unit Port 0 Core -30 crypto1_enc Cryptographic Unit Port 1 Encryption -31 crypto1_core Cryptographic Unit Port 1 Core - -The following is a list of provided IDs for Armada 380/385: -ID Clock Peripheral ------------------------------------ -0 audio Audio -2 ge2 Gigabit Ethernet 2 -3 ge1 Gigabit Ethernet 1 -4 ge0 Gigabit Ethernet 0 -5 pex1 PCIe 1 -6 pex2 PCIe 2 -7 pex3 PCIe 3 -8 pex0 PCIe 0 -9 usb3h0 USB3 Host 0 -10 usb3h1 USB3 Host 1 -11 usb3d USB3 Device -13 bm Buffer Management -14 crypto0z Cryptographic 0 Z -15 sata0 SATA 0 -16 crypto1z Cryptographic 1 Z -17 sdio SDIO -18 usb2 USB 2 -21 crypto1 Cryptographic 1 -22 xor0 XOR 0 -23 crypto0 Cryptographic 0 -25 tdm Time Division Multiplexing -28 xor1 XOR 1 -30 sata1 SATA 1 - -The following is a list of provided IDs for Armada 39x: -ID Clock Peripheral ------------------------------------ -5 pex1 PCIe 1 -6 pex2 PCIe 2 -7 pex3 PCIe 3 -8 pex0 PCIe 0 -9 usb3h0 USB3 Host 0 -10 usb3h1 USB3 Host 1 -15 sata0 SATA 0 -17 sdio SDIO -22 xor0 XOR 0 -28 xor1 XOR 1 - -The following is a list of provided IDs for Armada XP: -ID Clock Peripheral ------------------------------------ -0 audio Audio Cntrl -1 ge3 Gigabit Ethernet 3 -2 ge2 Gigabit Ethernet 2 -3 ge1 Gigabit Ethernet 1 -4 ge0 Gigabit Ethernet 0 -5 pex0 PCIe Cntrl 0 -6 pex1 PCIe Cntrl 1 -7 pex2 PCIe Cntrl 2 -8 pex3 PCIe Cntrl 3 -13 bp -14 sata0lnk -15 sata0 SATA Host 0 -16 lcd LCD Cntrl -17 sdio SDHCI Host -18 usb0 USB Host 0 -19 usb1 USB Host 1 -20 usb2 USB Host 2 -22 xor0 XOR DMA 0 -23 crypto CESA engine -25 tdm Time Division Mplx -28 xor1 XOR DMA 1 -29 sata1lnk -30 sata1 SATA Host 1 - -The following is a list of provided IDs for 98dx3236: -ID Clock Peripheral ------------------------------------ -3 ge1 Gigabit Ethernet 1 -4 ge0 Gigabit Ethernet 0 -5 pex0 PCIe Cntrl 0 -17 sdio SDHCI Host -18 usb0 USB Host 0 -22 xor0 XOR DMA 0 - -The following is a list of provided IDs for Dove: -ID Clock Peripheral ------------------------------------ -0 usb0 USB Host 0 -1 usb1 USB Host 1 -2 ge Gigabit Ethernet -3 sata SATA Host -4 pex0 PCIe Cntrl 0 -5 pex1 PCIe Cntrl 1 -8 sdio0 SDHCI Host 0 -9 sdio1 SDHCI Host 1 -10 nand NAND Cntrl -11 camera Camera Cntrl -12 i2s0 I2S Cntrl 0 -13 i2s1 I2S Cntrl 1 -15 crypto CESA engine -21 ac97 AC97 Cntrl -22 pdma Peripheral DMA -23 xor0 XOR DMA 0 -24 xor1 XOR DMA 1 -30 gephy Gigabit Ethernel PHY -Note: gephy(30) is implemented as a parent clock of ge(2) - -The following is a list of provided IDs for Kirkwood: -ID Clock Peripheral ------------------------------------ -0 ge0 Gigabit Ethernet 0 -2 pex0 PCIe Cntrl 0 -3 usb0 USB Host 0 -4 sdio SDIO Cntrl -5 tsu Transp. Stream Unit -6 dunit SDRAM Cntrl -7 runit Runit -8 xor0 XOR DMA 0 -9 audio I2S Cntrl 0 -14 sata0 SATA Host 0 -15 sata1 SATA Host 1 -16 xor1 XOR DMA 1 -17 crypto CESA engine -18 pex1 PCIe Cntrl 1 -19 ge1 Gigabit Ethernet 1 -20 tdm Time Division Mplx - -Required properties: -- compatible : shall be one of the following: - "marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating - "marvell,armada-375-gating-clock" - for Armada 375 SoC clock gating - "marvell,armada-380-gating-clock" - for Armada 380/385 SoC clock gating - "marvell,armada-390-gating-clock" - for Armada 39x SoC clock gating - "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating - "marvell,mv98dx3236-gating-clock" - for 98dx3236 SoC clock gating - "marvell,dove-gating-clock" - for Dove SoC clock gating - "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating -- reg : shall be the register address of the Clock Gating Control register -- #clock-cells : from common clock binding; shall be set to 1 - -Optional properties: -- clocks : default parent clock phandle (e.g. tclk) - -Example: - -gate_clk: clock-gating-control@d0038 { - compatible = "marvell,dove-gating-clock"; - reg = <0xd0038 0x4>; - /* default parent clock is tclk */ - clocks = <&core_clk 0>; - #clock-cells = <1>; -}; - -sdio0: sdio@92000 { - compatible = "marvell,dove-sdhci"; - /* get clk gate bit 8 (sdio0) */ - clocks = <&gate_clk 8>; -}; diff --git a/Documentation/devicetree/bindings/clock/nspire-clock.txt b/Documentation/devicetree/bindings/clock/nspire-clock.txt deleted file mode 100644 index 7c3bc8bb5b9f..000000000000 --- a/Documentation/devicetree/bindings/clock/nspire-clock.txt +++ /dev/null @@ -1,24 +0,0 @@ -TI-NSPIRE Clocks - -Required properties: -- compatible: Valid compatible properties include: - "lsi,nspire-cx-ahb-divider" for the AHB divider in the CX model - "lsi,nspire-classic-ahb-divider" for the AHB divider in the older model - "lsi,nspire-cx-clock" for the base clock in the CX model - "lsi,nspire-classic-clock" for the base clock in the older model - -- reg: Physical base address of the controller and length of memory mapped - region. - -Optional: -- clocks: For the "nspire-*-ahb-divider" compatible clocks, this is the parent - clock where it divides the rate from. - -Example: - -ahb_clk { - #clock-cells = <0>; - compatible = "lsi,nspire-cx-clock"; - reg = <0x900B0000 0x4>; - clocks = <&base_clk>; -}; diff --git a/Documentation/devicetree/bindings/clock/nuvoton,npcm750-clk.txt b/Documentation/devicetree/bindings/clock/nuvoton,npcm750-clk.txt deleted file mode 100644 index f82064546d11..000000000000 --- a/Documentation/devicetree/bindings/clock/nuvoton,npcm750-clk.txt +++ /dev/null @@ -1,100 +0,0 @@ -* Nuvoton NPCM7XX Clock Controller - -Nuvoton Poleg BMC NPCM7XX contains an integrated clock controller, which -generates and supplies clocks to all modules within the BMC. - -External clocks: - -There are six fixed clocks that are generated outside the BMC. All clocks are of -a known fixed value that cannot be changed. clk_refclk, clk_mcbypck and -clk_sysbypck are inputs to the clock controller. -clk_rg1refck, clk_rg2refck and clk_xin are external clocks suppling the -network. They are set on the device tree, but not used by the clock module. The -network devices use them directly. -Example can be found below. - -All available clocks are defined as preprocessor macros in: -dt-bindings/clock/nuvoton,npcm7xx-clock.h -and can be reused as DT sources. - -Required Properties of clock controller: - - - compatible: "nuvoton,npcm750-clk" : for clock controller of Nuvoton - Poleg BMC NPCM750 - - - reg: physical base address of the clock controller and length of - memory mapped region. - - - #clock-cells: should be 1. - -Example: Clock controller node: - - clk: clock-controller@f0801000 { - compatible = "nuvoton,npcm750-clk"; - #clock-cells = <1>; - reg = <0xf0801000 0x1000>; - clock-names = "refclk", "sysbypck", "mcbypck"; - clocks = <&clk_refclk>, <&clk_sysbypck>, <&clk_mcbypck>; - }; - -Example: Required external clocks for network: - - /* external reference clock */ - clk_refclk: clk-refclk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <25000000>; - clock-output-names = "refclk"; - }; - - /* external reference clock for cpu. float in normal operation */ - clk_sysbypck: clk-sysbypck { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <800000000>; - clock-output-names = "sysbypck"; - }; - - /* external reference clock for MC. float in normal operation */ - clk_mcbypck: clk-mcbypck { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <800000000>; - clock-output-names = "mcbypck"; - }; - - /* external clock signal rg1refck, supplied by the phy */ - clk_rg1refck: clk-rg1refck { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <125000000>; - clock-output-names = "clk_rg1refck"; - }; - - /* external clock signal rg2refck, supplied by the phy */ - clk_rg2refck: clk-rg2refck { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <125000000>; - clock-output-names = "clk_rg2refck"; - }; - - clk_xin: clk-xin { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <50000000>; - clock-output-names = "clk_xin"; - }; - - -Example: GMAC controller node that consumes two clocks: a generated clk by the -clock controller and a fixed clock from DT (clk_rg1refck). - - ethernet0: ethernet@f0802000 { - compatible = "snps,dwmac"; - reg = <0xf0802000 0x2000>; - interrupts = <0 14 4>; - interrupt-names = "macirq"; - clocks = <&clk_rg1refck>, <&clk NPCM7XX_CLK_AHB>; - clock-names = "stmmaceth", "clk_gmac"; - }; diff --git a/Documentation/devicetree/bindings/clock/nuvoton,npcm750-clk.yaml b/Documentation/devicetree/bindings/clock/nuvoton,npcm750-clk.yaml new file mode 100644 index 000000000000..694dac68619c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nuvoton,npcm750-clk.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/nuvoton,npcm750-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Nuvoton NPCM7XX Clock Controller + +maintainers: + - Tali Perry <tali.perry1@gmail.com> + +description: > + Nuvoton Poleg BMC NPCM7XX contains an integrated clock controller, which + generates and supplies clocks to all modules within the BMC. + + External clocks: + + There are six fixed clocks that are generated outside the BMC. All clocks are of + a known fixed value that cannot be changed. clk_refclk, clk_mcbypck and + clk_sysbypck are inputs to the clock controller. + clk_rg1refck, clk_rg2refck and clk_xin are external clocks suppling the + network. They are set on the device tree, but not used by the clock module. The + network devices use them directly. + + All available clocks are defined as preprocessor macros in: + dt-bindings/clock/nuvoton,npcm7xx-clock.h + and can be reused as DT sources. + +properties: + compatible: + const: nuvoton,npcm750-clk + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clock-names: + items: + - const: refclk + - const: sysbypck + - const: mcbypck + + clocks: + items: + - description: refclk + - description: sysbypck + - description: mcbypck + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@f0801000 { + compatible = "nuvoton,npcm750-clk"; + #clock-cells = <1>; + reg = <0xf0801000 0x1000>; + clock-names = "refclk", "sysbypck", "mcbypck"; + clocks = <&clk_refclk>, <&clk_sysbypck>, <&clk_mcbypck>; + }; diff --git a/Documentation/devicetree/bindings/clock/nxp,lpc1850-ccu.yaml b/Documentation/devicetree/bindings/clock/nxp,lpc1850-ccu.yaml new file mode 100644 index 000000000000..5459038cc954 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nxp,lpc1850-ccu.yaml @@ -0,0 +1,104 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/nxp,lpc1850-ccu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP LPC1850 Clock Control Unit (CCU) + +description: + Each CGU base clock has several clock branches which can be turned on + or off independently by the Clock Control Units CCU1 or CCU2. The + branch clocks are distributed between CCU1 and CCU2. + + Above text taken from NXP LPC1850 User Manual + +maintainers: + - Frank Li <Frank.Li@nxp.com> + +properties: + compatible: + const: nxp,lpc1850-ccu + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + minItems: 1 + maxItems: 8 + + clock-names: + minItems: 1 + maxItems: 8 + items: + enum: + - base_usb0_clk + - base_periph_clk + - base_usb1_clk + - base_cpu_clk + - base_spifi_clk + - base_spi_clk + - base_apb1_clk + - base_apb3_clk + - base_adchs_clk + - base_sdio_clk + - base_ssp0_clk + - base_ssp1_clk + - base_uart0_clk + - base_uart1_clk + - base_uart2_clk + - base_uart3_clk + - base_audio_clk + description: + Which branch clocks that are available on the CCU depends on the + specific LPC part. Check the user manual for your specific part. + + A list of CCU clocks can be found in dt-bindings/clock/lpc18xx-ccu.h. + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/lpc18xx-cgu.h> + + clock-controller@40051000 { + compatible = "nxp,lpc1850-ccu"; + reg = <0x40051000 0x1000>; + #clock-cells = <1>; + clocks = <&cgu BASE_APB3_CLK>, <&cgu BASE_APB1_CLK>, + <&cgu BASE_SPIFI_CLK>, <&cgu BASE_CPU_CLK>, + <&cgu BASE_PERIPH_CLK>, <&cgu BASE_USB0_CLK>, + <&cgu BASE_USB1_CLK>, <&cgu BASE_SPI_CLK>; + clock-names = "base_apb3_clk", "base_apb1_clk", + "base_spifi_clk", "base_cpu_clk", + "base_periph_clk", "base_usb0_clk", + "base_usb1_clk", "base_spi_clk"; + }; + + - | + #include <dt-bindings/clock/lpc18xx-cgu.h> + + clock-controller@40052000 { + compatible = "nxp,lpc1850-ccu"; + reg = <0x40052000 0x1000>; + #clock-cells = <1>; + clocks = <&cgu BASE_AUDIO_CLK>, <&cgu BASE_UART3_CLK>, + <&cgu BASE_UART2_CLK>, <&cgu BASE_UART1_CLK>, + <&cgu BASE_UART0_CLK>, <&cgu BASE_SSP1_CLK>, + <&cgu BASE_SSP0_CLK>, <&cgu BASE_SDIO_CLK>; + clock-names = "base_audio_clk", "base_uart3_clk", + "base_uart2_clk", "base_uart1_clk", + "base_uart0_clk", "base_ssp1_clk", + "base_ssp0_clk", "base_sdio_clk"; + }; + diff --git a/Documentation/devicetree/bindings/clock/nxp,lpc1850-cgu.yaml b/Documentation/devicetree/bindings/clock/nxp,lpc1850-cgu.yaml new file mode 100644 index 000000000000..ed178c7df00c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nxp,lpc1850-cgu.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/nxp,lpc1850-cgu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP LPC1850 Clock Generation Unit (CGU) + +description: > + The CGU generates multiple independent clocks for the core and the + peripheral blocks of the LPC18xx. Each independent clock is called + a base clock and itself is one of the inputs to the two Clock + Control Units (CCUs) which control the branch clocks to the + individual peripherals. + + The CGU selects the inputs to the clock generators from multiple + clock sources, controls the clock generation, and routes the outputs + of the clock generators through the clock source bus to the output + stages. Each output stage provides an independent clock source and + corresponds to one of the base clocks for the LPC18xx. + + Above text taken from NXP LPC1850 User Manual. + +maintainers: + - Frank Li <Frank.Li@nxp.com> + +properties: + compatible: + const: nxp,lpc1850-cgu + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + description: | + Which base clocks that are available on the CGU depends on the + specific LPC part. Base clocks are numbered from 0 to 27. + + Number: Name: Description: + 0 BASE_SAFE_CLK Base safe clock (always on) for WWDT + 1 BASE_USB0_CLK Base clock for USB0 + 2 BASE_PERIPH_CLK Base clock for Cortex-M0SUB subsystem, + SPI, and SGPIO + 3 BASE_USB1_CLK Base clock for USB1 + 4 BASE_CPU_CLK System base clock for ARM Cortex-M core + and APB peripheral blocks #0 and #2 + 5 BASE_SPIFI_CLK Base clock for SPIFI + 6 BASE_SPI_CLK Base clock for SPI + 7 BASE_PHY_RX_CLK Base clock for Ethernet PHY Receive clock + 8 BASE_PHY_TX_CLK Base clock for Ethernet PHY Transmit clock + 9 BASE_APB1_CLK Base clock for APB peripheral block # 1 + 10 BASE_APB3_CLK Base clock for APB peripheral block # 3 + 11 BASE_LCD_CLK Base clock for LCD + 12 BASE_ADCHS_CLK Base clock for ADCHS + 13 BASE_SDIO_CLK Base clock for SD/MMC + 14 BASE_SSP0_CLK Base clock for SSP0 + 15 BASE_SSP1_CLK Base clock for SSP1 + 16 BASE_UART0_CLK Base clock for UART0 + 17 BASE_UART1_CLK Base clock for UART1 + 18 BASE_UART2_CLK Base clock for UART2 + 19 BASE_UART3_CLK Base clock for UART3 + 20 BASE_OUT_CLK Base clock for CLKOUT pin + 24-21 - Reserved + 25 BASE_AUDIO_CLK Base clock for audio system (I2S) + 26 BASE_CGU_OUT0_CLK Base clock for CGU_OUT0 clock output + 27 BASE_CGU_OUT1_CLK Base clock for CGU_OUT1 clock output + + BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx. + BASE_ADCHS_CLK is only available on LPC4370. + + clocks: + maxItems: 5 + + clock-indices: + minItems: 1 + maxItems: 28 + + clock-output-names: + minItems: 1 + maxItems: 28 + +required: + - compatible + - reg + - clocks + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@40050000 { + compatible = "nxp,lpc1850-cgu"; + reg = <0x40050000 0x1000>; + #clock-cells = <1>; + clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>; + }; + diff --git a/Documentation/devicetree/bindings/clock/pistachio-clock.txt b/Documentation/devicetree/bindings/clock/pistachio-clock.txt deleted file mode 100644 index 868db499eed2..000000000000 --- a/Documentation/devicetree/bindings/clock/pistachio-clock.txt +++ /dev/null @@ -1,123 +0,0 @@ -Imagination Technologies Pistachio SoC clock controllers -======================================================== - -Pistachio has four clock controllers (core clock, peripheral clock, peripheral -general control, and top general control) which are instantiated individually -from the device-tree. - -External clocks: ----------------- - -There are three external inputs to the clock controllers which should be -defined with the following clock-output-names: -- "xtal": External 52Mhz oscillator (required) -- "audio_clk_in": Alternate audio reference clock (optional) -- "enet_clk_in": Alternate ethernet PHY clock (optional) - -Core clock controller: ----------------------- - -The core clock controller generates clocks for the CPU, RPU (WiFi + BT -co-processor), audio, and several peripherals. - -Required properties: -- compatible: Must be "img,pistachio-clk". -- reg: Must contain the base address and length of the core clock controller. -- #clock-cells: Must be 1. The single cell is the clock identifier. - See dt-bindings/clock/pistachio-clk.h for the list of valid identifiers. -- clocks: Must contain an entry for each clock in clock-names. -- clock-names: Must include "xtal" (see "External clocks") and - "audio_clk_in_gate", "enet_clk_in_gate" which are generated by the - top-level general control. - -Example: - clk_core: clock-controller@18144000 { - compatible = "img,pistachio-clk"; - reg = <0x18144000 0x800>; - clocks = <&xtal>, <&cr_top EXT_CLK_AUDIO_IN>, - <&cr_top EXT_CLK_ENET_IN>; - clock-names = "xtal", "audio_clk_in_gate", "enet_clk_in_gate"; - - #clock-cells = <1>; - }; - -Peripheral clock controller: ----------------------------- - -The peripheral clock controller generates clocks for the DDR, ROM, and other -peripherals. The peripheral system clock ("periph_sys") generated by the core -clock controller is the input clock to the peripheral clock controller. - -Required properties: -- compatible: Must be "img,pistachio-periph-clk". -- reg: Must contain the base address and length of the peripheral clock - controller. -- #clock-cells: Must be 1. The single cell is the clock identifier. - See dt-bindings/clock/pistachio-clk.h for the list of valid identifiers. -- clocks: Must contain an entry for each clock in clock-names. -- clock-names: Must include "periph_sys", the peripheral system clock generated - by the core clock controller. - -Example: - clk_periph: clock-controller@18144800 { - compatible = "img,pistachio-clk-periph"; - reg = <0x18144800 0x800>; - clocks = <&clk_core CLK_PERIPH_SYS>; - clock-names = "periph_sys"; - - #clock-cells = <1>; - }; - -Peripheral general control: ---------------------------- - -The peripheral general control block generates system interface clocks and -resets for various peripherals. It also contains miscellaneous peripheral -control registers. The system clock ("sys") generated by the peripheral clock -controller is the input clock to the system clock controller. - -Required properties: -- compatible: Must include "img,pistachio-periph-cr" and "syscon". -- reg: Must contain the base address and length of the peripheral general - control registers. -- #clock-cells: Must be 1. The single cell is the clock identifier. - See dt-bindings/clock/pistachio-clk.h for the list of valid identifiers. -- clocks: Must contain an entry for each clock in clock-names. -- clock-names: Must include "sys", the system clock generated by the peripheral - clock controller. - -Example: - cr_periph: syscon@18144800 { - compatible = "img,pistachio-cr-periph", "syscon"; - reg = <0x18148000 0x1000>; - clocks = <&clock_periph PERIPH_CLK_PERIPH_SYS>; - clock-names = "sys"; - - #clock-cells = <1>; - }; - -Top-level general control: --------------------------- - -The top-level general control block contains miscellaneous control registers and -gates for the external clocks "audio_clk_in" and "enet_clk_in". - -Required properties: -- compatible: Must include "img,pistachio-cr-top" and "syscon". -- reg: Must contain the base address and length of the top-level - control registers. -- clocks: Must contain an entry for each clock in clock-names. -- clock-names: Two optional clocks, "audio_clk_in" and "enet_clk_in" (see - "External clocks"). -- #clock-cells: Must be 1. The single cell is the clock identifier. - See dt-bindings/clock/pistachio-clk.h for the list of valid identifiers. - -Example: - cr_top: syscon@18144800 { - compatible = "img,pistachio-cr-top", "syscon"; - reg = <0x18149000 0x200>; - clocks = <&audio_refclk>, <&ext_enet_in>; - clock-names = "audio_clk_in", "enet_clk_in"; - - #clock-cells = <1>; - }; diff --git a/Documentation/devicetree/bindings/clock/qca,ath79-pll.txt b/Documentation/devicetree/bindings/clock/qca,ath79-pll.txt deleted file mode 100644 index 241fb0545b9e..000000000000 --- a/Documentation/devicetree/bindings/clock/qca,ath79-pll.txt +++ /dev/null @@ -1,33 +0,0 @@ -Binding for Qualcomm Atheros AR7xxx/AR9XXX PLL controller - -The PPL controller provides the 3 main clocks of the SoC: CPU, DDR and AHB. - -Required Properties: -- compatible: has to be "qca,<soctype>-pll" and one of the following - fallbacks: - - "qca,ar7100-pll" - - "qca,ar7240-pll" - - "qca,ar9130-pll" - - "qca,ar9330-pll" - - "qca,ar9340-pll" - - "qca,qca9550-pll" -- reg: Base address and size of the controllers memory area -- clock-names: Name of the input clock, has to be "ref" -- clocks: phandle of the external reference clock -- #clock-cells: has to be one - -Optional properties: -- clock-output-names: should be "cpu", "ddr", "ahb" - -Example: - - pll-controller@18050000 { - compatible = "qca,ar9132-pll", "qca,ar9130-pll"; - reg = <0x18050000 0x20>; - - clock-names = "ref"; - clocks = <&extosc>; - - #clock-cells = <1>; - clock-output-names = "cpu", "ddr", "ahb"; - }; diff --git a/Documentation/devicetree/bindings/clock/qca,ath79-pll.yaml b/Documentation/devicetree/bindings/clock/qca,ath79-pll.yaml new file mode 100644 index 000000000000..69863e8a4648 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qca,ath79-pll.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qca,ath79-pll.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Atheros ATH79 PLL controller + +maintainers: + - Alban Bedel <albeu@free.fr> + - Antony Pavlov <antonynpavlov@gmail.com> + +description: > + The PLL controller provides the 3 main clocks of the SoC: CPU, DDR and AHB. + +properties: + compatible: + oneOf: + - items: + - const: qca,ar9132-pll + - const: qca,ar9130-pll + - items: + - enum: + - qca,ar7100-pll + - qca,ar7240-pll + - qca,ar9130-pll + - qca,ar9330-pll + - qca,ar9340-pll + - qca,qca9530-pll + - qca,qca9550-pll + - qca,qca9560-pll + + reg: + maxItems: 1 + + clock-names: + items: + - const: ref + + clocks: + maxItems: 1 + + '#clock-cells': + const: 1 + + clock-output-names: + items: + - const: cpu + - const: ddr + - const: ahb + +required: + - compatible + - reg + - clock-names + - clocks + - '#clock-cells' + +additionalProperties: false + +examples: + - | + clock-controller@18050000 { + compatible = "qca,ar9132-pll", "qca,ar9130-pll"; + reg = <0x18050000 0x20>; + clock-names = "ref"; + clocks = <&extosc>; + #clock-cells = <1>; + clock-output-names = "cpu", "ddr", "ahb"; + }; diff --git a/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml index 3fd3dc1069fb..5c3ff37ec0d7 100644 --- a/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml @@ -13,7 +13,7 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SM8250. - See also:: include/dt-bindings/clock/qcom,camcc-sm8250.h + See also: include/dt-bindings/clock/qcom,camcc-sm8250.h allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml index 0a3ef7fd03fa..ef2b1e204430 100644 --- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks and power domains on SM6125. - See also:: include/dt-bindings/clock/qcom,dispcc-sm6125.h + See also: include/dt-bindings/clock/qcom,dispcc-sm6125.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml index 46403b98411f..a602e882e964 100644 --- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on SM6350. - See also:: include/dt-bindings/clock/qcom,dispcc-sm6350.h + See also: include/dt-bindings/clock/qcom,dispcc-sm6350.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq4019.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq4019.yaml index 012048921f92..c91039dc100e 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq4019.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq4019.yaml @@ -15,7 +15,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on IPQ4019. - See also:: include/dt-bindings/clock/qcom,gcc-ipq4019.h + See also: include/dt-bindings/clock/qcom,gcc-ipq4019.h allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml index 38b9e4283900..00d7df75b3d6 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on IPQ8074. - See also:: include/dt-bindings/clock/qcom,gcc-ipq8074.h + See also: include/dt-bindings/clock/qcom,gcc-ipq8074.h allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml index cd49704dcb95..92195091a919 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on MSM8976. - See also:: include/dt-bindings/clock/qcom,gcc-msm8976.h + See also: include/dt-bindings/clock/qcom,gcc-msm8976.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml index 10afe984e2fb..93bcd61461e7 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on MSM8994 and MSM8992. - See also:: include/dt-bindings/clock/qcom,gcc-msm8994.h + See also: include/dt-bindings/clock/qcom,gcc-msm8994.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml index 013fd074a8d5..64796f45f294 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module which provides the clocks, resets and power domains on MSM8996. - See also:: include/dt-bindings/clock/qcom,gcc-msm8996.h + See also: include/dt-bindings/clock/qcom,gcc-msm8996.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml index abae658c0ed9..d882f2b6620e 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on MSM8998. - See also:: include/dt-bindings/clock/qcom,gcc-msm8998.h + See also: include/dt-bindings/clock/qcom,gcc-msm8998.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml index 38c4c8c61b3a..b9194fa11e47 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on QCM2290. - See also:: include/dt-bindings/clock/qcom,gcc-qcm2290.h + See also: include/dt-bindings/clock/qcom,gcc-qcm2290.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml index 94755465c1fb..6b35a3c080a2 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on QCS404. - See also:: include/dt-bindings/clock/qcom,gcc-qcs404.h + See also: include/dt-bindings/clock/qcom,gcc-qcs404.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml index 1847bbeaa9d1..e30d1df3eeb5 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SC7180. - See also:: include/dt-bindings/clock/qcom,gcc-sc7180.h + See also: include/dt-bindings/clock/qcom,gcc-sc7180.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml index 4e4f68b9f6d2..5ddaf27bb1f4 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SC7280. - See also:: include/dt-bindings/clock/qcom,gcc-sc7280.h + See also: include/dt-bindings/clock/qcom,gcc-sc7280.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml index b4784ecaf58d..82c2ef39934d 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SC8180x. - See also:: include/dt-bindings/clock/qcom,gcc-sc8180x.h + See also: include/dt-bindings/clock/qcom,gcc-sc8180x.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml index 5cfde8a4de4e..c1eeccef66b4 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SC8280xp. - See also:: include/dt-bindings/clock/qcom,gcc-sc8280xp.h + See also: include/dt-bindings/clock/qcom,gcc-sc8280xp.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml index ef0a20456e8a..a7523a414341 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SDM670 and SDM845 - See also:: include/dt-bindings/clock/qcom,gcc-sdm845.h + See also: include/dt-bindings/clock/qcom,gcc-sdm845.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml index 30819f3d85c6..320e4f5b2b18 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SDX55 - See also:: include/dt-bindings/clock/qcom,gcc-sdx55.h + See also: include/dt-bindings/clock/qcom,gcc-sdx55.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml index 915449228668..9242e6e19139 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SDX65 - See also:: include/dt-bindings/clock/qcom,gcc-sdx65.h + See also: include/dt-bindings/clock/qcom,gcc-sdx65.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml index ecb69c707f09..c926630907c5 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM4250/6115. - See also:: include/dt-bindings/clock/qcom,gcc-sm6115.h + See also: include/dt-bindings/clock/qcom,gcc-sm6115.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml index 1fe68e07a2b2..5bd422e94a38 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM6125. - See also:: include/dt-bindings/clock/qcom,gcc-sm6125.h + See also: include/dt-bindings/clock/qcom,gcc-sm6125.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml index 78e232fa95dc..819e855eaf9a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM6350. - See also:: include/dt-bindings/clock/qcom,gcc-sm6350.h + See also: include/dt-bindings/clock/qcom,gcc-sm6350.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml index 1dcf97c0c064..5f3f69fe9ddb 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM8150. - See also:: include/dt-bindings/clock/qcom,gcc-sm8150.h + See also: include/dt-bindings/clock/qcom,gcc-sm8150.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml index 979ff0a8bf68..f4cd5a509c60 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM8250. - See also:: include/dt-bindings/clock/qcom,gcc-sm8250.h + See also: include/dt-bindings/clock/qcom,gcc-sm8250.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml index 594e87f5ba09..97ffae3b5522 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM8350. - See also:: include/dt-bindings/clock/qcom,gcc-sm8350.h + See also: include/dt-bindings/clock/qcom,gcc-sm8350.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml index 77273aee5d52..3169ac05e1d8 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM8450 - See also:: include/dt-bindings/clock/qcom,gcc-sm8450.h + See also: include/dt-bindings/clock/qcom,gcc-sm8450.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt deleted file mode 100644 index 030ba60dab08..000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt +++ /dev/null @@ -1,34 +0,0 @@ -Krait Clock Controller - -PROPERTIES - -- compatible: - Usage: required - Value type: <string> - Definition: must be one of: - "qcom,krait-cc-v1" - "qcom,krait-cc-v2" - -- #clock-cells: - Usage: required - Value type: <u32> - Definition: must be 1 - -- clocks: - Usage: required - Value type: <prop-encoded-array> - Definition: reference to the clock parents of hfpll, secondary muxes. - -- clock-names: - Usage: required - Value type: <stringlist> - Definition: must be "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb". - -Example: - - kraitcc: clock-controller { - compatible = "qcom,krait-cc-v1"; - clocks = <&hfpll0>, <&hfpll1>, <&acpu0_aux>, <&acpu1_aux>, <qsb>; - clock-names = "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb"; - #clock-cells = <1>; - }; diff --git a/Documentation/devicetree/bindings/clock/qcom,krait-cc.yaml b/Documentation/devicetree/bindings/clock/qcom,krait-cc.yaml new file mode 100644 index 000000000000..d6a019371fcf --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,krait-cc.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,krait-cc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Krait Clock Controller + +maintainers: + - Stephen Boyd <sboyd@kernel.org> + +properties: + compatible: + enum: + - qcom,krait-cc-v1 + - qcom,krait-cc-v2 + + '#clock-cells': + const: 1 + + clocks: + items: + - description: Parent clock phandle for hfpll0 + - description: Parent clock phandle for hfpll1 + - description: Parent clock phandle for acpu0_aux + - description: Parent clock phandle for acpu1_aux + - description: Parent clock phandle for qsb + + clock-names: + items: + - const: hfpll0 + - const: hfpll1 + - const: acpu0_aux + - const: acpu1_aux + - const: qsb + +required: + - compatible + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false diff --git a/Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml index b9b218ef9b68..374de7a6f8d9 100644 --- a/Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm graphics clock control module provides the clocks, resets and power domains on MSM8998. - See also:: include/dt-bindings/clock/qcom,gpucc-msm8998.h + See also: include/dt-bindings/clock/qcom,gpucc-msm8998.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml index 243be4f76db3..4a533b45eec2 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on qcm2290. - See also:: include/dt-bindings/clock/qcom,dispcc-qcm2290.h + See also: include/dt-bindings/clock/qcom,dispcc-qcm2290.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,qdu1000-ecpricc.yaml b/Documentation/devicetree/bindings/clock/qcom,qdu1000-ecpricc.yaml index fd21df0e7697..3038307ff2c5 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qdu1000-ecpricc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qdu1000-ecpricc.yaml @@ -14,7 +14,7 @@ description: | Qualcomm ECPRI Specification V2.0 Common Public Radio Interface clock control module which supports the clocks, resets on QDU1000 and QRU1000 - See also:: include/dt-bindings/clock/qcom,qdu1000-ecpricc.h + See also: include/dt-bindings/clock/qcom,qdu1000-ecpricc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,qdu1000-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qdu1000-gcc.yaml index 86befef02650..2c5a9ef4fe4d 100644 --- a/Documentation/devicetree/bindings/clock/qcom,qdu1000-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,qdu1000-gcc.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module which supports the clocks, resets and power domains on QDU1000 and QRU1000 - See also:: include/dt-bindings/clock/qcom,qdu1000-gcc.h + See also: include/dt-bindings/clock/qcom,qdu1000-gcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sa8775p-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sa8775p-gcc.yaml index addbd323fa6d..c641aac8c451 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sa8775p-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sa8775p-gcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on sa8775p. - See also:: include/dt-bindings/clock/qcom,sa8775p-gcc.h + See also: include/dt-bindings/clock/qcom,sa8775p-gcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml index c7fe6400ea13..98ee9be84794 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SC7180. - See also:: include/dt-bindings/clock/qcom,camcc-sc7180.h + See also: include/dt-bindings/clock/qcom,camcc-sc7180.h allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml index 0d8ea44d8141..f147d06ad2ef 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on SC7180. - See also:: include/dt-bindings/clock/qcom,dispcc-sc7180.h + See also: include/dt-bindings/clock/qcom,dispcc-sc7180.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml index fdfb389083c1..ad360debef7c 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm LPASS core clock control module provides the clocks and power domains on SC7180. - See also:: include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h + See also: include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml index dcef8de3a905..2f28be58e82e 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SC7280. - See also:: include/dt-bindings/clock/qcom,camcc-sc7280.h + See also: include/dt-bindings/clock/qcom,camcc-sc7280.h allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml index 23177661be40..95b1e4f48c4f 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on SC7280. - See also:: include/dt-bindings/clock/qcom,dispcc-sc7280.h + See also: include/dt-bindings/clock/qcom,dispcc-sc7280.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml index f44c5c130d2d..a90961d8656c 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm LPASS core clock control module provides the clocks and power domains on SC7280. - See also:: include/dt-bindings/clock/qcom,lpass-sc7280.h + See also: include/dt-bindings/clock/qcom,lpass-sc7280.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml index fa95c3a1ba3a..6214e41eec1f 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SDM845. - See also:: include/dt-bindings/clock/qcom,camcc-sm845.h + See also: include/dt-bindings/clock/qcom,camcc-sm845.h allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml index 220f4004f7fd..854c391c8307 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on SDM845. - See also:: include/dt-bindings/clock/qcom,dispcc-sdm845.h + See also: include/dt-bindings/clock/qcom,dispcc-sdm845.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sdm845-lpasscc.yaml b/Documentation/devicetree/bindings/clock/qcom,sdm845-lpasscc.yaml index a96fd837c70a..f9feb7049b21 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sdm845-lpasscc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sdm845-lpasscc.yaml @@ -12,7 +12,7 @@ maintainers: description: | Qualcomm SDM845 LPASS (Low Power Audio SubSystem) Clock Controller. - See also:: include/dt-bindings/clock/qcom,lpass-sdm845.h + See also: include/dt-bindings/clock/qcom,lpass-sdm845.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sdx75-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sdx75-gcc.yaml index 567182aba300..29a0b29bcb81 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sdx75-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sdx75-gcc.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SDX75 - See also:: include/dt-bindings/clock/qcom,sdx75-gcc.h + See also: include/dt-bindings/clock/qcom,sdx75-gcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm4450-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm4450-camcc.yaml index f54ce865880d..0b340b2f3205 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm4450-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm4450-camcc.yaml @@ -14,7 +14,7 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SM4450 - See also:: include/dt-bindings/clock/qcom,sm4450-camcc.h + See also: include/dt-bindings/clock/qcom,sm4450-camcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm4450-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm4450-dispcc.yaml index 2aa05353eff1..378f05e5988c 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm4450-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm4450-dispcc.yaml @@ -14,7 +14,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on SM4450 - See also:: include/dt-bindings/clock/qcom,sm4450-dispcc.h + See also: include/dt-bindings/clock/qcom,sm4450-dispcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml index 0ac92d7871e1..9cfe859bacc9 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm4450-gcc.yaml @@ -14,7 +14,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM4450 - See also:: include/dt-bindings/clock/qcom,sm4450-gcc.h + See also: include/dt-bindings/clock/qcom,sm4450-gcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml index 00be36683eb5..b31424306f49 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks and power domains on SM6115. - See also:: include/dt-bindings/clock/qcom,sm6115-dispcc.h + See also: include/dt-bindings/clock/qcom,sm6115-dispcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml index 4ff17a91344b..104ba10ca573 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-gpucc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm graphics clock control module provides clocks, resets and power domains on Qualcomm SoCs. - See also:: include/dt-bindings/clock/qcom,sm6115-gpucc.h + See also: include/dt-bindings/clock/qcom,sm6115-gpucc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml index 10a9c96a97b6..12d6f0cdbcd8 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6125-gpucc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm graphics clock control module provides clocks and power domains on Qualcomm SoCs. - See also:: include/dt-bindings/clock/qcom,sm6125-gpucc.h + See also: include/dt-bindings/clock/qcom,sm6125-gpucc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6350-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6350-camcc.yaml index c03b30f64f35..ba6f4c4d295e 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6350-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6350-camcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SM6350. - See also:: include/dt-bindings/clock/qcom,sm6350-camcc.h + See also: include/dt-bindings/clock/qcom,sm6350-camcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml index 3cd422a645fd..519ea76cb052 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on SM6375. - See also:: include/dt-bindings/clock/qcom,dispcc-sm6375.h + See also: include/dt-bindings/clock/qcom,dispcc-sm6375.h allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml index de4e9066eeb8..66dfa72fa975 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM6375 - See also:: include/dt-bindings/clock/qcom,sm6375-gcc.h + See also: include/dt-bindings/clock/qcom,sm6375-gcc.h allOf: - $ref: qcom,gcc.yaml# diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml index d9dd479c17bd..3aad6b5bb1c5 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-gpucc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm graphics clock control module provides clocks, resets and power domains on Qualcomm SoCs. - See also:: include/dt-bindings/clock/qcom,sm6375-gpucc.h + See also: include/dt-bindings/clock/qcom,sm6375-gpucc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm7150-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm7150-camcc.yaml index 7be4b10c430c..b96091c28c5a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm7150-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm7150-camcc.yaml @@ -15,7 +15,7 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SM7150. - See also:: include/dt-bindings/clock/qcom,sm7150-camcc.h + See also: include/dt-bindings/clock/qcom,sm7150-camcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm7150-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm7150-dispcc.yaml index b8d6e1d05ce2..13ab3359b592 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm7150-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm7150-dispcc.yaml @@ -15,7 +15,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on SM7150. - See also:: include/dt-bindings/clock/qcom,sm7150-dispcc.h + See also: include/dt-bindings/clock/qcom,sm7150-dispcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm7150-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm7150-gcc.yaml index 4d7bbbf4ce8a..3878808f811e 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm7150-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm7150-gcc.yaml @@ -15,7 +15,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM7150 - See also:: include/dt-bindings/clock/qcom,sm7150-gcc.h + See also: include/dt-bindings/clock/qcom,sm7150-gcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm7150-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm7150-videocc.yaml index 037ffc71e70e..9f7928730386 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm7150-videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm7150-videocc.yaml @@ -15,7 +15,7 @@ description: | Qualcomm video clock control module provides the clocks, resets and power domains on SM7150. - See also:: include/dt-bindings/clock/qcom,videocc-sm7150.h + See also: include/dt-bindings/clock/qcom,videocc-sm7150.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8150-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8150-camcc.yaml index 5e9f62d7866c..a210ec9d820c 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8150-camcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8150-camcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm camera clock control module provides the clocks, resets and power domains on SM8150. - See also:: include/dt-bindings/clock/qcom,sm8150-camcc.h + See also: include/dt-bindings/clock/qcom,sm8150-camcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml index e9123bbfd491..bd131a1ff165 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm display clock control module provides the clocks, resets and power domains on SM8450. - See also:: include/dt-bindings/clock/qcom,sm8450-dispcc.h + See also: include/dt-bindings/clock/qcom,sm8450-dispcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8550-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8550-gcc.yaml index d83b64dcce4f..c4e9b9bb63f5 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8550-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8550-gcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM8550 - See also:: include/dt-bindings/clock/qcom,sm8550-gcc.h + See also: include/dt-bindings/clock/qcom,sm8550-gcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8650-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8650-gcc.yaml index 976f29cce809..c7143e2abc80 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sm8650-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sm8650-gcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on SM8650 - See also:: include/dt-bindings/clock/qcom,sm8650-gcc.h + See also: include/dt-bindings/clock/qcom,sm8650-gcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/qcom,x1e80100-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,x1e80100-gcc.yaml index 28797d0c5d8d..68dde0720c71 100644 --- a/Documentation/devicetree/bindings/clock/qcom,x1e80100-gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,x1e80100-gcc.yaml @@ -13,7 +13,7 @@ description: | Qualcomm global clock control module provides the clocks, resets and power domains on X1E80100 - See also:: include/dt-bindings/clock/qcom,x1e80100-gcc.h + See also: include/dt-bindings/clock/qcom,x1e80100-gcc.h properties: compatible: diff --git a/Documentation/devicetree/bindings/clock/ti/autoidle.txt b/Documentation/devicetree/bindings/clock/ti/autoidle.txt deleted file mode 100644 index 05645a10a9e3..000000000000 --- a/Documentation/devicetree/bindings/clock/ti/autoidle.txt +++ /dev/null @@ -1,37 +0,0 @@ -Binding for Texas Instruments autoidle clock. - -This binding uses the common clock binding[1]. It assumes a register mapped -clock which can be put to idle automatically by hardware based on the usage -and a configuration bit setting. Autoidle clock is never an individual -clock, it is always a derivative of some basic clock like a gate, divider, -or fixed-factor. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- reg : offset for the register controlling the autoidle -- ti,autoidle-shift : bit shift of the autoidle enable bit -- ti,invert-autoidle-bit : autoidle is enabled by setting the bit to 0 - -Examples: - dpll_core_m4_ck: dpll_core_m4_ck { - #clock-cells = <0>; - compatible = "ti,divider-clock"; - clocks = <&dpll_core_x2_ck>; - ti,max-div = <31>; - ti,autoidle-shift = <8>; - reg = <0x2d38>; - ti,index-starts-at-one; - ti,invert-autoidle-bit; - }; - - dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck { - #clock-cells = <0>; - compatible = "ti,fixed-factor-clock"; - clocks = <&dpll_usb_ck>; - ti,clock-div = <1>; - ti,autoidle-shift = <8>; - reg = <0x01b4>; - ti,clock-mult = <1>; - ti,invert-autoidle-bit; - }; diff --git a/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt b/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt deleted file mode 100644 index dc69477b6e98..000000000000 --- a/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt +++ /dev/null @@ -1,42 +0,0 @@ -Binding for TI fixed factor rate clock sources. - -This binding uses the common clock binding[1], and also uses the autoidle -support from TI autoidle clock [2]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt -[2] Documentation/devicetree/bindings/clock/ti/autoidle.txt - -Required properties: -- compatible : shall be "ti,fixed-factor-clock". -- #clock-cells : from common clock binding; shall be set to 0. -- ti,clock-div: fixed divider. -- ti,clock-mult: fixed multiplier. -- clocks: parent clock. - -Optional properties: -- clock-output-names : from common clock binding. -- ti,autoidle-shift: bit shift of the autoidle enable bit for the clock, - see [2] -- reg: offset for the autoidle register of this clock, see [2] -- ti,invert-autoidle-bit: autoidle is enabled by setting the bit to 0, see [2] -- ti,set-rate-parent: clk_set_rate is propagated to parent - -Example: - clock { - compatible = "ti,fixed-factor-clock"; - clocks = <&parentclk>; - #clock-cells = <0>; - ti,clock-div = <2>; - ti,clock-mult = <1>; - }; - - dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck { - #clock-cells = <0>; - compatible = "ti,fixed-factor-clock"; - clocks = <&dpll_usb_ck>; - ti,clock-div = <1>; - ti,autoidle-shift = <8>; - reg = <0x01b4>; - ti,clock-mult = <1>; - ti,invert-autoidle-bit; - }; diff --git a/Documentation/devicetree/bindings/clock/ti/ti,autoidle.yaml b/Documentation/devicetree/bindings/clock/ti/ti,autoidle.yaml new file mode 100644 index 000000000000..ed1bf182b64d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/ti/ti,autoidle.yaml @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/ti/ti,autoidle.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI autoidle clock + +maintainers: + - Tero Kristo <kristo@kernel.org> + - Sukrut Bellary <sbellary@baylibre.com> + +description: + Some clocks in TI SoC support the autoidle feature. These properties are + applicable only if the clock supports autoidle feature. It assumes a register + mapped clock which can be put to idle automatically by hardware based on + usage and configuration bit setting. Autoidle clock is never an individual + clock, it is always a derivative of some basic clock like a gate, divider, or + fixed-factor. + +properties: + ti,autoidle-shift: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + bit shift of the autoidle enable bit for the clock + maximum: 31 + default: 0 + + ti,invert-autoidle-bit: + type: boolean + description: + autoidle is enabled by setting the bit to 0 + +additionalProperties: true diff --git a/Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml b/Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml index 3fbe236eb565..6729fcb839d2 100644 --- a/Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml +++ b/Documentation/devicetree/bindings/clock/ti/ti,divider-clock.yaml @@ -55,9 +55,10 @@ description: | is missing it is the same as supplying a zero shift. This binding can also optionally provide support to the hardware autoidle - feature, see [1]. + feature. - [1] Documentation/devicetree/bindings/clock/ti/autoidle.txt +allOf: + - $ref: ti,autoidle.yaml# properties: compatible: @@ -97,7 +98,6 @@ properties: minimum: 1 default: 1 - ti,max-div: $ref: /schemas/types.yaml#/definitions/uint32 description: @@ -116,20 +116,6 @@ properties: valid divisor programming must be a power of two, only valid if ti,dividers is not defined. - ti,autoidle-shift: - $ref: /schemas/types.yaml#/definitions/uint32 - description: - bit shift of the autoidle enable bit for the clock, - see [1]. - maximum: 31 - default: 0 - - ti,invert-autoidle-bit: - type: boolean - description: - autoidle is enabled by setting the bit to 0, - see [1] - ti,set-rate-parent: type: boolean description: @@ -156,7 +142,7 @@ required: - clocks - reg -additionalProperties: false +unevaluatedProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/clock/ti/ti,fixed-factor-clock.yaml b/Documentation/devicetree/bindings/clock/ti/ti,fixed-factor-clock.yaml new file mode 100644 index 000000000000..7a63b0992976 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/ti/ti,fixed-factor-clock.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/ti/ti,fixed-factor-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI fixed factor rate clock sources + +maintainers: + - Tero Kristo <kristo@kernel.org> + - Sukrut Bellary <sbellary@baylibre.com> + +description: + This consists of a divider and a multiplier used to generate a fixed rate + clock. This also uses the autoidle support from TI autoidle clock. + +allOf: + - $ref: ti,autoidle.yaml# + +properties: + compatible: + const: ti,fixed-factor-clock + + "#clock-cells": + const: 0 + + reg: + maxItems: 1 + + ti,clock-div: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Fixed divider + minimum: 1 + + ti,clock-mult: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Fixed multiplier + minimum: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + + ti,set-rate-parent: + description: + Propagate to parent clock + type: boolean + +required: + - compatible + - clocks + - "#clock-cells" + - ti,clock-mult + - ti,clock-div + +unevaluatedProperties: false + +examples: + - | + bus{ + #address-cells = <1>; + #size-cells = <0>; + + clock@1b4 { + compatible = "ti,fixed-factor-clock"; + reg = <0x1b4>; + clocks = <&dpll_usb_ck>; + #clock-cells = <0>; + ti,clock-mult = <1>; + ti,clock-div = <1>; + ti,autoidle-shift = <8>; + ti,invert-autoidle-bit; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/xgene.txt b/Documentation/devicetree/bindings/clock/xgene.txt deleted file mode 100644 index 8233e771711b..000000000000 --- a/Documentation/devicetree/bindings/clock/xgene.txt +++ /dev/null @@ -1,131 +0,0 @@ -Device Tree Clock bindings for APM X-Gene - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible : shall be one of the following: - "apm,xgene-socpll-clock" - for a X-Gene SoC PLL clock - "apm,xgene-pcppll-clock" - for a X-Gene PCP PLL clock - "apm,xgene-pmd-clock" - for a X-Gene PMD clock - "apm,xgene-device-clock" - for a X-Gene device clock - "apm,xgene-socpll-v2-clock" - for a X-Gene SoC PLL v2 clock - "apm,xgene-pcppll-v2-clock" - for a X-Gene PCP PLL v2 clock - -Required properties for SoC or PCP PLL clocks: -- reg : shall be the physical PLL register address for the pll clock. -- clocks : shall be the input parent clock phandle for the clock. This should - be the reference clock. -- #clock-cells : shall be set to 1. -- clock-output-names : shall be the name of the PLL referenced by derive - clock. -Optional properties for PLL clocks: -- clock-names : shall be the name of the PLL. If missing, use the device name. - -Required properties for PMD clocks: -- reg : shall be the physical register address for the pmd clock. -- clocks : shall be the input parent clock phandle for the clock. -- #clock-cells : shall be set to 1. -- clock-output-names : shall be the name of the clock referenced by derive - clock. -Optional properties for PLL clocks: -- clock-names : shall be the name of the clock. If missing, use the device name. - -Required properties for device clocks: -- reg : shall be a list of address and length pairs describing the CSR - reset and/or the divider. Either may be omitted, but at least - one must be present. - - reg-names : shall be a string list describing the reg resource. This - may include "csr-reg" and/or "div-reg". If this property - is not present, the reg property is assumed to describe - only "csr-reg". -- clocks : shall be the input parent clock phandle for the clock. -- #clock-cells : shall be set to 1. -- clock-output-names : shall be the name of the device referenced. -Optional properties for device clocks: -- clock-names : shall be the name of the device clock. If missing, use the - device name. -- csr-offset : Offset to the CSR reset register from the reset address base. - Default is 0. -- csr-mask : CSR reset mask bit. Default is 0xF. -- enable-offset : Offset to the enable register from the reset address base. - Default is 0x8. -- enable-mask : CSR enable mask bit. Default is 0xF. -- divider-offset : Offset to the divider CSR register from the divider base. - Default is 0x0. -- divider-width : Width of the divider register. Default is 0. -- divider-shift : Bit shift of the divider register. Default is 0. - -For example: - - pcppll: pcppll@17000100 { - compatible = "apm,xgene-pcppll-clock"; - #clock-cells = <1>; - clocks = <&refclk 0>; - clock-names = "pcppll"; - reg = <0x0 0x17000100 0x0 0x1000>; - clock-output-names = "pcppll"; - type = <0>; - }; - - pmd0clk: pmd0clk@7e200200 { - compatible = "apm,xgene-pmd-clock"; - #clock-cells = <1>; - clocks = <&pmdpll 0>; - reg = <0x0 0x7e200200 0x0 0x10>; - clock-output-names = "pmd0clk"; - }; - - socpll: socpll@17000120 { - compatible = "apm,xgene-socpll-clock"; - #clock-cells = <1>; - clocks = <&refclk 0>; - clock-names = "socpll"; - reg = <0x0 0x17000120 0x0 0x1000>; - clock-output-names = "socpll"; - type = <1>; - }; - - qmlclk: qmlclk { - compatible = "apm,xgene-device-clock"; - #clock-cells = <1>; - clocks = <&socplldiv2 0>; - clock-names = "qmlclk"; - reg = <0x0 0x1703C000 0x0 0x1000>; - reg-name = "csr-reg"; - clock-output-names = "qmlclk"; - }; - - ethclk: ethclk { - compatible = "apm,xgene-device-clock"; - #clock-cells = <1>; - clocks = <&socplldiv2 0>; - clock-names = "ethclk"; - reg = <0x0 0x17000000 0x0 0x1000>; - reg-names = "div-reg"; - divider-offset = <0x238>; - divider-width = <0x9>; - divider-shift = <0x0>; - clock-output-names = "ethclk"; - }; - - apbclk: apbclk { - compatible = "apm,xgene-device-clock"; - #clock-cells = <1>; - clocks = <&ahbclk 0>; - clock-names = "apbclk"; - reg = <0x0 0x1F2AC000 0x0 0x1000 - 0x0 0x1F2AC000 0x0 0x1000>; - reg-names = "csr-reg", "div-reg"; - csr-offset = <0x0>; - csr-mask = <0x200>; - enable-offset = <0x8>; - enable-mask = <0x200>; - divider-offset = <0x10>; - divider-width = <0x2>; - divider-shift = <0x0>; - flags = <0x8>; - clock-output-names = "apbclk"; - }; - diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml index b470901f5f56..4dbef86bd958 100644 --- a/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml @@ -15,7 +15,7 @@ description: | Some peripherals such as PWM have their I/O go through the 4 "GPIOs". maintainers: - - Jianlong Huang <jianlong.huang@starfivetech.com> + - Hal Feng <hal.feng@starfivetech.com> properties: compatible: diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml index 222b9e240f8a..e2a25a20f6a6 100644 --- a/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml @@ -18,7 +18,7 @@ description: | any GPIO can be set up to be controlled by any of the peripherals. maintainers: - - Jianlong Huang <jianlong.huang@starfivetech.com> + - Hal Feng <hal.feng@starfivetech.com> properties: compatible: diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst index 2a17865dfe39..5236cb52e357 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst @@ -584,7 +584,6 @@ encoded manner. The codes are the following: ms may share gd stack segment growns down pf pure PFN range - dw disabled write to the mapped file lo pages are locked in memory io memory mapped I/O area sr sequential read advise provided @@ -607,8 +606,11 @@ encoded manner. The codes are the following: mt arm64 MTE allocation tags are enabled um userfaultfd missing tracking uw userfaultfd wr-protect tracking + ui userfaultfd minor fault ss shadow/guarded control stack page sl sealed + lf lock on fault pages + dp always lazily freeable mapping == ======================================= Note that there is no guarantee that every flag and associated mnemonic will diff --git a/MAINTAINERS b/MAINTAINERS index a92290fffa16..4b1b37754bca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2884,7 +2884,7 @@ M: Krzysztof Kozlowski <krzk@kernel.org> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Odd Fixes F: Documentation/devicetree/bindings/arm/moxart.yaml -F: Documentation/devicetree/bindings/clock/moxa,moxart-clock.txt +F: Documentation/devicetree/bindings/clock/moxa,moxart-clock.yaml F: arch/arm/boot/dts/moxa/ F: drivers/clk/clk-moxart.c @@ -4555,6 +4555,7 @@ BPF [NETWORKING] (tcx & tc BPF, sock_addr) M: Martin KaFai Lau <martin.lau@linux.dev> M: Daniel Borkmann <daniel@iogearbox.net> R: John Fastabend <john.fastabend@gmail.com> +R: Stanislav Fomichev <sdf@fomichev.me> L: bpf@vger.kernel.org L: netdev@vger.kernel.org S: Maintained @@ -5979,6 +5980,7 @@ F: include/dt-bindings/clock/ F: include/linux/clk-pr* F: include/linux/clk/ F: include/linux/of_clk.h +F: scripts/gdb/linux/clk.py F: rust/helpers/clk.c F: rust/kernel/clk.rs X: drivers/clk/clkdev.c @@ -6254,6 +6256,7 @@ F: include/linux/cpuhotplug.h F: include/linux/smpboot.h F: kernel/cpu.c F: kernel/smpboot.* +F: rust/helper/cpu.c F: rust/kernel/cpu.rs CPU IDLE TIME MANAGEMENT FRAMEWORK @@ -15919,6 +15922,7 @@ R: Liam R. Howlett <Liam.Howlett@oracle.com> R: Nico Pache <npache@redhat.com> R: Ryan Roberts <ryan.roberts@arm.com> R: Dev Jain <dev.jain@arm.com> +R: Barry Song <baohua@kernel.org> L: linux-mm@kvack.org S: Maintained W: http://www.linux-mm.org @@ -17493,7 +17497,7 @@ F: tools/testing/selftests/net/srv6* NETWORKING [TCP] M: Eric Dumazet <edumazet@google.com> M: Neal Cardwell <ncardwell@google.com> -R: Kuniyuki Iwashima <kuniyu@amazon.com> +R: Kuniyuki Iwashima <kuniyu@google.com> L: netdev@vger.kernel.org S: Maintained F: Documentation/networking/net_cachelines/tcp_sock.rst @@ -17523,7 +17527,7 @@ F: net/tls/* NETWORKING [SOCKETS] M: Eric Dumazet <edumazet@google.com> -M: Kuniyuki Iwashima <kuniyu@amazon.com> +M: Kuniyuki Iwashima <kuniyu@google.com> M: Paolo Abeni <pabeni@redhat.com> M: Willem de Bruijn <willemb@google.com> S: Maintained @@ -17538,7 +17542,7 @@ F: net/core/scm.c F: net/socket.c NETWORKING [UNIX SOCKETS] -M: Kuniyuki Iwashima <kuniyu@amazon.com> +M: Kuniyuki Iwashima <kuniyu@google.com> S: Maintained F: include/net/af_unix.h F: include/net/netns/unix.h @@ -23661,7 +23665,6 @@ F: include/dt-bindings/clock/starfive?jh71*.h STARFIVE JH71X0 PINCTRL DRIVERS M: Emil Renner Berthing <kernel@esmil.dk> -M: Jianlong Huang <jianlong.huang@starfivetech.com> M: Hal Feng <hal.feng@starfivetech.com> L: linux-gpio@vger.kernel.org S: Maintained @@ -26967,6 +26970,7 @@ M: David S. Miller <davem@davemloft.net> M: Jakub Kicinski <kuba@kernel.org> M: Jesper Dangaard Brouer <hawk@kernel.org> M: John Fastabend <john.fastabend@gmail.com> +R: Stanislav Fomichev <sdf@fomichev.me> L: netdev@vger.kernel.org L: bpf@vger.kernel.org S: Supported @@ -26988,6 +26992,7 @@ M: Björn Töpel <bjorn@kernel.org> M: Magnus Karlsson <magnus.karlsson@intel.com> M: Maciej Fijalkowski <maciej.fijalkowski@intel.com> R: Jonathan Lemon <jonathan.lemon@gmail.com> +R: Stanislav Fomichev <sdf@fomichev.me> L: netdev@vger.kernel.org L: bpf@vger.kernel.org S: Maintained @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 16 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Baby Opossum Posse # *DOCUMENTATION* @@ -1832,12 +1832,9 @@ rustfmtcheck: rustfmt # Misc # --------------------------------------------------------------------------- -# Run misc checks when ${KBUILD_EXTRA_WARN} contains 1 PHONY += misc-check -ifneq ($(findstring 1,$(KBUILD_EXTRA_WARN)),) misc-check: $(Q)$(srctree)/scripts/misc-check -endif all: misc-check diff --git a/arch/alpha/include/asm/pgtable.h b/arch/alpha/include/asm/pgtable.h index 2676017f42f1..44e7aedac6e8 100644 --- a/arch/alpha/include/asm/pgtable.h +++ b/arch/alpha/include/asm/pgtable.h @@ -327,7 +327,7 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 005d9e4d187a..a31bbf5c8bbc 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -144,7 +144,7 @@ #define ARC_AUX_AGU_MOD2 0x5E2 #define ARC_AUX_AGU_MOD3 0x5E3 -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <soc/arc/arc_aux.h> diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h index 592d7fffc223..e615c42b93ba 100644 --- a/arch/arc/include/asm/atomic.h +++ b/arch/arc/include/asm/atomic.h @@ -6,7 +6,7 @@ #ifndef _ASM_ARC_ATOMIC_H #define _ASM_ARC_ATOMIC_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <linux/types.h> #include <linux/compiler.h> @@ -31,6 +31,6 @@ #include <asm/atomic64-arcv2.h> #endif -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/atomic64-arcv2.h b/arch/arc/include/asm/atomic64-arcv2.h index 9b5791b85471..73080a664369 100644 --- a/arch/arc/include/asm/atomic64-arcv2.h +++ b/arch/arc/include/asm/atomic64-arcv2.h @@ -137,12 +137,9 @@ ATOMIC64_OPS(xor, xor, xor) #undef ATOMIC64_OP_RETURN #undef ATOMIC64_OP -static inline s64 -arch_atomic64_cmpxchg(atomic64_t *ptr, s64 expected, s64 new) +static inline u64 __arch_cmpxchg64_relaxed(volatile void *ptr, u64 old, u64 new) { - s64 prev; - - smp_mb(); + u64 prev; __asm__ __volatile__( "1: llockd %0, [%1] \n" @@ -152,14 +149,12 @@ arch_atomic64_cmpxchg(atomic64_t *ptr, s64 expected, s64 new) " bnz 1b \n" "2: \n" : "=&r"(prev) - : "r"(ptr), "ir"(expected), "r"(new) - : "cc"); /* memory clobber comes from smp_mb() */ - - smp_mb(); + : "r"(ptr), "ir"(old), "r"(new) + : "memory", "cc"); return prev; } -#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg +#define arch_cmpxchg64_relaxed __arch_cmpxchg64_relaxed static inline s64 arch_atomic64_xchg(atomic64_t *ptr, s64 new) { diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h index f5a936496f06..5340c2871392 100644 --- a/arch/arc/include/asm/bitops.h +++ b/arch/arc/include/asm/bitops.h @@ -10,7 +10,7 @@ #error only <linux/bitops.h> can be included directly #endif -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <linux/types.h> #include <linux/compiler.h> @@ -192,6 +192,6 @@ static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x) #include <asm-generic/bitops/le.h> #include <asm-generic/bitops/ext2-atomic-setbit.h> -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/bug.h b/arch/arc/include/asm/bug.h index 4c453ba96c51..171c16021f70 100644 --- a/arch/arc/include/asm/bug.h +++ b/arch/arc/include/asm/bug.h @@ -6,7 +6,7 @@ #ifndef _ASM_ARC_BUG_H #define _ASM_ARC_BUG_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <asm/ptrace.h> @@ -29,6 +29,6 @@ void die(const char *str, struct pt_regs *regs, unsigned long address); #include <asm-generic/bug.h> -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index f0f1fc5d62b6..040a97f4dd82 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -23,7 +23,7 @@ */ #define ARC_UNCACHED_ADDR_SPACE 0xc0000000 -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <linux/build_bug.h> @@ -65,7 +65,7 @@ extern int ioc_enable; extern unsigned long perip_base, perip_end; -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ /* Instruction cache related Auxiliary registers */ #define ARC_REG_IC_BCR 0x77 /* Build Config reg */ diff --git a/arch/arc/include/asm/current.h b/arch/arc/include/asm/current.h index 06be89f6f2f0..03ffd005f3fa 100644 --- a/arch/arc/include/asm/current.h +++ b/arch/arc/include/asm/current.h @@ -9,7 +9,7 @@ #ifndef _ASM_ARC_CURRENT_H #define _ASM_ARC_CURRENT_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #ifdef CONFIG_ARC_CURR_IN_REG @@ -20,6 +20,6 @@ register struct task_struct *curr_arc asm("gp"); #include <asm-generic/current.h> #endif /* ! CONFIG_ARC_CURR_IN_REG */ -#endif /* ! __ASSEMBLY__ */ +#endif /* ! __ASSEMBLER__ */ #endif /* _ASM_ARC_CURRENT_H */ diff --git a/arch/arc/include/asm/dsp-impl.h b/arch/arc/include/asm/dsp-impl.h index cd5636dfeb6f..fd5fdaad90c1 100644 --- a/arch/arc/include/asm/dsp-impl.h +++ b/arch/arc/include/asm/dsp-impl.h @@ -11,7 +11,7 @@ #define DSP_CTRL_DISABLED_ALL 0 -#ifdef __ASSEMBLY__ +#ifdef __ASSEMBLER__ /* clobbers r5 register */ .macro DSP_EARLY_INIT diff --git a/arch/arc/include/asm/dsp.h b/arch/arc/include/asm/dsp.h index f496dbc4640b..eeaaf4e4eabd 100644 --- a/arch/arc/include/asm/dsp.h +++ b/arch/arc/include/asm/dsp.h @@ -7,7 +7,7 @@ #ifndef __ASM_ARC_DSP_H #define __ASM_ARC_DSP_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ /* * DSP-related saved registers - need to be saved only when you are @@ -24,6 +24,6 @@ struct dsp_callee_regs { #endif }; -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif /* __ASM_ARC_DSP_H */ diff --git a/arch/arc/include/asm/dwarf.h b/arch/arc/include/asm/dwarf.h index a0d5ebe1bc3f..1524c5cf8b59 100644 --- a/arch/arc/include/asm/dwarf.h +++ b/arch/arc/include/asm/dwarf.h @@ -6,7 +6,7 @@ #ifndef _ASM_ARC_DWARF_H #define _ASM_ARC_DWARF_H -#ifdef __ASSEMBLY__ +#ifdef __ASSEMBLER__ #ifdef ARC_DW2_UNWIND_AS_CFI @@ -38,6 +38,6 @@ #endif /* !ARC_DW2_UNWIND_AS_CFI */ -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif /* _ASM_ARC_DWARF_H */ diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index 38c35722cebf..f453af251a1a 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h @@ -13,7 +13,7 @@ #include <asm/processor.h> /* For VMALLOC_START */ #include <asm/mmu.h> -#ifdef __ASSEMBLY__ +#ifdef __ASSEMBLER__ #ifdef CONFIG_ISA_ARCOMPACT #include <asm/entry-compact.h> /* ISA specific bits */ @@ -146,7 +146,7 @@ #endif /* CONFIG_ARC_CURR_IN_REG */ -#else /* !__ASSEMBLY__ */ +#else /* !__ASSEMBLER__ */ extern void do_signal(struct pt_regs *); extern void do_notify_resume(struct pt_regs *); diff --git a/arch/arc/include/asm/irqflags-arcv2.h b/arch/arc/include/asm/irqflags-arcv2.h index fb3c21f1a238..30aea562f8aa 100644 --- a/arch/arc/include/asm/irqflags-arcv2.h +++ b/arch/arc/include/asm/irqflags-arcv2.h @@ -50,7 +50,7 @@ #define ISA_INIT_STATUS_BITS (STATUS_IE_MASK | __AD_ENB | \ (ARCV2_IRQ_DEF_PRIO << 1)) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ /* * Save IRQ state and disable IRQs @@ -170,6 +170,6 @@ static inline void arc_softirq_clear(int irq) seti .endm -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/irqflags-compact.h b/arch/arc/include/asm/irqflags-compact.h index 936a2f21f315..85c2f6bcde0c 100644 --- a/arch/arc/include/asm/irqflags-compact.h +++ b/arch/arc/include/asm/irqflags-compact.h @@ -40,7 +40,7 @@ #define ISA_INIT_STATUS_BITS STATUS_IE_MASK -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ /****************************************************************** * IRQ Control Macros @@ -196,6 +196,6 @@ static inline int arch_irqs_disabled(void) flag \scratch .endm -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/jump_label.h b/arch/arc/include/asm/jump_label.h index a339223d9e05..66ead75784d9 100644 --- a/arch/arc/include/asm/jump_label.h +++ b/arch/arc/include/asm/jump_label.h @@ -2,7 +2,7 @@ #ifndef _ASM_ARC_JUMP_LABEL_H #define _ASM_ARC_JUMP_LABEL_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <linux/stringify.h> #include <linux/types.h> @@ -68,5 +68,5 @@ struct jump_entry { jump_label_t key; }; -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h index 8a3fb71e9cfa..ba3cb65b5eaa 100644 --- a/arch/arc/include/asm/linkage.h +++ b/arch/arc/include/asm/linkage.h @@ -12,7 +12,7 @@ #define __ALIGN .align 4 #define __ALIGN_STR __stringify(__ALIGN) -#ifdef __ASSEMBLY__ +#ifdef __ASSEMBLER__ .macro ST2 e, o, off #ifdef CONFIG_ARC_HAS_LL64 @@ -61,7 +61,7 @@ CFI_ENDPROC ASM_NL \ .size name, .-name -#else /* !__ASSEMBLY__ */ +#else /* !__ASSEMBLER__ */ #ifdef CONFIG_ARC_HAS_ICCM #define __arcfp_code __section(".text.arcfp") @@ -75,6 +75,6 @@ #define __arcfp_data __section(".data") #endif -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/mmu-arcv2.h b/arch/arc/include/asm/mmu-arcv2.h index 41412642f279..5e5482026ac9 100644 --- a/arch/arc/include/asm/mmu-arcv2.h +++ b/arch/arc/include/asm/mmu-arcv2.h @@ -69,7 +69,7 @@ #define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK_PHYS | _PAGE_CACHEABLE) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ struct mm_struct; extern int pae40_exist_but_not_enab(void); @@ -100,6 +100,6 @@ static inline void mmu_setup_pgd(struct mm_struct *mm, void *pgd) sr \reg, [ARC_REG_PID] .endm -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h index 4ae2db59d494..e3b35ceab582 100644 --- a/arch/arc/include/asm/mmu.h +++ b/arch/arc/include/asm/mmu.h @@ -6,7 +6,7 @@ #ifndef _ASM_ARC_MMU_H #define _ASM_ARC_MMU_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <linux/threads.h> /* NR_CPUS */ diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h index def0dfb95b43..9720fe6b2c24 100644 --- a/arch/arc/include/asm/page.h +++ b/arch/arc/include/asm/page.h @@ -19,7 +19,7 @@ #endif /* CONFIG_ARC_HAS_PAE40 */ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #define clear_page(paddr) memset((paddr), 0, PAGE_SIZE) #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) @@ -136,6 +136,6 @@ static inline unsigned long virt_to_pfn(const void *kaddr) #include <asm-generic/memory_model.h> /* page_to_pfn, pfn_to_page */ #include <asm-generic/getorder.h> -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/pgtable-bits-arcv2.h b/arch/arc/include/asm/pgtable-bits-arcv2.h index 8ebec1b21d24..4630c5acca05 100644 --- a/arch/arc/include/asm/pgtable-bits-arcv2.h +++ b/arch/arc/include/asm/pgtable-bits-arcv2.h @@ -75,7 +75,7 @@ * This is to enable COW mechanism */ /* xwr */ -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #define pte_write(pte) (pte_val(pte) & _PAGE_WRITE) #define pte_dirty(pte) (pte_val(pte) & _PAGE_DIRTY) @@ -130,7 +130,7 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } @@ -142,6 +142,6 @@ PTE_BIT_FUNC(swp_clear_exclusive, &= ~(_PAGE_SWP_EXCLUSIVE)); #include <asm/hugepage.h> #endif -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/pgtable-levels.h b/arch/arc/include/asm/pgtable-levels.h index d1ce4b0f1071..c8f9273372c0 100644 --- a/arch/arc/include/asm/pgtable-levels.h +++ b/arch/arc/include/asm/pgtable-levels.h @@ -85,7 +85,7 @@ #define PTRS_PER_PTE BIT(PMD_SHIFT - PAGE_SHIFT) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #if CONFIG_PGTABLE_LEVELS > 3 #include <asm-generic/pgtable-nop4d.h> @@ -181,6 +181,6 @@ #define pmd_leaf(x) (pmd_val(x) & _PAGE_HW_SZ) #endif -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h index 4cf45a99fd79..bd580e2b62d7 100644 --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h @@ -19,7 +19,7 @@ */ #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ extern char empty_zero_page[PAGE_SIZE]; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) @@ -29,6 +29,6 @@ extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE); /* to cope with aliasing VIPT cache */ #define HAVE_ARCH_UNMAPPED_AREA -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLER__ */ #endif diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index d606658e2fe7..7f7901ac6643 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -11,7 +11,7 @@ #ifndef __ASM_ARC_PROCESSOR_H #define __ASM_ARC_PROCESSOR_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <asm/ptrace.h> #include <asm/dsp.h> @@ -66,7 +66,7 @@ extern void start_thread(struct pt_regs * regs, unsigned long pc, extern unsigned int __get_wchan(struct task_struct *p); -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ /* * Default System Memory Map on ARC diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index cf79df0b2570..f6c052af8f4d 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -10,7 +10,7 @@ #include <uapi/asm/ptrace.h> #include <linux/compiler.h> -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ typedef union { struct { @@ -172,6 +172,6 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, extern int syscall_trace_enter(struct pt_regs *); extern void syscall_trace_exit(struct pt_regs *); -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif /* __ASM_PTRACE_H */ diff --git a/arch/arc/include/asm/switch_to.h b/arch/arc/include/asm/switch_to.h index 1f85de8288b1..5806106a65f9 100644 --- a/arch/arc/include/asm/switch_to.h +++ b/arch/arc/include/asm/switch_to.h @@ -6,7 +6,7 @@ #ifndef _ASM_ARC_SWITCH_TO_H #define _ASM_ARC_SWITCH_TO_H -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <linux/sched.h> #include <asm/dsp-impl.h> diff --git a/arch/arc/include/asm/thread_info.h b/arch/arc/include/asm/thread_info.h index 12daaf3a61ea..255d2c774219 100644 --- a/arch/arc/include/asm/thread_info.h +++ b/arch/arc/include/asm/thread_info.h @@ -24,7 +24,7 @@ #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) #define THREAD_SHIFT (PAGE_SHIFT << THREAD_SIZE_ORDER) -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ #include <linux/thread_info.h> @@ -62,7 +62,7 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void) return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); } -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ /* * thread information flags diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h index 2a6eff57f6dd..3ae832db278c 100644 --- a/arch/arc/include/uapi/asm/ptrace.h +++ b/arch/arc/include/uapi/asm/ptrace.h @@ -14,7 +14,7 @@ #define PTRACE_GET_THREAD_AREA 25 -#ifndef __ASSEMBLY__ +#ifndef __ASSEMBLER__ /* * Userspace ABI: Register state needed by * -ptrace (gdbserver) @@ -53,6 +53,6 @@ struct user_regs_arcv2 { unsigned long r30, r58, r59; }; -#endif /* !__ASSEMBLY__ */ +#endif /* !__ASSEMBLER__ */ #endif /* _UAPI__ASM_ARC_PTRACE_H */ diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c index d8969dab12d4..789cfb9ea14e 100644 --- a/arch/arc/kernel/unwind.c +++ b/arch/arc/kernel/unwind.c @@ -241,15 +241,6 @@ static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2) return (e1->start > e2->start) - (e1->start < e2->start); } -static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size) -{ - struct eh_frame_hdr_table_entry *e1 = p1; - struct eh_frame_hdr_table_entry *e2 = p2; - - swap(e1->start, e2->start); - swap(e1->fde, e2->fde); -} - static void init_unwind_hdr(struct unwind_table *table, void *(*alloc) (unsigned long)) { @@ -345,7 +336,7 @@ static void init_unwind_hdr(struct unwind_table *table, sort(header->table, n, sizeof(*header->table), - cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries); + cmp_eh_frame_hdr_table_entries, NULL); table->hdrsz = hdrSize; smp_wmb(); diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 7f1c3b4e3e04..86378eec7757 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -301,7 +301,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(swp) __pte((swp).val) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_isset(pte, L_PTE_SWP_EXCLUSIVE); } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 6ce2c5173482..5ccca509dff1 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1107,14 +1107,36 @@ static inline u64 *___ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r) #define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r)) u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *, enum vcpu_sysreg, u64); + +#define __vcpu_assign_sys_reg(v, r, val) \ + do { \ + const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ + u64 __v = (val); \ + if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ + __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ + \ + ctxt_sys_reg(ctxt, (r)) = __v; \ + } while (0) + +#define __vcpu_rmw_sys_reg(v, r, op, val) \ + do { \ + const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ + u64 __v = ctxt_sys_reg(ctxt, (r)); \ + __v op (val); \ + if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ + __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ + \ + ctxt_sys_reg(ctxt, (r)) = __v; \ + } while (0) + #define __vcpu_sys_reg(v,r) \ - (*({ \ + ({ \ const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ - u64 *__r = __ctxt_sys_reg(ctxt, (r)); \ + u64 __v = ctxt_sys_reg(ctxt, (r)); \ if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ - *__r = kvm_vcpu_apply_reg_masks((v), (r), *__r);\ - __r; \ - })) + __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ + __v; \ + }) u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg); void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg); diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 88db8a0c0b37..192d86e1cc76 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -563,7 +563,7 @@ static inline pte_t pte_swp_mkexclusive(pte_t pte) return set_pte_bit(pte, __pgprot(PTE_SWP_EXCLUSIVE)); } -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & PTE_SWP_EXCLUSIVE; } diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index fdbc8beec930..701ea10a63f1 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -108,16 +108,16 @@ static void timer_set_ctl(struct arch_timer_context *ctxt, u32 ctl) switch(arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: - __vcpu_sys_reg(vcpu, CNTV_CTL_EL0) = ctl; + __vcpu_assign_sys_reg(vcpu, CNTV_CTL_EL0, ctl); break; case TIMER_PTIMER: - __vcpu_sys_reg(vcpu, CNTP_CTL_EL0) = ctl; + __vcpu_assign_sys_reg(vcpu, CNTP_CTL_EL0, ctl); break; case TIMER_HVTIMER: - __vcpu_sys_reg(vcpu, CNTHV_CTL_EL2) = ctl; + __vcpu_assign_sys_reg(vcpu, CNTHV_CTL_EL2, ctl); break; case TIMER_HPTIMER: - __vcpu_sys_reg(vcpu, CNTHP_CTL_EL2) = ctl; + __vcpu_assign_sys_reg(vcpu, CNTHP_CTL_EL2, ctl); break; default: WARN_ON(1); @@ -130,16 +130,16 @@ static void timer_set_cval(struct arch_timer_context *ctxt, u64 cval) switch(arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: - __vcpu_sys_reg(vcpu, CNTV_CVAL_EL0) = cval; + __vcpu_assign_sys_reg(vcpu, CNTV_CVAL_EL0, cval); break; case TIMER_PTIMER: - __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = cval; + __vcpu_assign_sys_reg(vcpu, CNTP_CVAL_EL0, cval); break; case TIMER_HVTIMER: - __vcpu_sys_reg(vcpu, CNTHV_CVAL_EL2) = cval; + __vcpu_assign_sys_reg(vcpu, CNTHV_CVAL_EL2, cval); break; case TIMER_HPTIMER: - __vcpu_sys_reg(vcpu, CNTHP_CVAL_EL2) = cval; + __vcpu_assign_sys_reg(vcpu, CNTHP_CVAL_EL2, cval); break; default: WARN_ON(1); @@ -1036,7 +1036,7 @@ void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu) if (vcpu_has_nv(vcpu)) { struct arch_timer_offset *offs = &vcpu_vtimer(vcpu)->offset; - offs->vcpu_offset = &__vcpu_sys_reg(vcpu, CNTVOFF_EL2); + offs->vcpu_offset = __ctxt_sys_reg(&vcpu->arch.ctxt, CNTVOFF_EL2); offs->vm_offset = &vcpu->kvm->arch.timer_data.poffset; } diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index 0e4c805e7e89..1a7dab333f55 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -216,9 +216,9 @@ void kvm_debug_set_guest_ownership(struct kvm_vcpu *vcpu) void kvm_debug_handle_oslar(struct kvm_vcpu *vcpu, u64 val) { if (val & OSLAR_EL1_OSLK) - __vcpu_sys_reg(vcpu, OSLSR_EL1) |= OSLSR_EL1_OSLK; + __vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, |=, OSLSR_EL1_OSLK); else - __vcpu_sys_reg(vcpu, OSLSR_EL1) &= ~OSLSR_EL1_OSLK; + __vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, &=, ~OSLSR_EL1_OSLK); preempt_disable(); kvm_arch_vcpu_put(vcpu); diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 7f6e43d25691..8f6c8f57c6b9 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -103,8 +103,8 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) fp_state.sve_state = vcpu->arch.sve_state; fp_state.sve_vl = vcpu->arch.sve_max_vl; fp_state.sme_state = NULL; - fp_state.svcr = &__vcpu_sys_reg(vcpu, SVCR); - fp_state.fpmr = &__vcpu_sys_reg(vcpu, FPMR); + fp_state.svcr = __ctxt_sys_reg(&vcpu->arch.ctxt, SVCR); + fp_state.fpmr = __ctxt_sys_reg(&vcpu->arch.ctxt, FPMR); fp_state.fp_type = &vcpu->arch.fp_type; if (vcpu_has_sve(vcpu)) diff --git a/arch/arm64/kvm/hyp/exception.c b/arch/arm64/kvm/hyp/exception.c index 424a5107cddb..6a2a899a344e 100644 --- a/arch/arm64/kvm/hyp/exception.c +++ b/arch/arm64/kvm/hyp/exception.c @@ -37,7 +37,7 @@ static inline void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) if (unlikely(vcpu_has_nv(vcpu))) vcpu_write_sys_reg(vcpu, val, reg); else if (!__vcpu_write_sys_reg_to_cpu(val, reg)) - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); } static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long target_mode, @@ -51,7 +51,7 @@ static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long target_mode, } else if (has_vhe()) { write_sysreg_el1(val, SYS_SPSR); } else { - __vcpu_sys_reg(vcpu, SPSR_EL1) = val; + __vcpu_assign_sys_reg(vcpu, SPSR_EL1, val); } } diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index bb9f2eecfb67..76dfda116e56 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -45,7 +45,7 @@ static inline void __fpsimd_save_fpexc32(struct kvm_vcpu *vcpu) if (!vcpu_el1_is_32bit(vcpu)) return; - __vcpu_sys_reg(vcpu, FPEXC32_EL2) = read_sysreg(fpexc32_el2); + __vcpu_assign_sys_reg(vcpu, FPEXC32_EL2, read_sysreg(fpexc32_el2)); } static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) @@ -456,7 +456,7 @@ static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu) */ if (vcpu_has_sve(vcpu)) { zcr_el1 = read_sysreg_el1(SYS_ZCR); - __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1; + __vcpu_assign_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu), zcr_el1); /* * The guest's state is always saved using the guest's max VL. diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h index b9cff893bbe0..4d0dbea4c56f 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -307,11 +307,11 @@ static inline void __sysreg32_save_state(struct kvm_vcpu *vcpu) vcpu->arch.ctxt.spsr_irq = read_sysreg(spsr_irq); vcpu->arch.ctxt.spsr_fiq = read_sysreg(spsr_fiq); - __vcpu_sys_reg(vcpu, DACR32_EL2) = read_sysreg(dacr32_el2); - __vcpu_sys_reg(vcpu, IFSR32_EL2) = read_sysreg(ifsr32_el2); + __vcpu_assign_sys_reg(vcpu, DACR32_EL2, read_sysreg(dacr32_el2)); + __vcpu_assign_sys_reg(vcpu, IFSR32_EL2, read_sysreg(ifsr32_el2)); if (has_vhe() || kvm_debug_regs_in_use(vcpu)) - __vcpu_sys_reg(vcpu, DBGVCR32_EL2) = read_sysreg(dbgvcr32_el2); + __vcpu_assign_sys_reg(vcpu, DBGVCR32_EL2, read_sysreg(dbgvcr32_el2)); } static inline void __sysreg32_restore_state(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 8e8848de4d47..e9198e56e784 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -26,7 +26,7 @@ void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt); static void __hyp_sve_save_guest(struct kvm_vcpu *vcpu) { - __vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR); + __vcpu_assign_sys_reg(vcpu, ZCR_EL1, read_sysreg_el1(SYS_ZCR)); /* * On saving/restoring guest sve state, always use the maximum VL for * the guest. The layout of the data when saving the sve state depends @@ -79,7 +79,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) has_fpmr = kvm_has_fpmr(kern_hyp_va(vcpu->kvm)); if (has_fpmr) - __vcpu_sys_reg(vcpu, FPMR) = read_sysreg_s(SYS_FPMR); + __vcpu_assign_sys_reg(vcpu, FPMR, read_sysreg_s(SYS_FPMR)); if (system_supports_sve()) __hyp_sve_restore_host(); diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index c9b330dc2066..09df2b42bc1b 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -223,9 +223,9 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) */ val = read_sysreg_el0(SYS_CNTP_CVAL); if (map.direct_ptimer == vcpu_ptimer(vcpu)) - __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = val; + __vcpu_assign_sys_reg(vcpu, CNTP_CVAL_EL0, val); if (map.direct_ptimer == vcpu_hptimer(vcpu)) - __vcpu_sys_reg(vcpu, CNTHP_CVAL_EL2) = val; + __vcpu_assign_sys_reg(vcpu, CNTHP_CVAL_EL2, val); offset = read_sysreg_s(SYS_CNTPOFF_EL2); diff --git a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c index 3814b0b2c937..73e4bc7fde9e 100644 --- a/arch/arm64/kvm/hyp/vhe/sysreg-sr.c +++ b/arch/arm64/kvm/hyp/vhe/sysreg-sr.c @@ -18,17 +18,17 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu) { /* These registers are common with EL1 */ - __vcpu_sys_reg(vcpu, PAR_EL1) = read_sysreg(par_el1); - __vcpu_sys_reg(vcpu, TPIDR_EL1) = read_sysreg(tpidr_el1); - - __vcpu_sys_reg(vcpu, ESR_EL2) = read_sysreg_el1(SYS_ESR); - __vcpu_sys_reg(vcpu, AFSR0_EL2) = read_sysreg_el1(SYS_AFSR0); - __vcpu_sys_reg(vcpu, AFSR1_EL2) = read_sysreg_el1(SYS_AFSR1); - __vcpu_sys_reg(vcpu, FAR_EL2) = read_sysreg_el1(SYS_FAR); - __vcpu_sys_reg(vcpu, MAIR_EL2) = read_sysreg_el1(SYS_MAIR); - __vcpu_sys_reg(vcpu, VBAR_EL2) = read_sysreg_el1(SYS_VBAR); - __vcpu_sys_reg(vcpu, CONTEXTIDR_EL2) = read_sysreg_el1(SYS_CONTEXTIDR); - __vcpu_sys_reg(vcpu, AMAIR_EL2) = read_sysreg_el1(SYS_AMAIR); + __vcpu_assign_sys_reg(vcpu, PAR_EL1, read_sysreg(par_el1)); + __vcpu_assign_sys_reg(vcpu, TPIDR_EL1, read_sysreg(tpidr_el1)); + + __vcpu_assign_sys_reg(vcpu, ESR_EL2, read_sysreg_el1(SYS_ESR)); + __vcpu_assign_sys_reg(vcpu, AFSR0_EL2, read_sysreg_el1(SYS_AFSR0)); + __vcpu_assign_sys_reg(vcpu, AFSR1_EL2, read_sysreg_el1(SYS_AFSR1)); + __vcpu_assign_sys_reg(vcpu, FAR_EL2, read_sysreg_el1(SYS_FAR)); + __vcpu_assign_sys_reg(vcpu, MAIR_EL2, read_sysreg_el1(SYS_MAIR)); + __vcpu_assign_sys_reg(vcpu, VBAR_EL2, read_sysreg_el1(SYS_VBAR)); + __vcpu_assign_sys_reg(vcpu, CONTEXTIDR_EL2, read_sysreg_el1(SYS_CONTEXTIDR)); + __vcpu_assign_sys_reg(vcpu, AMAIR_EL2, read_sysreg_el1(SYS_AMAIR)); /* * In VHE mode those registers are compatible between EL1 and EL2, @@ -46,21 +46,21 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu) * are always trapped, ensuring that the in-memory * copy is always up-to-date. A small blessing... */ - __vcpu_sys_reg(vcpu, SCTLR_EL2) = read_sysreg_el1(SYS_SCTLR); - __vcpu_sys_reg(vcpu, TTBR0_EL2) = read_sysreg_el1(SYS_TTBR0); - __vcpu_sys_reg(vcpu, TTBR1_EL2) = read_sysreg_el1(SYS_TTBR1); - __vcpu_sys_reg(vcpu, TCR_EL2) = read_sysreg_el1(SYS_TCR); + __vcpu_assign_sys_reg(vcpu, SCTLR_EL2, read_sysreg_el1(SYS_SCTLR)); + __vcpu_assign_sys_reg(vcpu, TTBR0_EL2, read_sysreg_el1(SYS_TTBR0)); + __vcpu_assign_sys_reg(vcpu, TTBR1_EL2, read_sysreg_el1(SYS_TTBR1)); + __vcpu_assign_sys_reg(vcpu, TCR_EL2, read_sysreg_el1(SYS_TCR)); if (ctxt_has_tcrx(&vcpu->arch.ctxt)) { - __vcpu_sys_reg(vcpu, TCR2_EL2) = read_sysreg_el1(SYS_TCR2); + __vcpu_assign_sys_reg(vcpu, TCR2_EL2, read_sysreg_el1(SYS_TCR2)); if (ctxt_has_s1pie(&vcpu->arch.ctxt)) { - __vcpu_sys_reg(vcpu, PIRE0_EL2) = read_sysreg_el1(SYS_PIRE0); - __vcpu_sys_reg(vcpu, PIR_EL2) = read_sysreg_el1(SYS_PIR); + __vcpu_assign_sys_reg(vcpu, PIRE0_EL2, read_sysreg_el1(SYS_PIRE0)); + __vcpu_assign_sys_reg(vcpu, PIR_EL2, read_sysreg_el1(SYS_PIR)); } if (ctxt_has_s1poe(&vcpu->arch.ctxt)) - __vcpu_sys_reg(vcpu, POR_EL2) = read_sysreg_el1(SYS_POR); + __vcpu_assign_sys_reg(vcpu, POR_EL2, read_sysreg_el1(SYS_POR)); } /* @@ -70,13 +70,13 @@ static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu) */ val = read_sysreg_el1(SYS_CNTKCTL); val &= CNTKCTL_VALID_BITS; - __vcpu_sys_reg(vcpu, CNTHCTL_EL2) &= ~CNTKCTL_VALID_BITS; - __vcpu_sys_reg(vcpu, CNTHCTL_EL2) |= val; + __vcpu_rmw_sys_reg(vcpu, CNTHCTL_EL2, &=, ~CNTKCTL_VALID_BITS); + __vcpu_rmw_sys_reg(vcpu, CNTHCTL_EL2, |=, val); } - __vcpu_sys_reg(vcpu, SP_EL2) = read_sysreg(sp_el1); - __vcpu_sys_reg(vcpu, ELR_EL2) = read_sysreg_el1(SYS_ELR); - __vcpu_sys_reg(vcpu, SPSR_EL2) = read_sysreg_el1(SYS_SPSR); + __vcpu_assign_sys_reg(vcpu, SP_EL2, read_sysreg(sp_el1)); + __vcpu_assign_sys_reg(vcpu, ELR_EL2, read_sysreg_el1(SYS_ELR)); + __vcpu_assign_sys_reg(vcpu, SPSR_EL2, read_sysreg_el1(SYS_SPSR)); } static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 4a53e4147fb0..5b191f4dc566 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -1757,7 +1757,7 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu) out: for (enum vcpu_sysreg sr = __SANITISED_REG_START__; sr < NR_SYS_REGS; sr++) - (void)__vcpu_sys_reg(vcpu, sr); + __vcpu_rmw_sys_reg(vcpu, sr, |=, 0); return 0; } diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 25c29107f13f..b03dbda7f1ab 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -178,7 +178,7 @@ static void kvm_pmu_set_pmc_value(struct kvm_pmc *pmc, u64 val, bool force) val |= lower_32_bits(val); } - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); /* Recreate the perf event to reflect the updated sample_period */ kvm_pmu_create_perf_event(pmc); @@ -204,7 +204,7 @@ void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) { kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx)); - __vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val; + __vcpu_assign_sys_reg(vcpu, counter_index_to_reg(select_idx), val); kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); } @@ -239,7 +239,7 @@ static void kvm_pmu_stop_counter(struct kvm_pmc *pmc) reg = counter_index_to_reg(pmc->idx); - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); kvm_pmu_release_perf_event(pmc); } @@ -503,14 +503,14 @@ static void kvm_pmu_counter_increment(struct kvm_vcpu *vcpu, reg = __vcpu_sys_reg(vcpu, counter_index_to_reg(i)) + 1; if (!kvm_pmc_is_64bit(pmc)) reg = lower_32_bits(reg); - __vcpu_sys_reg(vcpu, counter_index_to_reg(i)) = reg; + __vcpu_assign_sys_reg(vcpu, counter_index_to_reg(i), reg); /* No overflow? move on */ if (kvm_pmc_has_64bit_overflow(pmc) ? reg : lower_32_bits(reg)) continue; /* Mark overflow */ - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i); + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, BIT(i)); if (kvm_pmu_counter_can_chain(pmc)) kvm_pmu_counter_increment(vcpu, BIT(i + 1), @@ -556,7 +556,7 @@ static void kvm_pmu_perf_overflow(struct perf_event *perf_event, perf_event->attr.sample_period = period; perf_event->hw.sample_period = period; - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx); + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, BIT(idx)); if (kvm_pmu_counter_can_chain(pmc)) kvm_pmu_counter_increment(vcpu, BIT(idx + 1), @@ -602,7 +602,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); /* The reset bits don't indicate any state, and shouldn't be saved. */ - __vcpu_sys_reg(vcpu, PMCR_EL0) = val & ~(ARMV8_PMU_PMCR_C | ARMV8_PMU_PMCR_P); + __vcpu_assign_sys_reg(vcpu, PMCR_EL0, (val & ~(ARMV8_PMU_PMCR_C | ARMV8_PMU_PMCR_P))); if (val & ARMV8_PMU_PMCR_C) kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0); @@ -779,7 +779,7 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, u64 reg; reg = counter_index_to_evtreg(pmc->idx); - __vcpu_sys_reg(vcpu, reg) = data & kvm_pmu_evtyper_mask(vcpu->kvm); + __vcpu_assign_sys_reg(vcpu, reg, (data & kvm_pmu_evtyper_mask(vcpu->kvm))); kvm_pmu_create_perf_event(pmc); } @@ -914,9 +914,9 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu *vcpu) { u64 mask = kvm_pmu_implemented_counter_mask(vcpu); - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= mask; - __vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= mask; - __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= mask; + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, &=, mask); + __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, &=, mask); + __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, &=, mask); kvm_pmu_reprogram_counter_mask(vcpu, mask); } @@ -1038,7 +1038,7 @@ static void kvm_arm_set_nr_counters(struct kvm *kvm, unsigned int nr) u64 val = __vcpu_sys_reg(vcpu, MDCR_EL2); val &= ~MDCR_EL2_HPMN; val |= FIELD_PREP(MDCR_EL2_HPMN, kvm->arch.nr_pmu_counters); - __vcpu_sys_reg(vcpu, MDCR_EL2) = val; + __vcpu_assign_sys_reg(vcpu, MDCR_EL2, val); } } } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index a6cf2888d150..76c2f0da821f 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -228,7 +228,7 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) * to reverse-translate virtual EL2 system registers for a * non-VHE guest hypervisor. */ - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); switch (reg) { case CNTHCTL_EL2: @@ -263,7 +263,7 @@ void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg) return; memory_write: - __vcpu_sys_reg(vcpu, reg) = val; + __vcpu_assign_sys_reg(vcpu, reg, val); } /* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */ @@ -605,7 +605,7 @@ static int set_oslsr_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, if ((val ^ rd->val) & ~OSLSR_EL1_OSLK) return -EINVAL; - __vcpu_sys_reg(vcpu, rd->reg) = val; + __vcpu_assign_sys_reg(vcpu, rd->reg, val); return 0; } @@ -791,7 +791,7 @@ static u64 reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) mask |= GENMASK(n - 1, 0); reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= mask; + __vcpu_rmw_sys_reg(vcpu, r->reg, &=, mask); return __vcpu_sys_reg(vcpu, r->reg); } @@ -799,7 +799,7 @@ static u64 reset_pmu_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) static u64 reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= GENMASK(31, 0); + __vcpu_rmw_sys_reg(vcpu, r->reg, &=, GENMASK(31, 0)); return __vcpu_sys_reg(vcpu, r->reg); } @@ -811,7 +811,7 @@ static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) return 0; reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= kvm_pmu_evtyper_mask(vcpu->kvm); + __vcpu_rmw_sys_reg(vcpu, r->reg, &=, kvm_pmu_evtyper_mask(vcpu->kvm)); return __vcpu_sys_reg(vcpu, r->reg); } @@ -819,7 +819,7 @@ static u64 reset_pmevtyper(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) static u64 reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { reset_unknown(vcpu, r); - __vcpu_sys_reg(vcpu, r->reg) &= PMSELR_EL0_SEL_MASK; + __vcpu_rmw_sys_reg(vcpu, r->reg, &=, PMSELR_EL0_SEL_MASK); return __vcpu_sys_reg(vcpu, r->reg); } @@ -835,7 +835,7 @@ static u64 reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) * The value of PMCR.N field is included when the * vCPU register is read via kvm_vcpu_read_pmcr(). */ - __vcpu_sys_reg(vcpu, r->reg) = pmcr; + __vcpu_assign_sys_reg(vcpu, r->reg, pmcr); return __vcpu_sys_reg(vcpu, r->reg); } @@ -907,7 +907,7 @@ static bool access_pmselr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, return false; if (p->is_write) - __vcpu_sys_reg(vcpu, PMSELR_EL0) = p->regval; + __vcpu_assign_sys_reg(vcpu, PMSELR_EL0, p->regval); else /* return PMSELR.SEL field */ p->regval = __vcpu_sys_reg(vcpu, PMSELR_EL0) @@ -1076,7 +1076,7 @@ static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 va { u64 mask = kvm_pmu_accessible_counter_mask(vcpu); - __vcpu_sys_reg(vcpu, r->reg) = val & mask; + __vcpu_assign_sys_reg(vcpu, r->reg, val & mask); kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); return 0; @@ -1103,10 +1103,10 @@ static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p, val = p->regval & mask; if (r->Op2 & 0x1) /* accessing PMCNTENSET_EL0 */ - __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) |= val; + __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, |=, val); else /* accessing PMCNTENCLR_EL0 */ - __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= ~val; + __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, &=, ~val); kvm_pmu_reprogram_counter_mask(vcpu, val); } else { @@ -1129,10 +1129,10 @@ static bool access_pminten(struct kvm_vcpu *vcpu, struct sys_reg_params *p, if (r->Op2 & 0x1) /* accessing PMINTENSET_EL1 */ - __vcpu_sys_reg(vcpu, PMINTENSET_EL1) |= val; + __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, |=, val); else /* accessing PMINTENCLR_EL1 */ - __vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= ~val; + __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, &=, ~val); } else { p->regval = __vcpu_sys_reg(vcpu, PMINTENSET_EL1); } @@ -1151,10 +1151,10 @@ static bool access_pmovs(struct kvm_vcpu *vcpu, struct sys_reg_params *p, if (p->is_write) { if (r->CRm & 0x2) /* accessing PMOVSSET_EL0 */ - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= (p->regval & mask); + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, (p->regval & mask)); else /* accessing PMOVSCLR_EL0 */ - __vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= ~(p->regval & mask); + __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, &=, ~(p->regval & mask)); } else { p->regval = __vcpu_sys_reg(vcpu, PMOVSSET_EL0); } @@ -1185,8 +1185,8 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, if (!vcpu_mode_priv(vcpu)) return undef_access(vcpu, p, r); - __vcpu_sys_reg(vcpu, PMUSERENR_EL0) = - p->regval & ARMV8_PMU_USERENR_MASK; + __vcpu_assign_sys_reg(vcpu, PMUSERENR_EL0, + (p->regval & ARMV8_PMU_USERENR_MASK)); } else { p->regval = __vcpu_sys_reg(vcpu, PMUSERENR_EL0) & ARMV8_PMU_USERENR_MASK; @@ -1237,7 +1237,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, if (!kvm_supports_32bit_el0()) val |= ARMV8_PMU_PMCR_LC; - __vcpu_sys_reg(vcpu, r->reg) = val; + __vcpu_assign_sys_reg(vcpu, r->reg, val); kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); return 0; @@ -2213,7 +2213,7 @@ static u64 reset_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) if (kvm_has_mte(vcpu->kvm)) clidr |= 2ULL << CLIDR_TTYPE_SHIFT(loc); - __vcpu_sys_reg(vcpu, r->reg) = clidr; + __vcpu_assign_sys_reg(vcpu, r->reg, clidr); return __vcpu_sys_reg(vcpu, r->reg); } @@ -2227,7 +2227,7 @@ static int set_clidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, if ((val & CLIDR_EL1_RES0) || (!(ctr_el0 & CTR_EL0_IDC) && idc)) return -EINVAL; - __vcpu_sys_reg(vcpu, rd->reg) = val; + __vcpu_assign_sys_reg(vcpu, rd->reg, val); return 0; } @@ -2404,7 +2404,7 @@ static bool access_sp_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { if (p->is_write) - __vcpu_sys_reg(vcpu, SP_EL1) = p->regval; + __vcpu_assign_sys_reg(vcpu, SP_EL1, p->regval); else p->regval = __vcpu_sys_reg(vcpu, SP_EL1); @@ -2428,7 +2428,7 @@ static bool access_spsr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { if (p->is_write) - __vcpu_sys_reg(vcpu, SPSR_EL1) = p->regval; + __vcpu_assign_sys_reg(vcpu, SPSR_EL1, p->regval); else p->regval = __vcpu_sys_reg(vcpu, SPSR_EL1); @@ -2440,7 +2440,7 @@ static bool access_cntkctl_el12(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { if (p->is_write) - __vcpu_sys_reg(vcpu, CNTKCTL_EL1) = p->regval; + __vcpu_assign_sys_reg(vcpu, CNTKCTL_EL1, p->regval); else p->regval = __vcpu_sys_reg(vcpu, CNTKCTL_EL1); @@ -2454,7 +2454,9 @@ static u64 reset_hcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) if (!cpus_have_final_cap(ARM64_HAS_HCR_NV1)) val |= HCR_E2H; - return __vcpu_sys_reg(vcpu, r->reg) = val; + __vcpu_assign_sys_reg(vcpu, r->reg, val); + + return __vcpu_sys_reg(vcpu, r->reg); } static unsigned int __el2_visibility(const struct kvm_vcpu *vcpu, @@ -2625,7 +2627,7 @@ static bool access_mdcr(struct kvm_vcpu *vcpu, u64_replace_bits(val, hpmn, MDCR_EL2_HPMN); } - __vcpu_sys_reg(vcpu, MDCR_EL2) = val; + __vcpu_assign_sys_reg(vcpu, MDCR_EL2, val); /* * Request a reload of the PMU to enable/disable the counters @@ -2754,7 +2756,7 @@ static int set_imp_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, static u64 reset_mdcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { - __vcpu_sys_reg(vcpu, r->reg) = vcpu->kvm->arch.nr_pmu_counters; + __vcpu_assign_sys_reg(vcpu, r->reg, vcpu->kvm->arch.nr_pmu_counters); return vcpu->kvm->arch.nr_pmu_counters; } @@ -4790,7 +4792,7 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu) r->reset(vcpu, r); if (r->reg >= __SANITISED_REG_START__ && r->reg < NR_SYS_REGS) - (void)__vcpu_sys_reg(vcpu, r->reg); + __vcpu_rmw_sys_reg(vcpu, r->reg, |=, 0); } set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags); @@ -5012,7 +5014,7 @@ int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg, if (r->set_user) { ret = (r->set_user)(vcpu, r, val); } else { - __vcpu_sys_reg(vcpu, r->reg) = val; + __vcpu_assign_sys_reg(vcpu, r->reg, val); ret = 0; } diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h index cc6338d38766..ef97d9fc67cc 100644 --- a/arch/arm64/kvm/sys_regs.h +++ b/arch/arm64/kvm/sys_regs.h @@ -137,7 +137,7 @@ static inline u64 reset_unknown(struct kvm_vcpu *vcpu, { BUG_ON(!r->reg); BUG_ON(r->reg >= NR_SYS_REGS); - __vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL; + __vcpu_assign_sys_reg(vcpu, r->reg, 0x1de7ec7edbadc0deULL); return __vcpu_sys_reg(vcpu, r->reg); } @@ -145,7 +145,7 @@ static inline u64 reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { BUG_ON(!r->reg); BUG_ON(r->reg >= NR_SYS_REGS); - __vcpu_sys_reg(vcpu, r->reg) = r->val; + __vcpu_assign_sys_reg(vcpu, r->reg, r->val); return __vcpu_sys_reg(vcpu, r->reg); } diff --git a/arch/arm64/kvm/vgic/vgic-v3-nested.c b/arch/arm64/kvm/vgic/vgic-v3-nested.c index 4f6954c30674..d22a8ad7bcc5 100644 --- a/arch/arm64/kvm/vgic/vgic-v3-nested.c +++ b/arch/arm64/kvm/vgic/vgic-v3-nested.c @@ -356,12 +356,12 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu) val = __vcpu_sys_reg(vcpu, ICH_HCR_EL2); val &= ~ICH_HCR_EL2_EOIcount_MASK; val |= (s_cpu_if->vgic_hcr & ICH_HCR_EL2_EOIcount_MASK); - __vcpu_sys_reg(vcpu, ICH_HCR_EL2) = val; - __vcpu_sys_reg(vcpu, ICH_VMCR_EL2) = s_cpu_if->vgic_vmcr; + __vcpu_assign_sys_reg(vcpu, ICH_HCR_EL2, val); + __vcpu_assign_sys_reg(vcpu, ICH_VMCR_EL2, s_cpu_if->vgic_vmcr); for (i = 0; i < 4; i++) { - __vcpu_sys_reg(vcpu, ICH_AP0RN(i)) = s_cpu_if->vgic_ap0r[i]; - __vcpu_sys_reg(vcpu, ICH_AP1RN(i)) = s_cpu_if->vgic_ap1r[i]; + __vcpu_assign_sys_reg(vcpu, ICH_AP0RN(i), s_cpu_if->vgic_ap0r[i]); + __vcpu_assign_sys_reg(vcpu, ICH_AP1RN(i), s_cpu_if->vgic_ap1r[i]); } for_each_set_bit(i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) { @@ -370,7 +370,7 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu) val &= ~ICH_LR_STATE; val |= s_cpu_if->vgic_lr[i] & ICH_LR_STATE; - __vcpu_sys_reg(vcpu, ICH_LRN(i)) = val; + __vcpu_assign_sys_reg(vcpu, ICH_LRN(i), val); s_cpu_if->vgic_lr[i] = 0; } diff --git a/arch/csky/include/asm/pgtable.h b/arch/csky/include/asm/pgtable.h index b8378431aeff..5a394be09c35 100644 --- a/arch/csky/include/asm/pgtable.h +++ b/arch/csky/include/asm/pgtable.h @@ -200,7 +200,7 @@ static inline pte_t pte_mkyoung(pte_t pte) return pte; } -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/hexagon/include/asm/pgtable.h b/arch/hexagon/include/asm/pgtable.h index 9fbdfdbc539f..fbf24d1d1ca6 100644 --- a/arch/hexagon/include/asm/pgtable.h +++ b/arch/hexagon/include/asm/pgtable.h @@ -387,7 +387,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) (((type & 0x1f) << 1) | \ ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h index a3f17914dbab..b30185302c07 100644 --- a/arch/loongarch/include/asm/pgtable.h +++ b/arch/loongarch/include/asm/pgtable.h @@ -301,7 +301,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) #define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val(pmd) }) #define __swp_entry_to_pmd(x) ((pmd_t) { (x).val | _PAGE_HUGE }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/m68k/include/asm/mcf_pgtable.h b/arch/m68k/include/asm/mcf_pgtable.h index f5c596b211d4..d79fef609194 100644 --- a/arch/m68k/include/asm/mcf_pgtable.h +++ b/arch/m68k/include/asm/mcf_pgtable.h @@ -268,7 +268,7 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD]; #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) (__pte((x).val)) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/m68k/include/asm/motorola_pgtable.h b/arch/m68k/include/asm/motorola_pgtable.h index 040ac3bad713..14fee64d3e60 100644 --- a/arch/m68k/include/asm/motorola_pgtable.h +++ b/arch/m68k/include/asm/motorola_pgtable.h @@ -185,7 +185,7 @@ extern pgd_t kernel_pg_dir[128]; #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h index 73745dc0ec0e..858cbe936f5b 100644 --- a/arch/m68k/include/asm/sun3_pgtable.h +++ b/arch/m68k/include/asm/sun3_pgtable.h @@ -169,7 +169,7 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD]; #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h index b1bb2c65dd04..bae1abfa6f6b 100644 --- a/arch/microblaze/include/asm/pgtable.h +++ b/arch/microblaze/include/asm/pgtable.h @@ -398,7 +398,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 2 }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 2 }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 4852b005a72d..ae73ecf4c41a 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -534,7 +534,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #endif #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte.pte_low & _PAGE_SWP_EXCLUSIVE; } @@ -551,7 +551,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) return pte; } #else -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/nios2/include/asm/pgtable.h b/arch/nios2/include/asm/pgtable.h index e98578e27e26..844dce55569f 100644 --- a/arch/nios2/include/asm/pgtable.h +++ b/arch/nios2/include/asm/pgtable.h @@ -259,7 +259,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) #define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/openrisc/include/asm/pgtable.h b/arch/openrisc/include/asm/pgtable.h index 71bfb8c8c482..5bd6463bd514 100644 --- a/arch/openrisc/include/asm/pgtable.h +++ b/arch/openrisc/include/asm/pgtable.h @@ -411,7 +411,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf, #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 80f5e2a28413..1a86a4370b29 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -425,7 +425,7 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr, #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 42c3af90d1f0..92d21c6faf1e 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -365,7 +365,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 6ed93e290c2f..a2ddcbb3fcb9 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -693,7 +693,7 @@ static inline pte_t pte_swp_mkexclusive(pte_t pte) return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_EXCLUSIVE)); } -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SWP_EXCLUSIVE)); } diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h index 8d1f0b7062eb..7d6b9e5b286e 100644 --- a/arch/powerpc/include/asm/nohash/pgtable.h +++ b/arch/powerpc/include/asm/nohash/pgtable.h @@ -286,7 +286,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); } -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c index 0b6365d85d11..dc6f75d3ac6e 100644 --- a/arch/powerpc/platforms/book3s/vas-api.c +++ b/arch/powerpc/platforms/book3s/vas-api.c @@ -521,6 +521,15 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) return -EINVAL; } + /* + * Map complete page to the paste address. So the user + * space should pass 0ULL to the offset parameter. + */ + if (vma->vm_pgoff) { + pr_debug("Page offset unsupported to map paste address\n"); + return -EINVAL; + } + /* Ensure instance has an open send window */ if (!txwin) { pr_err("No send window open?\n"); diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index 4ac9808e55a4..2ea30b343354 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c @@ -48,11 +48,15 @@ static ssize_t memtrace_read(struct file *filp, char __user *ubuf, static int memtrace_mmap(struct file *filp, struct vm_area_struct *vma) { struct memtrace_entry *ent = filp->private_data; + unsigned long ent_nrpages = ent->size >> PAGE_SHIFT; + unsigned long vma_nrpages = vma_pages(vma); - if (ent->size < vma->vm_end - vma->vm_start) + /* The requested page offset should be within object's page count */ + if (vma->vm_pgoff >= ent_nrpages) return -EINVAL; - if (vma->vm_pgoff << PAGE_SHIFT >= ent->size) + /* The requested mapping range should remain within the bounds */ + if (vma_nrpages > ent_nrpages - vma->vm_pgoff) return -EINVAL; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index a11816bbf9e7..438ce7df24c3 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -1028,7 +1028,7 @@ static inline pud_t pud_modify(pud_t pud, pgprot_t newprot) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 1c661ac62ce8..6d8bc27a366e 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -915,7 +915,7 @@ static inline int pmd_protnone(pmd_t pmd) } #endif -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h index 71b18741cc11..5f51af18997b 100644 --- a/arch/sh/include/asm/pgtable_32.h +++ b/arch/sh/include/asm/pgtable_32.h @@ -470,7 +470,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) /* In both cases, we borrow bit 6 to store the exclusive marker in swap PTEs. */ #define _PAGE_SWP_EXCLUSIVE _PAGE_USER -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte.pte_low & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index 1454ebe91539..7c199c003ffe 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h @@ -348,7 +348,7 @@ static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & SRMMU_SWP_EXCLUSIVE; } diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 4af03e3c161b..669cd02469a1 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -1023,7 +1023,7 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp); #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h index ca2a519d53ab..24fdea6f88c3 100644 --- a/arch/um/include/asm/pgtable.h +++ b/arch/um/include/asm/pgtable.h @@ -314,7 +314,7 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_get_bits(pte, _PAGE_SWP_EXCLUSIVE); } diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 774430c3abff..97954c936c54 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1561,7 +1561,7 @@ static inline pte_t pte_swp_mkexclusive(pte_t pte) return pte_set_flags(pte, _PAGE_SWP_EXCLUSIVE); } -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_flags(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 18266cc3d98c..b014e6d229f9 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -299,3 +299,27 @@ struct smp_ops smp_ops = { .send_call_func_single_ipi = native_send_call_func_single_ipi, }; EXPORT_SYMBOL_GPL(smp_ops); + +int arch_cpu_rescan_dead_smt_siblings(void) +{ + enum cpuhp_smt_control old = cpu_smt_control; + int ret; + + /* + * If SMT has been disabled and SMT siblings are in HLT, bring them back + * online and offline them again so that they end up in MWAIT proper. + * + * Called with hotplug enabled. + */ + if (old != CPU_SMT_DISABLED && old != CPU_SMT_FORCE_DISABLED) + return 0; + + ret = cpuhp_smt_enable(); + if (ret) + return ret; + + ret = cpuhp_smt_disable(old); + + return ret; +} +EXPORT_SYMBOL_GPL(arch_cpu_rescan_dead_smt_siblings); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index fc78c2325fd2..58ede3fa6a75 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1244,6 +1244,10 @@ void play_dead_common(void) local_irq_disable(); } +/* + * We need to flush the caches before going to sleep, lest we have + * dirty data in our caches when we come back up. + */ void __noreturn mwait_play_dead(unsigned int eax_hint) { struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead); @@ -1290,50 +1294,6 @@ void __noreturn mwait_play_dead(unsigned int eax_hint) } /* - * We need to flush the caches before going to sleep, lest we have - * dirty data in our caches when we come back up. - */ -static inline void mwait_play_dead_cpuid_hint(void) -{ - unsigned int eax, ebx, ecx, edx; - unsigned int highest_cstate = 0; - unsigned int highest_subcstate = 0; - int i; - - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || - boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) - return; - if (!this_cpu_has(X86_FEATURE_MWAIT)) - return; - if (!this_cpu_has(X86_FEATURE_CLFLUSH)) - return; - - eax = CPUID_LEAF_MWAIT; - ecx = 0; - native_cpuid(&eax, &ebx, &ecx, &edx); - - /* - * eax will be 0 if EDX enumeration is not valid. - * Initialized below to cstate, sub_cstate value when EDX is valid. - */ - if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) { - eax = 0; - } else { - edx >>= MWAIT_SUBSTATE_SIZE; - for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) { - if (edx & MWAIT_SUBSTATE_MASK) { - highest_cstate = i; - highest_subcstate = edx & MWAIT_SUBSTATE_MASK; - } - } - eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | - (highest_subcstate - 1); - } - - mwait_play_dead(eax); -} - -/* * Kick all "offline" CPUs out of mwait on kexec(). See comment in * mwait_play_dead(). */ @@ -1383,9 +1343,9 @@ void native_play_dead(void) play_dead_common(); tboot_shutdown(TB_SHUTDOWN_WFS); - mwait_play_dead_cpuid_hint(); - if (cpuidle_play_dead()) - hlt_play_dead(); + /* Below returns only on error. */ + cpuidle_play_dead(); + hlt_play_dead(); } #else /* ... !CONFIG_HOTPLUG_CPU */ diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index cbc84c6abc2e..4e06e2e89a8f 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -4896,12 +4896,16 @@ long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, { u64 error_code = PFERR_GUEST_FINAL_MASK; u8 level = PG_LEVEL_4K; + u64 direct_bits; u64 end; int r; if (!vcpu->kvm->arch.pre_fault_allowed) return -EOPNOTSUPP; + if (kvm_is_gfn_alias(vcpu->kvm, gpa_to_gfn(range->gpa))) + return -EINVAL; + /* * reload is efficient when called repeatedly, so we can do it on * every iteration. @@ -4910,15 +4914,18 @@ long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, if (r) return r; + direct_bits = 0; if (kvm_arch_has_private_mem(vcpu->kvm) && kvm_mem_is_private(vcpu->kvm, gpa_to_gfn(range->gpa))) error_code |= PFERR_PRIVATE_ACCESS; + else + direct_bits = gfn_to_gpa(kvm_gfn_direct_bits(vcpu->kvm)); /* * Shadow paging uses GVA for kvm page fault, so restrict to * two-dimensional paging. */ - r = kvm_tdp_map_page(vcpu, range->gpa, error_code, &level); + r = kvm_tdp_map_page(vcpu, range->gpa | direct_bits, error_code, &level); if (r < 0) return r; diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 5a69b657dae9..459c3b791fd4 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2871,6 +2871,33 @@ void __init sev_set_cpu_caps(void) } } +static bool is_sev_snp_initialized(void) +{ + struct sev_user_data_snp_status *status; + struct sev_data_snp_addr buf; + bool initialized = false; + int ret, error = 0; + + status = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO); + if (!status) + return false; + + buf.address = __psp_pa(status); + ret = sev_do_cmd(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &error); + if (ret) { + pr_err("SEV: SNP_PLATFORM_STATUS failed ret=%d, fw_error=%d (%#x)\n", + ret, error, error); + goto out; + } + + initialized = !!status->state; + +out: + snp_free_firmware_page(status); + + return initialized; +} + void __init sev_hardware_setup(void) { unsigned int eax, ebx, ecx, edx, sev_asid_count, sev_es_asid_count; @@ -2975,6 +3002,14 @@ void __init sev_hardware_setup(void) sev_snp_supported = sev_snp_enabled && cc_platform_has(CC_ATTR_HOST_SEV_SNP); out: + if (sev_enabled) { + init_args.probe = true; + if (sev_platform_init(&init_args)) + sev_supported = sev_es_supported = sev_snp_supported = false; + else if (sev_snp_supported) + sev_snp_supported = is_sev_snp_initialized(); + } + if (boot_cpu_has(X86_FEATURE_SEV)) pr_info("SEV %s (ASIDs %u - %u)\n", sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" : @@ -3001,15 +3036,6 @@ out: sev_supported_vmsa_features = 0; if (sev_es_debug_swap_enabled) sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP; - - if (!sev_enabled) - return; - - /* - * Do both SNP and SEV initialization at KVM module load. - */ - init_args.probe = true; - sev_platform_init(&init_args); } void sev_hardware_unsetup(void) diff --git a/arch/x86/power/hibernate.c b/arch/x86/power/hibernate.c index a7c23f2a58c9..a2294c1649f6 100644 --- a/arch/x86/power/hibernate.c +++ b/arch/x86/power/hibernate.c @@ -192,7 +192,8 @@ out: int arch_resume_nosmt(void) { - int ret = 0; + int ret; + /* * We reached this while coming out of hibernation. This means * that SMT siblings are sleeping in hlt, as mwait is not safe @@ -206,18 +207,10 @@ int arch_resume_nosmt(void) * Called with hotplug disabled. */ cpu_hotplug_enable(); - if (cpu_smt_control == CPU_SMT_DISABLED || - cpu_smt_control == CPU_SMT_FORCE_DISABLED) { - enum cpuhp_smt_control old = cpu_smt_control; - - ret = cpuhp_smt_enable(); - if (ret) - goto out; - ret = cpuhp_smt_disable(old); - if (ret) - goto out; - } -out: + + ret = arch_cpu_rescan_dead_smt_siblings(); + cpu_hotplug_disable(); + return ret; } diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index cb1725c40e36..d62aa1c316fc 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h @@ -349,7 +349,7 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -static inline int pte_swp_exclusive(pte_t pte) +static inline bool pte_swp_exclusive(pte_t pte) { return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; } diff --git a/block/blk-merge.c b/block/blk-merge.c index 3af1d284add5..70d704615be5 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -998,20 +998,20 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, if (!plug || rq_list_empty(&plug->mq_list)) return false; - rq_list_for_each(&plug->mq_list, rq) { - if (rq->q == q) { - if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) == - BIO_MERGE_OK) - return true; - break; - } + rq = plug->mq_list.tail; + if (rq->q == q) + return blk_attempt_bio_merge(q, rq, bio, nr_segs, false) == + BIO_MERGE_OK; + else if (!plug->multiple_queues) + return false; - /* - * Only keep iterating plug list for merges if we have multiple - * queues - */ - if (!plug->multiple_queues) - break; + rq_list_for_each(&plug->mq_list, rq) { + if (rq->q != q) + continue; + if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) == + BIO_MERGE_OK) + return true; + break; } return false; } diff --git a/block/blk-zoned.c b/block/blk-zoned.c index 8f15d1aa6eb8..351d659280e1 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -1225,6 +1225,7 @@ void blk_zone_write_plug_bio_endio(struct bio *bio) if (bio_flagged(bio, BIO_EMULATES_ZONE_APPEND)) { bio->bi_opf &= ~REQ_OP_MASK; bio->bi_opf |= REQ_OP_ZONE_APPEND; + bio_clear_flag(bio, BIO_EMULATES_ZONE_APPEND); } /* @@ -1306,7 +1307,6 @@ again: spin_unlock_irqrestore(&zwplug->lock, flags); bdev = bio->bi_bdev; - submit_bio_noacct_nocheck(bio); /* * blk-mq devices will reuse the extra reference on the request queue @@ -1314,8 +1314,12 @@ again: * path for BIO-based devices will not do that. So drop this extra * reference here. */ - if (bdev_test_flag(bdev, BD_HAS_SUBMIT_BIO)) + if (bdev_test_flag(bdev, BD_HAS_SUBMIT_BIO)) { + bdev->bd_disk->fops->submit_bio(bio); blk_queue_exit(bdev->bd_disk->queue); + } else { + blk_mq_submit_bio(bio); + } put_zwplug: /* Drop the reference we took in disk_zone_wplug_schedule_bio_work(). */ diff --git a/crypto/hkdf.c b/crypto/hkdf.c index f24c2a8d4df9..82d1b32ca6ce 100644 --- a/crypto/hkdf.c +++ b/crypto/hkdf.c @@ -566,7 +566,7 @@ static int __init crypto_hkdf_module_init(void) static void __exit crypto_hkdf_module_exit(void) {} -module_init(crypto_hkdf_module_init); +late_initcall(crypto_hkdf_module_init); module_exit(crypto_hkdf_module_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/accel/amdxdna/aie2_psp.c b/drivers/accel/amdxdna/aie2_psp.c index dc3a072ce3b6..f28a060a8810 100644 --- a/drivers/accel/amdxdna/aie2_psp.c +++ b/drivers/accel/amdxdna/aie2_psp.c @@ -126,8 +126,8 @@ struct psp_device *aie2m_psp_create(struct drm_device *ddev, struct psp_config * psp->ddev = ddev; memcpy(psp->psp_regs, conf->psp_regs, sizeof(psp->psp_regs)); - psp->fw_buf_sz = ALIGN(conf->fw_size, PSP_FW_ALIGN) + PSP_FW_ALIGN; - psp->fw_buffer = drmm_kmalloc(ddev, psp->fw_buf_sz, GFP_KERNEL); + psp->fw_buf_sz = ALIGN(conf->fw_size, PSP_FW_ALIGN); + psp->fw_buffer = drmm_kmalloc(ddev, psp->fw_buf_sz + PSP_FW_ALIGN, GFP_KERNEL); if (!psp->fw_buffer) { drm_err(ddev, "no memory for fw buffer"); return NULL; diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 6f8bbe1247a5..c9a0bcaba2e4 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -33,7 +33,7 @@ static DEFINE_MUTEX(isolated_cpus_lock); static DEFINE_MUTEX(round_robin_lock); -static unsigned long power_saving_mwait_eax; +static unsigned int power_saving_mwait_eax; static unsigned char tsc_detected_unstable; static unsigned char tsc_marked_unstable; diff --git a/drivers/acpi/apei/einj-core.c b/drivers/acpi/apei/einj-core.c index fea11a35eea3..9b041415a9d0 100644 --- a/drivers/acpi/apei/einj-core.c +++ b/drivers/acpi/apei/einj-core.c @@ -883,19 +883,16 @@ static int __init einj_init(void) } einj_dev = faux_device_create("acpi-einj", NULL, &einj_device_ops); - if (!einj_dev) - return -ENODEV; - einj_initialized = true; + if (einj_dev) + einj_initialized = true; return 0; } static void __exit einj_exit(void) { - if (einj_initialized) - faux_device_destroy(einj_dev); - + faux_device_destroy(einj_dev); } module_init(einj_init); diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index a9ae2fd62863..6b649031808f 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -476,7 +476,7 @@ bool cppc_allow_fast_switch(void) struct cpc_desc *cpc_ptr; int cpu; - for_each_possible_cpu(cpu) { + for_each_present_cpu(cpu) { cpc_ptr = per_cpu(cpc_desc_ptr, cpu); desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF]; if (!CPC_IN_SYSTEM_MEMORY(desired_reg) && diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 6f4203716b53..75c7db8b156a 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -23,8 +23,10 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/list.h> +#include <linux/printk.h> #include <linux/spinlock.h> #include <linux/slab.h> +#include <linux/string.h> #include <linux/suspend.h> #include <linux/acpi.h> #include <linux/dmi.h> @@ -2031,6 +2033,21 @@ void __init acpi_ec_ecdt_probe(void) goto out; } + if (!strstarts(ecdt_ptr->id, "\\")) { + /* + * The ECDT table on some MSI notebooks contains invalid data, together + * with an empty ID string (""). + * + * Section 5.2.15 of the ACPI specification requires the ID string to be + * a "fully qualified reference to the (...) embedded controller device", + * so this string always has to start with a backslash. + * + * By verifying this we can avoid such faulty ECDT tables in a safe way. + */ + pr_err(FW_BUG "Ignoring ECDT due to invalid ID string \"%s\"\n", ecdt_ptr->id); + goto out; + } + ec = acpi_ec_alloc(); if (!ec) goto out; diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 00910ccd7eda..e2781864fdce 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -175,6 +175,12 @@ bool processor_physically_present(acpi_handle handle); static inline void acpi_early_processor_control_setup(void) {} #endif +#ifdef CONFIG_ACPI_PROCESSOR_CSTATE +void acpi_idle_rescan_dead_smt_siblings(void); +#else +static inline void acpi_idle_rescan_dead_smt_siblings(void) {} +#endif + /* -------------------------------------------------------------------------- Embedded Controller -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 3b281bc1e73c..65e779be64ff 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -279,6 +279,9 @@ static int __init acpi_processor_driver_init(void) * after acpi_cppc_processor_probe() has been called for all online CPUs */ acpi_processor_init_invariance_cppc(); + + acpi_idle_rescan_dead_smt_siblings(); + return 0; err: driver_unregister(&acpi_processor_driver); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e2febca2ec13..2c2dc559e0f8 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -24,6 +24,8 @@ #include <acpi/processor.h> #include <linux/context_tracking.h> +#include "internal.h" + /* * Include the apic definitions for x86 to have the APIC timer related defines * available also for UP (on SMP it gets magically included via linux/smp.h). @@ -55,6 +57,12 @@ struct cpuidle_driver acpi_idle_driver = { }; #ifdef CONFIG_ACPI_PROCESSOR_CSTATE +void acpi_idle_rescan_dead_smt_siblings(void) +{ + if (cpuidle_get_driver() == &acpi_idle_driver) + arch_cpu_rescan_dead_smt_siblings(); +} + static DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 7d59c6c9185f..b1ab192d7a08 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -667,6 +667,13 @@ static const struct dmi_system_id irq1_edge_low_force_override[] = { }, }, { + /* MACHENIKE L16P/L16P */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MACHENIKE"), + DMI_MATCH(DMI_BOARD_NAME, "L16P"), + }, + }, + { /* * TongFang GM5HG0A in case of the SKIKK Vanaheim relabel the * board-name is changed, so check OEM strings instead. Note diff --git a/drivers/base/faux.c b/drivers/base/faux.c index 9054d346bd7f..f5fbda0a9a44 100644 --- a/drivers/base/faux.c +++ b/drivers/base/faux.c @@ -86,6 +86,7 @@ static struct device_driver faux_driver = { .name = "faux_driver", .bus = &faux_bus_type, .probe_type = PROBE_FORCE_SYNCHRONOUS, + .suppress_bind_attrs = true, }; static void faux_device_release(struct device *dev) @@ -169,7 +170,7 @@ struct faux_device *faux_device_create_with_groups(const char *name, * successful is almost impossible to determine by the caller. */ if (!dev->driver) { - dev_err(dev, "probe did not succeed, tearing down the device\n"); + dev_dbg(dev, "probe did not succeed, tearing down the device\n"); faux_device_destroy(faux_dev); faux_dev = NULL; } diff --git a/drivers/block/loop.c b/drivers/block/loop.c index f8d136684109..500840e4a74e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1248,12 +1248,6 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) lo->lo_flags &= ~LOOP_SET_STATUS_CLEARABLE_FLAGS; lo->lo_flags |= (info->lo_flags & LOOP_SET_STATUS_SETTABLE_FLAGS); - if (size_changed) { - loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, - lo->lo_backing_file); - loop_set_size(lo, new_size); - } - /* update the direct I/O flag if lo_offset changed */ loop_update_dio(lo); @@ -1261,6 +1255,11 @@ out_unfreeze: blk_mq_unfreeze_queue(lo->lo_queue, memflags); if (partscan) clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); + if (!err && size_changed) { + loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, + lo->lo_backing_file); + loop_set_size(lo, new_size); + } out_unlock: mutex_unlock(&lo->lo_mutex); if (partscan) diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c index 50fe17f1e1d1..563165c5efae 100644 --- a/drivers/bluetooth/btintel_pcie.c +++ b/drivers/bluetooth/btintel_pcie.c @@ -396,8 +396,13 @@ static int btintel_pcie_submit_rx(struct btintel_pcie_data *data) static int btintel_pcie_start_rx(struct btintel_pcie_data *data) { int i, ret; + struct rxq *rxq = &data->rxq; + + /* Post (BTINTEL_PCIE_RX_DESCS_COUNT - 3) buffers to overcome the + * hardware issues leading to race condition at the firmware. + */ - for (i = 0; i < BTINTEL_PCIE_RX_MAX_QUEUE; i++) { + for (i = 0; i < rxq->count - 3; i++) { ret = btintel_pcie_submit_rx(data); if (ret) return ret; @@ -1782,8 +1787,8 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) * + size of index * Number of queues(2) * type of index array(4) * + size of context information */ - total = (sizeof(struct tfd) + sizeof(struct urbd0) + sizeof(struct frbd) - + sizeof(struct urbd1)) * BTINTEL_DESCS_COUNT; + total = (sizeof(struct tfd) + sizeof(struct urbd0)) * BTINTEL_PCIE_TX_DESCS_COUNT; + total += (sizeof(struct frbd) + sizeof(struct urbd1)) * BTINTEL_PCIE_RX_DESCS_COUNT; /* Add the sum of size of index array and size of ci struct */ total += (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4) + sizeof(struct ctx_info); @@ -1808,36 +1813,36 @@ static int btintel_pcie_alloc(struct btintel_pcie_data *data) data->dma_v_addr = v_addr; /* Setup descriptor count */ - data->txq.count = BTINTEL_DESCS_COUNT; - data->rxq.count = BTINTEL_DESCS_COUNT; + data->txq.count = BTINTEL_PCIE_TX_DESCS_COUNT; + data->rxq.count = BTINTEL_PCIE_RX_DESCS_COUNT; /* Setup tfds */ data->txq.tfds_p_addr = p_addr; data->txq.tfds = v_addr; - p_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); + v_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); /* Setup urbd0 */ data->txq.urbd0s_p_addr = p_addr; data->txq.urbd0s = v_addr; - p_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); + v_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); /* Setup FRBD*/ data->rxq.frbds_p_addr = p_addr; data->rxq.frbds = v_addr; - p_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); + v_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); /* Setup urbd1 */ data->rxq.urbd1s_p_addr = p_addr; data->rxq.urbd1s = v_addr; - p_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT); - v_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT); + p_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); + v_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); /* Setup data buffers for txq */ err = btintel_pcie_setup_txq_bufs(data, &data->txq); diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h index 21b964b15c1c..7dad4523236c 100644 --- a/drivers/bluetooth/btintel_pcie.h +++ b/drivers/bluetooth/btintel_pcie.h @@ -154,8 +154,11 @@ enum msix_mbox_int_causes { /* Default interrupt timeout in msec */ #define BTINTEL_DEFAULT_INTR_TIMEOUT_MS 3000 -/* The number of descriptors in TX/RX queues */ -#define BTINTEL_DESCS_COUNT 16 +/* The number of descriptors in TX queues */ +#define BTINTEL_PCIE_TX_DESCS_COUNT 32 + +/* The number of descriptors in RX queues */ +#define BTINTEL_PCIE_RX_DESCS_COUNT 64 /* Number of Queue for TX and RX * It indicates the index of the IA(Index Array) @@ -177,9 +180,6 @@ enum { /* Doorbell vector for TFD */ #define BTINTEL_PCIE_TX_DB_VEC 0 -/* Number of pending RX requests for downlink */ -#define BTINTEL_PCIE_RX_MAX_QUEUE 6 - /* Doorbell vector for FRBD */ #define BTINTEL_PCIE_RX_DB_VEC 513 diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 19c1ed280fd7..561fbc9eef2d 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -61,7 +61,6 @@ config LMK04832 config COMMON_CLK_APPLE_NCO tristate "Clock driver for Apple SoC NCOs" depends on ARCH_APPLE || COMPILE_TEST - default ARCH_APPLE help This driver supports NCO (Numerically Controlled Oscillator) blocks found on Apple SoCs such as t8103 (M1). The blocks are typically diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 42867cd37c33..862c3eefa5b5 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -18,6 +18,7 @@ clk-test-y := clk_test.o \ kunit_clk_assigned_rates_without_consumer.dtbo.o \ kunit_clk_assigned_rates_zero.dtbo.o \ kunit_clk_assigned_rates_zero_consumer.dtbo.o \ + kunit_clk_hw_get_dev_of_node.dtbo.o \ kunit_clk_parent_data_test.dtbo.o obj-$(CONFIG_COMMON_CLK) += clk-divider.o obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o diff --git a/drivers/clk/baikal-t1/clk-ccu-div.c b/drivers/clk/baikal-t1/clk-ccu-div.c index 84555a00f950..17d75e8e2e8f 100644 --- a/drivers/clk/baikal-t1/clk-ccu-div.c +++ b/drivers/clk/baikal-t1/clk-ccu-div.c @@ -405,7 +405,7 @@ static void ccu_div_clk_unregister(struct ccu_div_data *data, bool defer) { int idx; - /* Uninstall only the clocks registered on the specfied stage */ + /* Uninstall only the clocks registered on the specified stage */ for (idx = 0; idx < data->divs_num; ++idx) { if (!!(data->divs_info[idx].features & CCU_DIV_BASIC) ^ defer) continue; diff --git a/drivers/clk/baikal-t1/clk-ccu-pll.c b/drivers/clk/baikal-t1/clk-ccu-pll.c index fce02ce77347..921b87024feb 100644 --- a/drivers/clk/baikal-t1/clk-ccu-pll.c +++ b/drivers/clk/baikal-t1/clk-ccu-pll.c @@ -196,7 +196,7 @@ static void ccu_pll_clk_unregister(struct ccu_pll_data *data, bool defer) { int idx; - /* Uninstall only the clocks registered on the specfied stage */ + /* Uninstall only the clocks registered on the specified stage */ for (idx = 0; idx < CCU_PLL_NUM; ++idx) { if (!!(pll_info[idx].features & CCU_PLL_BASIC) ^ defer) continue; diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index fb04734afc80..02215ea79403 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -570,18 +570,23 @@ static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate, return rate >> A2W_PLL_FRAC_BITS; } -static long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int bcm2835_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw); const struct bcm2835_pll_data *data = pll->data; u32 ndiv, fdiv; - rate = clamp(rate, data->min_rate, data->max_rate); + req->rate = clamp(req->rate, data->min_rate, data->max_rate); - bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv); + bcm2835_pll_choose_ndiv_and_fdiv(req->rate, req->best_parent_rate, + &ndiv, &fdiv); - return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1); + req->rate = bcm2835_pll_rate_from_divisors(req->best_parent_rate, + ndiv, fdiv, + 1); + + return 0; } static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw, @@ -783,7 +788,7 @@ static const struct clk_ops bcm2835_pll_clk_ops = { .unprepare = bcm2835_pll_off, .recalc_rate = bcm2835_pll_get_rate, .set_rate = bcm2835_pll_set_rate, - .round_rate = bcm2835_pll_round_rate, + .determine_rate = bcm2835_pll_determine_rate, .debug_init = bcm2835_pll_debug_init, }; @@ -1550,7 +1555,7 @@ static const char *const bcm2835_clock_osc_parents[] = { .parents = bcm2835_clock_osc_parents, \ __VA_ARGS__) -/* main peripherial parent mux */ +/* main peripheral parent mux */ static const char *const bcm2835_clock_per_parents[] = { "gnd", "xosc", diff --git a/drivers/clk/bcm/clk-bcm53573-ilp.c b/drivers/clk/bcm/clk-bcm53573-ilp.c index 83ef41d618be..b2fc05b60783 100644 --- a/drivers/clk/bcm/clk-bcm53573-ilp.c +++ b/drivers/clk/bcm/clk-bcm53573-ilp.c @@ -59,7 +59,7 @@ static unsigned long bcm53573_ilp_recalc_rate(struct clk_hw *hw, /* * At minimum we should loop for a bit to let hardware do the * measurement. This isn't very accurate however, so for a better - * precision lets try getting 20 different values for and use average. + * precision let's try getting 20 different values and use average. */ while (num < 20) { regmap_read(regmap, PMU_XTAL_FREQ_RATIO, &cur_val); diff --git a/drivers/clk/berlin/berlin2-avpll.c b/drivers/clk/berlin/berlin2-avpll.c index aa89b4c9464e..79f3d37a0ee0 100644 --- a/drivers/clk/berlin/berlin2-avpll.c +++ b/drivers/clk/berlin/berlin2-avpll.c @@ -319,7 +319,7 @@ berlin2_avpll_channel_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) /* * AV3 divider start at VCO_CTRL14, bit 7; each 4 bits wide. - * AV2/AV3 form a fractional divider, where only specfic values for AV3 + * AV2/AV3 form a fractional divider, where only specific values for AV3 * are allowed. AV3 != 0 divides by AV2/2, AV3=0 is bypass. */ if (ch->index < 6) { diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c index 3432c801f1bd..595cfa533fb9 100644 --- a/drivers/clk/clk-asm9260.c +++ b/drivers/clk/clk-asm9260.c @@ -92,8 +92,8 @@ static const struct asm9260_div_clk asm9260_div_clks[] __initconst = { { CLKID_SYS_CPU, "cpu_div", "main_gate", HW_CPUCLKDIV }, { CLKID_SYS_AHB, "ahb_div", "cpu_div", HW_SYSAHBCLKDIV }, - /* i2s has two deviders: one for only external mclk and internal - * devider for all clks. */ + /* i2s has two dividers: one for only external mclk and internal + * divider for all clks. */ { CLKID_SYS_I2S0M, "i2s0m_div", "i2s0_mclk", HW_I2S0MCLKDIV }, { CLKID_SYS_I2S1M, "i2s1m_div", "i2s1_mclk", HW_I2S1MCLKDIV }, { CLKID_SYS_I2S0S, "i2s0s_div", "i2s0_gate", HW_I2S0SCLKDIV }, diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c index faf88324f7b1..114afc13d640 100644 --- a/drivers/clk/clk-ast2600.c +++ b/drivers/clk/clk-ast2600.c @@ -92,7 +92,7 @@ static u8 soc_rev; * * There are some gates that do not have an associated reset; these are * handled by using -1 as the index for the reset, and the consumer must - * explictly assert/deassert reset lines as required. + * explicitly assert/deassert reset lines as required. * * Clocks marked with CLK_IS_CRITICAL: * diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 934e53a96ddd..aec62301fa06 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -6,14 +6,17 @@ * Author: Lars-Peter Clausen <lars@metafoo.de> */ -#include <linux/platform_device.h> +#include <linux/adi-axi-common.h> +#include <linux/bits.h> #include <linux/clk.h> #include <linux/clk-provider.h> -#include <linux/slab.h> +#include <linux/err.h> #include <linux/io.h> -#include <linux/of.h> #include <linux/module.h> -#include <linux/err.h> +#include <linux/mod_devicetable.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/slab.h> #define AXI_CLKGEN_V2_REG_RESET 0x40 #define AXI_CLKGEN_V2_REG_CLKSEL 0x44 @@ -28,6 +31,9 @@ #define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16) +#define ADI_CLKGEN_REG_FPGA_VOLTAGE 0x0140 +#define ADI_CLKGEN_INFO_FPGA_VOLTAGE(val) ((val) & GENMASK(15, 0)) + #define MMCM_REG_CLKOUT5_2 0x07 #define MMCM_REG_CLKOUT0_1 0x08 #define MMCM_REG_CLKOUT0_2 0x09 @@ -90,7 +96,7 @@ static uint32_t axi_clkgen_lookup_filter(unsigned int m) } } -static const uint32_t axi_clkgen_lock_table[] = { +static const u32 axi_clkgen_lock_table[] = { 0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8, 0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8, 0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339, @@ -102,7 +108,7 @@ static const uint32_t axi_clkgen_lock_table[] = { 0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113, }; -static uint32_t axi_clkgen_lookup_lock(unsigned int m) +static u32 axi_clkgen_lookup_lock(unsigned int m) { if (m < ARRAY_SIZE(axi_clkgen_lock_table)) return axi_clkgen_lock_table[m]; @@ -118,14 +124,15 @@ static const struct axi_clkgen_limits axi_clkgen_zynqmp_default_limits = { static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = { .fpfd_min = 10000, - .fpfd_max = 300000, + .fpfd_max = 450000, .fvco_min = 600000, .fvco_max = 1200000, }; static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits, - unsigned long fin, unsigned long fout, - unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout) + unsigned long fin, unsigned long fout, + unsigned int *best_d, unsigned int *best_m, + unsigned int *best_dout) { unsigned long d, d_min, d_max, _d_min, _d_max; unsigned long m, m_min, m_max; @@ -141,15 +148,15 @@ static void axi_clkgen_calc_params(const struct axi_clkgen_limits *limits, *best_m = 0; *best_dout = 0; - d_min = max_t(unsigned long, DIV_ROUND_UP(fin, limits->fpfd_max), 1); - d_max = min_t(unsigned long, fin / limits->fpfd_min, 80); + d_min = max(DIV_ROUND_UP(fin, limits->fpfd_max), 1); + d_max = min(fin / limits->fpfd_min, 80); again: fvco_min_fract = limits->fvco_min << fract_shift; fvco_max_fract = limits->fvco_max << fract_shift; - m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1); - m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift); + m_min = max(DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1); + m_max = min(fvco_max_fract * d_max / fin, 64 << fract_shift); for (m = m_min; m <= m_max; m++) { _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max_fract)); @@ -172,7 +179,7 @@ again: } } - /* Lets see if we find a better setting in fractional mode */ + /* Let's see if we find a better setting in fractional mode */ if (fract_shift == 0) { fract_shift = 3; goto again; @@ -192,9 +199,9 @@ struct axi_clkgen_div_params { }; static void axi_clkgen_calc_clk_params(unsigned int divider, - unsigned int frac_divider, struct axi_clkgen_div_params *params) + unsigned int frac_divider, + struct axi_clkgen_div_params *params) { - memset(params, 0x0, sizeof(*params)); if (divider == 1) { @@ -222,7 +229,7 @@ static void axi_clkgen_calc_clk_params(unsigned int divider, if (params->edge == 0 || frac_divider == 1) params->low--; if (((params->edge == 0) ^ (frac_divider == 1)) || - (divider == 2 && frac_divider == 1)) + (divider == 2 && frac_divider == 1)) params->frac_wf_f = 1; params->frac_phase = params->edge * 4 + frac_divider / 2; @@ -230,13 +237,13 @@ static void axi_clkgen_calc_clk_params(unsigned int divider, } static void axi_clkgen_write(struct axi_clkgen *axi_clkgen, - unsigned int reg, unsigned int val) + unsigned int reg, unsigned int val) { writel(val, axi_clkgen->base + reg); } static void axi_clkgen_read(struct axi_clkgen *axi_clkgen, - unsigned int reg, unsigned int *val) + unsigned int reg, unsigned int *val) { *val = readl(axi_clkgen->base + reg); } @@ -257,7 +264,7 @@ static int axi_clkgen_wait_non_busy(struct axi_clkgen *axi_clkgen) } static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen, - unsigned int reg, unsigned int *val) + unsigned int reg, unsigned int *val) { unsigned int reg_val; int ret; @@ -281,7 +288,8 @@ static int axi_clkgen_mmcm_read(struct axi_clkgen *axi_clkgen, } static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen, - unsigned int reg, unsigned int val, unsigned int mask) + unsigned int reg, unsigned int val, + unsigned int mask) { unsigned int reg_val = 0; int ret; @@ -302,8 +310,7 @@ static int axi_clkgen_mmcm_write(struct axi_clkgen *axi_clkgen, return 0; } -static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, - bool enable) +static void axi_clkgen_mmcm_enable(struct axi_clkgen *axi_clkgen, bool enable) { unsigned int val = AXI_CLKGEN_V2_RESET_ENABLE; @@ -319,31 +326,31 @@ static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) } static void axi_clkgen_set_div(struct axi_clkgen *axi_clkgen, - unsigned int reg1, unsigned int reg2, unsigned int reg3, - struct axi_clkgen_div_params *params) + unsigned int reg1, unsigned int reg2, + unsigned int reg3, + struct axi_clkgen_div_params *params) { axi_clkgen_mmcm_write(axi_clkgen, reg1, - (params->high << 6) | params->low, 0xefff); + (params->high << 6) | params->low, 0xefff); axi_clkgen_mmcm_write(axi_clkgen, reg2, - (params->frac << 12) | (params->frac_en << 11) | - (params->frac_wf_r << 10) | (params->edge << 7) | - (params->nocount << 6), 0x7fff); + (params->frac << 12) | (params->frac_en << 11) | + (params->frac_wf_r << 10) | (params->edge << 7) | + (params->nocount << 6), 0x7fff); if (reg3 != 0) { axi_clkgen_mmcm_write(axi_clkgen, reg3, - (params->frac_phase << 11) | (params->frac_wf_f << 10), 0x3c00); + (params->frac_phase << 11) | (params->frac_wf_f << 10), + 0x3c00); } } -static int axi_clkgen_set_rate(struct clk_hw *clk_hw, - unsigned long rate, unsigned long parent_rate) +static int axi_clkgen_set_rate(struct clk_hw *clk_hw, unsigned long rate, + unsigned long parent_rate) { struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); const struct axi_clkgen_limits *limits = &axi_clkgen->limits; unsigned int d, m, dout; struct axi_clkgen_div_params params; - uint32_t power = 0; - uint32_t filter; - uint32_t lock; + u32 power = 0, filter, lock; if (parent_rate == 0 || rate == 0) return -EINVAL; @@ -363,22 +370,22 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw, axi_clkgen_calc_clk_params(dout >> 3, dout & 0x7, ¶ms); axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLKOUT0_1, MMCM_REG_CLKOUT0_2, - MMCM_REG_CLKOUT5_2, ¶ms); + MMCM_REG_CLKOUT5_2, ¶ms); axi_clkgen_calc_clk_params(d, 0, ¶ms); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV, - (params.edge << 13) | (params.nocount << 12) | - (params.high << 6) | params.low, 0x3fff); + (params.edge << 13) | (params.nocount << 12) | + (params.high << 6) | params.low, 0x3fff); axi_clkgen_calc_clk_params(m >> 3, m & 0x7, ¶ms); axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLK_FB1, MMCM_REG_CLK_FB2, - MMCM_REG_CLKOUT6_2, ¶ms); + MMCM_REG_CLKOUT6_2, ¶ms); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2, - (((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff); + (((lock >> 16) & 0x1f) << 10) | 0x1, 0x7fff); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK3, - (((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff); + (((lock >> 24) & 0x1f) << 10) | 0x3e9, 0x7fff); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER1, filter >> 16, 0x9900); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_FILTER2, filter, 0x9900); @@ -407,7 +414,7 @@ static int axi_clkgen_determine_rate(struct clk_hw *hw, } static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen, - unsigned int reg1, unsigned int reg2) + unsigned int reg1, unsigned int reg2) { unsigned int val1, val2; unsigned int div; @@ -434,7 +441,7 @@ static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen, } static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, - unsigned long parent_rate) + unsigned long parent_rate) { struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); unsigned int d, m, dout; @@ -442,9 +449,9 @@ static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, unsigned int val; dout = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLKOUT0_1, - MMCM_REG_CLKOUT0_2); + MMCM_REG_CLKOUT0_2); m = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLK_FB1, - MMCM_REG_CLK_FB2); + MMCM_REG_CLK_FB2); axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &val); if (val & MMCM_CLK_DIV_NOCOUNT) @@ -496,6 +503,54 @@ static u8 axi_clkgen_get_parent(struct clk_hw *clk_hw) return parent; } +static int axi_clkgen_setup_limits(struct axi_clkgen *axi_clkgen, + struct device *dev) +{ + unsigned int tech, family, speed_grade, reg_value; + + axi_clkgen_read(axi_clkgen, ADI_AXI_REG_FPGA_INFO, ®_value); + tech = ADI_AXI_INFO_FPGA_TECH(reg_value); + family = ADI_AXI_INFO_FPGA_FAMILY(reg_value); + speed_grade = ADI_AXI_INFO_FPGA_SPEED_GRADE(reg_value); + + axi_clkgen->limits.fpfd_min = 10000; + axi_clkgen->limits.fvco_min = 600000; + + switch (speed_grade) { + case ADI_AXI_FPGA_SPEED_1 ... ADI_AXI_FPGA_SPEED_1LV: + axi_clkgen->limits.fvco_max = 1200000; + axi_clkgen->limits.fpfd_max = 450000; + break; + case ADI_AXI_FPGA_SPEED_2 ... ADI_AXI_FPGA_SPEED_2LV: + axi_clkgen->limits.fvco_max = 1440000; + axi_clkgen->limits.fpfd_max = 500000; + if (family == ADI_AXI_FPGA_FAMILY_KINTEX || family == ADI_AXI_FPGA_FAMILY_ARTIX) { + axi_clkgen_read(axi_clkgen, ADI_CLKGEN_REG_FPGA_VOLTAGE, + ®_value); + if (ADI_CLKGEN_INFO_FPGA_VOLTAGE(reg_value) < 950) { + axi_clkgen->limits.fvco_max = 1200000; + axi_clkgen->limits.fpfd_max = 450000; + } + } + break; + case ADI_AXI_FPGA_SPEED_3: + axi_clkgen->limits.fvco_max = 1600000; + axi_clkgen->limits.fpfd_max = 550000; + break; + default: + return dev_err_probe(dev, -ENODEV, "Unknown speed grade %d\n", + speed_grade); + }; + + /* Overwrite vco limits for ultrascale+ */ + if (tech == ADI_AXI_FPGA_TECH_ULTRASCALE_PLUS) { + axi_clkgen->limits.fvco_max = 1600000; + axi_clkgen->limits.fvco_min = 800000; + } + + return 0; +} + static const struct clk_ops axi_clkgen_ops = { .recalc_rate = axi_clkgen_recalc_rate, .determine_rate = axi_clkgen_determine_rate, @@ -510,6 +565,7 @@ static int axi_clkgen_probe(struct platform_device *pdev) { const struct axi_clkgen_limits *dflt_limits; struct axi_clkgen *axi_clkgen; + unsigned int pcore_version; struct clk_init_data init; const char *parent_names[2]; const char *clk_name; @@ -555,11 +611,20 @@ static int axi_clkgen_probe(struct platform_device *pdev) return -EINVAL; } - memcpy(&axi_clkgen->limits, dflt_limits, sizeof(axi_clkgen->limits)); + axi_clkgen_read(axi_clkgen, ADI_AXI_REG_VERSION, &pcore_version); + + if (ADI_AXI_PCORE_VER_MAJOR(pcore_version) > 0x04) { + ret = axi_clkgen_setup_limits(axi_clkgen, &pdev->dev); + if (ret) + return ret; + } else { + memcpy(&axi_clkgen->limits, dflt_limits, + sizeof(axi_clkgen->limits)); + } clk_name = pdev->dev.of_node->name; of_property_read_string(pdev->dev.of_node, "clock-output-names", - &clk_name); + &clk_name); init.name = clk_name; init.ops = &axi_clkgen_ops; diff --git a/drivers/clk/clk-clps711x.c b/drivers/clk/clk-clps711x.c index f8417ee2961a..402ab74d9bfb 100644 --- a/drivers/clk/clk-clps711x.c +++ b/drivers/clk/clk-clps711x.c @@ -99,7 +99,7 @@ static void __init clps711x_clk_init_dt(struct device_node *np) */ tmp &= ~(SYSCON1_TC1M | SYSCON1_TC1S); /* Timer2 in prescale mode. - * Value writen is automatically re-loaded when + * Value written is automatically re-loaded when * the counter underflows. */ tmp |= SYSCON1_TC2M | SYSCON1_TC2S; diff --git a/drivers/clk/clk-eyeq.c b/drivers/clk/clk-eyeq.c index 640c25788487..ea1c3d78e7cd 100644 --- a/drivers/clk/clk-eyeq.c +++ b/drivers/clk/clk-eyeq.c @@ -131,7 +131,7 @@ struct eqc_early_match_data { * Both factors (mult and div) must fit in 32 bits. When an operation overflows, * this function throws away low bits so that factors still fit in 32 bits. * - * Precision loss depends on amplitude of mult and div. Worst theorical + * Precision loss depends on amplitude of mult and div. Worst theoretical * loss is: (UINT_MAX+1) / UINT_MAX - 1 = 2.3e-10. * This is 1Hz every 4.3GHz. */ diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 68e585a02fd9..4746f8219132 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -15,7 +15,7 @@ #include <linux/string.h> /** - * DOC: basic gatable clock which can gate and ungate its output + * DOC: basic gateable clock which can gate and ungate its output * * Traits of this clock: * prepare - clk_(un)prepare only ensures parent is (un)prepared diff --git a/drivers/clk/clk-hsdk-pll.c b/drivers/clk/clk-hsdk-pll.c index 5d2a90addf1a..921523fc26f2 100644 --- a/drivers/clk/clk-hsdk-pll.c +++ b/drivers/clk/clk-hsdk-pll.c @@ -265,7 +265,7 @@ static int hsdk_pll_core_update_rate(struct hsdk_pll_clk *clk, return -EINVAL; /* - * Program divider to div-by-1 if we succesfuly set core clock below + * Program divider to div-by-1 if we successfully set core clock below * 500MHz threshold. */ if (rate <= CORE_IF_CLK_THRESHOLD_HZ) diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index 8ddf3a9a53df..d4e9c3577b35 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -235,7 +235,7 @@ MODULE_DEVICE_TABLE(platform, s2mps11_clk_id); * through platform_device_id. * * However if device's DT node contains proper clock compatible and driver is - * built as a module, then the *module* matching will be done trough DT aliases. + * built as a module, then the *module* matching will be done through DT aliases. * This requires of_device_id table. In the same time this will not change the * actual *device* matching so do not add .of_match_table. */ diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index 15510c2ff21c..6a8f188629aa 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -451,7 +451,7 @@ static int scmi_clocks_probe(struct scmi_device *sdev) /* * Note that the scmi_clk_ops_db is on the stack, not global, - * because it cannot be shared between mulitple probe-sequences + * because it cannot be shared between multiple probe-sequences * to avoid sharing the devm_ allocated clk_ops between multiple * SCMI clk driver instances. */ diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index a4c92c5ef3ff..e755db545e2e 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -655,7 +655,7 @@ static int si5351_msynth_determine_rate(struct clk_hw *hw, unsigned long a, b, c; int divby4; - /* multisync6-7 can only handle freqencies < 150MHz */ + /* multisync6-7 can only handle frequencies < 150MHz */ if (hwdata->num >= 6 && rate > SI5351_MULTISYNTH67_MAX_FREQ) rate = SI5351_MULTISYNTH67_MAX_FREQ; @@ -1048,11 +1048,11 @@ static int si5351_clkout_determine_rate(struct clk_hw *hw, unsigned long rate = req->rate; unsigned char rdiv; - /* clkout6/7 can only handle output freqencies < 150MHz */ + /* clkout6/7 can only handle output frequencies < 150MHz */ if (hwdata->num >= 6 && rate > SI5351_CLKOUT67_MAX_FREQ) rate = SI5351_CLKOUT67_MAX_FREQ; - /* clkout freqency is 8kHz - 160MHz */ + /* clkout frequency is 8kHz - 160MHz */ if (rate > SI5351_CLKOUT_MAX_FREQ) rate = SI5351_CLKOUT_MAX_FREQ; if (rate < SI5351_CLKOUT_MIN_FREQ) diff --git a/drivers/clk/clk-si544.c b/drivers/clk/clk-si544.c index c88650558f32..ca3473efa314 100644 --- a/drivers/clk/clk-si544.c +++ b/drivers/clk/clk-si544.c @@ -39,7 +39,7 @@ /* Max freq depends on speed grade */ #define SI544_MIN_FREQ 200000U -/* Si544 Internal oscilator runs at 55.05 MHz */ +/* Si544 Internal oscillator runs at 55.05 MHz */ #define FXO 55050000U /* VCO range is 10.8 .. 12.1 GHz, max depends on speed grade */ diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c index a549ea13be20..e97fe90443a6 100644 --- a/drivers/clk/clk-si570.c +++ b/drivers/clk/clk-si570.c @@ -63,7 +63,7 @@ struct clk_si570_info { * struct clk_si570: * @hw: Clock hw struct * @regmap: Device's regmap - * @div_offset: Rgister offset for dividers + * @div_offset: Register offset for dividers * @info: Device info * @fxtal: Factory xtal frequency * @n1: Clock divider N1 @@ -181,7 +181,7 @@ static int si570_update_rfreq(struct clk_si570 *data) } /** - * si570_calc_divs() - Caluclate clock dividers + * si570_calc_divs() - Calculate clock dividers * @frequency: Target frequency * @data: Driver data structure * @out_rfreq: RFREG fractional multiplier (output) diff --git a/drivers/clk/clk-sp7021.c b/drivers/clk/clk-sp7021.c index 7cb7d501d7a6..95d66191df4b 100644 --- a/drivers/clk/clk-sp7021.c +++ b/drivers/clk/clk-sp7021.c @@ -14,7 +14,7 @@ #include <dt-bindings/clock/sunplus,sp7021-clkc.h> -/* speical div_width values for PLLTV/PLLA */ +/* special div_width values for PLLTV/PLLA */ #define DIV_TV 33 #define DIV_A 34 diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index 85e23961ec34..719cddc82ae6 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c @@ -19,7 +19,7 @@ #include <linux/mfd/syscon.h> /* - * Include list of clocks wich are not derived from system clock (SYSCLOCK) + * Include list of clocks which are not derived from system clock (SYSCLOCK) * The index of these clocks is the secondary index of DT bindings * */ diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 6d31cd54d7cf..4200022d2084 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -136,7 +136,7 @@ #define VC5_MAX_FOD_NUM 4 /* flags to describe chip features */ -/* chip has built-in oscilator */ +/* chip has built-in oscillator */ #define VC5_HAS_INTERNAL_XTAL BIT(0) /* chip has PFD requency doubler */ #define VC5_HAS_PFD_FREQ_DBL BIT(1) diff --git a/drivers/clk/clk-versaclock7.c b/drivers/clk/clk-versaclock7.c index f323263e32c3..483285b30c13 100644 --- a/drivers/clk/clk-versaclock7.c +++ b/drivers/clk/clk-versaclock7.c @@ -1257,7 +1257,7 @@ static const struct vc7_chip_info vc7_rc21008a_info = { .num_outputs = 8, }; -static struct regmap_range_cfg vc7_range_cfg[] = { +static const struct regmap_range_cfg vc7_range_cfg[] = { { .range_min = 0, .range_max = VC7_MAX_REG, diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0565c87656cf..b821b2cdb155 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -365,6 +365,18 @@ const char *clk_hw_get_name(const struct clk_hw *hw) } EXPORT_SYMBOL_GPL(clk_hw_get_name); +struct device *clk_hw_get_dev(const struct clk_hw *hw) +{ + return hw->core->dev; +} +EXPORT_SYMBOL_GPL(clk_hw_get_dev); + +struct device_node *clk_hw_get_of_node(const struct clk_hw *hw) +{ + return hw->core->of_node; +} +EXPORT_SYMBOL_GPL(clk_hw_get_of_node); + struct clk_hw *__clk_get_hw(struct clk *clk) { return !clk ? NULL : clk->core->hw; diff --git a/drivers/clk/clk_test.c b/drivers/clk/clk_test.c index f08feeaa3750..a268d7b5d4cb 100644 --- a/drivers/clk/clk_test.c +++ b/drivers/clk/clk_test.c @@ -292,7 +292,7 @@ static void clk_test_set_set_get_rate(struct kunit *test) } /* - * Test that clk_round_rate and clk_set_rate are consitent and will + * Test that clk_round_rate and clk_set_rate are consistent and will * return the same frequency. */ static void clk_test_round_set_get_rate(struct kunit *test) @@ -2794,49 +2794,49 @@ static struct kunit_suite clk_register_clk_parent_data_of_suite = { }; /** - * struct clk_register_clk_parent_data_device_ctx - Context for clk_parent_data device tests - * @dev: device of clk under test - * @hw: clk_hw for clk under test + * struct platform_driver_dev_ctx - Context to stash platform device + * @dev: device under test * @pdrv: driver to attach to find @dev */ -struct clk_register_clk_parent_data_device_ctx { +struct platform_driver_dev_ctx { struct device *dev; - struct clk_hw hw; struct platform_driver pdrv; }; -static inline struct clk_register_clk_parent_data_device_ctx * -clk_register_clk_parent_data_driver_to_test_context(struct platform_device *pdev) +static inline struct platform_driver_dev_ctx * +pdev_to_platform_driver_dev_ctx(struct platform_device *pdev) { return container_of(to_platform_driver(pdev->dev.driver), - struct clk_register_clk_parent_data_device_ctx, pdrv); + struct platform_driver_dev_ctx, pdrv); } -static int clk_register_clk_parent_data_device_probe(struct platform_device *pdev) +static int kunit_platform_driver_dev_probe(struct platform_device *pdev) { - struct clk_register_clk_parent_data_device_ctx *ctx; + struct platform_driver_dev_ctx *ctx; - ctx = clk_register_clk_parent_data_driver_to_test_context(pdev); + ctx = pdev_to_platform_driver_dev_ctx(pdev); ctx->dev = &pdev->dev; return 0; } -static void clk_register_clk_parent_data_device_driver(struct kunit *test) +static struct device * +kunit_of_platform_driver_dev(struct kunit *test, const struct of_device_id *match_table) { - struct clk_register_clk_parent_data_device_ctx *ctx = test->priv; - static const struct of_device_id match_table[] = { - { .compatible = "test,clk-parent-data" }, - { } - }; + struct platform_driver_dev_ctx *ctx; - ctx->pdrv.probe = clk_register_clk_parent_data_device_probe; + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + ctx->pdrv.probe = kunit_platform_driver_dev_probe; ctx->pdrv.driver.of_match_table = match_table; ctx->pdrv.driver.name = __func__; ctx->pdrv.driver.owner = THIS_MODULE; KUNIT_ASSERT_EQ(test, 0, kunit_platform_driver_register(test, &ctx->pdrv)); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->dev); + + return ctx->dev; } static const struct clk_register_clk_parent_data_test_case @@ -2909,30 +2909,34 @@ KUNIT_ARRAY_PARAM(clk_register_clk_parent_data_device_test, */ static void clk_register_clk_parent_data_device_test(struct kunit *test) { - struct clk_register_clk_parent_data_device_ctx *ctx; + struct device *dev; + struct clk_hw *hw; const struct clk_register_clk_parent_data_test_case *test_param; struct clk_hw *parent_hw; struct clk_init_data init = { }; struct clk *expected_parent, *actual_parent; + static const struct of_device_id match_table[] = { + { .compatible = "test,clk-parent-data" }, + { } + }; - ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); - test->priv = ctx; - - clk_register_clk_parent_data_device_driver(test); + dev = kunit_of_platform_driver_dev(test, match_table); - expected_parent = clk_get_kunit(test, ctx->dev, "50"); + expected_parent = clk_get_kunit(test, dev, "50"); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_parent); + hw = kunit_kzalloc(test, sizeof(*hw), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + test_param = test->param_value; init.parent_data = &test_param->pdata; init.num_parents = 1; init.name = "parent_data_device_test_clk"; init.ops = &clk_dummy_single_parent_ops; - ctx->hw.init = &init; - KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, ctx->dev, &ctx->hw)); + hw->init = &init; + KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, dev, hw)); - parent_hw = clk_hw_get_parent(&ctx->hw); + parent_hw = clk_hw_get_parent(hw); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent_hw); actual_parent = clk_hw_get_clk_kunit(test, parent_hw, __func__); @@ -3016,18 +3020,19 @@ KUNIT_ARRAY_PARAM(clk_register_clk_parent_data_device_hw_test, */ static void clk_register_clk_parent_data_device_hw_test(struct kunit *test) { - struct clk_register_clk_parent_data_device_ctx *ctx; + struct device *dev; + struct clk_hw *hw; const struct clk_register_clk_parent_data_test_case *test_param; struct clk_dummy_context *parent; struct clk_hw *parent_hw; struct clk_parent_data pdata = { }; struct clk_init_data init = { }; + static const struct of_device_id match_table[] = { + { .compatible = "test,clk-parent-data" }, + { } + }; - ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); - test->priv = ctx; - - clk_register_clk_parent_data_device_driver(test); + dev = kunit_of_platform_driver_dev(test, match_table); parent = kunit_kzalloc(test, sizeof(*parent), GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); @@ -3036,7 +3041,10 @@ static void clk_register_clk_parent_data_device_hw_test(struct kunit *test) parent_hw->init = CLK_HW_INIT_NO_PARENT("parent-clk", &clk_dummy_rate_ops, 0); - KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, ctx->dev, parent_hw)); + KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, dev, parent_hw)); + + hw = kunit_kzalloc(test, sizeof(*hw), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); test_param = test->param_value; memcpy(&pdata, &test_param->pdata, sizeof(pdata)); @@ -3045,10 +3053,10 @@ static void clk_register_clk_parent_data_device_hw_test(struct kunit *test) init.num_parents = 1; init.ops = &clk_dummy_single_parent_ops; init.name = "parent_data_device_hw_test_clk"; - ctx->hw.init = &init; - KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, ctx->dev, &ctx->hw)); + hw->init = &init; + KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, dev, hw)); - KUNIT_EXPECT_PTR_EQ(test, parent_hw, clk_hw_get_parent(&ctx->hw)); + KUNIT_EXPECT_PTR_EQ(test, parent_hw, clk_hw_get_parent(hw)); } static struct kunit_case clk_register_clk_parent_data_device_test_cases[] = { @@ -3395,8 +3403,148 @@ static struct kunit_suite clk_assigned_rates_suite = { .init = clk_assigned_rates_test_init, }; +static const struct clk_init_data clk_hw_get_dev_of_node_init_data = { + .name = "clk_hw_get_dev_of_node", + .ops = &empty_clk_ops, +}; + +/* + * Test that a clk registered with a struct device returns the device from + * clk_hw_get_dev() and the node from clk_hw_get_of_node() + */ +static void clk_hw_register_dev_get_dev_returns_dev(struct kunit *test) +{ + struct device *dev; + struct clk_hw *hw; + static const struct of_device_id match_table[] = { + { .compatible = "test,clk-hw-get-dev-of-node" }, + { } + }; + + KUNIT_ASSERT_EQ(test, 0, of_overlay_apply_kunit(test, kunit_clk_hw_get_dev_of_node)); + + dev = kunit_of_platform_driver_dev(test, match_table); + + hw = kunit_kzalloc(test, sizeof(*hw), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + + hw->init = &clk_hw_get_dev_of_node_init_data; + KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, dev, hw)); + + KUNIT_EXPECT_PTR_EQ(test, dev, clk_hw_get_dev(hw)); + KUNIT_EXPECT_PTR_EQ(test, dev_of_node(dev), clk_hw_get_of_node(hw)); +} + +/* + * Test that a clk registered with a struct device that's not associated with + * an OF node returns the device from clk_hw_get_dev() and NULL from + * clk_hw_get_of_node() + */ +static void clk_hw_register_dev_no_node_get_dev_returns_dev(struct kunit *test) +{ + struct platform_device *pdev; + struct device *dev; + struct clk_hw *hw; + + pdev = kunit_platform_device_alloc(test, "clk_hw_register_dev_no_node", -1); + KUNIT_ASSERT_NOT_NULL(test, pdev); + KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(test, pdev)); + dev = &pdev->dev; + + hw = kunit_kzalloc(test, sizeof(*hw), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + + hw->init = &clk_hw_get_dev_of_node_init_data; + KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, dev, hw)); + + KUNIT_EXPECT_PTR_EQ(test, dev, clk_hw_get_dev(hw)); + KUNIT_EXPECT_PTR_EQ(test, NULL, clk_hw_get_of_node(hw)); +} + +/* + * Test that a clk registered without a struct device returns NULL from + * clk_hw_get_dev() + */ +static void clk_hw_register_NULL_get_dev_of_node_returns_NULL(struct kunit *test) +{ + struct clk_hw *hw; + + hw = kunit_kzalloc(test, sizeof(*hw), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + + hw->init = &clk_hw_get_dev_of_node_init_data; + + KUNIT_ASSERT_EQ(test, 0, clk_hw_register_kunit(test, NULL, hw)); + + KUNIT_EXPECT_PTR_EQ(test, NULL, clk_hw_get_dev(hw)); + KUNIT_EXPECT_PTR_EQ(test, NULL, clk_hw_get_of_node(hw)); +} + +/* + * Test that a clk registered with an of_node returns the node from + * clk_hw_get_of_node() and NULL from clk_hw_get_dev() + */ +static void of_clk_hw_register_node_get_of_node_returns_node(struct kunit *test) +{ + struct device_node *np; + struct clk_hw *hw; + + hw = kunit_kzalloc(test, sizeof(*hw), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + + KUNIT_ASSERT_EQ(test, 0, of_overlay_apply_kunit(test, kunit_clk_hw_get_dev_of_node)); + + np = of_find_compatible_node(NULL, NULL, "test,clk-hw-get-dev-of-node"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np); + of_node_put_kunit(test, np); + + hw->init = &clk_hw_get_dev_of_node_init_data; + KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, np, hw)); + + KUNIT_EXPECT_PTR_EQ(test, NULL, clk_hw_get_dev(hw)); + KUNIT_EXPECT_PTR_EQ(test, np, clk_hw_get_of_node(hw)); +} + +/* + * Test that a clk registered without an of_node returns the node from + * clk_hw_get_of_node() and clk_hw_get_dev() + */ +static void of_clk_hw_register_NULL_get_of_node_returns_NULL(struct kunit *test) +{ + struct clk_hw *hw; + + hw = kunit_kzalloc(test, sizeof(*hw), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + + hw->init = &clk_hw_get_dev_of_node_init_data; + KUNIT_ASSERT_EQ(test, 0, of_clk_hw_register_kunit(test, NULL, hw)); + + KUNIT_EXPECT_PTR_EQ(test, NULL, clk_hw_get_dev(hw)); + KUNIT_EXPECT_PTR_EQ(test, NULL, clk_hw_get_of_node(hw)); +} + +static struct kunit_case clk_hw_get_dev_of_node_test_cases[] = { + KUNIT_CASE(clk_hw_register_dev_get_dev_returns_dev), + KUNIT_CASE(clk_hw_register_dev_no_node_get_dev_returns_dev), + KUNIT_CASE(clk_hw_register_NULL_get_dev_of_node_returns_NULL), + KUNIT_CASE(of_clk_hw_register_node_get_of_node_returns_node), + KUNIT_CASE(of_clk_hw_register_NULL_get_of_node_returns_NULL), + {} +}; + +/* + * Test suite to verify clk_hw_get_dev() and clk_hw_get_of_node() when clk + * registered with clk_hw_register() and of_clk_hw_register() + */ +static struct kunit_suite clk_hw_get_dev_of_node_test_suite = { + .name = "clk_hw_get_dev_of_node_test_suite", + .test_cases = clk_hw_get_dev_of_node_test_cases, +}; + + kunit_test_suites( &clk_assigned_rates_suite, + &clk_hw_get_dev_of_node_test_suite, &clk_leaf_mux_set_rate_parent_test_suite, &clk_test_suite, &clk_multiple_parents_mux_test_suite, diff --git a/drivers/clk/davinci/pll.h b/drivers/clk/davinci/pll.h index 20bfcec2d3b5..ad286ba4ce0c 100644 --- a/drivers/clk/davinci/pll.h +++ b/drivers/clk/davinci/pll.h @@ -80,7 +80,7 @@ static const struct davinci_pll_sysclk_info n = { \ * @name: The name of the clock * @parent_names: Array of names of the parent clocks * @num_parents: Length of @parent_names - * @table: Array of values to write to OCSEL[OCSRC] cooresponding to + * @table: Array of values to write to OCSEL[OCSRC] corresponding to * @parent_names * @ocsrc_mask: Bitmask for OCSEL[OCSRC] */ diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c index b48322176c21..f3ee9397bb0c 100644 --- a/drivers/clk/davinci/psc.c +++ b/drivers/clk/davinci/psc.c @@ -277,6 +277,11 @@ davinci_lpsc_clk_register(struct device *dev, const char *name, lpsc->pm_domain.name = devm_kasprintf(dev, GFP_KERNEL, "%s: %s", best_dev_name(dev), name); + if (!lpsc->pm_domain.name) { + clk_hw_unregister(&lpsc->hw); + kfree(lpsc); + return ERR_PTR(-ENOMEM); + } lpsc->pm_domain.attach_dev = davinci_psc_genpd_attach_dev; lpsc->pm_domain.detach_dev = davinci_psc_genpd_detach_dev; lpsc->pm_domain.flags = GENPD_FLAG_PM_CLK; diff --git a/drivers/clk/hisilicon/clkgate-separated.c b/drivers/clk/hisilicon/clkgate-separated.c index 90d858522967..21d4297f3225 100644 --- a/drivers/clk/hisilicon/clkgate-separated.c +++ b/drivers/clk/hisilicon/clkgate-separated.c @@ -17,9 +17,9 @@ #include "clk.h" /* clock separated gate register offset */ -#define CLKGATE_SEPERATED_ENABLE 0x0 -#define CLKGATE_SEPERATED_DISABLE 0x4 -#define CLKGATE_SEPERATED_STATUS 0x8 +#define CLKGATE_SEPARATED_ENABLE 0x0 +#define CLKGATE_SEPARATED_DISABLE 0x4 +#define CLKGATE_SEPARATED_STATUS 0x8 struct clkgate_separated { struct clk_hw hw; @@ -40,7 +40,7 @@ static int clkgate_separated_enable(struct clk_hw *hw) spin_lock_irqsave(sclk->lock, flags); reg = BIT(sclk->bit_idx); writel_relaxed(reg, sclk->enable); - readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS); + readl_relaxed(sclk->enable + CLKGATE_SEPARATED_STATUS); if (sclk->lock) spin_unlock_irqrestore(sclk->lock, flags); return 0; @@ -56,8 +56,8 @@ static void clkgate_separated_disable(struct clk_hw *hw) if (sclk->lock) spin_lock_irqsave(sclk->lock, flags); reg = BIT(sclk->bit_idx); - writel_relaxed(reg, sclk->enable + CLKGATE_SEPERATED_DISABLE); - readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS); + writel_relaxed(reg, sclk->enable + CLKGATE_SEPARATED_DISABLE); + readl_relaxed(sclk->enable + CLKGATE_SEPARATED_STATUS); if (sclk->lock) spin_unlock_irqrestore(sclk->lock, flags); } @@ -68,7 +68,7 @@ static int clkgate_separated_is_enabled(struct clk_hw *hw) u32 reg; sclk = container_of(hw, struct clkgate_separated, hw); - reg = readl_relaxed(sclk->enable + CLKGATE_SEPERATED_STATUS); + reg = readl_relaxed(sclk->enable + CLKGATE_SEPARATED_STATUS); reg &= BIT(sclk->bit_idx); return reg ? 1 : 0; @@ -100,7 +100,7 @@ struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name, init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); - sclk->enable = reg + CLKGATE_SEPERATED_ENABLE; + sclk->enable = reg + CLKGATE_SEPARATED_ENABLE; sclk->bit_idx = bit_idx; sclk->flags = clk_gate_flags; sclk->hw.init = &init; diff --git a/drivers/clk/imx/clk-busy.c b/drivers/clk/imx/clk-busy.c index f163df952ccc..eb27c6fee359 100644 --- a/drivers/clk/imx/clk-busy.c +++ b/drivers/clk/imx/clk-busy.c @@ -46,12 +46,12 @@ static unsigned long clk_busy_divider_recalc_rate(struct clk_hw *hw, return busy->div_ops->recalc_rate(&busy->div.hw, parent_rate); } -static long clk_busy_divider_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_busy_divider_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_busy_divider *busy = to_clk_busy_divider(hw); - return busy->div_ops->round_rate(&busy->div.hw, rate, prate); + return busy->div_ops->determine_rate(&busy->div.hw, req); } static int clk_busy_divider_set_rate(struct clk_hw *hw, unsigned long rate, @@ -69,7 +69,7 @@ static int clk_busy_divider_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_busy_divider_ops = { .recalc_rate = clk_busy_divider_recalc_rate, - .round_rate = clk_busy_divider_round_rate, + .determine_rate = clk_busy_divider_determine_rate, .set_rate = clk_busy_divider_set_rate, }; diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c index f187582ba491..1467d0a1b934 100644 --- a/drivers/clk/imx/clk-composite-8m.c +++ b/drivers/clk/imx/clk-composite-8m.c @@ -73,21 +73,6 @@ static int imx8m_clk_composite_compute_dividers(unsigned long rate, return ret; } -static long imx8m_clk_composite_divider_round_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long *prate) -{ - int prediv_value; - int div_value; - - imx8m_clk_composite_compute_dividers(rate, *prate, - &prediv_value, &div_value); - rate = DIV_ROUND_UP(*prate, prediv_value); - - return DIV_ROUND_UP(rate, div_value); - -} - static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) @@ -153,7 +138,6 @@ static int imx8m_divider_determine_rate(struct clk_hw *hw, static const struct clk_ops imx8m_clk_composite_divider_ops = { .recalc_rate = imx8m_clk_composite_divider_recalc_rate, - .round_rate = imx8m_clk_composite_divider_round_rate, .set_rate = imx8m_clk_composite_divider_set_rate, .determine_rate = imx8m_divider_determine_rate, }; diff --git a/drivers/clk/imx/clk-composite-93.c b/drivers/clk/imx/clk-composite-93.c index 6c6c5a30f328..513d74a39d3b 100644 --- a/drivers/clk/imx/clk-composite-93.c +++ b/drivers/clk/imx/clk-composite-93.c @@ -98,12 +98,6 @@ imx93_clk_composite_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_ return clk_divider_ops.recalc_rate(hw, parent_rate); } -static long -imx93_clk_composite_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) -{ - return clk_divider_ops.round_rate(hw, rate, prate); -} - static int imx93_clk_composite_divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { @@ -141,7 +135,6 @@ static int imx93_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned long static const struct clk_ops imx93_clk_composite_divider_ops = { .recalc_rate = imx93_clk_composite_divider_recalc_rate, - .round_rate = imx93_clk_composite_divider_round_rate, .determine_rate = imx93_clk_composite_divider_determine_rate, .set_rate = imx93_clk_composite_divider_set_rate, }; diff --git a/drivers/clk/imx/clk-cpu.c b/drivers/clk/imx/clk-cpu.c index cb6ca4cf0535..43637cb61693 100644 --- a/drivers/clk/imx/clk-cpu.c +++ b/drivers/clk/imx/clk-cpu.c @@ -30,12 +30,14 @@ static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw, return clk_get_rate(cpu->div); } -static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_cpu_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_cpu *cpu = to_clk_cpu(hw); - return clk_round_rate(cpu->pll, rate); + req->rate = clk_round_rate(cpu->pll, req->rate); + + return 0; } static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate, @@ -66,7 +68,7 @@ static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_cpu_ops = { .recalc_rate = clk_cpu_recalc_rate, - .round_rate = clk_cpu_round_rate, + .determine_rate = clk_cpu_determine_rate, .set_rate = clk_cpu_set_rate, }; diff --git a/drivers/clk/imx/clk-fixup-div.c b/drivers/clk/imx/clk-fixup-div.c index 100ca828b052..aa6addbeb5a8 100644 --- a/drivers/clk/imx/clk-fixup-div.c +++ b/drivers/clk/imx/clk-fixup-div.c @@ -18,7 +18,7 @@ * @fixup: a hook to fixup the write value * * The imx fixup divider clock is a subclass of basic clk_divider - * with an addtional fixup hook. + * with an additional fixup hook. */ struct clk_fixup_div { struct clk_divider divider; @@ -41,12 +41,12 @@ static unsigned long clk_fixup_div_recalc_rate(struct clk_hw *hw, return fixup_div->ops->recalc_rate(&fixup_div->divider.hw, parent_rate); } -static long clk_fixup_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_fixup_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_fixup_div *fixup_div = to_clk_fixup_div(hw); - return fixup_div->ops->round_rate(&fixup_div->divider.hw, rate, prate); + return fixup_div->ops->determine_rate(&fixup_div->divider.hw, req); } static int clk_fixup_div_set_rate(struct clk_hw *hw, unsigned long rate, @@ -81,7 +81,7 @@ static int clk_fixup_div_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_fixup_div_ops = { .recalc_rate = clk_fixup_div_recalc_rate, - .round_rate = clk_fixup_div_round_rate, + .determine_rate = clk_fixup_div_determine_rate, .set_rate = clk_fixup_div_set_rate, }; diff --git a/drivers/clk/imx/clk-fixup-mux.c b/drivers/clk/imx/clk-fixup-mux.c index b48701864ef0..418ac9fe2c26 100644 --- a/drivers/clk/imx/clk-fixup-mux.c +++ b/drivers/clk/imx/clk-fixup-mux.c @@ -17,7 +17,7 @@ * @fixup: a hook to fixup the write value * * The imx fixup multiplexer clock is a subclass of basic clk_mux - * with an addtional fixup hook. + * with an additional fixup hook. */ struct clk_fixup_mux { struct clk_mux mux; diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c index c703056fae85..eb668faaa38f 100644 --- a/drivers/clk/imx/clk-frac-pll.c +++ b/drivers/clk/imx/clk-frac-pll.c @@ -119,19 +119,19 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, return rate; } -static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - u64 parent_rate = *prate; + u64 parent_rate = req->best_parent_rate; u32 divff, divfi; u64 temp64; parent_rate *= 8; - rate *= 2; - temp64 = rate; + req->rate *= 2; + temp64 = req->rate; do_div(temp64, parent_rate); divfi = temp64; - temp64 = rate - divfi * parent_rate; + temp64 = req->rate - divfi * parent_rate; temp64 *= PLL_FRAC_DENOM; do_div(temp64, parent_rate); divff = temp64; @@ -140,9 +140,11 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, temp64 *= divff; do_div(temp64, PLL_FRAC_DENOM); - rate = parent_rate * divfi + temp64; + req->rate = parent_rate * divfi + temp64; + + req->rate = req->rate / 2; - return rate / 2; + return 0; } /* @@ -198,7 +200,7 @@ static const struct clk_ops clk_frac_pll_ops = { .unprepare = clk_pll_unprepare, .is_prepared = clk_pll_is_prepared, .recalc_rate = clk_pll_recalc_rate, - .round_rate = clk_pll_round_rate, + .determine_rate = clk_pll_determine_rate, .set_rate = clk_pll_set_rate, }; diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c index 85771afd4698..090d60867250 100644 --- a/drivers/clk/imx/clk-fracn-gppll.c +++ b/drivers/clk/imx/clk-fracn-gppll.c @@ -134,8 +134,8 @@ imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate) return NULL; } -static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_fracn_gppll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; @@ -143,11 +143,16 @@ static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate, /* Assuming rate_table is in descending order */ for (i = 0; i < pll->rate_count; i++) - if (rate >= rate_table[i].rate) - return rate_table[i].rate; + if (req->rate >= rate_table[i].rate) { + req->rate = rate_table[i].rate; + + return 0; + } /* return minimum supported value */ - return rate_table[pll->rate_count - 1].rate; + req->rate = rate_table[pll->rate_count - 1].rate; + + return 0; } static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -345,7 +350,7 @@ static const struct clk_ops clk_fracn_gppll_ops = { .unprepare = clk_fracn_gppll_unprepare, .is_prepared = clk_fracn_gppll_is_prepared, .recalc_rate = clk_fracn_gppll_recalc_rate, - .round_rate = clk_fracn_gppll_round_rate, + .determine_rate = clk_fracn_gppll_determine_rate, .set_rate = clk_fracn_gppll_set_rate, }; diff --git a/drivers/clk/imx/clk-gate-exclusive.c b/drivers/clk/imx/clk-gate-exclusive.c index 77342893bb71..7017e9d4e188 100644 --- a/drivers/clk/imx/clk-gate-exclusive.c +++ b/drivers/clk/imx/clk-gate-exclusive.c @@ -18,7 +18,7 @@ * gate clock * * The imx exclusive gate clock is a subclass of basic clk_gate - * with an addtional mask to indicate which other gate bits in the same + * with an additional mask to indicate which other gate bits in the same * register is mutually exclusive to this gate clock. */ struct clk_gate_exclusive { diff --git a/drivers/clk/imx/clk-imx5.c b/drivers/clk/imx/clk-imx5.c index b82044911603..9c5f489b3975 100644 --- a/drivers/clk/imx/clk-imx5.c +++ b/drivers/clk/imx/clk-imx5.c @@ -454,7 +454,7 @@ static void __init mx51_clocks_init(struct device_node *np) * longer supported. Set to one for better power saving. * * The effect of not setting these bits is that MIPI clocks can't be - * enabled without the IPU clock being enabled aswell. + * enabled without the IPU clock being enabled as well. */ val = readl(MXC_CCM_CCDR); val |= 1 << 18; diff --git a/drivers/clk/imx/clk-imx8-acm.c b/drivers/clk/imx/clk-imx8-acm.c index c169fe53a35f..790f7e44b11e 100644 --- a/drivers/clk/imx/clk-imx8-acm.c +++ b/drivers/clk/imx/clk-imx8-acm.c @@ -22,7 +22,7 @@ * struct clk_imx_acm_pm_domains - structure for multi power domain * @pd_dev: power domain device * @pd_dev_link: power domain device link - * @num_domains: power domain nummber + * @num_domains: power domain number */ struct clk_imx_acm_pm_domains { struct device **pd_dev; diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c index 5cf0149dfa15..31220fa7882b 100644 --- a/drivers/clk/imx/clk-pfd.c +++ b/drivers/clk/imx/clk-pfd.c @@ -62,24 +62,26 @@ static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw, return tmp; } -static long clk_pfd_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pfd_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - u64 tmp = *prate; + u64 tmp = req->best_parent_rate; u8 frac; - tmp = tmp * 18 + rate / 2; - do_div(tmp, rate); + tmp = tmp * 18 + req->rate / 2; + do_div(tmp, req->rate); frac = tmp; if (frac < 12) frac = 12; else if (frac > 35) frac = 35; - tmp = *prate; + tmp = req->best_parent_rate; tmp *= 18; do_div(tmp, frac); - return tmp; + req->rate = tmp; + + return 0; } static int clk_pfd_set_rate(struct clk_hw *hw, unsigned long rate, @@ -117,7 +119,7 @@ static const struct clk_ops clk_pfd_ops = { .enable = clk_pfd_enable, .disable = clk_pfd_disable, .recalc_rate = clk_pfd_recalc_rate, - .round_rate = clk_pfd_round_rate, + .determine_rate = clk_pfd_determine_rate, .set_rate = clk_pfd_set_rate, .is_enabled = clk_pfd_is_enabled, }; diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index f290981ea13b..36d0e80b55b8 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -216,8 +216,8 @@ found: t->mdiv, t->kdiv); } -static long clk_pll1416x_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pll1416x_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_pll14xx *pll = to_clk_pll14xx(hw); const struct imx_pll14xx_rate_table *rate_table = pll->rate_table; @@ -225,22 +225,29 @@ static long clk_pll1416x_round_rate(struct clk_hw *hw, unsigned long rate, /* Assuming rate_table is in descending order */ for (i = 0; i < pll->rate_count; i++) - if (rate >= rate_table[i].rate) - return rate_table[i].rate; + if (req->rate >= rate_table[i].rate) { + req->rate = rate_table[i].rate; + + return 0; + } /* return minimum supported value */ - return rate_table[pll->rate_count - 1].rate; + req->rate = rate_table[pll->rate_count - 1].rate; + + return 0; } -static long clk_pll1443x_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pll1443x_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_pll14xx *pll = to_clk_pll14xx(hw); struct imx_pll14xx_rate_table t; - imx_pll14xx_calc_settings(pll, rate, *prate, &t); + imx_pll14xx_calc_settings(pll, req->rate, req->best_parent_rate, &t); + + req->rate = t.rate; - return t.rate; + return 0; } static unsigned long clk_pll14xx_recalc_rate(struct clk_hw *hw, @@ -470,7 +477,7 @@ static const struct clk_ops clk_pll1416x_ops = { .unprepare = clk_pll14xx_unprepare, .is_prepared = clk_pll14xx_is_prepared, .recalc_rate = clk_pll14xx_recalc_rate, - .round_rate = clk_pll1416x_round_rate, + .determine_rate = clk_pll1416x_determine_rate, .set_rate = clk_pll1416x_set_rate, }; @@ -483,7 +490,7 @@ static const struct clk_ops clk_pll1443x_ops = { .unprepare = clk_pll14xx_unprepare, .is_prepared = clk_pll14xx_is_prepared, .recalc_rate = clk_pll14xx_recalc_rate, - .round_rate = clk_pll1443x_round_rate, + .determine_rate = clk_pll1443x_determine_rate, .set_rate = clk_pll1443x_set_rate, }; diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c index ff17f0664faa..bb497ad5e0ae 100644 --- a/drivers/clk/imx/clk-pllv2.c +++ b/drivers/clk/imx/clk-pllv2.c @@ -178,18 +178,25 @@ static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } -static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pllv2_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { u32 dp_op, dp_mfd, dp_mfn; int ret; - ret = __clk_pllv2_set_rate(rate, *prate, &dp_op, &dp_mfd, &dp_mfn); - if (ret) - return ret; + ret = __clk_pllv2_set_rate(req->rate, req->best_parent_rate, &dp_op, + &dp_mfd, &dp_mfn); + if (ret) { + req->rate = ret; - return __clk_pllv2_recalc_rate(*prate, MXC_PLL_DP_CTL_DPDCK0_2_EN, - dp_op, dp_mfd, dp_mfn); + return 0; + } + + req->rate = __clk_pllv2_recalc_rate(req->best_parent_rate, + MXC_PLL_DP_CTL_DPDCK0_2_EN, dp_op, + dp_mfd, dp_mfn); + + return 0; } static int clk_pllv2_prepare(struct clk_hw *hw) @@ -235,7 +242,7 @@ static const struct clk_ops clk_pllv2_ops = { .prepare = clk_pllv2_prepare, .unprepare = clk_pllv2_unprepare, .recalc_rate = clk_pllv2_recalc_rate, - .round_rate = clk_pllv2_round_rate, + .determine_rate = clk_pllv2_determine_rate, .set_rate = clk_pllv2_set_rate, }; diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 11fb238ee8f0..b99508367bcb 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -117,13 +117,14 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, return (div == 1) ? parent_rate * 22 : parent_rate * 20; } -static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pllv3_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned long parent_rate = *prate; + unsigned long parent_rate = req->best_parent_rate; - return (rate >= parent_rate * 22) ? parent_rate * 22 : - parent_rate * 20; + req->rate = (req->rate >= parent_rate * 22) ? parent_rate * 22 : parent_rate * 20; + + return 0; } static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate, @@ -152,7 +153,7 @@ static const struct clk_ops clk_pllv3_ops = { .unprepare = clk_pllv3_unprepare, .is_prepared = clk_pllv3_is_prepared, .recalc_rate = clk_pllv3_recalc_rate, - .round_rate = clk_pllv3_round_rate, + .determine_rate = clk_pllv3_determine_rate, .set_rate = clk_pllv3_set_rate, }; @@ -165,21 +166,23 @@ static unsigned long clk_pllv3_sys_recalc_rate(struct clk_hw *hw, return parent_rate * div / 2; } -static long clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pllv3_sys_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned long parent_rate = *prate; + unsigned long parent_rate = req->best_parent_rate; unsigned long min_rate = parent_rate * 54 / 2; unsigned long max_rate = parent_rate * 108 / 2; u32 div; - if (rate > max_rate) - rate = max_rate; - else if (rate < min_rate) - rate = min_rate; - div = rate * 2 / parent_rate; + if (req->rate > max_rate) + req->rate = max_rate; + else if (req->rate < min_rate) + req->rate = min_rate; + div = req->rate * 2 / parent_rate; - return parent_rate * div / 2; + req->rate = parent_rate * div / 2; + + return 0; } static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate, @@ -207,7 +210,7 @@ static const struct clk_ops clk_pllv3_sys_ops = { .unprepare = clk_pllv3_unprepare, .is_prepared = clk_pllv3_is_prepared, .recalc_rate = clk_pllv3_sys_recalc_rate, - .round_rate = clk_pllv3_sys_round_rate, + .determine_rate = clk_pllv3_sys_determine_rate, .set_rate = clk_pllv3_sys_set_rate, }; @@ -226,10 +229,10 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw, return parent_rate * div + (unsigned long)temp64; } -static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pllv3_av_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned long parent_rate = *prate; + unsigned long parent_rate = req->best_parent_rate; unsigned long min_rate = parent_rate * 27; unsigned long max_rate = parent_rate * 54; u32 div; @@ -237,16 +240,16 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, u32 max_mfd = 0x3FFFFFFF; u64 temp64; - if (rate > max_rate) - rate = max_rate; - else if (rate < min_rate) - rate = min_rate; + if (req->rate > max_rate) + req->rate = max_rate; + else if (req->rate < min_rate) + req->rate = min_rate; if (parent_rate <= max_mfd) mfd = parent_rate; - div = rate / parent_rate; - temp64 = (u64) (rate - div * parent_rate); + div = req->rate / parent_rate; + temp64 = (u64) (req->rate - div * parent_rate); temp64 *= mfd; temp64 = div64_ul(temp64, parent_rate); mfn = temp64; @@ -255,7 +258,9 @@ static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate, temp64 *= mfn; do_div(temp64, mfd); - return parent_rate * div + (unsigned long)temp64; + req->rate = parent_rate * div + (unsigned long)temp64; + + return 0; } static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate, @@ -296,7 +301,7 @@ static const struct clk_ops clk_pllv3_av_ops = { .unprepare = clk_pllv3_unprepare, .is_prepared = clk_pllv3_is_prepared, .recalc_rate = clk_pllv3_av_recalc_rate, - .round_rate = clk_pllv3_av_round_rate, + .determine_rate = clk_pllv3_av_determine_rate, .set_rate = clk_pllv3_av_set_rate, }; @@ -355,12 +360,15 @@ static unsigned long clk_pllv3_vf610_recalc_rate(struct clk_hw *hw, return clk_pllv3_vf610_mf_to_rate(parent_rate, mf); } -static long clk_pllv3_vf610_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pllv3_vf610_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - struct clk_pllv3_vf610_mf mf = clk_pllv3_vf610_rate_to_mf(*prate, rate); + struct clk_pllv3_vf610_mf mf = clk_pllv3_vf610_rate_to_mf(req->best_parent_rate, + req->rate); + + req->rate = clk_pllv3_vf610_mf_to_rate(req->best_parent_rate, mf); - return clk_pllv3_vf610_mf_to_rate(*prate, mf); + return 0; } static int clk_pllv3_vf610_set_rate(struct clk_hw *hw, unsigned long rate, @@ -389,7 +397,7 @@ static const struct clk_ops clk_pllv3_vf610_ops = { .unprepare = clk_pllv3_unprepare, .is_prepared = clk_pllv3_is_prepared, .recalc_rate = clk_pllv3_vf610_recalc_rate, - .round_rate = clk_pllv3_vf610_round_rate, + .determine_rate = clk_pllv3_vf610_determine_rate, .set_rate = clk_pllv3_vf610_set_rate, }; diff --git a/drivers/clk/imx/clk-pllv4.c b/drivers/clk/imx/clk-pllv4.c index 9b136c951762..01d05b5d5438 100644 --- a/drivers/clk/imx/clk-pllv4.c +++ b/drivers/clk/imx/clk-pllv4.c @@ -95,11 +95,11 @@ static unsigned long clk_pllv4_recalc_rate(struct clk_hw *hw, return (parent_rate * mult) + (u32)temp64; } -static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_pllv4_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_pllv4 *pll = to_clk_pllv4(hw); - unsigned long parent_rate = *prate; + unsigned long parent_rate = req->best_parent_rate; unsigned long round_rate, i; u32 mfn, mfd = DEFAULT_MFD; bool found = false; @@ -107,7 +107,7 @@ static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate, u32 mult; if (pll->use_mult_range) { - temp64 = (u64)rate; + temp64 = (u64) req->rate; do_div(temp64, parent_rate); mult = temp64; if (mult >= pllv4_mult_range[1] && @@ -118,7 +118,7 @@ static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate, } else { for (i = 0; i < ARRAY_SIZE(pllv4_mult_table); i++) { round_rate = parent_rate * pllv4_mult_table[i]; - if (rate >= round_rate) { + if (req->rate >= round_rate) { found = true; break; } @@ -127,14 +127,16 @@ static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate, if (!found) { pr_warn("%s: unable to round rate %lu, parent rate %lu\n", - clk_hw_get_name(hw), rate, parent_rate); + clk_hw_get_name(hw), req->rate, parent_rate); + req->rate = 0; + return 0; } if (parent_rate <= MAX_MFD) mfd = parent_rate; - temp64 = (u64)(rate - round_rate); + temp64 = (u64)(req->rate - round_rate); temp64 *= mfd; do_div(temp64, parent_rate); mfn = temp64; @@ -145,14 +147,19 @@ static long clk_pllv4_round_rate(struct clk_hw *hw, unsigned long rate, * pair of mfn/mfd, we simply return the round_rate without using * the frac part. */ - if (mfn >= mfd) - return round_rate; + if (mfn >= mfd) { + req->rate = round_rate; + + return 0; + } temp64 = (u64)parent_rate; temp64 *= mfn; do_div(temp64, mfd); - return round_rate + (u32)temp64; + req->rate = round_rate + (u32)temp64; + + return 0; } static bool clk_pllv4_is_valid_mult(struct clk_pllv4 *pll, unsigned int mult) @@ -229,7 +236,7 @@ static void clk_pllv4_unprepare(struct clk_hw *hw) static const struct clk_ops clk_pllv4_ops = { .recalc_rate = clk_pllv4_recalc_rate, - .round_rate = clk_pllv4_round_rate, + .determine_rate = clk_pllv4_determine_rate, .set_rate = clk_pllv4_set_rate, .prepare = clk_pllv4_prepare, .unprepare = clk_pllv4_unprepare, diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index b27186aaf2a1..6aa8cc939028 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -269,24 +269,6 @@ static int clk_scu_determine_rate(struct clk_hw *hw, return 0; } -/* - * clk_scu_round_rate - Round clock rate for a SCU clock - * @hw: clock to round rate for - * @rate: rate to round - * @parent_rate: parent rate provided by common clock framework, not used - * - * Returns the current clock rate, or zero in failure. - */ -static long clk_scu_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - /* - * Assume we support all the requested rate and let the SCU firmware - * to handle the left work - */ - return rate; -} - static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -454,7 +436,7 @@ static const struct clk_ops clk_scu_ops = { static const struct clk_ops clk_scu_cpu_ops = { .recalc_rate = clk_scu_recalc_rate, - .round_rate = clk_scu_round_rate, + .determine_rate = clk_scu_determine_rate, .set_rate = clk_scu_atf_set_cpu_rate, .prepare = clk_scu_prepare, .unprepare = clk_scu_unprepare, @@ -462,7 +444,7 @@ static const struct clk_ops clk_scu_cpu_ops = { static const struct clk_ops clk_scu_pi_ops = { .recalc_rate = clk_scu_recalc_rate, - .round_rate = clk_scu_round_rate, + .determine_rate = clk_scu_determine_rate, .set_rate = clk_scu_set_rate, }; @@ -729,7 +711,7 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, if (ret) goto put_device; - /* For API backwards compatiblilty, simply return NULL for success */ + /* For API backwards compatibility, simply return NULL for success */ return NULL; put_device: @@ -766,15 +748,15 @@ static unsigned long clk_gpr_div_scu_recalc_rate(struct clk_hw *hw, return err ? 0 : rate; } -static long clk_gpr_div_scu_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int clk_gpr_div_scu_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - if (rate < *prate) - rate = *prate / 2; + if (req->rate < req->best_parent_rate) + req->rate = req->best_parent_rate / 2; else - rate = *prate; + req->rate = req->best_parent_rate; - return rate; + return 0; } static int clk_gpr_div_scu_set_rate(struct clk_hw *hw, unsigned long rate, @@ -793,7 +775,7 @@ static int clk_gpr_div_scu_set_rate(struct clk_hw *hw, unsigned long rate, static const struct clk_ops clk_gpr_div_scu_ops = { .recalc_rate = clk_gpr_div_scu_recalc_rate, - .round_rate = clk_gpr_div_scu_round_rate, + .determine_rate = clk_gpr_div_scu_determine_rate, .set_rate = clk_gpr_div_scu_set_rate, }; diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h index 99da9bd86e63..0d417d69dab7 100644 --- a/drivers/clk/ingenic/cgu.h +++ b/drivers/clk/ingenic/cgu.h @@ -239,7 +239,7 @@ ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info, * * Register the clocks described by the CGU with the common clock framework. * - * Return: 0 on success or -errno if unsuccesful. + * Return: 0 on success or -errno if unsuccessful. */ int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu); diff --git a/drivers/clk/kunit_clk_hw_get_dev_of_node.dtso b/drivers/clk/kunit_clk_hw_get_dev_of_node.dtso new file mode 100644 index 000000000000..760717da3235 --- /dev/null +++ b/drivers/clk/kunit_clk_hw_get_dev_of_node.dtso @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; +/plugin/; + +&{/} { + kunit-clock-controller { + compatible = "test,clk-hw-get-dev-of-node"; + #clock-cells = <0>; + }; +}; diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 448eece246ca..663de28e315b 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -918,7 +918,7 @@ static const struct clk_parent_data axg_sd_emmc_clk0_parent_data[] = { /* * Following these parent clocks, we should also have had mpll2, mpll3 * and gp0_pll but these clocks are too precious to be used here. All - * the necessary rates for MMC and NAND operation can be acheived using + * the necessary rates for MMC and NAND operation can be achieved using * xtal or fclk_div clocks */ }; diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index d9e546e006d7..72767bc44715 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -2489,7 +2489,7 @@ static const struct clk_parent_data g12a_sd_emmc_clk0_parent_data[] = { /* * Following these parent clocks, we should also have had mpll2, mpll3 * and gp0_pll but these clocks are too precious to be used here. All - * the necessary rates for MMC and NAND operation can be acheived using + * the necessary rates for MMC and NAND operation can be achieved using * g12a_ee_core or fclk_div clocks */ }; @@ -3753,8 +3753,8 @@ static struct clk_regmap g12a_mipi_dsi_pxclk_sel = { }; /* - * FIXME: Force as bypass by forcing a single /1 table entry, and doensn't on boot value - * when setting a clock whith this node in the clock path, but doesn't garantee the divider + * FIXME: Force as bypass by forcing a single /1 table entry, and doesn't on boot value + * when setting a clock with this node in the clock path, but doesn't guarantee the divider * is at /1 at boot until a rate is set. */ static const struct clk_div_table g12a_mipi_dsi_pxclk_div_table[] = { diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 3abb44a2532b..9fcf026fc491 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -1335,7 +1335,7 @@ static const struct clk_parent_data gxbb_sd_emmc_clk0_parent_data[] = { /* * Following these parent clocks, we should also have had mpll2, mpll3 * and gp0_pll but these clocks are too precious to be used here. All - * the necessary rates for MMC and NAND operation can be acheived using + * the necessary rates for MMC and NAND operation can be achieved using * xtal or fclk_div clocks */ }; diff --git a/drivers/clk/microchip/clk-core.c b/drivers/clk/microchip/clk-core.c index 1b4f023cdc8b..6fbc6dc50ca3 100644 --- a/drivers/clk/microchip/clk-core.c +++ b/drivers/clk/microchip/clk-core.c @@ -326,7 +326,7 @@ static void roclk_calc_div_trim(unsigned long rate, * i.e. fout = fin / 2 * DIV * whereas DIV = rodiv + (rotrim / 512) * - * Since kernel does not perform floating-point arithmatic so + * Since kernel does not perform floating-point arithmetic so * (rotrim/512) will be zero. And DIV & rodiv will result same. * * ie. fout = (fin * 256) / [(512 * rodiv) + rotrim] ... from (1) diff --git a/drivers/clk/mmp/clk-gate.c b/drivers/clk/mmp/clk-gate.c index 350eeb3e9e25..6855815ee8be 100644 --- a/drivers/clk/mmp/clk-gate.c +++ b/drivers/clk/mmp/clk-gate.c @@ -15,7 +15,7 @@ #include "clk.h" /* - * Some clocks will have mutiple bits to enable the clocks, and + * Some clocks will have multiple bits to enable the clocks, and * the bits to disable the clock is not same as enabling bits. */ diff --git a/drivers/clk/mvebu/armada-xp.c b/drivers/clk/mvebu/armada-xp.c index 45665655a258..8d31a595a27c 100644 --- a/drivers/clk/mvebu/armada-xp.c +++ b/drivers/clk/mvebu/armada-xp.c @@ -7,7 +7,6 @@ * Gregory CLEMENT <gregory.clement@free-electrons.com> * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> * Andrew Lunn <andrew@lunn.ch> - * */ #include <linux/kernel.h> @@ -19,8 +18,8 @@ /* * Core Clocks * - * Armada XP Sample At Reset is a 64 bit bitfiled split in two - * register of 32 bits + * Armada XP Sample At Reset is a 64 bit bitfield split in two + * registers of 32 bits */ #define SARL 0 /* Low part [0:31] */ diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c index 928e8b1c46a1..0a78ef380646 100644 --- a/drivers/clk/mxs/clk-div.c +++ b/drivers/clk/mxs/clk-div.c @@ -16,7 +16,7 @@ * @busy: busy bit shift * * The mxs divider clock is a subclass of basic clk_divider with an - * addtional busy bit. + * additional busy bit. */ struct clk_div { struct clk_divider divider; diff --git a/drivers/clk/nuvoton/Kconfig b/drivers/clk/nuvoton/Kconfig index fe4b7f62f467..e7019b69ea74 100644 --- a/drivers/clk/nuvoton/Kconfig +++ b/drivers/clk/nuvoton/Kconfig @@ -4,7 +4,7 @@ config COMMON_CLK_NUVOTON bool "Nuvoton clock controller common support" depends on ARCH_MA35 || COMPILE_TEST - default y + default ARCH_MA35 help Say y here to enable common clock controller for Nuvoton platforms. @@ -12,7 +12,7 @@ if COMMON_CLK_NUVOTON config CLK_MA35D1 bool "Nuvoton MA35D1 clock controller support" - default y + default ARCH_MA35 help Build the clock controller driver for MA35D1 SoC. diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c index ddb28b38f549..751b786d73f8 100644 --- a/drivers/clk/nxp/clk-lpc18xx-ccu.c +++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c @@ -148,7 +148,7 @@ static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable) val |= LPC18XX_CCU_RUN; } else { /* - * To safely disable a branch clock a squence of two separate + * To safely disable a branch clock a sequence of two separate * writes must be used. First write should set the AUTO bit * and the next write should clear the RUN bit. */ diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c index cefceb780889..a93d1f412a7b 100644 --- a/drivers/clk/qcom/gcc-sm8150.c +++ b/drivers/clk/qcom/gcc-sm8150.c @@ -1245,7 +1245,7 @@ static struct clk_branch gcc_boot_rom_ahb_clk = { }; /* - * Clock ON depends on external parent 'config noc', so cant poll + * Clock ON depends on external parent 'config noc', so can't poll * delay and also mark as crtitical for camss boot */ static struct clk_branch gcc_camera_ahb_clk = { @@ -1398,7 +1398,7 @@ static struct clk_branch gcc_ddrss_gpu_axi_clk = { }; /* - * Clock ON depends on external parent 'config noc', so cant poll + * Clock ON depends on external parent 'config noc', so can't poll * delay and also mark as crtitical for disp boot */ static struct clk_branch gcc_disp_ahb_clk = { @@ -3339,7 +3339,7 @@ static struct clk_branch gcc_usb3_sec_phy_pipe_clk = { }; /* - * Clock ON depends on external parent 'config noc', so cant poll + * Clock ON depends on external parent 'config noc', so can't poll * delay and also mark as crtitical for video boot */ static struct clk_branch gcc_video_ahb_clk = { diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 398a226ad34e..dcc9dcb597ae 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -16,14 +16,14 @@ * of the SoC or supplied after the SoC characterization. * * The below implementation of the CPU clock allows the rate changes of the CPU - * clock and the corresponding rate changes of the auxillary clocks of the CPU + * clock and the corresponding rate changes of the auxiliary clocks of the CPU * domain. The platform clock driver provides a clock register configuration * for each configurable rate which is then used to program the clock hardware - * registers to acheive a fast co-oridinated rate change for all the CPU domain + * registers to achieve a fast co-oridinated rate change for all the CPU domain * clocks. * * On a rate change request for the CPU clock, the rate change is propagated - * upto the PLL supplying the clock to the CPU domain clock blocks. While the + * up to the PLL supplying the clock to the CPU domain clock blocks. While the * CPU domain PLL is reconfigured, the CPU domain clocks are driven using an * alternate clock source. If required, the alternate clock source is divided * down in order to keep the output clock rate within the previous OPP limits. diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c index b3ed8e7523e5..8b1292c56863 100644 --- a/drivers/clk/rockchip/clk-mmc-phase.c +++ b/drivers/clk/rockchip/clk-mmc-phase.c @@ -174,11 +174,11 @@ static int rockchip_mmc_clk_rate_notify(struct notifier_block *nb, /* * rockchip_mmc_clk is mostly used by mmc controllers to sample - * the intput data, which expects the fixed phase after the tuning + * the input data, which expects the fixed phase after the tuning * process. However if the clock rate is changed, the phase is stale * and may break the data sampling. So here we try to restore the phase * for that case, except that - * (1) cached_phase is invaild since we inevitably cached it when the + * (1) cached_phase is invalid since we inevitably cached it when the * clock provider be reparented from orphan to its real parent in the * first place. Otherwise we may mess up the initialization of MMC cards * since we only set the default sample phase and drive phase later on. diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index af74439a7457..c9d599c31923 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -68,7 +68,7 @@ static long rockchip_pll_round_rate(struct clk_hw *hw, const struct rockchip_pll_rate_table *rate_table = pll->rate_table; int i; - /* Assumming rate_table is in descending order */ + /* Assuming rate_table is in descending order */ for (i = 0; i < pll->rate_count; i++) { if (drate >= rate_table[i].rate) return rate_table[i].rate; diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 1e9c3c0d31e3..7c5e74c7a2e2 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -532,7 +532,7 @@ struct rockchip_pll_rate_table { * * Flags: * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the - * rate_table parameters and ajust them if necessary. + * rate_table parameters and adjust them if necessary. * ROCKCHIP_PLL_FIXED_MODE - the pll operates in normal mode only */ struct rockchip_pll_clock { diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c index 97982662e1a6..4e1ebd8a30b1 100644 --- a/drivers/clk/samsung/clk-cpu.c +++ b/drivers/clk/samsung/clk-cpu.c @@ -243,7 +243,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata, if (cpuclk->flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV) { /* * In Exynos4210, ATB clock parent is also mout_core. So - * ATB clock also needs to be mantained at safe speed. + * ATB clock also needs to be maintained at safe speed. */ alt_div |= E4210_DIV0_ATB_MASK; alt_div_mask |= E4210_DIV0_ATB_MASK; diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index fe8abe442c51..e4faf02b631e 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -56,7 +56,7 @@ static long samsung_pll_round_rate(struct clk_hw *hw, const struct samsung_pll_rate_table *rate_table = pll->rate_table; int i; - /* Assumming rate_table is in descending order */ + /* Assuming rate_table is in descending order */ for (i = 0; i < pll->rate_count; i++) { if (drate >= rate_table[i].rate) return rate_table[i].rate; diff --git a/drivers/clk/sophgo/clk-sg2042-clkgen.c b/drivers/clk/sophgo/clk-sg2042-clkgen.c index a334963e83ce..9e61288d34f3 100644 --- a/drivers/clk/sophgo/clk-sg2042-clkgen.c +++ b/drivers/clk/sophgo/clk-sg2042-clkgen.c @@ -968,7 +968,7 @@ static int sg2042_mux_notifier_cb(struct notifier_block *nb, /* * "1" is the array index of the second parent input source of * mux. For SG2042, it's fpll for all mux clocks. - * "0" is the array index of the frist parent input source of + * "0" is the array index of the first parent input source of * mux, For SG2042, it's mpll. * FIXME, any good idea to avoid magic number? */ diff --git a/drivers/clk/sophgo/clk-sg2042-pll.c b/drivers/clk/sophgo/clk-sg2042-pll.c index 1537f4f05860..e5fb0bb7ac4f 100644 --- a/drivers/clk/sophgo/clk-sg2042-pll.c +++ b/drivers/clk/sophgo/clk-sg2042-pll.c @@ -155,7 +155,7 @@ static unsigned long sg2042_pll_recalc_rate(unsigned int reg_value, numerator = (u64)parent_rate * ctrl_table.fbdiv; denominator = ctrl_table.refdiv * ctrl_table.postdiv1 * ctrl_table.postdiv2; - do_div(numerator, denominator); + numerator = div64_u64(numerator, denominator); return numerator; } @@ -212,7 +212,7 @@ static int sg2042_pll_get_postdiv_1_2(unsigned long rate, tmp0 *= fbdiv; /* ((prate/REFDIV) x FBDIV)/rate and result save to tmp0 */ - do_div(tmp0, rate); + tmp0 = div64_ul(tmp0, rate); /* tmp0 is POSTDIV1*POSTDIV2, now we calculate div1 and div2 value */ if (tmp0 <= 7) { diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index 361d344bfaf0..fdfb26c67188 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c @@ -199,7 +199,7 @@ static struct frac_rate_tbl amba_synth_rtbl[] = { * We can program this synthesizer to make cpu run on different clock * frequencies. * Following table provides configuration values to let cpu run on 200, - * 250, 332, 400 or 500 MHz considering different possibilites of input + * 250, 332, 400 or 500 MHz considering different possibilities of input * (vco1div2) clock. * * -------------------------------------------------------------------- diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h index e738dafa4fe9..775519eb1cb6 100644 --- a/drivers/clk/sprd/gate.h +++ b/drivers/clk/sprd/gate.h @@ -26,7 +26,7 @@ struct sprd_gate { * CLK_GATE_BIG_ENDIAN BIT(2) * so we define new flags from BIT(3) */ -#define SPRD_GATE_NON_AON BIT(3) /* not alway powered on, check before read */ +#define SPRD_GATE_NON_AON BIT(3) /* not always powered on, check before read */ #define SPRD_SC_GATE_CLK_HW_INIT_FN(_struct, _name, _parent, _reg, \ _sc_offset, _enable_mask, _flags, \ diff --git a/drivers/clk/sprd/ums512-clk.c b/drivers/clk/sprd/ums512-clk.c index 9384ecc6c741..f763d83de9ee 100644 --- a/drivers/clk/sprd/ums512-clk.c +++ b/drivers/clk/sprd/ums512-clk.c @@ -1550,7 +1550,7 @@ static struct sprd_clk_desc ums512_aon_gate_desc = { /* audcp apb gates */ /* Audcp apb clocks configure CLK_IGNORE_UNUSED because these clocks may be - * controlled by audcp sys at the same time. It may be cause an execption if + * controlled by audcp sys at the same time. It may cause an exception if * kernel gates these clock. */ static SPRD_SC_GATE_CLK_HW(audcp_wdg_eb, "audcp-wdg-eb", @@ -1592,7 +1592,7 @@ static const struct sprd_clk_desc ums512_audcpapb_gate_desc = { /* audcp ahb gates */ /* Audcp aphb clocks configure CLK_IGNORE_UNUSED because these clocks may be - * controlled by audcp sys at the same time. It may be cause an execption if + * controlled by audcp sys at the same time. It may cause an exception if * kernel gates these clock. */ static SPRD_SC_GATE_CLK_HW(audcp_iis0_eb, "audcp-iis0-eb", diff --git a/drivers/clk/starfive/clk-starfive-jh7110-sys.c b/drivers/clk/starfive/clk-starfive-jh7110-sys.c index e9d8168d02b8..52833d4241c5 100644 --- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c +++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c @@ -376,7 +376,7 @@ EXPORT_SYMBOL_GPL(jh7110_reset_controller_register); /* * This clock notifier is called when the rate of PLL0 clock is to be changed. - * The cpu_root clock should save the curent parent clock and switch its parent + * The cpu_root clock should save the current parent clock and switch its parent * clock to osc before PLL0 rate will be changed. Then switch its parent clock * back after the PLL0 rate is completed. */ diff --git a/drivers/clk/stm32/Kconfig b/drivers/clk/stm32/Kconfig index dca409d52652..4d2eb993ea08 100644 --- a/drivers/clk/stm32/Kconfig +++ b/drivers/clk/stm32/Kconfig @@ -4,7 +4,7 @@ menuconfig COMMON_CLK_STM32MP bool "Clock support for common STM32MP clocks" depends on ARCH_STM32 || COMPILE_TEST - default y + default ARCH_STM32 select RESET_CONTROLLER help Support for STM32MP SoC family clocks. @@ -14,21 +14,21 @@ if COMMON_CLK_STM32MP config COMMON_CLK_STM32MP135 bool "Clock driver for stm32mp13x clocks" depends on ARM || COMPILE_TEST - default y + default ARCH_STM32 help Support for stm32mp13x SoC family clocks. config COMMON_CLK_STM32MP157 bool "Clock driver for stm32mp15x clocks" depends on ARM || COMPILE_TEST - default y + default ARCH_STM32 help Support for stm32mp15x SoC family clocks. config COMMON_CLK_STM32MP257 bool "Clock driver for stm32mp25x clocks" depends on ARM64 || COMPILE_TEST - default y + default ARCH_STM32 help Support for stm32mp25x SoC family clocks. diff --git a/drivers/clk/stm32/clk-stm32mp1.c b/drivers/clk/stm32/clk-stm32mp1.c index 5fcc4c77c11f..b8b45ed22f98 100644 --- a/drivers/clk/stm32/clk-stm32mp1.c +++ b/drivers/clk/stm32/clk-stm32mp1.c @@ -2041,7 +2041,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = { KCLK(ADFSDM_K, "adfsdm_k", sai_src, 0, G_ADFSDM, M_SAI1), KCLK(USBO_K, "usbo_k", usbo_src, 0, G_USBO, M_USBO), - /* Particulary Kernel Clocks (no mux or no gate) */ + /* Particularly Kernel Clocks (no mux or no gate) */ MGATE_MP1(DFSDM_K, "dfsdm_k", "ck_mcu", 0, G_DFSDM), MGATE_MP1(DSI_PX, "dsi_px", "pll4_q", CLK_SET_RATE_PARENT, G_DSI), MGATE_MP1(LTDC_PX, "ltdc_px", "pll4_q", CLK_SET_RATE_PARENT, G_LTDC), diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c index acb4e8b9b1ba..d24fa3449303 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -80,7 +80,7 @@ static struct ccu_div r_apb2_clk = { * in the BSP source code, although most of them are unused. The existence * of the hardware block is verified with "3.1 Memory Mapping" chapter in * "Allwinner H6 V200 User Manual V1.1"; and the parent APB buses are verified - * with "3.3.2.1 System Bus Tree" chapter inthe same document. + * with "3.3.2.1 System Bus Tree" chapter in the same document. */ static SUNXI_CCU_GATE(r_apb1_timer_clk, "r-apb1-timer", "r-apb1", 0x11c, BIT(0), 0); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c index 8b729c9b3545..44565830881d 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c @@ -439,7 +439,7 @@ static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x06c, BIT(3), 0); /* - * In datasheet here's "Reserved", however the gate exists in BSP soucre + * In datasheet here's "Reserved", however the gate exists in BSP source * code. */ static SUNXI_CCU_GATE(bus_can_clk, "bus-can", "apb2", diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c index 88ed89658d45..c7e00f0c29a5 100644 --- a/drivers/clk/sunxi-ng/ccu_common.c +++ b/drivers/clk/sunxi-ng/ccu_common.c @@ -66,7 +66,7 @@ EXPORT_SYMBOL_NS_GPL(ccu_is_better_rate, "SUNXI_CCU"); * changed. In common PLL designs, changes to the dividers take effect * almost immediately, while changes to the multipliers (implemented * as dividers in the feedback loop) take a few cycles to work into - * the feedback loop for the PLL to stablize. + * the feedback loop for the PLL to stabilize. * * Sometimes when the PLL clock rate is changed, the decrease in the * divider is too much for the decrease in the multiplier to catch up. diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 0626650a7011..fa0cd7bb8ee6 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -51,7 +51,7 @@ static int clk_periph_determine_rate(struct clk_hw *hw, struct tegra_clk_periph *periph = to_clk_periph(hw); const struct clk_ops *div_ops = periph->div_ops; struct clk_hw *div_hw = &periph->divider.hw; - unsigned long rate; + long rate; __clk_hw_set_clk(div_hw, hw); @@ -59,7 +59,7 @@ static int clk_periph_determine_rate(struct clk_hw *hw, if (rate < 0) return rate; - req->rate = rate; + req->rate = (unsigned long)rate; return 0; } @@ -132,7 +132,7 @@ static void clk_periph_restore_context(struct clk_hw *hw) clk_periph_set_parent(hw, parent_id); } -const struct clk_ops tegra_clk_periph_ops = { +static const struct clk_ops tegra_clk_periph_ops = { .get_parent = clk_periph_get_parent, .set_parent = clk_periph_set_parent, .recalc_rate = clk_periph_recalc_rate, diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index a3488aaac3f7..412902f573b5 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -255,7 +255,7 @@ /* VIC register to handle during MBIST WAR */ #define NV_PVIC_THI_SLCG_OVERRIDE_LOW 0x8c -/* APE, DISPA and VIC base addesses needed for MBIST WAR */ +/* APE, DISPA and VIC base addresses needed for MBIST WAR */ #define TEGRA210_AHUB_BASE 0x702d0000 #define TEGRA210_DISPA_BASE 0x54200000 #define TEGRA210_VIC_BASE 0x54340000 diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 5d80d8b79b8e..9ea839af14bc 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -629,7 +629,6 @@ struct tegra_clk_periph { #define TEGRA_CLK_PERIPH_MAGIC 0x18221223 -extern const struct clk_ops tegra_clk_periph_ops; struct clk *tegra_clk_register_periph(const char *name, const char * const *parent_names, int num_parents, struct tegra_clk_periph *periph, void __iomem *clk_base, diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c index 27e6b9cb1881..a99aaf2e7684 100644 --- a/drivers/clk/ti/autoidle.c +++ b/drivers/clk/ti/autoidle.c @@ -30,7 +30,7 @@ static LIST_HEAD(autoidle_clks); /* * we have some non-atomic read/write - * operations behind it, so lets + * operations behind it, so let's * take one lock for handling autoidle * of all clocks */ diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c index f24f6eb2157a..35af3079c002 100644 --- a/drivers/clk/ti/clk-43xx.c +++ b/drivers/clk/ti/clk-43xx.c @@ -286,7 +286,7 @@ int __init am43xx_dt_clk_init(void) /* * cpsw_cpts_rft_clk has got the choice of 3 clocksources * dpll_core_m4_ck, dpll_core_m5_ck and dpll_disp_m2_ck. - * By default dpll_core_m4_ck is selected, witn this as clock + * By default dpll_core_m4_ck is selected, with this as clock * source the CPTS doesnot work properly. It gives clockcheck errors * while running PTP. * clockcheck: clock jumped backward or running slower than expected! diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c index 9c75dcc9a534..693a4459a01b 100644 --- a/drivers/clk/ti/clk.c +++ b/drivers/clk/ti/clk.c @@ -118,13 +118,10 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops) * Eventually we could standardize to using '_' for clk-*.c files to follow the * TRM naming. */ -static struct device_node *ti_find_clock_provider(struct device_node *from, - const char *name) +static struct device_node *ti_find_clock_provider(const char *name) { char *tmp __free(kfree) = NULL; struct device_node *np; - bool found = false; - const char *n; char *p; tmp = kstrdup_and_replace(name, '-', '_', GFP_KERNEL); @@ -137,25 +134,13 @@ static struct device_node *ti_find_clock_provider(struct device_node *from, *p = '\0'; /* Node named "clock" with "clock-output-names" */ - for_each_of_allnodes_from(from, np) { - if (of_property_read_string_index(np, "clock-output-names", - 0, &n)) - continue; - - if (!strncmp(n, tmp, strlen(tmp))) { - of_node_get(np); - found = true; - break; - } - } - - if (found) { - of_node_put(from); - return np; + for_each_node_with_property(np, "clock-output-names") { + if (of_property_match_string(np, "clock-output-names", tmp) == 0) + return np; } /* Fall back to using old node name base provider name */ - return of_find_node_by_name(from, tmp); + return of_find_node_by_name(NULL, tmp); } /** @@ -208,7 +193,7 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) if (num_args && clkctrl_nodes_missing) continue; - node = ti_find_clock_provider(NULL, buf); + node = ti_find_clock_provider(buf); if (num_args && compat_mode) { parent = node; child = of_get_child_by_name(parent, "clock"); diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c index f684fc306ecc..d6d247ff2be5 100644 --- a/drivers/clk/ti/mux.c +++ b/drivers/clk/ti/mux.c @@ -84,7 +84,7 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index) } /** - * clk_mux_save_context - Save the parent selcted in the mux + * clk_mux_save_context - Save the parent selected in the mux * @hw: pointer struct clk_hw * * Save the parent mux value. diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index d5cb372f0901..b69c3fbdfbce 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -194,7 +194,7 @@ static int vco_set(struct clk_icst *icst, struct icst_vco vco) pr_err("ICST error: tried to use RDW != 22\n"); break; default: - /* Regular auxilary oscillator */ + /* Regular auxiliary oscillator */ mask = VERSATILE_AUX_OSC_BITS; val = vco.v | (vco.r << 9) | (vco.s << 16); break; diff --git a/drivers/clk/visconti/pll.c b/drivers/clk/visconti/pll.c index 3f929cf8dd2f..8ca1bad61864 100644 --- a/drivers/clk/visconti/pll.c +++ b/drivers/clk/visconti/pll.c @@ -107,7 +107,7 @@ static long visconti_pll_round_rate(struct clk_hw *hw, const struct visconti_pll_rate_table *rate_table = pll->rate_table; int i; - /* Assumming rate_table is in descending order */ + /* Assuming rate_table is in descending order */ for (i = 0; i < pll->rate_count; i++) if (rate >= rate_table[i].rate) return rate_table[i].rate; diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c index bbf7714480e7..0295a13a811c 100644 --- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -669,7 +669,7 @@ static long clk_wzrd_ver_round_rate_all(struct clk_hw *hw, unsigned long rate, u32 m, d, o, div, f; int err; - err = clk_wzrd_get_divisors(hw, rate, *prate); + err = clk_wzrd_get_divisors_ver(hw, rate, *prate); if (err) return err; diff --git a/drivers/clk/xilinx/xlnx_vcu.c b/drivers/clk/xilinx/xlnx_vcu.c index 81501b48412e..1ded67bee06c 100644 --- a/drivers/clk/xilinx/xlnx_vcu.c +++ b/drivers/clk/xilinx/xlnx_vcu.c @@ -11,6 +11,7 @@ #include <linux/clk-provider.h> #include <linux/device.h> #include <linux/errno.h> +#include <linux/gpio/consumer.h> #include <linux/io.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/xlnx-vcu.h> @@ -51,6 +52,7 @@ * @dev: Platform device * @pll_ref: pll ref clock source * @aclk: axi clock source + * @reset_gpio: vcu reset gpio * @logicore_reg_ba: logicore reg base address * @vcu_slcr_ba: vcu_slcr Register base address * @pll: handle for the VCU PLL @@ -61,6 +63,7 @@ struct xvcu_device { struct device *dev; struct clk *pll_ref; struct clk *aclk; + struct gpio_desc *reset_gpio; struct regmap *logicore_reg_ba; void __iomem *vcu_slcr_ba; struct clk_hw *pll; @@ -587,8 +590,8 @@ static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu) xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]); if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE])) xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]); - - clk_hw_unregister_fixed_factor(xvcu->pll_post); + if (!IS_ERR_OR_NULL(xvcu->pll_post)) + clk_hw_unregister_fixed_factor(xvcu->pll_post); } /** @@ -676,6 +679,24 @@ static int xvcu_probe(struct platform_device *pdev) * Bit 0 : Gasket isolation * Bit 1 : put VCU out of reset */ + xvcu->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(xvcu->reset_gpio)) { + ret = PTR_ERR(xvcu->reset_gpio); + dev_err_probe(&pdev->dev, ret, "failed to get reset gpio for vcu.\n"); + goto error_get_gpio; + } + + if (xvcu->reset_gpio) { + gpiod_set_value(xvcu->reset_gpio, 0); + /* min 2 clock cycle of vcu pll_ref, slowest freq is 33.33KHz */ + usleep_range(60, 120); + gpiod_set_value(xvcu->reset_gpio, 1); + usleep_range(60, 120); + } else { + dev_dbg(&pdev->dev, "No reset gpio info found in dts for VCU. This may result in incorrect functionality if VCU isolation is removed after initialization in designs where the VCU reset is driven by gpio.\n"); + } + regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE); ret = xvcu_register_clock_provider(xvcu); @@ -690,6 +711,7 @@ static int xvcu_probe(struct platform_device *pdev) error_clk_provider: xvcu_unregister_clock_provider(xvcu); +error_get_gpio: clk_disable_unprepare(xvcu->aclk); return ret; } @@ -711,6 +733,13 @@ static void xvcu_remove(struct platform_device *pdev) xvcu_unregister_clock_provider(xvcu); /* Add the Gasket isolation and put the VCU in reset. */ + if (xvcu->reset_gpio) { + gpiod_set_value(xvcu->reset_gpio, 0); + /* min 2 clock cycle of vcu pll_ref, slowest freq is 33.33KHz */ + usleep_range(60, 120); + gpiod_set_value(xvcu->reset_gpio, 1); + usleep_range(60, 120); + } regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0); clk_disable_unprepare(xvcu->aclk); diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs index 94ed81644fe1..43c87d0259b6 100644 --- a/drivers/cpufreq/rcpufreq_dt.rs +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -26,9 +26,9 @@ fn find_supply_name_exact(dev: &Device, name: &str) -> Option<CString> { } /// Finds supply name for the CPU from DT. -fn find_supply_names(dev: &Device, cpu: u32) -> Option<KVec<CString>> { +fn find_supply_names(dev: &Device, cpu: cpu::CpuId) -> Option<KVec<CString>> { // Try "cpu0" for older DTs, fallback to "cpu". - let name = (cpu == 0) + let name = (cpu.as_u32() == 0) .then(|| find_supply_name_exact(dev, "cpu0")) .flatten() .or_else(|| find_supply_name_exact(dev, "cpu"))?; diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 890ecac04dac..2bcf9ceca997 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -1118,7 +1118,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, * Catch exporters making buffers inaccessible even when * attachments preventing that exist. */ - WARN_ON_ONCE(ret == EBUSY); + WARN_ON_ONCE(ret == -EBUSY); if (ret) return ERR_PTR(ret); } diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 7eee3eb47a8e..c9d0c68d2fcb 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -264,8 +264,7 @@ static int begin_cpu_udmabuf(struct dma_buf *buf, ubuf->sg = NULL; } } else { - dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, - direction); + dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction); } return ret; @@ -280,7 +279,7 @@ static int end_cpu_udmabuf(struct dma_buf *buf, if (!ubuf->sg) return -EINVAL; - dma_sync_sg_for_device(dev, ubuf->sg->sgl, ubuf->sg->nents, direction); + dma_sync_sgtable_for_device(dev, ubuf->sg, direction); return 0; } diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 36943b0c6d60..5b06b0dc67ee 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -6,6 +6,7 @@ * Author: Lars-Peter Clausen <lars@metafoo.de> */ +#include <linux/adi-axi-common.h> #include <linux/bitfield.h> #include <linux/clk.h> #include <linux/device.h> @@ -22,7 +23,6 @@ #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> -#include <linux/fpga/adi-axi-common.h> #include <dt-bindings/dma/axi-dmac.h> diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c index 47136bbbe8c6..ab08d690d882 100644 --- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c +++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c @@ -109,7 +109,7 @@ static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi, venc_freq /= 2; dev_dbg(priv->dev, - "vclk:%lluHz phy=%lluHz venc=%lluHz hdmi=%lluHz enci=%d\n", + "phy:%lluHz vclk=%lluHz venc=%lluHz hdmi=%lluHz enci=%d\n", phy_freq, vclk_freq, venc_freq, hdmi_freq, priv->venc.hdmi_use_enci); diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index 3325580d885d..dfe0c28a0f05 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -110,10 +110,7 @@ #define HDMI_PLL_LOCK BIT(31) #define HDMI_PLL_LOCK_G12A (3 << 30) -#define PIXEL_FREQ_1000_1001(_freq) \ - DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL) -#define PHY_FREQ_1000_1001(_freq) \ - (PIXEL_FREQ_1000_1001(DIV_ROUND_DOWN_ULL(_freq, 10ULL)) * 10) +#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL) /* VID PLL Dividers */ enum { @@ -772,6 +769,36 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv, pll_freq); } +static bool meson_vclk_freqs_are_matching_param(unsigned int idx, + unsigned long long phy_freq, + unsigned long long vclk_freq) +{ + DRM_DEBUG_DRIVER("i = %d vclk_freq = %lluHz alt = %lluHz\n", + idx, params[idx].vclk_freq, + FREQ_1000_1001(params[idx].vclk_freq)); + DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n", + idx, params[idx].phy_freq, + FREQ_1000_1001(params[idx].phy_freq)); + + /* Match strict frequency */ + if (phy_freq == params[idx].phy_freq && + vclk_freq == params[idx].vclk_freq) + return true; + + /* Match 1000/1001 variant: vclk deviation has to be less than 1kHz + * (drm EDID is defined in 1kHz steps, so everything smaller must be + * rounding error) and the PHY freq deviation has to be less than + * 10kHz (as the TMDS clock is 10 times the pixel clock, so anything + * smaller must be rounding error as well). + */ + if (abs(vclk_freq - FREQ_1000_1001(params[idx].vclk_freq)) < 1000 && + abs(phy_freq - FREQ_1000_1001(params[idx].phy_freq)) < 10000) + return true; + + /* no match */ + return false; +} + enum drm_mode_status meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned long long phy_freq, @@ -790,19 +817,7 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv, } for (i = 0 ; params[i].pixel_freq ; ++i) { - DRM_DEBUG_DRIVER("i = %d pixel_freq = %lluHz alt = %lluHz\n", - i, params[i].pixel_freq, - PIXEL_FREQ_1000_1001(params[i].pixel_freq)); - DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n", - i, params[i].phy_freq, - PHY_FREQ_1000_1001(params[i].phy_freq)); - /* Match strict frequency */ - if (phy_freq == params[i].phy_freq && - vclk_freq == params[i].vclk_freq) - return MODE_OK; - /* Match 1000/1001 variant */ - if (phy_freq == PHY_FREQ_1000_1001(params[i].phy_freq) && - vclk_freq == PIXEL_FREQ_1000_1001(params[i].vclk_freq)) + if (meson_vclk_freqs_are_matching_param(i, phy_freq, vclk_freq)) return MODE_OK; } @@ -1075,10 +1090,8 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, } for (freq = 0 ; params[freq].pixel_freq ; ++freq) { - if ((phy_freq == params[freq].phy_freq || - phy_freq == PHY_FREQ_1000_1001(params[freq].phy_freq)) && - (vclk_freq == params[freq].vclk_freq || - vclk_freq == PIXEL_FREQ_1000_1001(params[freq].vclk_freq))) { + if (meson_vclk_freqs_are_matching_param(freq, phy_freq, + vclk_freq)) { if (vclk_freq != params[freq].vclk_freq) vic_alternate_clock = true; else diff --git a/drivers/gpu/drm/sitronix/Kconfig b/drivers/gpu/drm/sitronix/Kconfig index c069d0d41775..741d1bb4b83f 100644 --- a/drivers/gpu/drm/sitronix/Kconfig +++ b/drivers/gpu/drm/sitronix/Kconfig @@ -5,6 +5,7 @@ config DRM_ST7571_I2C select DRM_GEM_SHMEM_HELPER select DRM_KMS_HELPER select REGMAP_I2C + select VIDEOMODE_HELPERS help DRM driver for Sitronix ST7571 panels controlled over I2C. diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index a29a6ef266f9..163d092bd973 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -560,12 +560,6 @@ static int vc4_hdmi_connector_init(struct drm_device *dev, if (ret) return ret; - ret = drm_connector_hdmi_audio_init(connector, dev->dev, - &vc4_hdmi_audio_funcs, - 8, false, -1); - if (ret) - return ret; - drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); /* @@ -2291,6 +2285,12 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi) return ret; } + ret = drm_connector_hdmi_audio_init(&vc4_hdmi->connector, dev, + &vc4_hdmi_audio_funcs, 8, false, + -1); + if (ret) + return ret; + dai_link->cpus = &vc4_hdmi->audio.cpu; dai_link->codecs = &vc4_hdmi->audio.codec; dai_link->platforms = &vc4_hdmi->audio.platform; diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 63d74e27f54c..bf7c3981897d 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -941,11 +941,18 @@ static void xe_lrc_finish(struct xe_lrc *lrc) * store it in the PPHSWP. */ #define CONTEXT_ACTIVE 1ULL -static void xe_lrc_setup_utilization(struct xe_lrc *lrc) +static int xe_lrc_setup_utilization(struct xe_lrc *lrc) { - u32 *cmd; + u32 *cmd, *buf = NULL; - cmd = lrc->bb_per_ctx_bo->vmap.vaddr; + if (lrc->bb_per_ctx_bo->vmap.is_iomem) { + buf = kmalloc(lrc->bb_per_ctx_bo->size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + cmd = buf; + } else { + cmd = lrc->bb_per_ctx_bo->vmap.vaddr; + } *cmd++ = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; *cmd++ = ENGINE_ID(0).addr; @@ -966,9 +973,16 @@ static void xe_lrc_setup_utilization(struct xe_lrc *lrc) *cmd++ = MI_BATCH_BUFFER_END; + if (buf) { + xe_map_memcpy_to(gt_to_xe(lrc->gt), &lrc->bb_per_ctx_bo->vmap, 0, + buf, (cmd - buf) * sizeof(*cmd)); + kfree(buf); + } + xe_lrc_write_ctx_reg(lrc, CTX_BB_PER_CTX_PTR, xe_bo_ggtt_addr(lrc->bb_per_ctx_bo) | 1); + return 0; } #define PVC_CTX_ASID (0x2e + 1) @@ -1125,7 +1139,9 @@ static int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, map = __xe_lrc_start_seqno_map(lrc); xe_map_write32(lrc_to_xe(lrc), &map, lrc->fence_ctx.next_seqno - 1); - xe_lrc_setup_utilization(lrc); + err = xe_lrc_setup_utilization(lrc); + if (err) + goto err_lrc_finish; return 0; diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 6345896585de..f0b167b3fb6a 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -764,7 +764,7 @@ static bool xe_svm_range_needs_migrate_to_vram(struct xe_svm_range *range, return false; } - if (range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { + if (range_size < SZ_64K && !supports_4K_migration(vm->xe)) { drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); return false; } diff --git a/drivers/hwmon/axi-fan-control.c b/drivers/hwmon/axi-fan-control.c index 35c862eb158b..b7bb325c3ad9 100644 --- a/drivers/hwmon/axi-fan-control.c +++ b/drivers/hwmon/axi-fan-control.c @@ -4,9 +4,9 @@ * * Copyright 2019 Analog Devices Inc. */ +#include <linux/adi-axi-common.h> #include <linux/bits.h> #include <linux/clk.h> -#include <linux/fpga/adi-axi-common.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/interrupt.h> diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 8ccb483204fa..73747d20df85 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -152,8 +152,8 @@ static __always_inline int __intel_idle(struct cpuidle_device *dev, int index, bool irqoff) { struct cpuidle_state *state = &drv->states[index]; - unsigned long eax = flg2MWAIT(state->flags); - unsigned long ecx = 1*irqoff; /* break on interrupt flag */ + unsigned int eax = flg2MWAIT(state->flags); + unsigned int ecx = 1*irqoff; /* break on interrupt flag */ mwait_idle_with_hints(eax, ecx); @@ -226,9 +226,9 @@ static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev, static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { - unsigned long ecx = 1; /* break on interrupt flag */ struct cpuidle_state *state = &drv->states[index]; - unsigned long eax = flg2MWAIT(state->flags); + unsigned int eax = flg2MWAIT(state->flags); + unsigned int ecx = 1; /* break on interrupt flag */ if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) fpu_idle_fpregs(); @@ -2507,6 +2507,8 @@ static int __init intel_idle_init(void) pr_debug("Local APIC timer is reliable in %s\n", boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1"); + arch_cpu_rescan_dead_smt_siblings(); + return 0; hp_setup_fail: @@ -2518,7 +2520,7 @@ init_driver_fail: return retval; } -device_initcall(intel_idle_init); +subsys_initcall_sync(intel_idle_init); /* * We are not really modular, but we used to support that. Meaning we also diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index 4116c44197b8..b3cc78187c9d 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -6,6 +6,7 @@ * Copyright 2012-2020 Analog Devices Inc. */ +#include <linux/adi-axi-common.h> #include <linux/bitfield.h> #include <linux/cleanup.h> #include <linux/clk.h> @@ -20,8 +21,6 @@ #include <linux/regmap.h> #include <linux/slab.h> -#include <linux/fpga/adi-axi-common.h> - #include <linux/iio/backend.h> #include <linux/iio/buffer-dmaengine.h> #include <linux/iio/buffer.h> diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c index 33faba4b02c2..890a0ac0d85e 100644 --- a/drivers/iio/dac/adi-axi-dac.c +++ b/drivers/iio/dac/adi-axi-dac.c @@ -5,6 +5,7 @@ * * Copyright 2016-2024 Analog Devices Inc. */ +#include <linux/adi-axi-common.h> #include <linux/bitfield.h> #include <linux/bits.h> #include <linux/cleanup.h> @@ -23,7 +24,6 @@ #include <linux/regmap.h> #include <linux/units.h> -#include <linux/fpga/adi-axi-common.h> #include <linux/iio/backend.h> #include <linux/iio/buffer-dmaengine.h> #include <linux/iio/buffer.h> diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 61897d50162d..e58fe9d8b9e7 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -559,11 +559,11 @@ static void tegra_smmu_set_pde(struct tegra_smmu_as *as, unsigned long iova, { unsigned int pd_index = iova_pd_index(iova); struct tegra_smmu *smmu = as->smmu; - struct tegra_pd *pd = as->pd; + u32 *pd = &as->pd->val[pd_index]; unsigned long offset = pd_index * sizeof(*pd); /* Set the page directory entry first */ - pd->val[pd_index] = value; + *pd = value; /* The flush the page directory entry from caches */ dma_sync_single_range_for_device(smmu->dev, as->pd_dma, offset, diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 862bdccb7439..dc2f4adac9bc 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -2034,9 +2034,6 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge, b53_get_vlan_entry(dev, pvid, vl); vl->members &= ~BIT(port); - if (vl->members == BIT(cpu_port)) - vl->members &= ~BIT(cpu_port); - vl->untag = vl->members; b53_set_vlan_entry(dev, pvid, vl); } @@ -2115,8 +2112,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge) } b53_get_vlan_entry(dev, pvid, vl); - vl->members |= BIT(port) | BIT(cpu_port); - vl->untag |= BIT(port) | BIT(cpu_port); + vl->members |= BIT(port); b53_set_vlan_entry(dev, pvid, vl); } } diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h index 04187eb40ec6..150c85995cc1 100644 --- a/drivers/net/ethernet/airoha/airoha_regs.h +++ b/drivers/net/ethernet/airoha/airoha_regs.h @@ -614,8 +614,9 @@ RX19_DONE_INT_MASK | RX18_DONE_INT_MASK | \ RX17_DONE_INT_MASK | RX16_DONE_INT_MASK) -#define RX_DONE_INT_MASK (RX_DONE_HIGH_INT_MASK | RX_DONE_LOW_INT_MASK) #define RX_DONE_HIGH_OFFSET fls(RX_DONE_HIGH_INT_MASK) +#define RX_DONE_INT_MASK \ + ((RX_DONE_HIGH_INT_MASK << RX_DONE_HIGH_OFFSET) | RX_DONE_LOW_INT_MASK) #define INT_RX2_MASK(_n) \ ((RX_NO_CPU_DSCP_HIGH_INT_MASK & (_n)) | \ diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig index e917132d3714..54b0f0a5a6bb 100644 --- a/drivers/net/ethernet/freescale/enetc/Kconfig +++ b/drivers/net/ethernet/freescale/enetc/Kconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config FSL_ENETC_CORE tristate + select NXP_NETC_LIB if NXP_NTMP help This module supports common functionality between the PF and VF drivers for the NXP ENETC controller. @@ -22,6 +23,9 @@ config NXP_NETC_LIB Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc flower and debugfs interfaces and so on. +config NXP_NTMP + bool + config FSL_ENETC tristate "ENETC PF driver" depends on PCI_MSI @@ -45,7 +49,7 @@ config NXP_ENETC4 select FSL_ENETC_CORE select FSL_ENETC_MDIO select NXP_ENETC_PF_COMMON - select NXP_NETC_LIB + select NXP_NTMP select PHYLINK select DIMLIB help diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 3f089c3d47b2..d8595e84326d 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -477,10 +477,6 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter) cancel_delayed_work_sync(&adapter->phy_info_task); cancel_delayed_work_sync(&adapter->fifo_stall_task); - - /* Only kill reset task if adapter is not resetting */ - if (!test_bit(__E1000_RESETTING, &adapter->flags)) - cancel_work_sync(&adapter->reset_task); } void e1000_down(struct e1000_adapter *adapter) @@ -1266,6 +1262,10 @@ static void e1000_remove(struct pci_dev *pdev) unregister_netdev(netdev); + /* Only kill reset task if adapter is not resetting */ + if (!test_bit(__E1000_RESETTING, &adapter->flags)) + cancel_work_sync(&adapter->reset_task); + e1000_phy_hw_reset(hw); kfree(adapter->tx_ring); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 1120f8e4bb67..88e6bef69342 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1546,8 +1546,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf) * @vf: pointer to the VF structure * @flr: VFLR was issued or not * - * Returns true if the VF is in reset, resets successfully, or resets - * are disabled and false otherwise. + * Return: True if reset was performed successfully or if resets are disabled. + * False if reset is already in progress. **/ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) { @@ -1566,7 +1566,7 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) /* If VF is being reset already we don't need to continue. */ if (test_and_set_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) - return true; + return false; i40e_trigger_vf_reset(vf, flr); @@ -4328,7 +4328,10 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf) reg = rd32(hw, I40E_GLGEN_VFLRSTAT(reg_idx)); if (reg & BIT(bit_idx)) /* i40e_reset_vf will clear the bit in GLGEN_VFLRSTAT */ - i40e_reset_vf(vf, true); + if (!i40e_reset_vf(vf, true)) { + /* At least one VF did not finish resetting, retry next time */ + set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); + } } return 0; diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 2c0bb41809a4..81d7249d1149 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -3209,6 +3209,17 @@ static void iavf_reset_task(struct work_struct *work) } continue_reset: + /* If we are still early in the state machine, just restart. */ + if (adapter->state <= __IAVF_INIT_FAILED) { + iavf_shutdown_adminq(hw); + iavf_change_state(adapter, __IAVF_STARTUP); + iavf_startup(adapter); + queue_delayed_work(adapter->wq, &adapter->watchdog_task, + msecs_to_jiffies(30)); + netdev_unlock(netdev); + return; + } + /* We don't use netif_running() because it may be true prior to * ndo_open() returning, so we can't assume it means all our open * tasks have finished, since we're not holding the rtnl_lock here. diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index a6f0e5990be2..07f0d0a0f1e2 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -79,6 +79,23 @@ iavf_poll_virtchnl_msg(struct iavf_hw *hw, struct iavf_arq_event_info *event, return iavf_status_to_errno(status); received_op = (enum virtchnl_ops)le32_to_cpu(event->desc.cookie_high); + + if (received_op == VIRTCHNL_OP_EVENT) { + struct iavf_adapter *adapter = hw->back; + struct virtchnl_pf_event *vpe = + (struct virtchnl_pf_event *)event->msg_buf; + + if (vpe->event != VIRTCHNL_EVENT_RESET_IMPENDING) + continue; + + dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n"); + if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) + iavf_schedule_reset(adapter, + IAVF_FLAG_RESET_PENDING); + + return -EIO; + } + if (op_to_poll == received_op) break; } diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index b79a148ed0f2..55cad824c5b9 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -2299,6 +2299,7 @@ static int ice_capture_crosststamp(ktime_t *device, ts = ((u64)ts_hi << 32) | ts_lo; system->cycles = ts; system->cs_id = CSID_X86_ART; + system->use_nsecs = true; /* Read Device source clock time */ ts_lo = rd32(hw, cfg->dev_time_l[tmr_idx]); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index ea078c9f5d15..3cb8d3bf9044 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -43,7 +43,6 @@ #include "en/fs_ethtool.h" #define LANES_UNKNOWN 0 -#define MAX_LANES 8 void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv, struct ethtool_drvinfo *drvinfo) @@ -1098,10 +1097,8 @@ static void get_link_properties(struct net_device *netdev, speed = info->speed; lanes = info->lanes; duplex = DUPLEX_FULL; - } else if (data_rate_oper) { + } else if (data_rate_oper) speed = 100 * data_rate_oper; - lanes = MAX_LANES; - } out: link_ksettings->base.duplex = duplex; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index f1d908f61134..fef418e1ed1a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -2028,9 +2028,8 @@ err_out: return err; } -static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow) +static bool mlx5_flow_has_geneve_opt(struct mlx5_flow_spec *spec) { - struct mlx5_flow_spec *spec = &flow->attr->parse_attr->spec; void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_3); @@ -2069,7 +2068,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, } complete_all(&flow->del_hw_done); - if (mlx5_flow_has_geneve_opt(flow)) + if (mlx5_flow_has_geneve_opt(&attr->parse_attr->spec)) mlx5_geneve_tlv_option_del(priv->mdev->geneve); if (flow->decap_route) @@ -2574,12 +2573,13 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv, err = mlx5e_tc_tun_parse(filter_dev, priv, tmp_spec, f, match_level); if (err) { - kvfree(tmp_spec); NL_SET_ERR_MSG_MOD(extack, "Failed to parse tunnel attributes"); netdev_warn(priv->netdev, "Failed to parse tunnel attributes"); - return err; + } else { + err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec); } - err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec); + if (mlx5_flow_has_geneve_opt(tmp_spec)) + mlx5_geneve_tlv_option_del(priv->mdev->geneve); kvfree(tmp_spec); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 7fb8a3381f84..4917d185d0c3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1295,12 +1295,15 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events); if (ret) goto ecpf_err; - if (mlx5_core_ec_sriov_enabled(esw->dev)) { - ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs, - enabled_events); - if (ret) - goto ec_vf_err; - } + } + + /* Enable ECVF vports */ + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + ret = mlx5_eswitch_load_ec_vf_vports(esw, + esw->esw_funcs.num_ec_vfs, + enabled_events); + if (ret) + goto ec_vf_err; } /* Enable VF vports */ @@ -1331,9 +1334,11 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) { mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); + if (mlx5_core_ec_sriov_enabled(esw->dev)) + mlx5_eswitch_unload_ec_vf_vports(esw, + esw->esw_funcs.num_ec_vfs); + if (mlx5_ecpf_vport_exists(esw->dev)) { - if (mlx5_core_ec_sriov_enabled(esw->dev)) - mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs); mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 23a7e8e7adfa..a8046200d376 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -2228,6 +2228,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft, struct mlx5_flow_handle *rule; struct match_list *iter; bool take_write = false; + bool try_again = false; struct fs_fte *fte; u64 version = 0; int err; @@ -2292,6 +2293,7 @@ skip_search: nested_down_write_ref_node(&g->node, FS_LOCK_PARENT); if (!g->node.active) { + try_again = true; up_write_ref_node(&g->node, false); continue; } @@ -2313,7 +2315,8 @@ skip_search: tree_put_node(&fte->node, false); return rule; } - rule = ERR_PTR(-ENOENT); + err = try_again ? -EAGAIN : -ENOENT; + rule = ERR_PTR(err); out: kmem_cache_free(steering->ftes_cache, fte); return rule; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index 972e8e9df585..9bc9bd83c232 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -291,7 +291,7 @@ static void free_4k(struct mlx5_core_dev *dev, u64 addr, u32 function) static int alloc_system_page(struct mlx5_core_dev *dev, u32 function) { struct device *device = mlx5_core_dma_dev(dev); - int nid = dev_to_node(device); + int nid = dev->priv.numa_node; struct page *page; u64 zero_addr = 1; u64 addr; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c index fb62f3bc4bd4..447ea3f8722c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c @@ -1370,8 +1370,8 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, struct mlx5hws_cmd_set_fte_attr fte_attr = {0}; struct mlx5hws_cmd_forward_tbl *fw_island; struct mlx5hws_action *action; - u32 i /*, packet_reformat_id*/; - int ret; + int ret, last_dest_idx = -1; + u32 i; if (num_dest <= 1) { mlx5hws_err(ctx, "Action must have multiple dests\n"); @@ -1401,11 +1401,8 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, dest_list[i].destination_id = dests[i].dest->dest_obj.obj_id; fte_attr.action_flags |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; fte_attr.ignore_flow_level = ignore_flow_level; - /* ToDo: In SW steering we have a handling of 'go to WIRE' - * destination here by upper layer setting 'is_wire_ft' flag - * if the destination is wire. - * This is because uplink should be last dest in the list. - */ + if (dests[i].is_wire_ft) + last_dest_idx = i; break; case MLX5HWS_ACTION_TYP_VPORT: dest_list[i].destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT; @@ -1429,6 +1426,9 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, } } + if (last_dest_idx != -1) + swap(dest_list[last_dest_idx], dest_list[num_dest - 1]); + fte_attr.dests_num = num_dest; fte_attr.dests = dest_list; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c index 70768953a4f6..ca7501c57468 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c @@ -1070,7 +1070,7 @@ hws_bwc_rule_complex_hash_node_get(struct mlx5hws_bwc_rule *bwc_rule, struct mlx5hws_bwc_matcher *bwc_matcher = bwc_rule->bwc_matcher; struct mlx5hws_bwc_complex_rule_hash_node *node, *old_node; struct rhashtable *refcount_hash; - int i; + int ret, i; bwc_rule->complex_hash_node = NULL; @@ -1078,7 +1078,11 @@ hws_bwc_rule_complex_hash_node_get(struct mlx5hws_bwc_rule *bwc_rule, if (unlikely(!node)) return -ENOMEM; - node->tag = ida_alloc(&bwc_matcher->complex->metadata_ida, GFP_KERNEL); + ret = ida_alloc(&bwc_matcher->complex->metadata_ida, GFP_KERNEL); + if (ret < 0) + goto err_free_node; + node->tag = ret; + refcount_set(&node->refcount, 1); /* Clear match buffer - turn off all the unrelated fields @@ -1094,6 +1098,11 @@ hws_bwc_rule_complex_hash_node_get(struct mlx5hws_bwc_rule *bwc_rule, old_node = rhashtable_lookup_get_insert_fast(refcount_hash, &node->hash_node, hws_refcount_hash); + if (IS_ERR(old_node)) { + ret = PTR_ERR(old_node); + goto err_free_ida; + } + if (old_node) { /* Rule with the same tag already exists - update refcount */ refcount_inc(&old_node->refcount); @@ -1112,6 +1121,12 @@ hws_bwc_rule_complex_hash_node_get(struct mlx5hws_bwc_rule *bwc_rule, bwc_rule->complex_hash_node = node; return 0; + +err_free_ida: + ida_free(&bwc_matcher->complex->metadata_ida, node->tag); +err_free_node: + kfree(node); + return ret; } static void diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c index 5cc0dc002ac1..d45e1145d197 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c @@ -785,6 +785,9 @@ hws_definer_conv_outer(struct mlx5hws_definer_conv_data *cd, HWS_SET_HDR(fc, match_param, IP_PROTOCOL_O, outer_headers.ip_protocol, eth_l3_outer.protocol_next_header); + HWS_SET_HDR(fc, match_param, IP_VERSION_O, + outer_headers.ip_version, + eth_l3_outer.ip_version); HWS_SET_HDR(fc, match_param, IP_TTL_O, outer_headers.ttl_hoplimit, eth_l3_outer.time_to_live_hop_limit); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c index 9d1c0e4b224a..bf4643d0ce17 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c @@ -966,6 +966,9 @@ static int mlx5_fs_fte_get_hws_actions(struct mlx5_flow_root_namespace *ns, switch (attr->type) { case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: dest_action = mlx5_fs_get_dest_action_ft(fs_ctx, dst); + if (dst->dest_attr.ft->flags & + MLX5_FLOW_TABLE_UPLINK_VPORT) + dest_actions[num_dest_actions].is_wire_ft = true; break; case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM: dest_action = mlx5_fs_get_dest_action_table_num(fs_ctx, @@ -1357,6 +1360,7 @@ mlx5_cmd_hws_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns, pkt_reformat->fs_hws_action.pr_data = pr_data; } + mutex_init(&pkt_reformat->fs_hws_action.lock); pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_HWS; pkt_reformat->fs_hws_action.hws_action = hws_action; return 0; @@ -1503,7 +1507,6 @@ static int mlx5_cmd_hws_modify_header_alloc(struct mlx5_flow_root_namespace *ns, err = -ENOMEM; goto release_mh; } - mutex_init(&modify_hdr->fs_hws_action.lock); modify_hdr->fs_hws_action.mh_data = mh_data; modify_hdr->fs_hws_action.fs_pool = pool; modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h index 9bbadc4d8a0b..d8ac6c196211 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h @@ -213,6 +213,7 @@ struct mlx5hws_action_dest_attr { struct mlx5hws_action *dest; /* Optional reformat action */ struct mlx5hws_action *reformat; + bool is_wire_ft; }; /** diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 3d315e30ee47..7edbe76b5455 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -247,15 +247,39 @@ static sci_t make_sci(const u8 *addr, __be16 port) return sci; } -static sci_t macsec_frame_sci(struct macsec_eth_header *hdr, bool sci_present) +static sci_t macsec_active_sci(struct macsec_secy *secy) { - sci_t sci; + struct macsec_rx_sc *rx_sc = rcu_dereference_bh(secy->rx_sc); + + /* Case single RX SC */ + if (rx_sc && !rcu_dereference_bh(rx_sc->next)) + return (rx_sc->active) ? rx_sc->sci : 0; + /* Case no RX SC or multiple */ + else + return 0; +} + +static sci_t macsec_frame_sci(struct macsec_eth_header *hdr, bool sci_present, + struct macsec_rxh_data *rxd) +{ + struct macsec_dev *macsec; + sci_t sci = 0; - if (sci_present) + /* SC = 1 */ + if (sci_present) { memcpy(&sci, hdr->secure_channel_id, sizeof(hdr->secure_channel_id)); - else + /* SC = 0; ES = 0 */ + } else if ((!(hdr->tci_an & (MACSEC_TCI_ES | MACSEC_TCI_SC))) && + (list_is_singular(&rxd->secys))) { + /* Only one SECY should exist on this scenario */ + macsec = list_first_or_null_rcu(&rxd->secys, struct macsec_dev, + secys); + if (macsec) + return macsec_active_sci(&macsec->secy); + } else { sci = make_sci(hdr->eth.h_source, MACSEC_PORT_ES); + } return sci; } @@ -1109,7 +1133,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) struct macsec_rxh_data *rxd; struct macsec_dev *macsec; unsigned int len; - sci_t sci; + sci_t sci = 0; u32 hdr_pn; bool cbit; struct pcpu_rx_sc_stats *rxsc_stats; @@ -1156,11 +1180,14 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) macsec_skb_cb(skb)->has_sci = !!(hdr->tci_an & MACSEC_TCI_SC); macsec_skb_cb(skb)->assoc_num = hdr->tci_an & MACSEC_AN_MASK; - sci = macsec_frame_sci(hdr, macsec_skb_cb(skb)->has_sci); rcu_read_lock(); rxd = macsec_data_rcu(skb->dev); + sci = macsec_frame_sci(hdr, macsec_skb_cb(skb)->has_sci, rxd); + if (!sci) + goto drop_nosc; + list_for_each_entry_rcu(macsec, &rxd->secys, secys) { struct macsec_rx_sc *sc = find_rx_sc(&macsec->secy, sci); @@ -1283,6 +1310,7 @@ drop: macsec_rxsa_put(rx_sa); drop_nosa: macsec_rxsc_put(rx_sc); +drop_nosc: rcu_read_unlock(); drop_direct: kfree_skb(skb); diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 4289ccd3e41b..176935a8645f 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -1252,7 +1252,6 @@ static int sysdata_append_release(struct netconsole_target *nt, int offset) */ static int prepare_extradata(struct netconsole_target *nt) { - u32 fields = SYSDATA_CPU_NR | SYSDATA_TASKNAME; int extradata_len; /* userdata was appended when configfs write helper was called @@ -1260,7 +1259,7 @@ static int prepare_extradata(struct netconsole_target *nt) */ extradata_len = nt->userdata_length; - if (!(nt->sysdata_fields & fields)) + if (!nt->sysdata_fields) goto out; if (nt->sysdata_fields & SYSDATA_CPU_NR) diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index af545d42961c..fa5fbd97ad69 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -371,7 +371,8 @@ static int nsim_poll(struct napi_struct *napi, int budget) int done; done = nsim_rcv(rq, budget); - napi_complete(napi); + if (done < budget) + napi_complete_done(napi, done); return done; } diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index a6bcb0fee863..fda2e27c1810 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -445,6 +445,9 @@ int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) lockdep_assert_held_once(&bus->mdio_lock); + if (addr >= PHY_MAX_ADDR) + return -ENXIO; + if (bus->read) retval = bus->read(bus, addr, regnum); else @@ -474,6 +477,9 @@ int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val) lockdep_assert_held_once(&bus->mdio_lock); + if (addr >= PHY_MAX_ADDR) + return -ENXIO; + if (bus->write) err = bus->write(bus, addr, regnum, val); else @@ -535,6 +541,9 @@ int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum) lockdep_assert_held_once(&bus->mdio_lock); + if (addr >= PHY_MAX_ADDR) + return -ENXIO; + if (bus->read_c45) retval = bus->read_c45(bus, addr, devad, regnum); else @@ -566,6 +575,9 @@ int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum, lockdep_assert_held_once(&bus->mdio_lock); + if (addr >= PHY_MAX_ADDR) + return -ENXIO; + if (bus->write_c45) err = bus->write_c45(bus, addr, devad, regnum, val); else diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c index 703321689726..38417e288611 100644 --- a/drivers/net/phy/phy_caps.c +++ b/drivers/net/phy/phy_caps.c @@ -188,6 +188,9 @@ phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only) * When @exact is not set, we return either an exact match, or matching capabilities * at lower speed, or the lowest matching speed, or NULL. * + * Non-exact matches will try to return an exact speed and duplex match, but may + * return matching capabilities with same speed but a different duplex. + * * Returns: a matched link_capabilities according to the above process, NULL * otherwise. */ @@ -195,7 +198,7 @@ const struct link_capabilities * phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported, bool exact) { - const struct link_capabilities *lcap, *last = NULL; + const struct link_capabilities *lcap, *match = NULL, *last = NULL; for_each_link_caps_desc_speed(lcap) { if (linkmode_intersects(lcap->linkmodes, supported)) { @@ -204,16 +207,19 @@ phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported, if (lcap->speed == speed && lcap->duplex == duplex) { return lcap; } else if (!exact) { - if (lcap->speed <= speed) - return lcap; + if (!match && lcap->speed <= speed) + match = lcap; + + if (lcap->speed < speed) + break; } } } - if (!exact) - return last; + if (!match && !exact) + match = last; - return NULL; + return match; } EXPORT_SYMBOL_GPL(phy_caps_lookup); diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index d6589b24c68d..44cba7acfe7d 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -10054,6 +10054,7 @@ static const struct usb_device_id rtl8152_table[] = { { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) }, { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, + { USB_DEVICE(VENDOR_ID_TPLINK, 0x0602) }, { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) }, { USB_DEVICE(VENDOR_ID_DELL, 0xb097) }, { USB_DEVICE(VENDOR_ID_ASUS, 0x1976) }, diff --git a/drivers/net/veth.c b/drivers/net/veth.c index e58a0f1b5c5b..a3046142cb8e 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -909,7 +909,7 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, /* NAPI functions as RCU section */ peer_dev = rcu_dereference_check(priv->peer, rcu_read_lock_bh_held()); - peer_txq = netdev_get_tx_queue(peer_dev, queue_idx); + peer_txq = peer_dev ? netdev_get_tx_queue(peer_dev, queue_idx) : NULL; for (i = 0; i < budget; i++) { void *ptr = __ptr_ring_consume(&rq->xdp_ring); @@ -959,7 +959,7 @@ static int veth_xdp_rcv(struct veth_rq *rq, int budget, rq->stats.vs.xdp_packets += done; u64_stats_update_end(&rq->stats.syncp); - if (unlikely(netif_tx_queue_stopped(peer_txq))) + if (peer_txq && unlikely(netif_tx_queue_stopped(peer_txq))) netif_tx_wake_queue(peer_txq); return done; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 8c7ffea0fa44..07fe05384cdf 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4,6 +4,7 @@ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include "mac.h" @@ -1022,6 +1023,26 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar) return ar->last_wmi_vdev_start_status; } +static inline int ath10k_vdev_delete_sync(struct ath10k *ar) +{ + unsigned long time_left; + + lockdep_assert_held(&ar->conf_mutex); + + if (!test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) + return 0; + + if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) + return -ESHUTDOWN; + + time_left = wait_for_completion_timeout(&ar->vdev_delete_done, + ATH10K_VDEV_DELETE_TIMEOUT_HZ); + if (time_left == 0) + return -ETIMEDOUT; + + return 0; +} + static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) { struct cfg80211_chan_def *chandef = NULL; @@ -5900,7 +5921,6 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_peer *peer; - unsigned long time_left; int ret; int i; @@ -5940,13 +5960,10 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n", arvif->vdev_id, ret); - if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { - time_left = wait_for_completion_timeout(&ar->vdev_delete_done, - ATH10K_VDEV_DELETE_TIMEOUT_HZ); - if (time_left == 0) { - ath10k_warn(ar, "Timeout in receiving vdev delete response\n"); - goto out; - } + ret = ath10k_vdev_delete_sync(ar); + if (ret) { + ath10k_warn(ar, "Error in receiving vdev delete response: %d\n", ret); + goto out; } /* Some firmware revisions don't notify host about self-peer removal diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index b2bf9d72b92f..d51f2e5a79a4 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -938,7 +938,9 @@ static int ath10k_snoc_hif_start(struct ath10k *ar) dev_set_threaded(ar->napi_dev, true); ath10k_core_napi_enable(ar); - ath10k_snoc_irq_enable(ar); + /* IRQs are left enabled when we restart due to a firmware crash */ + if (!test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags)) + ath10k_snoc_irq_enable(ar); ath10k_snoc_rx_post(ar); clear_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags); diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 2e9f8a5e61e4..22a101136135 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -990,6 +990,7 @@ void ath11k_fw_stats_init(struct ath11k *ar) INIT_LIST_HEAD(&ar->fw_stats.bcn); init_completion(&ar->fw_stats_complete); + init_completion(&ar->fw_stats_done); } void ath11k_fw_stats_free(struct ath11k_fw_stats *stats) @@ -2134,6 +2135,20 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) { int ret; + switch (ath11k_crypto_mode) { + case ATH11K_CRYPT_MODE_SW: + set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); + set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); + break; + case ATH11K_CRYPT_MODE_HW: + clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); + clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); + break; + default: + ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode); + return -EINVAL; + } + ret = ath11k_core_start_firmware(ab, ab->fw_mode); if (ret) { ath11k_err(ab, "failed to start firmware: %d\n", ret); @@ -2152,20 +2167,6 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) goto err_firmware_stop; } - switch (ath11k_crypto_mode) { - case ATH11K_CRYPT_MODE_SW: - set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); - set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); - break; - case ATH11K_CRYPT_MODE_HW: - clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); - clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); - break; - default: - ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode); - return -EINVAL; - } - if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW) set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 339d4fca1ed5..6b2f207975e3 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -600,6 +600,8 @@ struct ath11k_fw_stats { struct list_head pdevs; struct list_head vdevs; struct list_head bcn; + u32 num_vdev_recvd; + u32 num_bcn_recvd; }; struct ath11k_dbg_htt_stats { @@ -784,7 +786,7 @@ struct ath11k { u8 alpha2[REG_ALPHA2_LEN + 1]; struct ath11k_fw_stats fw_stats; struct completion fw_stats_complete; - bool fw_stats_done; + struct completion fw_stats_done; /* protected by conf_mutex */ bool ps_state_enable; diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c index bf192529e3fe..5d46f8e4c231 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/vmalloc.h> @@ -93,57 +93,14 @@ void ath11k_debugfs_add_dbring_entry(struct ath11k *ar, spin_unlock_bh(&dbr_data->lock); } -static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar) -{ - spin_lock_bh(&ar->data_lock); - ar->fw_stats_done = false; - ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); - ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs); - spin_unlock_bh(&ar->data_lock); -} - void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats) { struct ath11k_base *ab = ar->ab; - struct ath11k_pdev *pdev; - bool is_end; - static unsigned int num_vdev, num_bcn; - size_t total_vdevs_started = 0; - int i; - - /* WMI_REQUEST_PDEV_STAT request has been already processed */ - - if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) { - ar->fw_stats_done = true; - return; - } - - if (stats->stats_id == WMI_REQUEST_VDEV_STAT) { - if (list_empty(&stats->vdevs)) { - ath11k_warn(ab, "empty vdev stats"); - return; - } - /* FW sends all the active VDEV stats irrespective of PDEV, - * hence limit until the count of all VDEVs started - */ - for (i = 0; i < ab->num_radios; i++) { - pdev = rcu_dereference(ab->pdevs_active[i]); - if (pdev && pdev->ar) - total_vdevs_started += ar->num_started_vdevs; - } - - is_end = ((++num_vdev) == total_vdevs_started); - - list_splice_tail_init(&stats->vdevs, - &ar->fw_stats.vdevs); - - if (is_end) { - ar->fw_stats_done = true; - num_vdev = 0; - } - return; - } + bool is_end = true; + /* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_RSSI_PER_CHAIN_STAT and + * WMI_REQUEST_VDEV_STAT requests have been already processed. + */ if (stats->stats_id == WMI_REQUEST_BCN_STAT) { if (list_empty(&stats->bcn)) { ath11k_warn(ab, "empty bcn stats"); @@ -152,97 +109,18 @@ void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats * /* Mark end until we reached the count of all started VDEVs * within the PDEV */ - is_end = ((++num_bcn) == ar->num_started_vdevs); + if (ar->num_started_vdevs) + is_end = ((++ar->fw_stats.num_bcn_recvd) == + ar->num_started_vdevs); list_splice_tail_init(&stats->bcn, &ar->fw_stats.bcn); - if (is_end) { - ar->fw_stats_done = true; - num_bcn = 0; - } + if (is_end) + complete(&ar->fw_stats_done); } } -static int ath11k_debugfs_fw_stats_request(struct ath11k *ar, - struct stats_request_params *req_param) -{ - struct ath11k_base *ab = ar->ab; - unsigned long timeout, time_left; - int ret; - - lockdep_assert_held(&ar->conf_mutex); - - /* FW stats can get split when exceeding the stats data buffer limit. - * In that case, since there is no end marking for the back-to-back - * received 'update stats' event, we keep a 3 seconds timeout in case, - * fw_stats_done is not marked yet - */ - timeout = jiffies + secs_to_jiffies(3); - - ath11k_debugfs_fw_stats_reset(ar); - - reinit_completion(&ar->fw_stats_complete); - - ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); - - if (ret) { - ath11k_warn(ab, "could not request fw stats (%d)\n", - ret); - return ret; - } - - time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ); - - if (!time_left) - return -ETIMEDOUT; - - for (;;) { - if (time_after(jiffies, timeout)) - break; - - spin_lock_bh(&ar->data_lock); - if (ar->fw_stats_done) { - spin_unlock_bh(&ar->data_lock); - break; - } - spin_unlock_bh(&ar->data_lock); - } - return 0; -} - -int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, - u32 vdev_id, u32 stats_id) -{ - struct ath11k_base *ab = ar->ab; - struct stats_request_params req_param; - int ret; - - mutex_lock(&ar->conf_mutex); - - if (ar->state != ATH11K_STATE_ON) { - ret = -ENETDOWN; - goto err_unlock; - } - - req_param.pdev_id = pdev_id; - req_param.vdev_id = vdev_id; - req_param.stats_id = stats_id; - - ret = ath11k_debugfs_fw_stats_request(ar, &req_param); - if (ret) - ath11k_warn(ab, "failed to request fw stats: %d\n", ret); - - ath11k_dbg(ab, ATH11K_DBG_WMI, - "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n", - pdev_id, vdev_id, stats_id); - -err_unlock: - mutex_unlock(&ar->conf_mutex); - - return ret; -} - static int ath11k_open_pdev_stats(struct inode *inode, struct file *file) { struct ath11k *ar = inode->i_private; @@ -268,7 +146,7 @@ static int ath11k_open_pdev_stats(struct inode *inode, struct file *file) req_param.vdev_id = 0; req_param.stats_id = WMI_REQUEST_PDEV_STAT; - ret = ath11k_debugfs_fw_stats_request(ar, &req_param); + ret = ath11k_mac_fw_stats_request(ar, &req_param); if (ret) { ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret); goto err_free; @@ -339,7 +217,7 @@ static int ath11k_open_vdev_stats(struct inode *inode, struct file *file) req_param.vdev_id = 0; req_param.stats_id = WMI_REQUEST_VDEV_STAT; - ret = ath11k_debugfs_fw_stats_request(ar, &req_param); + ret = ath11k_mac_fw_stats_request(ar, &req_param); if (ret) { ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret); goto err_free; @@ -415,7 +293,7 @@ static int ath11k_open_bcn_stats(struct inode *inode, struct file *file) continue; req_param.vdev_id = arvif->vdev_id; - ret = ath11k_debugfs_fw_stats_request(ar, &req_param); + ret = ath11k_mac_fw_stats_request(ar, &req_param); if (ret) { ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret); goto err_free; diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h index a39e458637b0..ed7fec177588 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022, 2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _ATH11K_DEBUGFS_H_ @@ -273,8 +273,6 @@ void ath11k_debugfs_unregister(struct ath11k *ar); void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats); void ath11k_debugfs_fw_stats_init(struct ath11k *ar); -int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, - u32 vdev_id, u32 stats_id); static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar) { @@ -381,12 +379,6 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar) return 0; } -static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar, - u32 pdev_id, u32 vdev_id, u32 stats_id) -{ - return 0; -} - static inline void ath11k_debugfs_add_dbring_entry(struct ath11k *ar, enum wmi_direct_buffer_module id, diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 08d7b136851f..13301ca317a5 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -8997,6 +8997,81 @@ static void ath11k_mac_put_chain_rssi(struct station_info *sinfo, } } +static void ath11k_mac_fw_stats_reset(struct ath11k *ar) +{ + spin_lock_bh(&ar->data_lock); + ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); + ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs); + ar->fw_stats.num_vdev_recvd = 0; + ar->fw_stats.num_bcn_recvd = 0; + spin_unlock_bh(&ar->data_lock); +} + +int ath11k_mac_fw_stats_request(struct ath11k *ar, + struct stats_request_params *req_param) +{ + struct ath11k_base *ab = ar->ab; + unsigned long time_left; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + ath11k_mac_fw_stats_reset(ar); + + reinit_completion(&ar->fw_stats_complete); + reinit_completion(&ar->fw_stats_done); + + ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); + + if (ret) { + ath11k_warn(ab, "could not request fw stats (%d)\n", + ret); + return ret; + } + + time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ); + if (!time_left) + return -ETIMEDOUT; + + /* FW stats can get split when exceeding the stats data buffer limit. + * In that case, since there is no end marking for the back-to-back + * received 'update stats' event, we keep a 3 seconds timeout in case, + * fw_stats_done is not marked yet + */ + time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ); + if (!time_left) + return -ETIMEDOUT; + + return 0; +} + +static int ath11k_mac_get_fw_stats(struct ath11k *ar, u32 pdev_id, + u32 vdev_id, u32 stats_id) +{ + struct ath11k_base *ab = ar->ab; + struct stats_request_params req_param; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + if (ar->state != ATH11K_STATE_ON) + return -ENETDOWN; + + req_param.pdev_id = pdev_id; + req_param.vdev_id = vdev_id; + req_param.stats_id = stats_id; + + ret = ath11k_mac_fw_stats_request(ar, &req_param); + if (ret) + ath11k_warn(ab, "failed to request fw stats: %d\n", ret); + + ath11k_dbg(ab, ATH11K_DBG_WMI, + "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n", + pdev_id, vdev_id, stats_id); + + return ret; +} + static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -9031,11 +9106,12 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, ath11k_mac_put_chain_rssi(sinfo, arsta, "ppdu", false); + mutex_lock(&ar->conf_mutex); if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) && arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && ar->ab->hw_params.supports_rssi_stats && - !ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0, - WMI_REQUEST_RSSI_PER_CHAIN_STAT)) { + !ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, + WMI_REQUEST_RSSI_PER_CHAIN_STAT)) { ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true); } @@ -9043,9 +9119,10 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, if (!signal && arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && ar->ab->hw_params.supports_rssi_stats && - !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0, - WMI_REQUEST_VDEV_STAT))) + !(ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, + WMI_REQUEST_VDEV_STAT))) signal = arsta->rssi_beacon; + mutex_unlock(&ar->conf_mutex); ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n", @@ -9380,38 +9457,6 @@ exit: return ret; } -static int ath11k_fw_stats_request(struct ath11k *ar, - struct stats_request_params *req_param) -{ - struct ath11k_base *ab = ar->ab; - unsigned long time_left; - int ret; - - lockdep_assert_held(&ar->conf_mutex); - - spin_lock_bh(&ar->data_lock); - ar->fw_stats_done = false; - ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); - spin_unlock_bh(&ar->data_lock); - - reinit_completion(&ar->fw_stats_complete); - - ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); - if (ret) { - ath11k_warn(ab, "could not request fw stats (%d)\n", - ret); - return ret; - } - - time_left = wait_for_completion_timeout(&ar->fw_stats_complete, - 1 * HZ); - - if (!time_left) - return -ETIMEDOUT; - - return 0; -} - static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned int link_id, @@ -9419,7 +9464,6 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, { struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; - struct stats_request_params req_param = {0}; struct ath11k_fw_stats_pdev *pdev; int ret; @@ -9431,9 +9475,6 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, */ mutex_lock(&ar->conf_mutex); - if (ar->state != ATH11K_STATE_ON) - goto err_fallback; - /* Firmware doesn't provide Tx power during CAC hence no need to fetch * the stats. */ @@ -9442,10 +9483,8 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, return -EAGAIN; } - req_param.pdev_id = ar->pdev->pdev_id; - req_param.stats_id = WMI_REQUEST_PDEV_STAT; - - ret = ath11k_fw_stats_request(ar, &req_param); + ret = ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, + WMI_REQUEST_PDEV_STAT); if (ret) { ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret); goto err_fallback; diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index f5800fbecff8..5e61eea1bb03 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef ATH11K_MAC_H @@ -179,4 +179,6 @@ int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif, void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_chanctx_conf *ctx); +int ath11k_mac_fw_stats_request(struct ath11k *ar, + struct stats_request_params *req_param); #endif diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index d7f852bebf4a..56af2e9634f4 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8158,6 +8158,11 @@ static void ath11k_peer_assoc_conf_event(struct ath11k_base *ab, struct sk_buff static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *skb) { struct ath11k_fw_stats stats = {}; + size_t total_vdevs_started = 0; + struct ath11k_pdev *pdev; + bool is_end = true; + int i; + struct ath11k *ar; int ret; @@ -8184,25 +8189,57 @@ static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *sk spin_lock_bh(&ar->data_lock); - /* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via + /* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_VDEV_STAT and + * WMI_REQUEST_RSSI_PER_CHAIN_STAT can be requested via mac ops or via * debugfs fw stats. Therefore, processing it separately. */ if (stats.stats_id == WMI_REQUEST_PDEV_STAT) { list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs); - ar->fw_stats_done = true; + complete(&ar->fw_stats_done); + goto complete; + } + + if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) { + complete(&ar->fw_stats_done); goto complete; } - /* WMI_REQUEST_VDEV_STAT, WMI_REQUEST_BCN_STAT and WMI_REQUEST_RSSI_PER_CHAIN_STAT - * are currently requested only via debugfs fw stats. Hence, processing these - * in debugfs context + if (stats.stats_id == WMI_REQUEST_VDEV_STAT) { + if (list_empty(&stats.vdevs)) { + ath11k_warn(ab, "empty vdev stats"); + goto complete; + } + /* FW sends all the active VDEV stats irrespective of PDEV, + * hence limit until the count of all VDEVs started + */ + for (i = 0; i < ab->num_radios; i++) { + pdev = rcu_dereference(ab->pdevs_active[i]); + if (pdev && pdev->ar) + total_vdevs_started += ar->num_started_vdevs; + } + + if (total_vdevs_started) + is_end = ((++ar->fw_stats.num_vdev_recvd) == + total_vdevs_started); + + list_splice_tail_init(&stats.vdevs, + &ar->fw_stats.vdevs); + + if (is_end) + complete(&ar->fw_stats_done); + + goto complete; + } + + /* WMI_REQUEST_BCN_STAT is currently requested only via debugfs fw stats. + * Hence, processing it in debugfs context */ ath11k_debugfs_fw_stats_process(ar, &stats); complete: complete(&ar->fw_stats_complete); - rcu_read_unlock(); spin_unlock_bh(&ar->data_lock); + rcu_read_unlock(); /* Since the stats's pdev, vdev and beacon list are spliced and reinitialised * at this point, no need to free the individual list. diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 31d851d8e688..ebc0560d40e3 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -2129,7 +2129,8 @@ int ath12k_core_init(struct ath12k_base *ab) if (!ag) { mutex_unlock(&ath12k_hw_group_mutex); ath12k_warn(ab, "unable to get hw group\n"); - return -ENODEV; + ret = -ENODEV; + goto err_unregister_notifier; } mutex_unlock(&ath12k_hw_group_mutex); @@ -2144,7 +2145,7 @@ int ath12k_core_init(struct ath12k_base *ab) if (ret) { mutex_unlock(&ag->mutex); ath12k_warn(ab, "unable to create hw group\n"); - goto err; + goto err_destroy_hw_group; } } @@ -2152,9 +2153,12 @@ int ath12k_core_init(struct ath12k_base *ab) return 0; -err: +err_destroy_hw_group: ath12k_core_hw_group_destroy(ab->ag); ath12k_core_hw_group_unassign(ab); +err_unregister_notifier: + ath12k_core_panic_notifier_unregister(ab); + return ret; } diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h index 0ee9c6b26dab..c1750b5dc03c 100644 --- a/drivers/net/wireless/ath/ath12k/hal.h +++ b/drivers/net/wireless/ath/ath12k/hal.h @@ -585,7 +585,8 @@ enum hal_reo_cmd_type { * or cache was blocked * @HAL_REO_CMD_FAILED: Command execution failed, could be due to * invalid queue desc - * @HAL_REO_CMD_RESOURCE_BLOCKED: + * @HAL_REO_CMD_RESOURCE_BLOCKED: Command could not be executed because + * one or more descriptors were blocked * @HAL_REO_CMD_DRAIN: */ enum hal_reo_cmd_status { diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c index 7e2cf0fb2085..8254dc10b53b 100644 --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c @@ -951,6 +951,8 @@ static const struct ath12k_hw_regs qcn9274_v1_regs = { .hal_umac_ce0_dest_reg_base = 0x01b81000, .hal_umac_ce1_src_reg_base = 0x01b82000, .hal_umac_ce1_dest_reg_base = 0x01b83000, + + .gcc_gcc_pcie_hot_rst = 0x1e38338, }; static const struct ath12k_hw_regs qcn9274_v2_regs = { @@ -1042,6 +1044,8 @@ static const struct ath12k_hw_regs qcn9274_v2_regs = { .hal_umac_ce0_dest_reg_base = 0x01b81000, .hal_umac_ce1_src_reg_base = 0x01b82000, .hal_umac_ce1_dest_reg_base = 0x01b83000, + + .gcc_gcc_pcie_hot_rst = 0x1e38338, }; static const struct ath12k_hw_regs ipq5332_regs = { @@ -1215,6 +1219,8 @@ static const struct ath12k_hw_regs wcn7850_regs = { .hal_umac_ce0_dest_reg_base = 0x01b81000, .hal_umac_ce1_src_reg_base = 0x01b82000, .hal_umac_ce1_dest_reg_base = 0x01b83000, + + .gcc_gcc_pcie_hot_rst = 0x1e40304, }; static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = { diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h index 0fbc17649df4..0a75bc5abfa2 100644 --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h @@ -375,6 +375,8 @@ struct ath12k_hw_regs { u32 hal_reo_cmd_ring_base; u32 hal_reo_status_ring_base; + + u32 gcc_gcc_pcie_hot_rst; }; static inline const char *ath12k_bd_ie_type_str(enum ath12k_bd_ie_type type) diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c index 489d546390fc..1f3cfd9b89fd 100644 --- a/drivers/net/wireless/ath/ath12k/pci.c +++ b/drivers/net/wireless/ath/ath12k/pci.c @@ -292,10 +292,10 @@ static void ath12k_pci_enable_ltssm(struct ath12k_base *ab) ath12k_dbg(ab, ATH12K_DBG_PCI, "pci ltssm 0x%x\n", val); - val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST); + val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST(ab)); val |= GCC_GCC_PCIE_HOT_RST_VAL; - ath12k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST, val); - val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST); + ath12k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST(ab), val); + val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST(ab)); ath12k_dbg(ab, ATH12K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val); diff --git a/drivers/net/wireless/ath/ath12k/pci.h b/drivers/net/wireless/ath/ath12k/pci.h index 0b4c459d6d8e..d1ec8aad7f6c 100644 --- a/drivers/net/wireless/ath/ath12k/pci.h +++ b/drivers/net/wireless/ath/ath12k/pci.h @@ -28,7 +28,9 @@ #define PCIE_PCIE_PARF_LTSSM 0x1e081b0 #define PARM_LTSSM_VALUE 0x111 -#define GCC_GCC_PCIE_HOT_RST 0x1e38338 +#define GCC_GCC_PCIE_HOT_RST(ab) \ + ((ab)->hw_params->regs->gcc_gcc_pcie_hot_rst) + #define GCC_GCC_PCIE_HOT_RST_VAL 0x10 #define PCIE_PCIE_INT_ALL_CLEAR 0x1e08228 diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 67172385a5d6..89d4394cedcf 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -179,9 +179,11 @@ void wil_mask_irq(struct wil6210_priv *wil) wil_dbg_irq(wil, "mask_irq\n"); wil6210_mask_irq_tx(wil); - wil6210_mask_irq_tx_edma(wil); + if (wil->use_enhanced_dma_hw) + wil6210_mask_irq_tx_edma(wil); wil6210_mask_irq_rx(wil); - wil6210_mask_irq_rx_edma(wil); + if (wil->use_enhanced_dma_hw) + wil6210_mask_irq_rx_edma(wil); wil6210_mask_irq_misc(wil, true); wil6210_mask_irq_pseudo(wil); } @@ -190,10 +192,12 @@ void wil_unmask_irq(struct wil6210_priv *wil) { wil_dbg_irq(wil, "unmask_irq\n"); - wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC), - WIL_ICR_ICC_VALUE); - wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), - WIL_ICR_ICC_VALUE); + if (wil->use_enhanced_dma_hw) { + wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC), + WIL_ICR_ICC_VALUE); + wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), + WIL_ICR_ICC_VALUE); + } wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_MISC_VALUE); wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC), @@ -845,10 +849,12 @@ void wil6210_clear_irq(struct wil6210_priv *wil) offsetof(struct RGF_ICR, ICR)); wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + offsetof(struct RGF_ICR, ICR)); - wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) + - offsetof(struct RGF_ICR, ICR)); - wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) + - offsetof(struct RGF_ICR, ICR)); + if (wil->use_enhanced_dma_hw) { + wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) + + offsetof(struct RGF_ICR, ICR)); + wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) + + offsetof(struct RGF_ICR, ICR)); + } wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + offsetof(struct RGF_ICR, ICR)); wmb(); /* make sure write completed */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 656f8b06c27b..0a9e0dbb58fb 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1501,11 +1501,27 @@ static int _iwl_pci_resume(struct device *device, bool restore) * Scratch value was altered, this means the device was powered off, we * need to reset it completely. * Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan, - * so assume that any bits there mean that the device is usable. + * but not bits [15:8]. So if we have bits set in lower word, assume + * the device is alive. + * For older devices, just try silently to grab the NIC. */ - if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ && - !iwl_read32(trans, CSR_FUNC_SCRATCH)) - device_was_powered_off = true; + if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { + if (!(iwl_read32(trans, CSR_FUNC_SCRATCH) & + CSR_FUNC_SCRATCH_POWER_OFF_MASK)) + device_was_powered_off = true; + } else { + /* + * bh are re-enabled by iwl_trans_pcie_release_nic_access, + * so re-enable them if _iwl_trans_pcie_grab_nic_access fails. + */ + local_bh_disable(); + if (_iwl_trans_pcie_grab_nic_access(trans, true)) { + iwl_trans_pcie_release_nic_access(trans); + } else { + device_was_powered_off = true; + local_bh_enable(); + } + } if (restore || device_was_powered_off) { trans->state = IWL_TRANS_NO_FW; diff --git a/drivers/net/wireless/marvell/mwifiex/11n.c b/drivers/net/wireless/marvell/mwifiex/11n.c index 738bafc3749b..66f0f5377ac1 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n.c +++ b/drivers/net/wireless/marvell/mwifiex/11n.c @@ -403,14 +403,12 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && bss_desc->bcn_ht_oper->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { - chan_list->chan_scan_param[0].radio_type |= - CHAN_BW_40MHZ << 2; + IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. radio_type, (bss_desc->bcn_ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); - } + *buffer += struct_size(chan_list, chan_scan_param, 1); ret_len += struct_size(chan_list, chan_scan_param, 1); } diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index 0b50da2f1175..6b3ac8ae3f34 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -429,21 +429,14 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req, pdu->result = le64_to_cpu(nvme_req(req)->result.u64); /* - * For iopoll, complete it directly. Note that using the uring_cmd - * helper for this is safe only because we check blk_rq_is_poll(). - * As that returns false if we're NOT on a polled queue, then it's - * safe to use the polled completion helper. - * - * Otherwise, move the completion to task work. + * IOPOLL could potentially complete this request directly, but + * if multiple rings are polling on the same queue, then it's possible + * for one ring to find completions for another ring. Punting the + * completion via task_work will always direct it to the right + * location, rather than potentially complete requests for ringA + * under iopoll invocations from ringB. */ - if (blk_rq_is_poll(req)) { - if (pdu->bio) - blk_rq_unmap_user(pdu->bio); - io_uring_cmd_iopoll_done(ioucmd, pdu->result, pdu->status); - } else { - io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb); - } - + io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb); return RQ_END_IO_FREE; } diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index fe2d52e434db..8a2ef74862d3 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -374,11 +374,6 @@ static struct st_pio_control *st_get_pio_control( } /* Low level functions.. */ -static inline int st_gpio_bank(int gpio) -{ - return gpio/ST_GPIO_PINS_PER_BANK; -} - static inline int st_gpio_pin(int gpio) { return gpio%ST_GPIO_PINS_PER_BANK; diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c index d6bb8f58978d..4edb20e61951 100644 --- a/drivers/pinctrl/pinctrl-tb10x.c +++ b/drivers/pinctrl/pinctrl-tb10x.c @@ -823,7 +823,7 @@ static struct platform_driver tb10x_pinctrl_pdrv = { .remove = tb10x_pinctrl_remove, .driver = { .name = "tb10x_pinctrl", - .of_match_table = of_match_ptr(tb10x_pinctrl_dt_ids), + .of_match_table = tb10x_pinctrl_dt_ids, } }; diff --git a/drivers/pinctrl/qcom/pinctrl-apq8064.c b/drivers/pinctrl/qcom/pinctrl-apq8064.c index 20c3b9025044..3654913f1ae5 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8064.c @@ -629,7 +629,6 @@ static struct platform_driver apq8064_pinctrl_driver = { .of_match_table = apq8064_pinctrl_of_match, }, .probe = apq8064_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init apq8064_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-apq8084.c b/drivers/pinctrl/qcom/pinctrl-apq8084.c index 3fc0a40762b6..27693cd64881 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8084.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8084.c @@ -1207,7 +1207,6 @@ static struct platform_driver apq8084_pinctrl_driver = { .of_match_table = apq8084_pinctrl_of_match, }, .probe = apq8084_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init apq8084_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c index 1f7944dd829d..6ede3149b6e1 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -710,7 +710,6 @@ static struct platform_driver ipq4019_pinctrl_driver = { .of_match_table = ipq4019_pinctrl_of_match, }, .probe = ipq4019_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq4019_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5018.c b/drivers/pinctrl/qcom/pinctrl-ipq5018.c index e2951f81c3ee..10b99d5d8a11 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq5018.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c @@ -754,7 +754,6 @@ static struct platform_driver ipq5018_pinctrl_driver = { .of_match_table = ipq5018_pinctrl_of_match, }, .probe = ipq5018_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq5018_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5332.c b/drivers/pinctrl/qcom/pinctrl-ipq5332.c index 625f8014051f..1ac2fc09c119 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq5332.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq5332.c @@ -834,7 +834,6 @@ static struct platform_driver ipq5332_pinctrl_driver = { .of_match_table = ipq5332_pinctrl_of_match, }, .probe = ipq5332_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq5332_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq5424.c b/drivers/pinctrl/qcom/pinctrl-ipq5424.c index 0d610b076da3..7ff1f8acc1a3 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq5424.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq5424.c @@ -791,7 +791,6 @@ static struct platform_driver ipq5424_pinctrl_driver = { .of_match_table = ipq5424_pinctrl_of_match, }, .probe = ipq5424_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq5424_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq6018.c b/drivers/pinctrl/qcom/pinctrl-ipq6018.c index 0ad08647dbcd..a4ba980252e1 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq6018.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq6018.c @@ -1080,7 +1080,6 @@ static struct platform_driver ipq6018_pinctrl_driver = { .of_match_table = ipq6018_pinctrl_of_match, }, .probe = ipq6018_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq6018_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8064.c b/drivers/pinctrl/qcom/pinctrl-ipq8064.c index e2bb94e86aef..0a9e357e64c6 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8064.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8064.c @@ -631,7 +631,6 @@ static struct platform_driver ipq8064_pinctrl_driver = { .of_match_table = ipq8064_pinctrl_of_match, }, .probe = ipq8064_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq8064_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq8074.c b/drivers/pinctrl/qcom/pinctrl-ipq8074.c index 337f3a1c92c1..482f13282fc2 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq8074.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq8074.c @@ -1041,7 +1041,6 @@ static struct platform_driver ipq8074_pinctrl_driver = { .of_match_table = ipq8074_pinctrl_of_match, }, .probe = ipq8074_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq8074_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-ipq9574.c b/drivers/pinctrl/qcom/pinctrl-ipq9574.c index e2491617b236..89c05d8eb550 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq9574.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq9574.c @@ -799,7 +799,6 @@ static struct platform_driver ipq9574_pinctrl_driver = { .of_match_table = ipq9574_pinctrl_of_match, }, .probe = ipq9574_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init ipq9574_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c index e7cd3ef1cf3e..3e18ba124fed 100644 --- a/drivers/pinctrl/qcom/pinctrl-mdm9607.c +++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c @@ -1059,7 +1059,6 @@ static struct platform_driver mdm9607_pinctrl_driver = { .of_match_table = mdm9607_pinctrl_of_match, }, .probe = mdm9607_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init mdm9607_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9615.c b/drivers/pinctrl/qcom/pinctrl-mdm9615.c index 0a2ae383d3d5..bea1ca3d1b7f 100644 --- a/drivers/pinctrl/qcom/pinctrl-mdm9615.c +++ b/drivers/pinctrl/qcom/pinctrl-mdm9615.c @@ -446,7 +446,6 @@ static struct platform_driver mdm9615_pinctrl_driver = { .of_match_table = mdm9615_pinctrl_of_match, }, .probe = mdm9615_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init mdm9615_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index f012ea88aa22..5c4687de1464 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -1442,7 +1442,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) girq->handler = handle_bad_irq; girq->parents[0] = pctrl->irq; - ret = gpiochip_add_data(&pctrl->chip, pctrl); + ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl); if (ret) { dev_err(pctrl->dev, "Failed register gpiochip\n"); return ret; @@ -1463,7 +1463,6 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) dev_name(pctrl->dev), 0, 0, chip->ngpio); if (ret) { dev_err(pctrl->dev, "Failed to add pin range\n"); - gpiochip_remove(&pctrl->chip); return ret; } } @@ -1599,13 +1598,5 @@ int msm_pinctrl_probe(struct platform_device *pdev, } EXPORT_SYMBOL(msm_pinctrl_probe); -void msm_pinctrl_remove(struct platform_device *pdev) -{ - struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); - - gpiochip_remove(&pctrl->chip); -} -EXPORT_SYMBOL(msm_pinctrl_remove); - MODULE_DESCRIPTION("Qualcomm Technologies, Inc. TLMM driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h index 63852ed70295..d7dc0947bb16 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.h +++ b/drivers/pinctrl/qcom/pinctrl-msm.h @@ -171,6 +171,5 @@ extern const struct dev_pm_ops msm_pinctrl_dev_pm_ops; int msm_pinctrl_probe(struct platform_device *pdev, const struct msm_pinctrl_soc_data *soc_data); -void msm_pinctrl_remove(struct platform_device *pdev); #endif diff --git a/drivers/pinctrl/qcom/pinctrl-msm8226.c b/drivers/pinctrl/qcom/pinctrl-msm8226.c index 64fee70f1772..f9a957347340 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8226.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8226.c @@ -654,7 +654,6 @@ static struct platform_driver msm8226_pinctrl_driver = { .of_match_table = msm8226_pinctrl_of_match, }, .probe = msm8226_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8226_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8660.c b/drivers/pinctrl/qcom/pinctrl-msm8660.c index 999a5f867eb5..4dbc19ffd80e 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8660.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8660.c @@ -981,7 +981,6 @@ static struct platform_driver msm8660_pinctrl_driver = { .of_match_table = msm8660_pinctrl_of_match, }, .probe = msm8660_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8660_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8909.c b/drivers/pinctrl/qcom/pinctrl-msm8909.c index 756856d20d6b..0aa4f77b774f 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8909.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8909.c @@ -929,7 +929,6 @@ static struct platform_driver msm8909_pinctrl_driver = { .of_match_table = msm8909_pinctrl_of_match, }, .probe = msm8909_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8909_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8916.c b/drivers/pinctrl/qcom/pinctrl-msm8916.c index cea5c54f92fe..0dfc6dd33d58 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8916.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8916.c @@ -969,7 +969,6 @@ static struct platform_driver msm8916_pinctrl_driver = { .of_match_table = msm8916_pinctrl_of_match, }, .probe = msm8916_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8916_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8917.c b/drivers/pinctrl/qcom/pinctrl-msm8917.c index 350636807b07..2e1a94ab18b2 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8917.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8917.c @@ -1607,7 +1607,6 @@ static struct platform_driver msm8917_pinctrl_driver = { .of_match_table = msm8917_pinctrl_of_match, }, .probe = msm8917_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8917_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8953.c b/drivers/pinctrl/qcom/pinctrl-msm8953.c index 998351bdfee1..956383341a7a 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8953.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8953.c @@ -1816,7 +1816,6 @@ static struct platform_driver msm8953_pinctrl_driver = { .of_match_table = msm8953_pinctrl_of_match, }, .probe = msm8953_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8953_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8960.c b/drivers/pinctrl/qcom/pinctrl-msm8960.c index ebe230b3b437..a937ea867de7 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8960.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8960.c @@ -1246,7 +1246,6 @@ static struct platform_driver msm8960_pinctrl_driver = { .of_match_table = msm8960_pinctrl_of_match, }, .probe = msm8960_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8960_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8976.c b/drivers/pinctrl/qcom/pinctrl-msm8976.c index c30d80e4e98c..3bcb03387781 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8976.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8976.c @@ -1096,7 +1096,6 @@ static struct platform_driver msm8976_pinctrl_driver = { .of_match_table = msm8976_pinctrl_of_match, }, .probe = msm8976_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8976_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c index b1a6759ab4a5..7a3b6cbccb68 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8994.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c @@ -1343,7 +1343,6 @@ static struct platform_driver msm8994_pinctrl_driver = { .of_match_table = msm8994_pinctrl_of_match, }, .probe = msm8994_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8994_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8996.c b/drivers/pinctrl/qcom/pinctrl-msm8996.c index 1b5d80eaab83..d86d83106d3b 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8996.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8996.c @@ -1920,7 +1920,6 @@ static struct platform_driver msm8996_pinctrl_driver = { .of_match_table = msm8996_pinctrl_of_match, }, .probe = msm8996_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8996_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8998.c b/drivers/pinctrl/qcom/pinctrl-msm8998.c index b7cbf32b3125..1daee815888f 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8998.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8998.c @@ -1535,7 +1535,6 @@ static struct platform_driver msm8998_pinctrl_driver = { .of_match_table = msm8998_pinctrl_of_match, }, .probe = msm8998_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8998_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-msm8x74.c b/drivers/pinctrl/qcom/pinctrl-msm8x74.c index 238c83f6ec4f..8253aa25775b 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm8x74.c +++ b/drivers/pinctrl/qcom/pinctrl-msm8x74.c @@ -1083,7 +1083,6 @@ static struct platform_driver msm8x74_pinctrl_driver = { .of_match_table = msm8x74_pinctrl_of_match, }, .probe = msm8x74_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init msm8x74_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qcm2290.c b/drivers/pinctrl/qcom/pinctrl-qcm2290.c index f885af571ec9..eeeec6434f6a 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcm2290.c +++ b/drivers/pinctrl/qcom/pinctrl-qcm2290.c @@ -167,6 +167,10 @@ static const struct pinctrl_pin_desc qcm2290_pins[] = { PINCTRL_PIN(62, "GPIO_62"), PINCTRL_PIN(63, "GPIO_63"), PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), PINCTRL_PIN(69, "GPIO_69"), PINCTRL_PIN(70, "GPIO_70"), PINCTRL_PIN(71, "GPIO_71"), @@ -181,12 +185,17 @@ static const struct pinctrl_pin_desc qcm2290_pins[] = { PINCTRL_PIN(80, "GPIO_80"), PINCTRL_PIN(81, "GPIO_81"), PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), PINCTRL_PIN(86, "GPIO_86"), PINCTRL_PIN(87, "GPIO_87"), PINCTRL_PIN(88, "GPIO_88"), PINCTRL_PIN(89, "GPIO_89"), PINCTRL_PIN(90, "GPIO_90"), PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), PINCTRL_PIN(94, "GPIO_94"), PINCTRL_PIN(95, "GPIO_95"), PINCTRL_PIN(96, "GPIO_96"), @@ -1125,7 +1134,6 @@ static struct platform_driver qcm2290_pinctrl_driver = { .of_match_table = qcm2290_pinctrl_of_match, }, .probe = qcm2290_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init qcm2290_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index ae7224012f8a..54e3b4435349 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -1644,7 +1644,6 @@ static struct platform_driver qcs404_pinctrl_driver = { .of_match_table = qcs404_pinctrl_of_match, }, .probe = qcs404_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init qcs404_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qcs615.c b/drivers/pinctrl/qcom/pinctrl-qcs615.c index 17ca743c2210..2a943bc46a62 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs615.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs615.c @@ -1087,7 +1087,6 @@ static struct platform_driver qcs615_tlmm_driver = { .of_match_table = qcs615_tlmm_of_match, }, .probe = qcs615_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init qcs615_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qcs8300.c b/drivers/pinctrl/qcom/pinctrl-qcs8300.c index 5f5f7c4ac644..d6437e26392b 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs8300.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs8300.c @@ -1227,7 +1227,6 @@ static struct platform_driver qcs8300_pinctrl_driver = { .of_match_table = qcs8300_pinctrl_of_match, }, .probe = qcs8300_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init qcs8300_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c index b5808fcfb13c..9ecc4d40e4dc 100644 --- a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c +++ b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c @@ -145,7 +145,6 @@ static struct platform_driver qdf2xxx_pinctrl_driver = { .acpi_match_table = qdf2xxx_acpi_ids, }, .probe = qdf2xxx_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init qdf2xxx_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-qdu1000.c b/drivers/pinctrl/qcom/pinctrl-qdu1000.c index 47bc529ef550..eacb89fa3888 100644 --- a/drivers/pinctrl/qcom/pinctrl-qdu1000.c +++ b/drivers/pinctrl/qcom/pinctrl-qdu1000.c @@ -1248,7 +1248,6 @@ static struct platform_driver qdu1000_tlmm_driver = { .of_match_table = qdu1000_tlmm_of_match, }, .probe = qdu1000_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init qdu1000_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sa8775p.c b/drivers/pinctrl/qcom/pinctrl-sa8775p.c index a5b38221aea8..1b62eb3e6620 100644 --- a/drivers/pinctrl/qcom/pinctrl-sa8775p.c +++ b/drivers/pinctrl/qcom/pinctrl-sa8775p.c @@ -1540,7 +1540,6 @@ static struct platform_driver sa8775p_pinctrl_driver = { .of_match_table = sa8775p_pinctrl_of_match, }, .probe = sa8775p_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sa8775p_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sar2130p.c b/drivers/pinctrl/qcom/pinctrl-sar2130p.c index 19a2e37826c7..3dd1b5e5cfee 100644 --- a/drivers/pinctrl/qcom/pinctrl-sar2130p.c +++ b/drivers/pinctrl/qcom/pinctrl-sar2130p.c @@ -1486,7 +1486,6 @@ static struct platform_driver sar2130p_tlmm_driver = { .of_match_table = sar2130p_tlmm_of_match, }, .probe = sar2130p_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sar2130p_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sc7180.c b/drivers/pinctrl/qcom/pinctrl-sc7180.c index 6eb0c73791c0..c43fe10b71ad 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7180.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7180.c @@ -1159,7 +1159,6 @@ static struct platform_driver sc7180_pinctrl_driver = { .of_match_table = sc7180_pinctrl_of_match, }, .probe = sc7180_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sc7180_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c index 0c10eeb60b55..1b070e9d41f5 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7280.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c @@ -1505,7 +1505,6 @@ static struct platform_driver sc7280_pinctrl_driver = { .of_match_table = sc7280_pinctrl_of_match, }, .probe = sc7280_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sc7280_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sc8180x.c b/drivers/pinctrl/qcom/pinctrl-sc8180x.c index d6a79ad41a40..26dd165d1543 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8180x.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8180x.c @@ -1720,7 +1720,6 @@ static struct platform_driver sc8180x_pinctrl_driver = { .acpi_match_table = sc8180x_pinctrl_acpi_match, }, .probe = sc8180x_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sc8180x_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c index 96f4fb5a5d29..6ccd7e5648d4 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc8280xp.c +++ b/drivers/pinctrl/qcom/pinctrl-sc8280xp.c @@ -1926,7 +1926,6 @@ static struct platform_driver sc8280xp_pinctrl_driver = { .of_match_table = sc8280xp_pinctrl_of_match, }, .probe = sc8280xp_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sc8280xp_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660.c b/drivers/pinctrl/qcom/pinctrl-sdm660.c index 907e4ffca5e7..1a78288f1bc8 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm660.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm660.c @@ -1442,7 +1442,6 @@ static struct platform_driver sdm660_pinctrl_driver = { .of_match_table = sdm660_pinctrl_of_match, }, .probe = sdm660_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdm660_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c index c76183ba95e1..0fe1fa94cd6d 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm670.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c @@ -1337,7 +1337,6 @@ static struct platform_driver sdm670_pinctrl_driver = { .of_match_table = sdm670_pinctrl_of_match, }, .probe = sdm670_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdm670_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index cc05c415ed15..0446e291aa48 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -1351,7 +1351,6 @@ static struct platform_driver sdm845_pinctrl_driver = { .acpi_match_table = ACPI_PTR(sdm845_pinctrl_acpi_match), }, .probe = sdm845_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdm845_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdx55.c b/drivers/pinctrl/qcom/pinctrl-sdx55.c index 8826db9d21d0..2c17bf889146 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx55.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx55.c @@ -990,7 +990,6 @@ static struct platform_driver sdx55_pinctrl_driver = { .of_match_table = sdx55_pinctrl_of_match, }, .probe = sdx55_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdx55_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdx65.c b/drivers/pinctrl/qcom/pinctrl-sdx65.c index f6f319c997fc..85b5c0206dbd 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx65.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx65.c @@ -939,7 +939,6 @@ static struct platform_driver sdx65_pinctrl_driver = { .of_match_table = sdx65_pinctrl_of_match, }, .probe = sdx65_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdx65_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sdx75.c b/drivers/pinctrl/qcom/pinctrl-sdx75.c index 3cfe8c7f04df..ab13a3a57a83 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx75.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx75.c @@ -1124,7 +1124,6 @@ static struct platform_driver sdx75_pinctrl_driver = { .of_match_table = sdx75_pinctrl_of_match, }, .probe = sdx75_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sdx75_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm4450.c b/drivers/pinctrl/qcom/pinctrl-sm4450.c index 622f20e6f6f8..1ecdf1ab4f27 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm4450.c +++ b/drivers/pinctrl/qcom/pinctrl-sm4450.c @@ -994,7 +994,6 @@ static struct platform_driver sm4450_tlmm_driver = { .of_match_table = sm4450_tlmm_of_match, }, .probe = sm4450_tlmm_probe, - .remove = msm_pinctrl_remove, }; MODULE_DEVICE_TABLE(of, sm4450_tlmm_of_match); diff --git a/drivers/pinctrl/qcom/pinctrl-sm6115.c b/drivers/pinctrl/qcom/pinctrl-sm6115.c index 4e91c75ad952..c273efa43996 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6115.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6115.c @@ -907,7 +907,6 @@ static struct platform_driver sm6115_tlmm_driver = { .of_match_table = sm6115_tlmm_of_match, }, .probe = sm6115_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm6115_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm6125.c b/drivers/pinctrl/qcom/pinctrl-sm6125.c index c188842047aa..5092f20e0c1b 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6125.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6125.c @@ -1266,7 +1266,6 @@ static struct platform_driver sm6125_tlmm_driver = { .of_match_table = sm6125_tlmm_of_match, }, .probe = sm6125_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm6125_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm6350.c b/drivers/pinctrl/qcom/pinctrl-sm6350.c index f3828c07b134..ba4686c86c54 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6350.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6350.c @@ -1373,7 +1373,6 @@ static struct platform_driver sm6350_tlmm_driver = { .of_match_table = sm6350_tlmm_of_match, }, .probe = sm6350_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm6350_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm6375.c b/drivers/pinctrl/qcom/pinctrl-sm6375.c index c82c8516932e..49031571e65e 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm6375.c +++ b/drivers/pinctrl/qcom/pinctrl-sm6375.c @@ -1516,7 +1516,6 @@ static struct platform_driver sm6375_tlmm_driver = { .of_match_table = sm6375_tlmm_of_match, }, .probe = sm6375_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm6375_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm7150.c b/drivers/pinctrl/qcom/pinctrl-sm7150.c index 3c7fd8af6635..6e89966cd70e 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm7150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm7150.c @@ -1255,7 +1255,6 @@ static struct platform_driver sm7150_tlmm_driver = { .of_match_table = sm7150_tlmm_of_match, }, .probe = sm7150_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm7150_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c b/drivers/pinctrl/qcom/pinctrl-sm8150.c index 01aea9c70b7a..794ed99463f7 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8150.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c @@ -1542,7 +1542,6 @@ static struct platform_driver sm8150_pinctrl_driver = { .of_match_table = sm8150_pinctrl_of_match, }, .probe = sm8150_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8150_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c index e9961a49ff98..fb6f005d64f5 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c @@ -1351,7 +1351,6 @@ static struct platform_driver sm8250_pinctrl_driver = { .of_match_table = sm8250_pinctrl_of_match, }, .probe = sm8250_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8250_pinctrl_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8350.c b/drivers/pinctrl/qcom/pinctrl-sm8350.c index 9c69458bd910..c8a3f39ce6f1 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8350.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8350.c @@ -1642,7 +1642,6 @@ static struct platform_driver sm8350_tlmm_driver = { .of_match_table = sm8350_tlmm_of_match, }, .probe = sm8350_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8350_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8450.c b/drivers/pinctrl/qcom/pinctrl-sm8450.c index d11bb1ee9e3d..f2e52d5a0f93 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8450.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8450.c @@ -1677,7 +1677,6 @@ static struct platform_driver sm8450_tlmm_driver = { .of_match_table = sm8450_tlmm_of_match, }, .probe = sm8450_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8450_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550.c b/drivers/pinctrl/qcom/pinctrl-sm8550.c index 3c847d9cb5d9..1b4496cb39eb 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8550.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8550.c @@ -1762,7 +1762,6 @@ static struct platform_driver sm8550_tlmm_driver = { .of_match_table = sm8550_tlmm_of_match, }, .probe = sm8550_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8550_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8650.c b/drivers/pinctrl/qcom/pinctrl-sm8650.c index 104708252d12..449a0077f4b1 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8650.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8650.c @@ -1742,7 +1742,6 @@ static struct platform_driver sm8650_tlmm_driver = { .of_match_table = sm8650_tlmm_of_match, }, .probe = sm8650_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8650_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-sm8750.c b/drivers/pinctrl/qcom/pinctrl-sm8750.c index b94fb4ee0ec3..8516693d1db5 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8750.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8750.c @@ -1711,7 +1711,6 @@ static struct platform_driver sm8750_tlmm_driver = { .of_match_table = sm8750_tlmm_of_match, }, .probe = sm8750_tlmm_probe, - .remove = msm_pinctrl_remove, }; static int __init sm8750_tlmm_init(void) diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c index 419cb8facb2f..d4b215f34c39 100644 --- a/drivers/pinctrl/qcom/pinctrl-x1e80100.c +++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c @@ -1861,7 +1861,6 @@ static struct platform_driver x1e80100_pinctrl_driver = { .of_match_table = x1e80100_pinctrl_of_match, }, .probe = x1e80100_pinctrl_probe, - .remove = msm_pinctrl_remove, }; static int __init x1e80100_pinctrl_init(void) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c b/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c index 1833078f6877..4e34b0cd3b73 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c @@ -143,7 +143,7 @@ static struct sunxi_desc_pin *init_pins_table(struct device *dev, */ static int prepare_function_table(struct device *dev, struct device_node *pnode, struct sunxi_desc_pin *pins, int npins, - const u8 *irq_bank_muxes) + unsigned pin_base, const u8 *irq_bank_muxes) { struct device_node *node; struct property *prop; @@ -166,7 +166,7 @@ static int prepare_function_table(struct device *dev, struct device_node *pnode, */ for (i = 0; i < npins; i++) { struct sunxi_desc_pin *pin = &pins[i]; - int bank = pin->pin.number / PINS_PER_BANK; + int bank = (pin->pin.number - pin_base) / PINS_PER_BANK; if (irq_bank_muxes[bank]) { pin->variant++; @@ -211,7 +211,7 @@ static int prepare_function_table(struct device *dev, struct device_node *pnode, last_bank = 0; for (i = 0; i < npins; i++) { struct sunxi_desc_pin *pin = &pins[i]; - int bank = pin->pin.number / PINS_PER_BANK; + int bank = (pin->pin.number - pin_base) / PINS_PER_BANK; int lastfunc = pin->variant + 1; int irq_mux = irq_bank_muxes[bank]; @@ -353,7 +353,7 @@ int sunxi_pinctrl_dt_table_init(struct platform_device *pdev, return PTR_ERR(pins); ret = prepare_function_table(&pdev->dev, pnode, pins, desc->npins, - irq_bank_muxes); + desc->pin_base, irq_bank_muxes); if (ret) return ret; diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h index 18934e28469e..528d86a33f37 100644 --- a/drivers/ptp/ptp_private.h +++ b/drivers/ptp/ptp_private.h @@ -98,17 +98,7 @@ static inline int queue_cnt(const struct timestamp_event_queue *q) /* Check if ptp virtual clock is in use */ static inline bool ptp_vclock_in_use(struct ptp_clock *ptp) { - bool in_use = false; - - if (mutex_lock_interruptible(&ptp->n_vclocks_mux)) - return true; - - if (!ptp->is_virtual_clock && ptp->n_vclocks) - in_use = true; - - mutex_unlock(&ptp->n_vclocks_mux); - - return in_use; + return !ptp->is_virtual_clock; } /* Check if ptp clock shall be free running */ diff --git a/drivers/pwm/pwm-axi-pwmgen.c b/drivers/pwm/pwm-axi-pwmgen.c index 60dcd3542373..b40522f01002 100644 --- a/drivers/pwm/pwm-axi-pwmgen.c +++ b/drivers/pwm/pwm-axi-pwmgen.c @@ -18,10 +18,10 @@ * - Supports normal polarity. Does not support changing polarity. * - On disable, the PWM output becomes low (inactive). */ +#include <linux/adi-axi-common.h> #include <linux/bits.h> #include <linux/clk.h> #include <linux/err.h> -#include <linux/fpga/adi-axi-common.h> #include <linux/io.h> #include <linux/minmax.h> #include <linux/module.h> diff --git a/drivers/rapidio/rio_cm.c b/drivers/rapidio/rio_cm.c index 97287e838ce1..66464674223f 100644 --- a/drivers/rapidio/rio_cm.c +++ b/drivers/rapidio/rio_cm.c @@ -783,6 +783,9 @@ static int riocm_ch_send(u16 ch_id, void *buf, int len) if (buf == NULL || ch_id == 0 || len == 0 || len > RIO_MAX_MSG_SIZE) return -EINVAL; + if (len < sizeof(struct rio_ch_chan_hdr)) + return -EINVAL; /* insufficient data from user */ + ch = riocm_get_channel(ch_id); if (!ch) { riocm_error("%s(%d) ch_%d not found", current->comm, diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c index b4fe76e33ff2..fcdd2d0317a5 100644 --- a/drivers/regulator/max20086-regulator.c +++ b/drivers/regulator/max20086-regulator.c @@ -5,6 +5,7 @@ // Copyright (C) 2022 Laurent Pinchart <laurent.pinchart@idesonboard.com> // Copyright (C) 2018 Avnet, Inc. +#include <linux/cleanup.h> #include <linux/err.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> @@ -133,11 +134,11 @@ static int max20086_regulators_register(struct max20086 *chip) static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) { struct of_regulator_match *matches; - struct device_node *node; unsigned int i; int ret; - node = of_get_child_by_name(chip->dev->of_node, "regulators"); + struct device_node *node __free(device_node) = + of_get_child_by_name(chip->dev->of_node, "regulators"); if (!node) { dev_err(chip->dev, "regulators node not found\n"); return -ENODEV; @@ -153,7 +154,6 @@ static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) ret = of_regulator_match(chip->dev, node, matches, chip->info->num_outputs); - of_node_put(node); if (ret < 0) { dev_err(chip->dev, "Failed to match regulators\n"); return -EINVAL; diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 41e36af35488..90a84ae98b97 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -449,6 +449,8 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, if (kstrtoull(buf, 0, (unsigned long long *) &fcp_lun)) return -EINVAL; + flush_work(&port->rport_work); + retval = zfcp_unit_add(port, fcp_lun); if (retval) return retval; diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h index 8ef174cd4d37..3e4124177b2a 100644 --- a/drivers/scsi/mvsas/mv_defs.h +++ b/drivers/scsi/mvsas/mv_defs.h @@ -215,7 +215,7 @@ enum hw_register_bits { /* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */ PHYEV_DEC_ERR = (1U << 24), /* Phy Decoding Error */ - PHYEV_DCDR_ERR = (1U << 23), /* STP Deocder Error */ + PHYEV_DCDR_ERR = (1U << 23), /* STP Decoder Error */ PHYEV_CRC_ERR = (1U << 22), /* STP CRC Error */ PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */ PHYEV_AN = (1U << 18), /* SATA async notification */ @@ -347,7 +347,7 @@ enum sas_cmd_port_registers { CMD_SATA_PORT_MEM_CTL0 = 0x158, /* SATA Port Memory Control 0 */ CMD_SATA_PORT_MEM_CTL1 = 0x15c, /* SATA Port Memory Control 1 */ CMD_XOR_MEM_BIST_CTL = 0x160, /* XOR Memory BIST Control */ - CMD_XOR_MEM_BIST_STAT = 0x164, /* XOR Memroy BIST Status */ + CMD_XOR_MEM_BIST_STAT = 0x164, /* XOR Memory BIST Status */ CMD_DMA_MEM_BIST_CTL = 0x168, /* DMA Memory BIST Control */ CMD_DMA_MEM_BIST_STAT = 0x16c, /* DMA Memory BIST Status */ CMD_PORT_MEM_BIST_CTL = 0x170, /* Port Memory BIST Control */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 376b8897ab90..746ff6a1f309 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -665,7 +665,8 @@ enum scsi_disposition scsi_check_sense(struct scsi_cmnd *scmd) * if the device is in the process of becoming ready, we * should retry. */ - if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01)) + if ((sshdr.asc == 0x04) && + (sshdr.ascq == 0x01 || sshdr.ascq == 0x0a)) return NEEDS_RETRY; /* * if the device is not started, we need to wake diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 0b8c91bf793f..c75a806496d6 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -3499,7 +3499,7 @@ static int iscsi_new_flashnode(struct iscsi_transport *transport, pr_err("%s could not find host no %u\n", __func__, ev->u.new_flashnode.host_no); err = -ENODEV; - goto put_host; + goto exit_new_fnode; } index = transport->new_flashnode(shost, data, len); @@ -3509,7 +3509,6 @@ static int iscsi_new_flashnode(struct iscsi_transport *transport, else err = -EIO; -put_host: scsi_host_put(shost); exit_new_fnode: @@ -3534,7 +3533,7 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport, pr_err("%s could not find host no %u\n", __func__, ev->u.del_flashnode.host_no); err = -ENODEV; - goto put_host; + goto exit_del_fnode; } idx = ev->u.del_flashnode.flashnode_idx; @@ -3576,7 +3575,7 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport, pr_err("%s could not find host no %u\n", __func__, ev->u.login_flashnode.host_no); err = -ENODEV; - goto put_host; + goto exit_login_fnode; } idx = ev->u.login_flashnode.flashnode_idx; @@ -3628,7 +3627,7 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport, pr_err("%s could not find host no %u\n", __func__, ev->u.logout_flashnode.host_no); err = -ENODEV; - goto put_host; + goto exit_logout_fnode; } idx = ev->u.logout_flashnode.flashnode_idx; @@ -3678,7 +3677,7 @@ static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport, pr_err("%s could not find host no %u\n", __func__, ev->u.logout_flashnode.host_no); err = -ENODEV; - goto put_host; + goto exit_logout_sid; } session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid); diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 2e6b2412d2c9..d9e59204a9c3 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -362,7 +362,7 @@ MODULE_PARM_DESC(ring_avail_percent_lowater, /* * Timeout in seconds for all devices managed by this driver. */ -static int storvsc_timeout = 180; +static const int storvsc_timeout = 180; #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) static struct scsi_transport_template *fc_transport_template; @@ -768,7 +768,7 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) return; } - t = wait_for_completion_timeout(&request->wait_event, 10*HZ); + t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ); if (t == 0) { dev_err(dev, "Failed to create sub-channel: timed out\n"); return; @@ -833,7 +833,7 @@ static int storvsc_execute_vstor_op(struct hv_device *device, if (ret != 0) return ret; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ); if (t == 0) return -ETIMEDOUT; @@ -1350,6 +1350,8 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size, return ret; ret = storvsc_channel_init(device, is_fc); + if (ret) + vmbus_close(device->channel); return ret; } @@ -1668,7 +1670,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) if (ret != 0) return FAILED; - t = wait_for_completion_timeout(&request->wait_event, 5*HZ); + t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ); if (t == 0) return TIMEOUT_ERROR; diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 8cc19934b48b..512d53a8ef4d 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -6,12 +6,12 @@ * Author: Lars-Peter Clausen <lars@metafoo.de> */ +#include <linux/adi-axi-common.h> #include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/clk.h> #include <linux/completion.h> #include <linux/dmaengine.h> -#include <linux/fpga/adi-axi-common.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/iopoll.h> diff --git a/drivers/spi/spi-loongson-core.c b/drivers/spi/spi-loongson-core.c index 4fec226456d1..b46f072a0387 100644 --- a/drivers/spi/spi-loongson-core.c +++ b/drivers/spi/spi-loongson-core.c @@ -5,6 +5,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> diff --git a/drivers/spi/spi-offload.c b/drivers/spi/spi-offload.c index e674097bf3be..d336f4d228d5 100644 --- a/drivers/spi/spi-offload.c +++ b/drivers/spi/spi-offload.c @@ -297,7 +297,7 @@ int spi_offload_trigger_enable(struct spi_offload *offload, if (trigger->ops->enable) { ret = trigger->ops->enable(trigger, config); if (ret) { - if (offload->ops->trigger_disable) + if (offload->ops && offload->ops->trigger_disable) offload->ops->trigger_disable(offload); return ret; } diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 29c616e2c408..70bb74b3bd9c 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -134,6 +134,7 @@ struct omap2_mcspi { size_t max_xfer_len; u32 ref_clk_hz; bool use_multi_mode; + bool last_msg_kept_cs; }; struct omap2_mcspi_cs { @@ -1269,6 +1270,10 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr, * multi-mode is applicable. */ mcspi->use_multi_mode = true; + + if (mcspi->last_msg_kept_cs) + mcspi->use_multi_mode = false; + list_for_each_entry(tr, &msg->transfers, transfer_list) { if (!tr->bits_per_word) bits_per_word = msg->spi->bits_per_word; @@ -1287,18 +1292,19 @@ static int omap2_mcspi_prepare_message(struct spi_controller *ctlr, mcspi->use_multi_mode = false; } - /* Check if transfer asks to change the CS status after the transfer */ - if (!tr->cs_change) - mcspi->use_multi_mode = false; - - /* - * If at least one message is not compatible, switch back to single mode - * - * The bits_per_word of certain transfer can be different, but it will have no - * impact on the signal itself. - */ - if (!mcspi->use_multi_mode) - break; + if (list_is_last(&tr->transfer_list, &msg->transfers)) { + /* Check if transfer asks to keep the CS status after the whole message */ + if (tr->cs_change) { + mcspi->use_multi_mode = false; + mcspi->last_msg_kept_cs = true; + } else { + mcspi->last_msg_kept_cs = false; + } + } else { + /* Check if transfer asks to change the CS status after the transfer */ + if (!tr->cs_change) + mcspi->use_multi_mode = false; + } } omap2_mcspi_set_mode(ctlr); diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index c6489e90b8b9..e27642c4dea4 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -762,10 +762,10 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * return -EINVAL; num_vector = pci_alloc_irq_vectors(pdev, 1, hw_inst_cnt, - PCI_IRQ_ALL_TYPES); + PCI_IRQ_INTX | PCI_IRQ_MSI); if (num_vector < 0) { dev_err(&pdev->dev, "Error allocating MSI vectors\n"); - return ret; + return num_vector; } init_completion(&spi_sub_ptr->spi_xfer_done); diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c index 7c1fa55fbc47..4ab7e86f4bd5 100644 --- a/drivers/spi/spi-stm32-ospi.c +++ b/drivers/spi/spi-stm32-ospi.c @@ -804,7 +804,7 @@ static int stm32_ospi_get_resources(struct platform_device *pdev) return ret; } - ospi->rstc = devm_reset_control_array_get_exclusive(dev); + ospi->rstc = devm_reset_control_array_get_exclusive_released(dev); if (IS_ERR(ospi->rstc)) return dev_err_probe(dev, PTR_ERR(ospi->rstc), "Can't get reset\n"); @@ -936,12 +936,16 @@ static int stm32_ospi_probe(struct platform_device *pdev) if (ret < 0) goto err_pm_enable; - if (ospi->rstc) { - reset_control_assert(ospi->rstc); - udelay(2); - reset_control_deassert(ospi->rstc); + ret = reset_control_acquire(ospi->rstc); + if (ret) { + dev_err_probe(dev, ret, "Can not acquire reset %d\n", ret); + goto err_pm_resume; } + reset_control_assert(ospi->rstc); + udelay(2); + reset_control_deassert(ospi->rstc); + ret = spi_register_controller(ctrl); if (ret) { /* Disable ospi */ @@ -987,6 +991,8 @@ static void stm32_ospi_remove(struct platform_device *pdev) if (ospi->dma_chrx) dma_release_channel(ospi->dma_chrx); + reset_control_release(ospi->rstc); + pm_runtime_put_sync_suspend(ospi->dev); pm_runtime_force_suspend(ospi->dev); } @@ -997,6 +1003,8 @@ static int __maybe_unused stm32_ospi_suspend(struct device *dev) pinctrl_pm_select_sleep_state(dev); + reset_control_release(ospi->rstc); + return pm_runtime_force_suspend(ospi->dev); } @@ -1016,6 +1024,12 @@ static int __maybe_unused stm32_ospi_resume(struct device *dev) if (ret < 0) return ret; + ret = reset_control_acquire(ospi->rstc); + if (ret) { + dev_err(dev, "Can not acquire reset\n"); + return ret; + } + writel_relaxed(ospi->cr_reg, regs_base + OSPI_CR); writel_relaxed(ospi->dcr_reg, regs_base + OSPI_DCR1); pm_runtime_mark_last_busy(ospi->dev); diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 4410e7d93b7d..f62d89c8e580 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -6623,9 +6623,14 @@ static void ufshcd_err_handler(struct work_struct *work) up(&hba->host_sem); return; } - ufshcd_set_eh_in_progress(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); + ufshcd_err_handling_prepare(hba); + + spin_lock_irqsave(hba->host->host_lock, flags); + ufshcd_set_eh_in_progress(hba); + spin_unlock_irqrestore(hba->host->host_lock, flags); + /* Complete requests that have door-bell cleared by h/w */ ufshcd_complete_requests(hba, false); spin_lock_irqsave(hba->host->host_lock, flags); diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 3651a296d506..5a1cede2febf 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -296,7 +296,6 @@ do { \ #define bch2_fmt(_c, fmt) bch2_log_msg(_c, fmt "\n") void bch2_print_str(struct bch_fs *, const char *, const char *); -void bch2_print_str_nonblocking(struct bch_fs *, const char *, const char *); __printf(2, 3) void bch2_print_opts(struct bch_opts *, const char *, ...); diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 9ddcbe1bda78..e92cf3928c63 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -397,7 +397,11 @@ again: continue; } - ret = btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan); + ret = lockrestart_do(trans, + btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan)); + if (ret < 0) + goto err; + if (ret == DID_FILL_FROM_SCAN) { new_pass = true; ret = 0; @@ -438,7 +442,8 @@ again: if (!ret && !IS_ERR_OR_NULL(prev)) { BUG_ON(cur); - ret = btree_repair_node_end(trans, b, prev, pulled_from_scan); + ret = lockrestart_do(trans, + btree_repair_node_end(trans, b, prev, pulled_from_scan)); if (ret == DID_FILL_FROM_SCAN) { new_pass = true; ret = 0; @@ -519,6 +524,46 @@ fsck_err: bch2_bkey_buf_exit(&prev_k, c); bch2_bkey_buf_exit(&cur_k, c); printbuf_exit(&buf); + bch_err_fn(c, ret); + return ret; +} + +static int bch2_check_root(struct btree_trans *trans, enum btree_id i, + bool *reconstructed_root) +{ + struct bch_fs *c = trans->c; + struct btree_root *r = bch2_btree_id_root(c, i); + struct printbuf buf = PRINTBUF; + int ret = 0; + + bch2_btree_id_to_text(&buf, i); + + if (r->error) { + bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf); + + r->alive = false; + r->error = 0; + + if (!bch2_btree_has_scanned_nodes(c, i)) { + __fsck_err(trans, + FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0), + btree_root_unreadable_and_scan_found_nothing, + "no nodes found for btree %s, continue?", buf.buf); + bch2_btree_root_alloc_fake_trans(trans, i, 0); + } else { + bch2_btree_root_alloc_fake_trans(trans, i, 1); + bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX); + ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX); + if (ret) + goto err; + } + + *reconstructed_root = true; + } +err: +fsck_err: + printbuf_exit(&buf); + bch_err_fn(c, ret); return ret; } @@ -526,42 +571,18 @@ int bch2_check_topology(struct bch_fs *c) { struct btree_trans *trans = bch2_trans_get(c); struct bpos pulled_from_scan = POS_MIN; - struct printbuf buf = PRINTBUF; int ret = 0; bch2_trans_srcu_unlock(trans); for (unsigned i = 0; i < btree_id_nr_alive(c) && !ret; i++) { - struct btree_root *r = bch2_btree_id_root(c, i); bool reconstructed_root = false; +recover: + ret = lockrestart_do(trans, bch2_check_root(trans, i, &reconstructed_root)); + if (ret) + break; - printbuf_reset(&buf); - bch2_btree_id_to_text(&buf, i); - - if (r->error) { -reconstruct_root: - bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf); - - r->alive = false; - r->error = 0; - - if (!bch2_btree_has_scanned_nodes(c, i)) { - __fsck_err(trans, - FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0), - btree_root_unreadable_and_scan_found_nothing, - "no nodes found for btree %s, continue?", buf.buf); - bch2_btree_root_alloc_fake_trans(trans, i, 0); - } else { - bch2_btree_root_alloc_fake_trans(trans, i, 1); - bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX); - ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX); - if (ret) - break; - } - - reconstructed_root = true; - } - + struct btree_root *r = bch2_btree_id_root(c, i); struct btree *b = r->b; btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read); @@ -575,17 +596,21 @@ reconstruct_root: r->b = NULL; - if (!reconstructed_root) - goto reconstruct_root; + if (!reconstructed_root) { + r->error = -EIO; + goto recover; + } + struct printbuf buf = PRINTBUF; + bch2_btree_id_to_text(&buf, i); bch_err(c, "empty btree root %s", buf.buf); + printbuf_exit(&buf); bch2_btree_root_alloc_fake_trans(trans, i, 0); r->alive = false; ret = 0; } } -fsck_err: - printbuf_exit(&buf); + bch2_trans_put(trans); return ret; } diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 57eff3012a7b..d8f3c4c65e90 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -741,16 +741,22 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca, BCH_VERSION_MAJOR(version), BCH_VERSION_MINOR(version)); - if (btree_err_on(version < c->sb.version_min, + if (c->recovery.curr_pass != BCH_RECOVERY_PASS_scan_for_btree_nodes && + btree_err_on(version < c->sb.version_min, -BCH_ERR_btree_node_read_err_fixable, c, NULL, b, i, NULL, btree_node_bset_older_than_sb_min, "bset version %u older than superblock version_min %u", version, c->sb.version_min)) { - mutex_lock(&c->sb_lock); - c->disk_sb.sb->version_min = cpu_to_le16(version); - bch2_write_super(c); - mutex_unlock(&c->sb_lock); + if (bch2_version_compatible(version)) { + mutex_lock(&c->sb_lock); + c->disk_sb.sb->version_min = cpu_to_le16(version); + bch2_write_super(c); + mutex_unlock(&c->sb_lock); + } else { + /* We have no idea what's going on: */ + i->version = cpu_to_le16(c->sb.version); + } } if (btree_err_on(BCH_VERSION_MAJOR(version) > @@ -1045,6 +1051,7 @@ got_good_key: le16_add_cpu(&i->u64s, -next_good_key); memmove_u64s_down(k, (u64 *) k + next_good_key, (u64 *) vstruct_end(i) - (u64 *) k); set_btree_node_need_rewrite(b); + set_btree_node_need_rewrite_error(b); } fsck_err: printbuf_exit(&buf); @@ -1305,6 +1312,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca, (u64 *) vstruct_end(i) - (u64 *) k); set_btree_bset_end(b, b->set); set_btree_node_need_rewrite(b); + set_btree_node_need_rewrite_error(b); continue; } if (ret) @@ -1329,12 +1337,16 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct bch_dev *ca, bkey_for_each_ptr(bch2_bkey_ptrs(bkey_i_to_s(&b->key)), ptr) { struct bch_dev *ca2 = bch2_dev_rcu(c, ptr->dev); - if (!ca2 || ca2->mi.state != BCH_MEMBER_STATE_rw) + if (!ca2 || ca2->mi.state != BCH_MEMBER_STATE_rw) { set_btree_node_need_rewrite(b); + set_btree_node_need_rewrite_degraded(b); + } } - if (!ptr_written) + if (!ptr_written) { set_btree_node_need_rewrite(b); + set_btree_node_need_rewrite_ptr_written_zero(b); + } fsck_err: mempool_free(iter, &c->fill_iter); printbuf_exit(&buf); diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c index 47035aae232e..91a51aef82f1 100644 --- a/fs/bcachefs/btree_locking.c +++ b/fs/bcachefs/btree_locking.c @@ -213,7 +213,7 @@ static noinline __noreturn void break_cycle_fail(struct lock_graph *g) prt_newline(&buf); } - bch2_print_str_nonblocking(g->g->trans->c, KERN_ERR, buf.buf); + bch2_print_str(g->g->trans->c, KERN_ERR, buf.buf); printbuf_exit(&buf); BUG(); } diff --git a/fs/bcachefs/btree_locking.h b/fs/bcachefs/btree_locking.h index 9adca77e2580..f2173a3316f4 100644 --- a/fs/bcachefs/btree_locking.h +++ b/fs/bcachefs/btree_locking.h @@ -417,8 +417,10 @@ static inline void btree_path_set_should_be_locked(struct btree_trans *trans, st EBUG_ON(!btree_node_locked(path, path->level)); EBUG_ON(path->uptodate); - path->should_be_locked = true; - trace_btree_path_should_be_locked(trans, path); + if (!path->should_be_locked) { + path->should_be_locked = true; + trace_btree_path_should_be_locked(trans, path); + } } static inline void __btree_path_set_level_up(struct btree_trans *trans, diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index c61c4171ae50..3aa4a602bd02 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -617,6 +617,9 @@ enum btree_write_type { x(dying) \ x(fake) \ x(need_rewrite) \ + x(need_rewrite_error) \ + x(need_rewrite_degraded) \ + x(need_rewrite_ptr_written_zero) \ x(never_write) \ x(pinned) @@ -641,6 +644,32 @@ static inline void clear_btree_node_ ## flag(struct btree *b) \ BTREE_FLAGS() #undef x +#define BTREE_NODE_REWRITE_REASON() \ + x(none) \ + x(unknown) \ + x(error) \ + x(degraded) \ + x(ptr_written_zero) + +enum btree_node_rewrite_reason { +#define x(n) BTREE_NODE_REWRITE_##n, + BTREE_NODE_REWRITE_REASON() +#undef x +}; + +static inline enum btree_node_rewrite_reason btree_node_rewrite_reason(struct btree *b) +{ + if (btree_node_need_rewrite_ptr_written_zero(b)) + return BTREE_NODE_REWRITE_ptr_written_zero; + if (btree_node_need_rewrite_degraded(b)) + return BTREE_NODE_REWRITE_degraded; + if (btree_node_need_rewrite_error(b)) + return BTREE_NODE_REWRITE_error; + if (btree_node_need_rewrite(b)) + return BTREE_NODE_REWRITE_unknown; + return BTREE_NODE_REWRITE_none; +} + static inline struct btree_write *btree_current_write(struct btree *b) { return b->writes + btree_node_write_idx(b); diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index d2ecb782919b..e77584607f0d 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1138,6 +1138,13 @@ static void bch2_btree_update_done(struct btree_update *as, struct btree_trans * start_time); } +static const char * const btree_node_reawrite_reason_strs[] = { +#define x(n) #n, + BTREE_NODE_REWRITE_REASON() +#undef x + NULL, +}; + static struct btree_update * bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, unsigned level_start, bool split, @@ -1232,6 +1239,15 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, list_add_tail(&as->list, &c->btree_interior_update_list); mutex_unlock(&c->btree_interior_update_lock); + struct btree *b = btree_path_node(path, path->level); + as->node_start = b->data->min_key; + as->node_end = b->data->max_key; + as->node_needed_rewrite = btree_node_rewrite_reason(b); + as->node_written = b->written; + as->node_sectors = btree_buf_bytes(b) >> 9; + as->node_remaining = __bch2_btree_u64s_remaining(b, + btree_bkey_last(b, bset_tree_last(b))); + /* * We don't want to allocate if we're in an error state, that can cause * deadlock on emergency shutdown due to open buckets getting stuck in @@ -2108,6 +2124,9 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans, if (ret) goto err; + as->node_start = prev->data->min_key; + as->node_end = next->data->max_key; + trace_and_count(c, btree_node_merge, trans, b); n = bch2_btree_node_alloc(as, trans, b->c.level); @@ -2681,9 +2700,19 @@ static void bch2_btree_update_to_text(struct printbuf *out, struct btree_update prt_str(out, " "); bch2_btree_id_to_text(out, as->btree_id); - prt_printf(out, " l=%u-%u mode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n", + prt_printf(out, " l=%u-%u ", as->update_level_start, - as->update_level_end, + as->update_level_end); + bch2_bpos_to_text(out, as->node_start); + prt_char(out, ' '); + bch2_bpos_to_text(out, as->node_end); + prt_printf(out, "\nwritten %u/%u u64s_remaining %u need_rewrite %s", + as->node_written, + as->node_sectors, + as->node_remaining, + btree_node_reawrite_reason_strs[as->node_needed_rewrite]); + + prt_printf(out, "\nmode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n", bch2_btree_update_modes[as->mode], as->nodes_written, closure_nr_remaining(&as->cl), diff --git a/fs/bcachefs/btree_update_interior.h b/fs/bcachefs/btree_update_interior.h index 7fe793788a79..b649c36c3fbb 100644 --- a/fs/bcachefs/btree_update_interior.h +++ b/fs/bcachefs/btree_update_interior.h @@ -57,6 +57,13 @@ struct btree_update { unsigned took_gc_lock:1; enum btree_id btree_id; + struct bpos node_start; + struct bpos node_end; + enum btree_node_rewrite_reason node_needed_rewrite; + u16 node_written; + u16 node_sectors; + u16 node_remaining; + unsigned update_level_start; unsigned update_level_end; diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index 2d38466eddfd..fde3c2380e28 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -399,7 +399,7 @@ static long bch2_ioctl_data(struct bch_fs *c, return ret; } -static long bch2_ioctl_fs_usage(struct bch_fs *c, +static noinline_for_stack long bch2_ioctl_fs_usage(struct bch_fs *c, struct bch_ioctl_fs_usage __user *user_arg) { struct bch_ioctl_fs_usage arg = {}; @@ -469,7 +469,7 @@ err: } /* obsolete, didn't allow for new data types: */ -static long bch2_ioctl_dev_usage(struct bch_fs *c, +static noinline_for_stack long bch2_ioctl_dev_usage(struct bch_fs *c, struct bch_ioctl_dev_usage __user *user_arg) { struct bch_ioctl_dev_usage arg; diff --git a/fs/bcachefs/disk_accounting.c b/fs/bcachefs/disk_accounting.c index 3d59a57a5256..f7528cd69c73 100644 --- a/fs/bcachefs/disk_accounting.c +++ b/fs/bcachefs/disk_accounting.c @@ -618,7 +618,9 @@ int bch2_gc_accounting_done(struct bch_fs *c) for (unsigned j = 0; j < nr; j++) src_v[j] -= dst_v[j]; - if (fsck_err(trans, accounting_mismatch, "%s", buf.buf)) { + bch2_trans_unlock_long(trans); + + if (fsck_err(c, accounting_mismatch, "%s", buf.buf)) { percpu_up_write(&c->mark_lock); ret = commit_do(trans, NULL, NULL, 0, bch2_disk_accounting_mod(trans, &acc_k, src_v, nr, false)); diff --git a/fs/bcachefs/error.c b/fs/bcachefs/error.c index 63951e293c47..a8ec6aae5738 100644 --- a/fs/bcachefs/error.c +++ b/fs/bcachefs/error.c @@ -69,7 +69,7 @@ static bool bch2_fs_trans_inconsistent(struct bch_fs *c, struct btree_trans *tra if (trans) bch2_trans_updates_to_text(&buf, trans); bool ret = __bch2_inconsistent_error(c, &buf); - bch2_print_str_nonblocking(c, KERN_ERR, buf.buf); + bch2_print_str(c, KERN_ERR, buf.buf); printbuf_exit(&buf); return ret; @@ -620,6 +620,9 @@ print: if (s) s->ret = ret; + + if (trans) + ret = bch2_trans_log_str(trans, bch2_sb_error_strs[err]) ?: ret; err_unlock: mutex_unlock(&c->fsck_error_msgs_lock); err: diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index 85d13f800165..3063a8ddc2df 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -2490,6 +2490,14 @@ static int bch2_fs_get_tree(struct fs_context *fc) if (ret) goto err_stop_fs; + /* + * We might be doing a RO mount because other options required it, or we + * have no alloc info and it's a small image with no room to regenerate + * it + */ + if (c->opts.read_only) + fc->sb_flags |= SB_RDONLY; + sb = sget(fc->fs_type, NULL, bch2_set_super, fc->sb_flags|SB_NOSEC, c); ret = PTR_ERR_OR_ZERO(sb); if (ret) diff --git a/fs/bcachefs/io_read.c b/fs/bcachefs/io_read.c index a77779afad01..04bbdcf58e40 100644 --- a/fs/bcachefs/io_read.c +++ b/fs/bcachefs/io_read.c @@ -343,6 +343,10 @@ static struct bch_read_bio *promote_alloc(struct btree_trans *trans, *bounce = true; *read_full = promote_full; + + if (have_io_error(failed)) + orig->self_healing = true; + return promote; nopromote: trace_io_read_nopromote(c, ret); @@ -635,12 +639,15 @@ static void bch2_rbio_retry(struct work_struct *work) prt_str(&buf, "(internal move) "); prt_str(&buf, "data read error, "); - if (!ret) + if (!ret) { prt_str(&buf, "successful retry"); - else + if (rbio->self_healing) + prt_str(&buf, ", self healing"); + } else prt_str(&buf, bch2_err_str(ret)); prt_newline(&buf); + if (!bkey_deleted(&sk.k->k)) { bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(sk.k)); prt_newline(&buf); diff --git a/fs/bcachefs/io_read.h b/fs/bcachefs/io_read.h index 45c959018919..9c5ddbf861b3 100644 --- a/fs/bcachefs/io_read.h +++ b/fs/bcachefs/io_read.h @@ -44,6 +44,7 @@ struct bch_read_bio { have_ioref:1, narrow_crcs:1, saw_error:1, + self_healing:1, context:2; }; u16 _state; diff --git a/fs/bcachefs/movinggc.c b/fs/bcachefs/movinggc.c index 6d7b1d5f7697..27e68d470ad0 100644 --- a/fs/bcachefs/movinggc.c +++ b/fs/bcachefs/movinggc.c @@ -28,7 +28,7 @@ #include <linux/wait.h> struct buckets_in_flight { - struct rhashtable table; + struct rhashtable *table; struct move_bucket *first; struct move_bucket *last; size_t nr; @@ -98,7 +98,7 @@ out: static void move_bucket_free(struct buckets_in_flight *list, struct move_bucket *b) { - int ret = rhashtable_remove_fast(&list->table, &b->hash, + int ret = rhashtable_remove_fast(list->table, &b->hash, bch_move_bucket_params); BUG_ON(ret); kfree(b); @@ -133,7 +133,7 @@ static void move_buckets_wait(struct moving_context *ctxt, static bool bucket_in_flight(struct buckets_in_flight *list, struct move_bucket_key k) { - return rhashtable_lookup_fast(&list->table, &k, bch_move_bucket_params); + return rhashtable_lookup_fast(list->table, &k, bch_move_bucket_params); } static int bch2_copygc_get_buckets(struct moving_context *ctxt, @@ -185,7 +185,7 @@ static int bch2_copygc_get_buckets(struct moving_context *ctxt, goto err; } - ret2 = rhashtable_lookup_insert_fast(&buckets_in_flight->table, &b_i->hash, + ret2 = rhashtable_lookup_insert_fast(buckets_in_flight->table, &b_i->hash, bch_move_bucket_params); BUG_ON(ret2); @@ -350,10 +350,13 @@ static int bch2_copygc_thread(void *arg) struct buckets_in_flight buckets = {}; u64 last, wait; - int ret = rhashtable_init(&buckets.table, &bch_move_bucket_params); + buckets.table = kzalloc(sizeof(*buckets.table), GFP_KERNEL); + int ret = !buckets.table + ? -ENOMEM + : rhashtable_init(buckets.table, &bch_move_bucket_params); bch_err_msg(c, ret, "allocating copygc buckets in flight"); if (ret) - return ret; + goto err; set_freezable(); @@ -421,11 +424,12 @@ static int bch2_copygc_thread(void *arg) } move_buckets_wait(&ctxt, &buckets, true); - rhashtable_destroy(&buckets.table); + rhashtable_destroy(buckets.table); bch2_moving_ctxt_exit(&ctxt); bch2_move_stats_exit(&move_stats, c); - - return 0; +err: + kfree(buckets.table); + return ret; } void bch2_copygc_stop(struct bch_fs *c) diff --git a/fs/bcachefs/namei.c b/fs/bcachefs/namei.c index 24120037c031..779c22eb3979 100644 --- a/fs/bcachefs/namei.c +++ b/fs/bcachefs/namei.c @@ -175,6 +175,16 @@ int bch2_create_trans(struct btree_trans *trans, new_inode->bi_dir_offset = dir_offset; } + if (S_ISDIR(mode)) { + ret = bch2_maybe_propagate_has_case_insensitive(trans, + (subvol_inum) { + new_inode->bi_subvol ?: dir.subvol, + new_inode->bi_inum }, + new_inode); + if (ret) + goto err; + } + if (S_ISDIR(mode) && !new_inode->bi_subvol) new_inode->bi_depth = dir_u->bi_depth + 1; diff --git a/fs/bcachefs/rcu_pending.c b/fs/bcachefs/rcu_pending.c index bef2aa1b8bcd..b1438be9d690 100644 --- a/fs/bcachefs/rcu_pending.c +++ b/fs/bcachefs/rcu_pending.c @@ -182,11 +182,6 @@ static inline void kfree_bulk(size_t nr, void ** p) while (nr--) kfree(*p); } - -#define local_irq_save(flags) \ -do { \ - flags = 0; \ -} while (0) #endif static noinline void __process_finished_items(struct rcu_pending *pending, @@ -429,9 +424,15 @@ __rcu_pending_enqueue(struct rcu_pending *pending, struct rcu_head *head, BUG_ON((ptr != NULL) != (pending->process == RCU_PENDING_KVFREE_FN)); - local_irq_save(flags); - p = this_cpu_ptr(pending->p); - spin_lock(&p->lock); + /* We could technically be scheduled before taking the lock and end up + * using a different cpu's rcu_pending_pcpu: that's ok, it needs a lock + * anyways + * + * And we have to do it this way to avoid breaking PREEMPT_RT, which + * redefines how spinlocks work: + */ + p = raw_cpu_ptr(pending->p); + spin_lock_irqsave(&p->lock, flags); rcu_gp_poll_state_t seq = __get_state_synchronize_rcu(pending->srcu); restart: if (may_sleep && @@ -520,9 +521,8 @@ check_expired: goto free_node; } - local_irq_save(flags); - p = this_cpu_ptr(pending->p); - spin_lock(&p->lock); + p = raw_cpu_ptr(pending->p); + spin_lock_irqsave(&p->lock, flags); goto restart; } diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 1e68e61f08e8..0b21fa6ff062 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -99,9 +99,11 @@ int bch2_btree_lost_data(struct bch_fs *c, goto out; case BTREE_ID_snapshots: ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_reconstruct_snapshots, 0) ?: ret; + ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_topology, 0) ?: ret; ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret; goto out; default: + ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_topology, 0) ?: ret; ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret; goto out; } @@ -271,13 +273,24 @@ static int bch2_journal_replay_key(struct btree_trans *trans, goto out; struct btree_path *path = btree_iter_path(trans, &iter); - if (unlikely(!btree_path_node(path, k->level))) { + if (unlikely(!btree_path_node(path, k->level) && + !k->allocated)) { + struct bch_fs *c = trans->c; + + if (!(c->recovery.passes_complete & (BIT_ULL(BCH_RECOVERY_PASS_scan_for_btree_nodes)| + BIT_ULL(BCH_RECOVERY_PASS_check_topology)))) { + bch_err(c, "have key in journal replay for btree depth that does not exist, confused"); + ret = -EINVAL; + } +#if 0 bch2_trans_iter_exit(trans, &iter); bch2_trans_node_iter_init(trans, &iter, k->btree_id, k->k->k.p, BTREE_MAX_DEPTH, 0, iter_flags); ret = bch2_btree_iter_traverse(trans, &iter) ?: bch2_btree_increase_depth(trans, iter.path, 0) ?: -BCH_ERR_transaction_restart_nested; +#endif + k->overwritten = true; goto out; } @@ -739,9 +752,11 @@ int bch2_fs_recovery(struct bch_fs *c) ? min(c->opts.recovery_pass_last, BCH_RECOVERY_PASS_snapshots_read) : BCH_RECOVERY_PASS_snapshots_read; c->opts.nochanges = true; - c->opts.read_only = true; } + if (c->opts.nochanges) + c->opts.read_only = true; + mutex_lock(&c->sb_lock); struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext); bool write_sb = false; @@ -1093,9 +1108,6 @@ use_clean: out: bch2_flush_fsck_errs(c); - if (!IS_ERR(clean)) - kfree(clean); - if (!ret && test_bit(BCH_FS_need_delete_dead_snapshots, &c->flags) && !c->opts.nochanges) { @@ -1104,6 +1116,9 @@ out: } bch_err_fn(c, ret); +final_out: + if (!IS_ERR(clean)) + kfree(clean); return ret; err: fsck_err: @@ -1117,7 +1132,7 @@ fsck_err: bch2_print_str(c, KERN_ERR, buf.buf); printbuf_exit(&buf); } - return ret; + goto final_out; } int bch2_fs_initialize(struct bch_fs *c) diff --git a/fs/bcachefs/recovery_passes.c b/fs/bcachefs/recovery_passes.c index 605588e33fb3..35ac0d64d73a 100644 --- a/fs/bcachefs/recovery_passes.c +++ b/fs/bcachefs/recovery_passes.c @@ -294,8 +294,13 @@ static bool recovery_pass_needs_set(struct bch_fs *c, enum bch_run_recovery_pass_flags *flags) { struct bch_fs_recovery *r = &c->recovery; - bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags); - bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent); + + /* + * Never run scan_for_btree_nodes persistently: check_topology will run + * it if required + */ + if (pass == BCH_RECOVERY_PASS_scan_for_btree_nodes) + *flags |= RUN_RECOVERY_PASS_nopersistent; if ((*flags & RUN_RECOVERY_PASS_ratelimit) && !bch2_recovery_pass_want_ratelimit(c, pass)) @@ -310,6 +315,8 @@ static bool recovery_pass_needs_set(struct bch_fs *c, * Otherwise, we run run_explicit_recovery_pass when we find damage, so * it should run again even if it's already run: */ + bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags); + bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent); if (persistent ? !(c->sb.recovery_passes_required & BIT_ULL(pass)) @@ -334,6 +341,7 @@ int __bch2_run_explicit_recovery_pass(struct bch_fs *c, struct bch_fs_recovery *r = &c->recovery; int ret = 0; + lockdep_assert_held(&c->sb_lock); bch2_printbuf_make_room(out, 1024); @@ -446,7 +454,7 @@ int bch2_require_recovery_pass(struct bch_fs *c, int bch2_run_print_explicit_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass) { - enum bch_run_recovery_pass_flags flags = RUN_RECOVERY_PASS_nopersistent; + enum bch_run_recovery_pass_flags flags = 0; if (!recovery_pass_needs_set(c, pass, &flags)) return 0; diff --git a/fs/bcachefs/sb-downgrade.c b/fs/bcachefs/sb-downgrade.c index b61f88450a6d..1506d05e0665 100644 --- a/fs/bcachefs/sb-downgrade.c +++ b/fs/bcachefs/sb-downgrade.c @@ -253,6 +253,7 @@ DOWNGRADE_TABLE() static int downgrade_table_extra(struct bch_fs *c, darray_char *table) { + unsigned dst_offset = table->nr; struct bch_sb_field_downgrade_entry *dst = (void *) &darray_top(*table); unsigned bytes = sizeof(*dst) + sizeof(dst->errors[0]) * le16_to_cpu(dst->nr_errors); int ret = 0; @@ -268,6 +269,9 @@ static int downgrade_table_extra(struct bch_fs *c, darray_char *table) if (ret) return ret; + dst = (void *) &table->data[dst_offset]; + dst->nr_errors = cpu_to_le16(nr_errors + 1); + /* open coded __set_bit_le64, as dst is packed and * dst->recovery_passes is misaligned */ unsigned b = BCH_RECOVERY_PASS_STABLE_check_allocations; @@ -278,7 +282,6 @@ static int downgrade_table_extra(struct bch_fs *c, darray_char *table) break; } - dst->nr_errors = cpu_to_le16(nr_errors); return ret; } diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h index 6fdbf265e4c0..d06e73884871 100644 --- a/fs/bcachefs/sb-errors_format.h +++ b/fs/bcachefs/sb-errors_format.h @@ -134,7 +134,7 @@ enum bch_fsck_flags { x(bucket_gens_to_invalid_buckets, 121, FSCK_AUTOFIX) \ x(bucket_gens_nonzero_for_invalid_buckets, 122, FSCK_AUTOFIX) \ x(need_discard_freespace_key_to_invalid_dev_bucket, 123, 0) \ - x(need_discard_freespace_key_bad, 124, 0) \ + x(need_discard_freespace_key_bad, 124, FSCK_AUTOFIX) \ x(discarding_bucket_not_in_need_discard_btree, 291, 0) \ x(backpointer_bucket_offset_wrong, 125, 0) \ x(backpointer_level_bad, 294, 0) \ @@ -165,7 +165,7 @@ enum bch_fsck_flags { x(ptr_to_missing_replicas_entry, 149, FSCK_AUTOFIX) \ x(ptr_to_missing_stripe, 150, 0) \ x(ptr_to_incorrect_stripe, 151, 0) \ - x(ptr_gen_newer_than_bucket_gen, 152, 0) \ + x(ptr_gen_newer_than_bucket_gen, 152, FSCK_AUTOFIX) \ x(ptr_too_stale, 153, 0) \ x(stale_dirty_ptr, 154, FSCK_AUTOFIX) \ x(ptr_bucket_data_type_mismatch, 155, 0) \ @@ -236,7 +236,7 @@ enum bch_fsck_flags { x(inode_multiple_links_but_nlink_0, 207, FSCK_AUTOFIX) \ x(inode_wrong_backpointer, 208, FSCK_AUTOFIX) \ x(inode_wrong_nlink, 209, FSCK_AUTOFIX) \ - x(inode_has_child_snapshots_wrong, 287, 0) \ + x(inode_has_child_snapshots_wrong, 287, FSCK_AUTOFIX) \ x(inode_unreachable, 210, FSCK_AUTOFIX) \ x(inode_journal_seq_in_future, 299, FSCK_AUTOFIX) \ x(inode_i_sectors_underflow, 312, FSCK_AUTOFIX) \ @@ -279,8 +279,8 @@ enum bch_fsck_flags { x(root_dir_missing, 239, 0) \ x(root_inode_not_dir, 240, 0) \ x(dir_loop, 241, 0) \ - x(hash_table_key_duplicate, 242, 0) \ - x(hash_table_key_wrong_offset, 243, 0) \ + x(hash_table_key_duplicate, 242, FSCK_AUTOFIX) \ + x(hash_table_key_wrong_offset, 243, FSCK_AUTOFIX) \ x(unlinked_inode_not_on_deleted_list, 244, FSCK_AUTOFIX) \ x(reflink_p_front_pad_bad, 245, 0) \ x(journal_entry_dup_same_device, 246, 0) \ diff --git a/fs/bcachefs/sb-members.c b/fs/bcachefs/sb-members.c index 363eb0c6eb7c..6245e342a8a8 100644 --- a/fs/bcachefs/sb-members.c +++ b/fs/bcachefs/sb-members.c @@ -325,9 +325,17 @@ static void bch2_sb_members_v1_to_text(struct printbuf *out, struct bch_sb *sb, { struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1); struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups); - unsigned i; - for (i = 0; i < sb->nr_devices; i++) + if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) { + prt_printf(out, "field ends before start of entries"); + return; + } + + unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / sizeof(mi->_members[0]); + if (nr != sb->nr_devices) + prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices); + + for (unsigned i = 0; i < min(sb->nr_devices, nr); i++) member_to_text(out, members_v1_get(mi, i), gi, sb, i); } @@ -341,9 +349,27 @@ static void bch2_sb_members_v2_to_text(struct printbuf *out, struct bch_sb *sb, { struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2); struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups); - unsigned i; - for (i = 0; i < sb->nr_devices; i++) + if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) { + prt_printf(out, "field ends before start of entries"); + return; + } + + if (!le16_to_cpu(mi->member_bytes)) { + prt_printf(out, "member_bytes 0"); + return; + } + + unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / le16_to_cpu(mi->member_bytes); + if (nr != sb->nr_devices) + prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices); + + /* + * We call to_text() on superblock sections that haven't passed + * validate, so we can't trust sb->nr_devices. + */ + + for (unsigned i = 0; i < min(sb->nr_devices, nr); i++) member_to_text(out, members_v2_get(mi, i), gi, sb, i); } diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 397a69da5a75..a5b97c9c5163 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -104,7 +104,7 @@ const char * const bch2_dev_write_refs[] = { #undef x static void __bch2_print_str(struct bch_fs *c, const char *prefix, - const char *str, bool nonblocking) + const char *str) { #ifdef __KERNEL__ struct stdio_redirect *stdio = bch2_fs_stdio_redirect(c); @@ -114,17 +114,12 @@ static void __bch2_print_str(struct bch_fs *c, const char *prefix, return; } #endif - bch2_print_string_as_lines(KERN_ERR, str, nonblocking); + bch2_print_string_as_lines(KERN_ERR, str); } void bch2_print_str(struct bch_fs *c, const char *prefix, const char *str) { - __bch2_print_str(c, prefix, str, false); -} - -void bch2_print_str_nonblocking(struct bch_fs *c, const char *prefix, const char *str) -{ - __bch2_print_str(c, prefix, str, true); + __bch2_print_str(c, prefix, str); } __printf(2, 0) @@ -1072,12 +1067,13 @@ noinline_for_stack static void print_mount_opts(struct bch_fs *c) { enum bch_opt_id i; - struct printbuf p = PRINTBUF; - bool first = true; + CLASS(printbuf, p)(); + bch2_log_msg_start(c, &p); prt_str(&p, "starting version "); bch2_version_to_text(&p, c->sb.version); + bool first = true; for (i = 0; i < bch2_opts_nr; i++) { const struct bch_option *opt = &bch2_opt_table[i]; u64 v = bch2_opt_get_by_id(&c->opts, i); @@ -1094,17 +1090,24 @@ static void print_mount_opts(struct bch_fs *c) } if (c->sb.version_incompat_allowed != c->sb.version) { - prt_printf(&p, "\n allowing incompatible features above "); + prt_printf(&p, "\nallowing incompatible features above "); bch2_version_to_text(&p, c->sb.version_incompat_allowed); } if (c->opts.verbose) { - prt_printf(&p, "\n features: "); + prt_printf(&p, "\nfeatures: "); prt_bitflags(&p, bch2_sb_features, c->sb.features); } - bch_info(c, "%s", p.buf); - printbuf_exit(&p); + if (c->sb.multi_device) { + prt_printf(&p, "\nwith devices"); + for_each_online_member(c, ca, BCH_DEV_READ_REF_bch2_online_devs) { + prt_char(&p, ' '); + prt_str(&p, ca->name); + } + } + + bch2_print_str(c, KERN_INFO, p.buf); } static bool bch2_fs_may_start(struct bch_fs *c) @@ -1995,6 +1998,22 @@ int bch2_dev_add(struct bch_fs *c, const char *path) goto err_late; } + /* + * We just changed the superblock UUID, invalidate cache and send a + * uevent to update /dev/disk/by-uuid + */ + invalidate_bdev(ca->disk_sb.bdev); + + char uuid_str[37]; + snprintf(uuid_str, sizeof(uuid_str), "UUID=%pUb", &c->sb.uuid); + + char *envp[] = { + "CHANGE=uuid", + uuid_str, + NULL, + }; + kobject_uevent_env(&ca->disk_sb.bdev->bd_device.kobj, KOBJ_CHANGE, envp); + up_write(&c->state_lock); out: printbuf_exit(&label); diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index dc3817f545fa..df9a6071fe18 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -262,8 +262,7 @@ static bool string_is_spaces(const char *str) return true; } -void bch2_print_string_as_lines(const char *prefix, const char *lines, - bool nonblocking) +void bch2_print_string_as_lines(const char *prefix, const char *lines) { bool locked = false; const char *p; @@ -273,12 +272,7 @@ void bch2_print_string_as_lines(const char *prefix, const char *lines, return; } - if (!nonblocking) { - console_lock(); - locked = true; - } else { - locked = console_trylock(); - } + locked = console_trylock(); while (*lines) { p = strchrnul(lines, '\n'); diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h index 0a4b1d433621..6488f098d140 100644 --- a/fs/bcachefs/util.h +++ b/fs/bcachefs/util.h @@ -214,7 +214,7 @@ u64 bch2_read_flag_list(const char *, const char * const[]); void bch2_prt_u64_base2_nbits(struct printbuf *, u64, unsigned); void bch2_prt_u64_base2(struct printbuf *, u64); -void bch2_print_string_as_lines(const char *, const char *, bool); +void bch2_print_string_as_lines(const char *, const char *); typedef DARRAY(unsigned long) bch_stacktrace; int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *, unsigned, gfp_t); diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h index 1dfe79d947a6..bc8a812ff95f 100644 --- a/fs/smb/client/cached_dir.h +++ b/fs/smb/client/cached_dir.h @@ -21,10 +21,10 @@ struct cached_dirent { struct cached_dirents { bool is_valid:1; bool is_failed:1; - struct dir_context *ctx; /* - * Only used to make sure we only take entries - * from a single context. Never dereferenced. - */ + struct file *file; /* + * Used to associate the cache with a single + * open file instance. + */ struct mutex de_mutex; int pos; /* Expected ctx->pos */ struct list_head entries; diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 28bc33496623..c4fb80b37738 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -3718,9 +3718,15 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx) goto out; } - /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */ - if (tcon->posix_extensions) + /* + * if new SMB3.11 POSIX extensions are supported, do not change anything in the + * path (i.e., do not remap / and \ and do not map any special characters) + */ + if (tcon->posix_extensions) { cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; + cifs_sb->mnt_cifs_flags &= ~(CIFS_MOUNT_MAP_SFM_CHR | + CIFS_MOUNT_MAP_SPECIAL_CHR); + } #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY /* tell server which Unix caps we support */ diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index d2df10b8e6fd..9835672267d2 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -999,15 +999,18 @@ int cifs_open(struct inode *inode, struct file *file) rc = cifs_get_readable_path(tcon, full_path, &cfile); } if (rc == 0) { - if (file->f_flags == cfile->f_flags) { + unsigned int oflags = file->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC); + unsigned int cflags = cfile->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC); + + if (cifs_convert_flags(oflags, 0) == cifs_convert_flags(cflags, 0) && + (oflags & (O_SYNC|O_DIRECT)) == (cflags & (O_SYNC|O_DIRECT))) { file->private_data = cfile; spin_lock(&CIFS_I(inode)->deferred_lock); cifs_del_deferred_close(cfile); spin_unlock(&CIFS_I(inode)->deferred_lock); goto use_cache; - } else { - _cifsFileInfo_put(cfile, true, false); } + _cifsFileInfo_put(cfile, true, false); } else { /* hard link on the defeered close file */ rc = cifs_get_hardlink_path(tcon, inode, file); diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c index f9f11cbf89be..ba0193cf9033 100644 --- a/fs/smb/client/readdir.c +++ b/fs/smb/client/readdir.c @@ -851,9 +851,9 @@ static bool emit_cached_dirents(struct cached_dirents *cde, } static void update_cached_dirents_count(struct cached_dirents *cde, - struct dir_context *ctx) + struct file *file) { - if (cde->ctx != ctx) + if (cde->file != file) return; if (cde->is_valid || cde->is_failed) return; @@ -862,9 +862,9 @@ static void update_cached_dirents_count(struct cached_dirents *cde, } static void finished_cached_dirents_count(struct cached_dirents *cde, - struct dir_context *ctx) + struct dir_context *ctx, struct file *file) { - if (cde->ctx != ctx) + if (cde->file != file) return; if (cde->is_valid || cde->is_failed) return; @@ -877,11 +877,12 @@ static void finished_cached_dirents_count(struct cached_dirents *cde, static void add_cached_dirent(struct cached_dirents *cde, struct dir_context *ctx, const char *name, int namelen, - struct cifs_fattr *fattr) + struct cifs_fattr *fattr, + struct file *file) { struct cached_dirent *de; - if (cde->ctx != ctx) + if (cde->file != file) return; if (cde->is_valid || cde->is_failed) return; @@ -911,7 +912,8 @@ static void add_cached_dirent(struct cached_dirents *cde, static bool cifs_dir_emit(struct dir_context *ctx, const char *name, int namelen, struct cifs_fattr *fattr, - struct cached_fid *cfid) + struct cached_fid *cfid, + struct file *file) { bool rc; ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); @@ -923,7 +925,7 @@ static bool cifs_dir_emit(struct dir_context *ctx, if (cfid) { mutex_lock(&cfid->dirents.de_mutex); add_cached_dirent(&cfid->dirents, ctx, name, namelen, - fattr); + fattr, file); mutex_unlock(&cfid->dirents.de_mutex); } @@ -1023,7 +1025,7 @@ static int cifs_filldir(char *find_entry, struct file *file, cifs_prime_dcache(file_dentry(file), &name, &fattr); return !cifs_dir_emit(ctx, name.name, name.len, - &fattr, cfid); + &fattr, cfid, file); } @@ -1074,8 +1076,8 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) * we need to initialize scanning and storing the * directory content. */ - if (ctx->pos == 0 && cfid->dirents.ctx == NULL) { - cfid->dirents.ctx = ctx; + if (ctx->pos == 0 && cfid->dirents.file == NULL) { + cfid->dirents.file = file; cfid->dirents.pos = 2; } /* @@ -1143,7 +1145,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) } else { if (cfid) { mutex_lock(&cfid->dirents.de_mutex); - finished_cached_dirents_count(&cfid->dirents, ctx); + finished_cached_dirents_count(&cfid->dirents, ctx, file); mutex_unlock(&cfid->dirents.de_mutex); } cifs_dbg(FYI, "Could not find entry\n"); @@ -1184,7 +1186,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx) ctx->pos++; if (cfid) { mutex_lock(&cfid->dirents.de_mutex); - update_cached_dirents_count(&cfid->dirents, ctx); + update_cached_dirents_count(&cfid->dirents, file); mutex_unlock(&cfid->dirents.de_mutex); } diff --git a/include/linux/adi-axi-common.h b/include/linux/adi-axi-common.h new file mode 100644 index 000000000000..f64f4ad4beda --- /dev/null +++ b/include/linux/adi-axi-common.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Analog Devices AXI common registers & definitions + * + * Copyright 2019 Analog Devices Inc. + * + * https://wiki.analog.com/resources/fpga/docs/axi_ip + * https://wiki.analog.com/resources/fpga/docs/hdl/regmap + */ + +#ifndef ADI_AXI_COMMON_H_ +#define ADI_AXI_COMMON_H_ + +#define ADI_AXI_REG_VERSION 0x0000 +#define ADI_AXI_REG_FPGA_INFO 0x001C + +#define ADI_AXI_PCORE_VER(major, minor, patch) \ + (((major) << 16) | ((minor) << 8) | (patch)) + +#define ADI_AXI_PCORE_VER_MAJOR(version) (((version) >> 16) & 0xff) +#define ADI_AXI_PCORE_VER_MINOR(version) (((version) >> 8) & 0xff) +#define ADI_AXI_PCORE_VER_PATCH(version) ((version) & 0xff) + +#define ADI_AXI_INFO_FPGA_TECH(info) (((info) >> 24) & 0xff) +#define ADI_AXI_INFO_FPGA_FAMILY(info) (((info) >> 16) & 0xff) +#define ADI_AXI_INFO_FPGA_SPEED_GRADE(info) (((info) >> 8) & 0xff) + +enum adi_axi_fpga_technology { + ADI_AXI_FPGA_TECH_UNKNOWN = 0, + ADI_AXI_FPGA_TECH_SERIES7, + ADI_AXI_FPGA_TECH_ULTRASCALE, + ADI_AXI_FPGA_TECH_ULTRASCALE_PLUS, +}; + +enum adi_axi_fpga_family { + ADI_AXI_FPGA_FAMILY_UNKNOWN = 0, + ADI_AXI_FPGA_FAMILY_ARTIX, + ADI_AXI_FPGA_FAMILY_KINTEX, + ADI_AXI_FPGA_FAMILY_VIRTEX, + ADI_AXI_FPGA_FAMILY_ZYNQ, +}; + +enum adi_axi_fpga_speed_grade { + ADI_AXI_FPGA_SPEED_UNKNOWN = 0, + ADI_AXI_FPGA_SPEED_1 = 10, + ADI_AXI_FPGA_SPEED_1L = 11, + ADI_AXI_FPGA_SPEED_1H = 12, + ADI_AXI_FPGA_SPEED_1HV = 13, + ADI_AXI_FPGA_SPEED_1LV = 14, + ADI_AXI_FPGA_SPEED_2 = 20, + ADI_AXI_FPGA_SPEED_2L = 21, + ADI_AXI_FPGA_SPEED_2LV = 22, + ADI_AXI_FPGA_SPEED_3 = 30, +}; + +#endif /* ADI_AXI_COMMON_H_ */ diff --git a/include/linux/bio.h b/include/linux/bio.h index 9c37c66ef9ca..46ffac5caab7 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -291,7 +291,7 @@ static inline void bio_first_folio(struct folio_iter *fi, struct bio *bio, fi->folio = page_folio(bvec->bv_page); fi->offset = bvec->bv_offset + - PAGE_SIZE * (bvec->bv_page - &fi->folio->page); + PAGE_SIZE * folio_page_idx(fi->folio, bvec->bv_page); fi->_seg_count = bvec->bv_len; fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count); fi->_next = folio_next(fi->folio); diff --git a/include/linux/bvec.h b/include/linux/bvec.h index 204b22a99c4b..0a80e1f9aa20 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -57,9 +57,12 @@ static inline void bvec_set_page(struct bio_vec *bv, struct page *page, * @offset: offset into the folio */ static inline void bvec_set_folio(struct bio_vec *bv, struct folio *folio, - unsigned int len, unsigned int offset) + size_t len, size_t offset) { - bvec_set_page(bv, &folio->page, len, offset); + unsigned long nr = offset / PAGE_SIZE; + + WARN_ON_ONCE(len > UINT_MAX); + bvec_set_page(bv, folio_page(folio, nr), len, offset % PAGE_SIZE); } /** diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 2e6e603b7493..630705a47129 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1360,6 +1360,32 @@ void clk_hw_unregister(struct clk_hw *hw); /* helper functions */ const char *__clk_get_name(const struct clk *clk); const char *clk_hw_get_name(const struct clk_hw *hw); + +/** + * clk_hw_get_dev() - get device from an hardware clock. + * @hw: the clk_hw pointer to get the struct device from + * + * This is a helper to get the struct device associated with a hardware + * clock. Some clock controllers, such as the one registered with + * CLK_OF_DECLARE(), may have not provided a device pointer while + * registering the clock. + * + * Return: the struct device associated with the clock, or NULL if there + * is none. + */ +struct device *clk_hw_get_dev(const struct clk_hw *hw); + +/** + * clk_hw_get_of_node() - get device_node from a hardware clock. + * @hw: the clk_hw pointer to get the struct device_node from + * + * This is a helper to get the struct device_node associated with a + * hardware clock. + * + * Return: the struct device_node associated with the clock, or NULL + * if there is none. + */ +struct device_node *clk_hw_get_of_node(const struct clk_hw *hw); #ifdef CONFIG_COMMON_CLK struct clk_hw *__clk_get_hw(struct clk *clk); #else diff --git a/include/linux/cpu.h b/include/linux/cpu.h index e6089abc28e2..96a3a0d6a60e 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -120,6 +120,7 @@ extern void cpu_maps_update_begin(void); extern void cpu_maps_update_done(void); int bringup_hibernate_cpu(unsigned int sleep_cpu); void bringup_nonboot_cpus(unsigned int max_cpus); +int arch_cpu_rescan_dead_smt_siblings(void); #else /* CONFIG_SMP */ #define cpuhp_tasks_frozen 0 @@ -134,6 +135,8 @@ static inline void cpu_maps_update_done(void) static inline int add_cpu(unsigned int cpu) { return 0;} +static inline int arch_cpu_rescan_dead_smt_siblings(void) { return 0; } + #endif /* CONFIG_SMP */ extern const struct bus_type cpu_subsys; diff --git a/include/linux/fpga/adi-axi-common.h b/include/linux/fpga/adi-axi-common.h deleted file mode 100644 index 141ac3f251e6..000000000000 --- a/include/linux/fpga/adi-axi-common.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Analog Devices AXI common registers & definitions - * - * Copyright 2019 Analog Devices Inc. - * - * https://wiki.analog.com/resources/fpga/docs/axi_ip - * https://wiki.analog.com/resources/fpga/docs/hdl/regmap - */ - -#ifndef ADI_AXI_COMMON_H_ -#define ADI_AXI_COMMON_H_ - -#define ADI_AXI_REG_VERSION 0x0000 - -#define ADI_AXI_PCORE_VER(major, minor, patch) \ - (((major) << 16) | ((minor) << 8) | (patch)) - -#define ADI_AXI_PCORE_VER_MAJOR(version) (((version) >> 16) & 0xff) -#define ADI_AXI_PCORE_VER_MINOR(version) (((version) >> 8) & 0xff) -#define ADI_AXI_PCORE_VER_PATCH(version) ((version) & 0xff) - -#endif /* ADI_AXI_COMMON_H_ */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 96c7925a6551..4ec77da65f14 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2274,10 +2274,12 @@ static inline bool file_has_valid_mmap_hooks(struct file *file) return true; } +int compat_vma_mmap_prepare(struct file *file, struct vm_area_struct *vma); + static inline int call_mmap(struct file *file, struct vm_area_struct *vma) { - if (WARN_ON_ONCE(file->f_op->mmap_prepare)) - return -EINVAL; + if (file->f_op->mmap_prepare) + return compat_vma_mmap_prepare(file, vma); return file->f_op->mmap(file, vma); } diff --git a/include/linux/key.h b/include/linux/key.h index ba05de8579ec..81b8f05c6898 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -236,7 +236,7 @@ struct key { #define KEY_FLAG_ROOT_CAN_INVAL 7 /* set if key can be invalidated by root without permission */ #define KEY_FLAG_KEEP 8 /* set if key should not be removed */ #define KEY_FLAG_UID_KEYRING 9 /* set if key is a user or user session keyring */ -#define KEY_FLAG_FINAL_PUT 10 /* set if final put has happened on key */ +#define KEY_FLAG_USER_ALIVE 10 /* set if final put has not happened on key yet */ /* the key type and key description string * - the desc is used to match a key against search criteria diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 0cdbfc42f153..6f8a4965f9b9 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -99,7 +99,7 @@ static inline bool sg_is_last(struct scatterlist *sg) * @sg: The current sg entry * * Description: - * Usually the next entry will be @sg@ + 1, but if this sg element is part + * Usually the next entry will be @sg + 1, but if this sg element is part * of a chained scatterlist, it could jump to the start of a new * scatterlist array. * @@ -254,7 +254,7 @@ static inline void __sg_chain(struct scatterlist *chain_sg, * @sgl: Second scatterlist * * Description: - * Links @prv@ and @sgl@ together, to form a longer scatterlist. + * Links @prv and @sgl together, to form a longer scatterlist. * **/ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2b261e74e2c4..a760f05fa3fb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -242,6 +242,7 @@ struct adv_info { __u8 mesh; __u8 instance; __u8 handle; + __u8 sid; __u32 flags; __u16 timeout; __u16 remaining_time; @@ -546,6 +547,7 @@ struct hci_dev { struct hci_conn_hash conn_hash; struct list_head mesh_pending; + struct mutex mgmt_pending_lock; struct list_head mgmt_pending; struct list_head reject_list; struct list_head accept_list; @@ -1550,13 +1552,14 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, u16 timeout); struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type, struct bt_iso_qos *qos); -struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, +struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid, struct bt_iso_qos *qos, __u8 base_len, __u8 *base); struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type, struct bt_iso_qos *qos); struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, - __u8 dst_type, struct bt_iso_qos *qos, + __u8 dst_type, __u8 sid, + struct bt_iso_qos *qos, __u8 data_len, __u8 *data); struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type, __u8 sid, struct bt_iso_qos *qos); @@ -1831,6 +1834,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, void hci_adv_instances_clear(struct hci_dev *hdev); struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance); +struct adv_info *hci_find_adv_sid(struct hci_dev *hdev, u8 sid); struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance); struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u32 flags, u16 adv_data_len, u8 *adv_data, @@ -1838,7 +1842,7 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance, u16 timeout, u16 duration, s8 tx_power, u32 min_interval, u32 max_interval, u8 mesh_handle); -struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, +struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid, u32 flags, u8 data_len, u8 *data, u32 min_interval, u32 max_interval); int hci_set_adv_instance_data(struct hci_dev *hdev, u8 instance, @@ -2400,7 +2404,6 @@ void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev, u8 instance); void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev, u8 instance); -void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle); int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip); void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle, bdaddr_t *bdaddr, u8 addr_type); diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h index 72558c826aa1..5224f57f6af2 100644 --- a/include/net/bluetooth/hci_sync.h +++ b/include/net/bluetooth/hci_sync.h @@ -115,8 +115,8 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance); int hci_enable_advertising_sync(struct hci_dev *hdev); int hci_enable_advertising(struct hci_dev *hdev); -int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len, - u8 *data, u32 flags, u16 min_interval, +int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid, + u8 data_len, u8 *data, u32 flags, u16 min_interval, u16 max_interval, u16 sync_interval); int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance); diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 629368ab2787..638948be4c50 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -973,14 +973,6 @@ static inline void qdisc_qstats_qlen_backlog(struct Qdisc *sch, __u32 *qlen, *backlog = qstats.backlog; } -static inline void qdisc_tree_flush_backlog(struct Qdisc *sch) -{ - __u32 qlen, backlog; - - qdisc_qstats_qlen_backlog(sch, &qlen, &backlog); - qdisc_tree_reduce_backlog(sch, qlen, backlog); -} - static inline void qdisc_purge_queue(struct Qdisc *sch) { __u32 qlen, backlog; diff --git a/include/net/sock.h b/include/net/sock.h index 92e7c1aae3cc..4c37015b7cf7 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -3010,8 +3010,11 @@ int sock_ioctl_inout(struct sock *sk, unsigned int cmd, int sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); static inline bool sk_is_readable(struct sock *sk) { - if (sk->sk_prot->sock_is_readable) - return sk->sk_prot->sock_is_readable(sk); + const struct proto *prot = READ_ONCE(sk->sk_prot); + + if (prot->sock_is_readable) + return prot->sock_is_readable(sk); + return false; } #endif /* _SOCK_H */ diff --git a/include/uapi/linux/bits.h b/include/uapi/linux/bits.h index 682b406e1067..a04afef9efca 100644 --- a/include/uapi/linux/bits.h +++ b/include/uapi/linux/bits.h @@ -4,9 +4,9 @@ #ifndef _UAPI_LINUX_BITS_H #define _UAPI_LINUX_BITS_H -#define __GENMASK(h, l) (((~_UL(0)) << (l)) & (~_UL(0) >> (BITS_PER_LONG - 1 - (h)))) +#define __GENMASK(h, l) (((~_UL(0)) << (l)) & (~_UL(0) >> (__BITS_PER_LONG - 1 - (h)))) -#define __GENMASK_ULL(h, l) (((~_ULL(0)) << (l)) & (~_ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h)))) +#define __GENMASK_ULL(h, l) (((~_ULL(0)) << (l)) & (~_ULL(0) >> (__BITS_PER_LONG_LONG - 1 - (h)))) #define __GENMASK_U128(h, l) \ ((_BIT128((h)) << 1) - (_BIT128(l))) diff --git a/init/initramfs.c b/init/initramfs.c index 72bad44a1d41..097673b97784 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include <linux/init.h> #include <linux/async.h> +#include <linux/export.h> #include <linux/fs.h> #include <linux/slab.h> #include <linux/types.h> diff --git a/init/main.c b/init/main.c index ed576c7f475d..225a58279acd 100644 --- a/init/main.c +++ b/init/main.c @@ -13,6 +13,7 @@ #define DEBUG /* Enable initcall_debug */ #include <linux/types.h> +#include <linux/export.h> #include <linux/extable.h> #include <linux/module.h> #include <linux/proc_fs.h> diff --git a/io_uring/fdinfo.c b/io_uring/fdinfo.c index e9355276ab5d..9798d6fb4ec7 100644 --- a/io_uring/fdinfo.c +++ b/io_uring/fdinfo.c @@ -141,18 +141,26 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) if (ctx->flags & IORING_SETUP_SQPOLL) { struct io_sq_data *sq = ctx->sq_data; + struct task_struct *tsk; + rcu_read_lock(); + tsk = rcu_dereference(sq->thread); /* * sq->thread might be NULL if we raced with the sqpoll * thread termination. */ - if (sq->thread) { + if (tsk) { + get_task_struct(tsk); + rcu_read_unlock(); + getrusage(tsk, RUSAGE_SELF, &sq_usage); + put_task_struct(tsk); sq_pid = sq->task_pid; sq_cpu = sq->sq_cpu; - getrusage(sq->thread, RUSAGE_SELF, &sq_usage); sq_total_time = (sq_usage.ru_stime.tv_sec * 1000000 + sq_usage.ru_stime.tv_usec); sq_work_time = sq->work_time; + } else { + rcu_read_unlock(); } } diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index cf759c172083..5111ec040c53 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -1523,6 +1523,9 @@ static __cold void io_iopoll_try_reap_events(struct io_ring_ctx *ctx) } } mutex_unlock(&ctx->uring_lock); + + if (ctx->flags & IORING_SETUP_DEFER_TASKRUN) + io_move_task_work_from_local(ctx); } static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned int min_events) @@ -2906,7 +2909,7 @@ static __cold void io_ring_exit_work(struct work_struct *work) struct task_struct *tsk; io_sq_thread_park(sqd); - tsk = sqd->thread; + tsk = sqpoll_task_locked(sqd); if (tsk && tsk->io_uring && tsk->io_uring->io_wq) io_wq_cancel_cb(tsk->io_uring->io_wq, io_cancel_ctx_cb, ctx, true); @@ -3142,7 +3145,7 @@ __cold void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd) s64 inflight; DEFINE_WAIT(wait); - WARN_ON_ONCE(sqd && sqd->thread != current); + WARN_ON_ONCE(sqd && sqpoll_task_locked(sqd) != current); if (!current->io_uring) return; diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index 2ea65f3cef72..ce95e3af44a9 100644 --- a/io_uring/kbuf.c +++ b/io_uring/kbuf.c @@ -270,8 +270,11 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg, /* truncate end piece, if needed, for non partial buffers */ if (len > arg->max_len) { len = arg->max_len; - if (!(bl->flags & IOBL_INC)) + if (!(bl->flags & IOBL_INC)) { + if (iov != arg->iovs) + break; buf->len = len; + } } iov->iov_base = u64_to_user_ptr(buf->addr); diff --git a/io_uring/register.c b/io_uring/register.c index cc23a4c205cd..a59589249fce 100644 --- a/io_uring/register.c +++ b/io_uring/register.c @@ -273,6 +273,8 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx, if (ctx->flags & IORING_SETUP_SQPOLL) { sqd = ctx->sq_data; if (sqd) { + struct task_struct *tsk; + /* * Observe the correct sqd->lock -> ctx->uring_lock * ordering. Fine to drop uring_lock here, we hold @@ -282,8 +284,9 @@ static __cold int io_register_iowq_max_workers(struct io_ring_ctx *ctx, mutex_unlock(&ctx->uring_lock); mutex_lock(&sqd->lock); mutex_lock(&ctx->uring_lock); - if (sqd->thread) - tctx = sqd->thread->io_uring; + tsk = sqpoll_task_locked(sqd); + if (tsk) + tctx = tsk->io_uring; } } else { tctx = current->io_uring; diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c index 03c699493b5a..268d2fbe6160 100644 --- a/io_uring/sqpoll.c +++ b/io_uring/sqpoll.c @@ -30,7 +30,7 @@ enum { void io_sq_thread_unpark(struct io_sq_data *sqd) __releases(&sqd->lock) { - WARN_ON_ONCE(sqd->thread == current); + WARN_ON_ONCE(sqpoll_task_locked(sqd) == current); /* * Do the dance but not conditional clear_bit() because it'd race with @@ -46,24 +46,32 @@ void io_sq_thread_unpark(struct io_sq_data *sqd) void io_sq_thread_park(struct io_sq_data *sqd) __acquires(&sqd->lock) { - WARN_ON_ONCE(data_race(sqd->thread) == current); + struct task_struct *tsk; atomic_inc(&sqd->park_pending); set_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state); mutex_lock(&sqd->lock); - if (sqd->thread) - wake_up_process(sqd->thread); + + tsk = sqpoll_task_locked(sqd); + if (tsk) { + WARN_ON_ONCE(tsk == current); + wake_up_process(tsk); + } } void io_sq_thread_stop(struct io_sq_data *sqd) { - WARN_ON_ONCE(sqd->thread == current); + struct task_struct *tsk; + WARN_ON_ONCE(test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state)); set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state); mutex_lock(&sqd->lock); - if (sqd->thread) - wake_up_process(sqd->thread); + tsk = sqpoll_task_locked(sqd); + if (tsk) { + WARN_ON_ONCE(tsk == current); + wake_up_process(tsk); + } mutex_unlock(&sqd->lock); wait_for_completion(&sqd->exited); } @@ -270,7 +278,8 @@ static int io_sq_thread(void *data) /* offload context creation failed, just exit */ if (!current->io_uring) { mutex_lock(&sqd->lock); - sqd->thread = NULL; + rcu_assign_pointer(sqd->thread, NULL); + put_task_struct(current); mutex_unlock(&sqd->lock); goto err_out; } @@ -379,7 +388,8 @@ static int io_sq_thread(void *data) io_sq_tw(&retry_list, UINT_MAX); io_uring_cancel_generic(true, sqd); - sqd->thread = NULL; + rcu_assign_pointer(sqd->thread, NULL); + put_task_struct(current); list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) atomic_or(IORING_SQ_NEED_WAKEUP, &ctx->rings->sq_flags); io_run_task_work(); @@ -484,7 +494,10 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx, goto err_sqpoll; } - sqd->thread = tsk; + mutex_lock(&sqd->lock); + rcu_assign_pointer(sqd->thread, tsk); + mutex_unlock(&sqd->lock); + task_to_put = get_task_struct(tsk); ret = io_uring_alloc_task_context(tsk, ctx); wake_up_new_task(tsk); @@ -495,9 +508,6 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx, ret = -EINVAL; goto err; } - - if (task_to_put) - put_task_struct(task_to_put); return 0; err_sqpoll: complete(&ctx->sq_data->exited); @@ -515,10 +525,13 @@ __cold int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx, int ret = -EINVAL; if (sqd) { + struct task_struct *tsk; + io_sq_thread_park(sqd); /* Don't set affinity for a dying thread */ - if (sqd->thread) - ret = io_wq_cpu_affinity(sqd->thread->io_uring, mask); + tsk = sqpoll_task_locked(sqd); + if (tsk) + ret = io_wq_cpu_affinity(tsk->io_uring, mask); io_sq_thread_unpark(sqd); } diff --git a/io_uring/sqpoll.h b/io_uring/sqpoll.h index 4171666b1cf4..b83dcdec9765 100644 --- a/io_uring/sqpoll.h +++ b/io_uring/sqpoll.h @@ -8,7 +8,7 @@ struct io_sq_data { /* ctx's that are using this sqd */ struct list_head ctx_list; - struct task_struct *thread; + struct task_struct __rcu *thread; struct wait_queue_head wait; unsigned sq_thread_idle; @@ -29,3 +29,9 @@ void io_sq_thread_unpark(struct io_sq_data *sqd); void io_put_sq_data(struct io_sq_data *sqd); void io_sqpoll_wait_sq(struct io_ring_ctx *ctx); int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx, cpumask_var_t mask); + +static inline struct task_struct *sqpoll_task_locked(struct io_sq_data *sqd) +{ + return rcu_dereference_protected(sqd->thread, + lockdep_is_held(&sqd->lock)); +} diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index 50e8d04ab661..2e5b89d7d866 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -1406,6 +1406,15 @@ void run_posix_cpu_timers(void) lockdep_assert_irqs_disabled(); /* + * Ensure that release_task(tsk) can't happen while + * handle_posix_cpu_timers() is running. Otherwise, a concurrent + * posix_cpu_timer_del() may fail to lock_task_sighand(tsk) and + * miss timer->it.cpu.firing != 0. + */ + if (tsk->exit_state) + return; + + /* * If the actual expiry is deferred to task work context and the * work is already scheduled there is no point to do anything here. */ diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index ea8b364b6818..08141f105c95 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1437,10 +1437,8 @@ static void filter_free_subsystem_filters(struct trace_subsystem_dir *dir, INIT_LIST_HEAD(&head->list); item = kmalloc(sizeof(*item), GFP_KERNEL); - if (!item) { - kfree(head); + if (!item) goto free_now; - } item->filter = filter; list_add_tail(&item->list, &head->list); diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 7582dfab7fe3..4af1c8b0775a 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -73,9 +73,9 @@ EXPORT_SYMBOL(sg_nents_for_len); * Should only be used casually, it (currently) scans the entire list * to get the last entry. * - * Note that the @sgl@ pointer passed in need not be the first one, - * the important bit is that @nents@ denotes the number of entries that - * exist from @sgl@. + * Note that the @sgl pointer passed in need not be the first one, + * the important bit is that @nents denotes the number of entries that + * exist from @sgl. * **/ struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents) @@ -345,7 +345,7 @@ EXPORT_SYMBOL(__sg_alloc_table); * @gfp_mask: GFP allocation mask * * Description: - * Allocate and initialize an sg table. If @nents@ is larger than + * Allocate and initialize an sg table. If @nents is larger than * SG_MAX_SINGLE_ALLOC a chained sg table will be setup. * **/ diff --git a/mm/damon/Kconfig b/mm/damon/Kconfig index 551745df011b..c93d0c56b963 100644 --- a/mm/damon/Kconfig +++ b/mm/damon/Kconfig @@ -4,7 +4,6 @@ menu "Data Access Monitoring" config DAMON bool "DAMON: Data Access Monitoring Framework" - default y help This builds a framework that allows kernel subsystems to monitor access frequency of each memory region. The information can be useful diff --git a/mm/madvise.c b/mm/madvise.c index 5f7a66a1617e..1d44a35ae85c 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -508,6 +508,7 @@ restart: pte_offset_map_lock(mm, pmd, addr, &ptl); if (!start_pte) break; + flush_tlb_batched_pending(mm); arch_enter_lazy_mmu_mode(); if (!err) nr = 0; @@ -741,6 +742,7 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr, start_pte = pte; if (!start_pte) break; + flush_tlb_batched_pending(mm); arch_enter_lazy_mmu_mode(); if (!err) nr = 0; diff --git a/mm/util.c b/mm/util.c index 448117da071f..0b270c43d7d1 100644 --- a/mm/util.c +++ b/mm/util.c @@ -1131,3 +1131,43 @@ void flush_dcache_folio(struct folio *folio) } EXPORT_SYMBOL(flush_dcache_folio); #endif + +/** + * compat_vma_mmap_prepare() - Apply the file's .mmap_prepare() hook to an + * existing VMA + * @file: The file which possesss an f_op->mmap_prepare() hook + * @vma: The VMA to apply the .mmap_prepare() hook to. + * + * Ordinarily, .mmap_prepare() is invoked directly upon mmap(). However, certain + * 'wrapper' file systems invoke a nested mmap hook of an underlying file. + * + * Until all filesystems are converted to use .mmap_prepare(), we must be + * conservative and continue to invoke these 'wrapper' filesystems using the + * deprecated .mmap() hook. + * + * However we have a problem if the underlying file system possesses an + * .mmap_prepare() hook, as we are in a different context when we invoke the + * .mmap() hook, already having a VMA to deal with. + * + * compat_vma_mmap_prepare() is a compatibility function that takes VMA state, + * establishes a struct vm_area_desc descriptor, passes to the underlying + * .mmap_prepare() hook and applies any changes performed by it. + * + * Once the conversion of filesystems is complete this function will no longer + * be required and will be removed. + * + * Returns: 0 on success or error. + */ +int compat_vma_mmap_prepare(struct file *file, struct vm_area_struct *vma) +{ + struct vm_area_desc desc; + int err; + + err = file->f_op->mmap_prepare(vma_to_desc(vma, &desc)); + if (err) + return err; + set_vma_from_desc(vma, &desc); + + return 0; +} +EXPORT_SYMBOL(compat_vma_mmap_prepare); @@ -967,26 +967,9 @@ static __must_check struct vm_area_struct *vma_merge_existing_range( err = dup_anon_vma(next, middle, &anon_dup); } - if (err) + if (err || commit_merge(vmg)) goto abort; - err = commit_merge(vmg); - if (err) { - VM_WARN_ON(err != -ENOMEM); - - if (anon_dup) - unlink_anon_vmas(anon_dup); - - /* - * We've cleaned up any cloned anon_vma's, no VMAs have been - * modified, no harm no foul if the user requests that we not - * report this and just give up, leaving the VMAs unmerged. - */ - if (!vmg->give_up_on_oom) - vmg->state = VMA_MERGE_ERROR_NOMEM; - return NULL; - } - khugepaged_enter_vma(vmg->target, vmg->flags); vmg->state = VMA_MERGE_SUCCESS; return vmg->target; @@ -995,6 +978,9 @@ abort: vma_iter_set(vmg->vmi, start); vma_iter_load(vmg->vmi); + if (anon_dup) + unlink_anon_vmas(anon_dup); + /* * This means we have failed to clone anon_vma's correctly, but no * actual changes to VMAs have occurred, so no harm no foul - if the @@ -3127,7 +3113,6 @@ int __vm_munmap(unsigned long start, size_t len, bool unlock) return ret; } - /* Insert vm structure into process list sorted by address * and into the inode's i_mmap tree. If vm_file is non-NULL * then i_mmap_rwsem is taken here. @@ -222,6 +222,53 @@ static inline int vma_iter_store_gfp(struct vma_iterator *vmi, return 0; } + +/* + * Temporary helper functions for file systems which wrap an invocation of + * f_op->mmap() but which might have an underlying file system which implements + * f_op->mmap_prepare(). + */ + +static inline struct vm_area_desc *vma_to_desc(struct vm_area_struct *vma, + struct vm_area_desc *desc) +{ + desc->mm = vma->vm_mm; + desc->start = vma->vm_start; + desc->end = vma->vm_end; + + desc->pgoff = vma->vm_pgoff; + desc->file = vma->vm_file; + desc->vm_flags = vma->vm_flags; + desc->page_prot = vma->vm_page_prot; + + desc->vm_ops = NULL; + desc->private_data = NULL; + + return desc; +} + +static inline void set_vma_from_desc(struct vm_area_struct *vma, + struct vm_area_desc *desc) +{ + /* + * Since we're invoking .mmap_prepare() despite having a partially + * established VMA, we must take care to handle setting fields + * correctly. + */ + + /* Mutable fields. Populated with initial state. */ + vma->vm_pgoff = desc->pgoff; + if (vma->vm_file != desc->file) + vma_set_file(vma, desc->file); + if (vma->vm_flags != desc->vm_flags) + vm_flags_set(vma, desc->vm_flags); + vma->vm_page_prot = desc->page_prot; + + /* User-defined fields. */ + vma->vm_ops = desc->vm_ops; + vma->vm_private_data = desc->private_data; +} + int do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma, struct mm_struct *mm, unsigned long start, diff --git a/net/bluetooth/eir.c b/net/bluetooth/eir.c index 1bc51e2b05a3..3f72111ba651 100644 --- a/net/bluetooth/eir.c +++ b/net/bluetooth/eir.c @@ -242,7 +242,7 @@ u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) return ad_len; } -u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) +u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size) { struct adv_info *adv = NULL; u8 ad_len = 0, flags = 0; @@ -286,7 +286,7 @@ u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) /* If flags would still be empty, then there is no need to * include the "Flags" AD field". */ - if (flags) { + if (flags && (ad_len + eir_precalc_len(1) <= size)) { ptr[0] = 0x02; ptr[1] = EIR_FLAGS; ptr[2] = flags; @@ -316,7 +316,8 @@ skip_flags: } /* Provide Tx Power only if we can provide a valid value for it */ - if (adv_tx_power != HCI_TX_POWER_INVALID) { + if (adv_tx_power != HCI_TX_POWER_INVALID && + (ad_len + eir_precalc_len(1) <= size)) { ptr[0] = 0x02; ptr[1] = EIR_TX_POWER; ptr[2] = (u8)adv_tx_power; @@ -366,17 +367,19 @@ u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr) void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len) { - while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, len))) { + size_t dlen; + + while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, &dlen))) { u16 value = get_unaligned_le16(eir); if (uuid == value) { if (len) - *len -= 2; + *len = dlen - 2; return &eir[2]; } - eir += *len; - eir_len -= *len; + eir += dlen; + eir_len -= dlen; } return NULL; diff --git a/net/bluetooth/eir.h b/net/bluetooth/eir.h index 5c89a05e8b29..9372db83f912 100644 --- a/net/bluetooth/eir.h +++ b/net/bluetooth/eir.h @@ -9,7 +9,7 @@ void eir_create(struct hci_dev *hdev, u8 *data); -u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr); +u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size); u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr); u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 99efeed6a766..4f379184df5b 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1501,8 +1501,8 @@ static int qos_set_bis(struct hci_dev *hdev, struct bt_iso_qos *qos) /* This function requires the caller holds hdev->lock */ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst, - struct bt_iso_qos *qos, __u8 base_len, - __u8 *base) + __u8 sid, struct bt_iso_qos *qos, + __u8 base_len, __u8 *base) { struct hci_conn *conn; int err; @@ -1543,6 +1543,7 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst, return conn; conn->state = BT_CONNECT; + conn->sid = sid; hci_conn_hold(conn); return conn; @@ -2062,7 +2063,8 @@ static int create_big_sync(struct hci_dev *hdev, void *data) if (qos->bcast.bis) sync_interval = interval * 4; - err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->le_per_adv_data_len, + err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->sid, + conn->le_per_adv_data_len, conn->le_per_adv_data, flags, interval, interval, sync_interval); if (err) @@ -2134,7 +2136,7 @@ static void create_big_complete(struct hci_dev *hdev, void *data, int err) } } -struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, +struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid, struct bt_iso_qos *qos, __u8 base_len, __u8 *base) { @@ -2156,7 +2158,7 @@ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, base, base_len); /* We need hci_conn object using the BDADDR_ANY as dst */ - conn = hci_add_bis(hdev, dst, qos, base_len, eir); + conn = hci_add_bis(hdev, dst, sid, qos, base_len, eir); if (IS_ERR(conn)) return conn; @@ -2207,20 +2209,35 @@ static void bis_mark_per_adv(struct hci_conn *conn, void *data) } struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, - __u8 dst_type, struct bt_iso_qos *qos, + __u8 dst_type, __u8 sid, + struct bt_iso_qos *qos, __u8 base_len, __u8 *base) { struct hci_conn *conn; int err; struct iso_list_data data; - conn = hci_bind_bis(hdev, dst, qos, base_len, base); + conn = hci_bind_bis(hdev, dst, sid, qos, base_len, base); if (IS_ERR(conn)) return conn; if (conn->state == BT_CONNECTED) return conn; + /* Check if SID needs to be allocated then search for the first + * available. + */ + if (conn->sid == HCI_SID_INVALID) { + u8 sid; + + for (sid = 0; sid <= 0x0f; sid++) { + if (!hci_find_adv_sid(hdev, sid)) { + conn->sid = sid; + break; + } + } + } + data.big = qos->bcast.big; data.bis = qos->bcast.bis; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 3b49828160b7..07a8b4281a39 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1585,6 +1585,19 @@ struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance) } /* This function requires the caller holds hdev->lock */ +struct adv_info *hci_find_adv_sid(struct hci_dev *hdev, u8 sid) +{ + struct adv_info *adv; + + list_for_each_entry(adv, &hdev->adv_instances, list) { + if (adv->sid == sid) + return adv; + } + + return NULL; +} + +/* This function requires the caller holds hdev->lock */ struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance) { struct adv_info *cur_instance; @@ -1736,7 +1749,7 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance, } /* This function requires the caller holds hdev->lock */ -struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, +struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid, u32 flags, u8 data_len, u8 *data, u32 min_interval, u32 max_interval) { @@ -1748,6 +1761,7 @@ struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, if (IS_ERR(adv)) return adv; + adv->sid = sid; adv->periodic = true; adv->per_adv_data_len = data_len; @@ -1877,10 +1891,8 @@ void hci_free_adv_monitor(struct hci_dev *hdev, struct adv_monitor *monitor) if (monitor->handle) idr_remove(&hdev->adv_monitors_idr, monitor->handle); - if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED) { + if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED) hdev->adv_monitors_cnt--; - mgmt_adv_monitor_removed(hdev, monitor->handle); - } kfree(monitor); } @@ -2487,6 +2499,7 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv) mutex_init(&hdev->lock); mutex_init(&hdev->req_lock); + mutex_init(&hdev->mgmt_pending_lock); ida_init(&hdev->unset_handle_ida); @@ -3417,23 +3430,18 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) bt_dev_err(hdev, "link tx timeout"); - rcu_read_lock(); + hci_dev_lock(hdev); /* Kill stalled connections */ - list_for_each_entry_rcu(c, &h->list, list) { + list_for_each_entry(c, &h->list, list) { if (c->type == type && c->sent) { bt_dev_err(hdev, "killing stalled connection %pMR", &c->dst); - /* hci_disconnect might sleep, so, we have to release - * the RCU read lock before calling it. - */ - rcu_read_unlock(); hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); - rcu_read_lock(); } } - rcu_read_unlock(); + hci_dev_unlock(hdev); } static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 62d1ff951ebe..6687f2a4d1eb 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -1261,10 +1261,12 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) hci_cpu_to_le24(adv->min_interval, cp.min_interval); hci_cpu_to_le24(adv->max_interval, cp.max_interval); cp.tx_power = adv->tx_power; + cp.sid = adv->sid; } else { hci_cpu_to_le24(hdev->le_adv_min_interval, cp.min_interval); hci_cpu_to_le24(hdev->le_adv_max_interval, cp.max_interval); cp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE; + cp.sid = 0x00; } secondary_adv = (flags & MGMT_ADV_FLAG_SEC_MASK); @@ -1559,7 +1561,8 @@ static int hci_enable_per_advertising_sync(struct hci_dev *hdev, u8 instance) static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv) { u8 bid[3]; - u8 ad[4 + 3]; + u8 ad[HCI_MAX_EXT_AD_LENGTH]; + u8 len; /* Skip if NULL adv as instance 0x00 is used for general purpose * advertising so it cannot used for the likes of Broadcast Announcement @@ -1585,14 +1588,16 @@ static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv) /* Generate Broadcast ID */ get_random_bytes(bid, sizeof(bid)); - eir_append_service_data(ad, 0, 0x1852, bid, sizeof(bid)); - hci_set_adv_instance_data(hdev, adv->instance, sizeof(ad), ad, 0, NULL); + len = eir_append_service_data(ad, 0, 0x1852, bid, sizeof(bid)); + memcpy(ad + len, adv->adv_data, adv->adv_data_len); + hci_set_adv_instance_data(hdev, adv->instance, len + adv->adv_data_len, + ad, 0, NULL); return hci_update_adv_data_sync(hdev, adv->instance); } -int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len, - u8 *data, u32 flags, u16 min_interval, +int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid, + u8 data_len, u8 *data, u32 flags, u16 min_interval, u16 max_interval, u16 sync_interval) { struct adv_info *adv = NULL; @@ -1603,9 +1608,28 @@ int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len, if (instance) { adv = hci_find_adv_instance(hdev, instance); - /* Create an instance if that could not be found */ - if (!adv) { - adv = hci_add_per_instance(hdev, instance, flags, + if (adv) { + if (sid != HCI_SID_INVALID && adv->sid != sid) { + /* If the SID don't match attempt to find by + * SID. + */ + adv = hci_find_adv_sid(hdev, sid); + if (!adv) { + bt_dev_err(hdev, + "Unable to find adv_info"); + return -EINVAL; + } + } + + /* Turn it into periodic advertising */ + adv->periodic = true; + adv->per_adv_data_len = data_len; + if (data) + memcpy(adv->per_adv_data, data, data_len); + adv->flags = flags; + } else if (!adv) { + /* Create an instance if that could not be found */ + adv = hci_add_per_instance(hdev, instance, sid, flags, data_len, data, sync_interval, sync_interval); @@ -1812,7 +1836,8 @@ static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance) return 0; } - len = eir_create_adv_data(hdev, instance, pdu->data); + len = eir_create_adv_data(hdev, instance, pdu->data, + HCI_MAX_EXT_AD_LENGTH); pdu->length = len; pdu->handle = adv ? adv->handle : instance; @@ -1843,7 +1868,7 @@ static int hci_set_adv_data_sync(struct hci_dev *hdev, u8 instance) memset(&cp, 0, sizeof(cp)); - len = eir_create_adv_data(hdev, instance, cp.data); + len = eir_create_adv_data(hdev, instance, cp.data, sizeof(cp.data)); /* There's nothing to do if the data hasn't changed */ if (hdev->adv_data_len == len && diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index 6e2c752aaa8f..3c2c98eecc62 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -336,7 +336,7 @@ static int iso_connect_bis(struct sock *sk) struct hci_dev *hdev; int err; - BT_DBG("%pMR", &iso_pi(sk)->src); + BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid); hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src, iso_pi(sk)->src_type); @@ -365,7 +365,7 @@ static int iso_connect_bis(struct sock *sk) /* Just bind if DEFER_SETUP has been set */ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { - hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst, + hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst, iso_pi(sk)->bc_sid, &iso_pi(sk)->qos, iso_pi(sk)->base_len, iso_pi(sk)->base); if (IS_ERR(hcon)) { @@ -375,12 +375,16 @@ static int iso_connect_bis(struct sock *sk) } else { hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst, le_addr_type(iso_pi(sk)->dst_type), - &iso_pi(sk)->qos, iso_pi(sk)->base_len, - iso_pi(sk)->base); + iso_pi(sk)->bc_sid, &iso_pi(sk)->qos, + iso_pi(sk)->base_len, iso_pi(sk)->base); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); goto unlock; } + + /* Update SID if it was not set */ + if (iso_pi(sk)->bc_sid == HCI_SID_INVALID) + iso_pi(sk)->bc_sid = hcon->sid; } conn = iso_conn_add(hcon); @@ -1337,10 +1341,13 @@ static int iso_sock_getname(struct socket *sock, struct sockaddr *addr, addr->sa_family = AF_BLUETOOTH; if (peer) { + struct hci_conn *hcon = iso_pi(sk)->conn ? + iso_pi(sk)->conn->hcon : NULL; + bacpy(&sa->iso_bdaddr, &iso_pi(sk)->dst); sa->iso_bdaddr_type = iso_pi(sk)->dst_type; - if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) { + if (hcon && hcon->type == BIS_LINK) { sa->iso_bc->bc_sid = iso_pi(sk)->bc_sid; sa->iso_bc->bc_num_bis = iso_pi(sk)->bc_num_bis; memcpy(sa->iso_bc->bc_bis, iso_pi(sk)->bc_bis, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 14a9462fced5..d540f7b4f75f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1447,22 +1447,17 @@ static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data) send_settings_rsp(cmd->sk, cmd->opcode, match->hdev); - list_del(&cmd->list); - if (match->sk == NULL) { match->sk = cmd->sk; sock_hold(match->sk); } - - mgmt_pending_free(cmd); } static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data) { u8 *status = data; - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status); - mgmt_pending_remove(cmd); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, *status); } static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data) @@ -1476,8 +1471,6 @@ static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data) if (cmd->cmd_complete) { cmd->cmd_complete(cmd, match->mgmt_status); - mgmt_pending_remove(cmd); - return; } @@ -1486,13 +1479,13 @@ static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data) static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status) { - return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, + return mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, cmd->param, cmd->param_len); } static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status) { - return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, + return mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, cmd->param, sizeof(struct mgmt_addr_info)); } @@ -1532,7 +1525,7 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data, if (err) { u8 mgmt_err = mgmt_status(err); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); goto done; } @@ -1707,7 +1700,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data, if (err) { u8 mgmt_err = mgmt_status(err); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); goto done; } @@ -1943,8 +1936,8 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) new_settings(hdev, NULL); } - mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, - &mgmt_err); + mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, + cmd_status_rsp, &mgmt_err); return; } @@ -1954,7 +1947,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED); } - mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, settings_rsp, &match); if (changed) new_settings(hdev, match.sk); @@ -2074,12 +2067,12 @@ static void set_le_complete(struct hci_dev *hdev, void *data, int err) bt_dev_dbg(hdev, "err %d", err); if (status) { - mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, - &status); + mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, cmd_status_rsp, + &status); return; } - mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, settings_rsp, &match); new_settings(hdev, match.sk); @@ -2138,7 +2131,7 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err) struct sock *sk = cmd->sk; if (status) { - mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, + mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, cmd_status_rsp, &status); return; } @@ -2638,7 +2631,7 @@ static void mgmt_class_complete(struct hci_dev *hdev, void *data, int err) bt_dev_dbg(hdev, "err %d", err); - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), hdev->dev_class, 3); mgmt_pending_free(cmd); @@ -3427,7 +3420,7 @@ static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status) bacpy(&rp.addr.bdaddr, &conn->dst); rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type); - err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, + err = mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_PAIR_DEVICE, status, &rp, sizeof(rp)); /* So we don't get further callbacks for this connection */ @@ -5108,24 +5101,14 @@ static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev, mgmt_event(MGMT_EV_ADV_MONITOR_ADDED, hdev, &ev, sizeof(ev), sk); } -void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle) +static void mgmt_adv_monitor_removed(struct sock *sk, struct hci_dev *hdev, + __le16 handle) { struct mgmt_ev_adv_monitor_removed ev; - struct mgmt_pending_cmd *cmd; - struct sock *sk_skip = NULL; - struct mgmt_cp_remove_adv_monitor *cp; - - cmd = pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev); - if (cmd) { - cp = cmd->param; - - if (cp->monitor_handle) - sk_skip = cmd->sk; - } - ev.monitor_handle = cpu_to_le16(handle); + ev.monitor_handle = handle; - mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk_skip); + mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk); } static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev, @@ -5196,7 +5179,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, hci_update_passive_scan(hdev); } - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(status), &rp, sizeof(rp)); mgmt_pending_remove(cmd); @@ -5227,8 +5210,7 @@ static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev, if (pending_find(MGMT_OP_SET_LE, hdev) || pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) || - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev) || - pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) { + pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) { status = MGMT_STATUS_BUSY; goto unlock; } @@ -5398,8 +5380,7 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd = data; struct mgmt_cp_remove_adv_monitor *cp; - if (status == -ECANCELED || - cmd != pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) + if (status == -ECANCELED) return; hci_dev_lock(hdev); @@ -5408,12 +5389,14 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, rp.monitor_handle = cp->monitor_handle; - if (!status) + if (!status) { + mgmt_adv_monitor_removed(cmd->sk, hdev, cp->monitor_handle); hci_update_passive_scan(hdev); + } - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(status), &rp, sizeof(rp)); - mgmt_pending_remove(cmd); + mgmt_pending_free(cmd); hci_dev_unlock(hdev); bt_dev_dbg(hdev, "remove monitor %d complete, status %d", @@ -5423,10 +5406,6 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, static int mgmt_remove_adv_monitor_sync(struct hci_dev *hdev, void *data) { struct mgmt_pending_cmd *cmd = data; - - if (cmd != pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) - return -ECANCELED; - struct mgmt_cp_remove_adv_monitor *cp = cmd->param; u16 handle = __le16_to_cpu(cp->monitor_handle); @@ -5445,14 +5424,13 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev, hci_dev_lock(hdev); if (pending_find(MGMT_OP_SET_LE, hdev) || - pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev) || pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) || pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) { status = MGMT_STATUS_BUSY; goto unlock; } - cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len); + cmd = mgmt_pending_new(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len); if (!cmd) { status = MGMT_STATUS_NO_RESOURCES; goto unlock; @@ -5462,7 +5440,7 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev, mgmt_remove_adv_monitor_complete); if (err) { - mgmt_pending_remove(cmd); + mgmt_pending_free(cmd); if (err == -ENOMEM) status = MGMT_STATUS_NO_RESOURCES; @@ -5792,7 +5770,7 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err) cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev)) return; - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), cmd->param, 1); mgmt_pending_remove(cmd); @@ -6013,7 +5991,7 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err) bt_dev_dbg(hdev, "err %d", err); - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), cmd->param, 1); mgmt_pending_remove(cmd); @@ -6238,7 +6216,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) u8 status = mgmt_status(err); if (status) { - mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, + mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, cmd_status_rsp, &status); return; } @@ -6248,7 +6226,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) else hci_dev_clear_flag(hdev, HCI_ADVERTISING); - mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp, + mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, settings_rsp, &match); new_settings(hdev, match.sk); @@ -6592,7 +6570,7 @@ static void set_bredr_complete(struct hci_dev *hdev, void *data, int err) */ hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); } else { send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev); new_settings(hdev, cmd->sk); @@ -6729,7 +6707,7 @@ static void set_secure_conn_complete(struct hci_dev *hdev, void *data, int err) if (err) { u8 mgmt_err = mgmt_status(err); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); goto done; } @@ -7176,7 +7154,7 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err) rp.max_tx_power = HCI_TX_POWER_INVALID; } - mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status, &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -7336,7 +7314,7 @@ static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err) } complete: - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -8586,10 +8564,10 @@ static void add_advertising_complete(struct hci_dev *hdev, void *data, int err) rp.instance = cp->instance; if (err) - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err)); else - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), &rp, sizeof(rp)); add_adv_complete(hdev, cmd->sk, cp->instance, err); @@ -8777,10 +8755,10 @@ static void add_ext_adv_params_complete(struct hci_dev *hdev, void *data, hci_remove_adv_instance(hdev, cp->instance); - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err)); } else { - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), &rp, sizeof(rp)); } @@ -8927,10 +8905,10 @@ static void add_ext_adv_data_complete(struct hci_dev *hdev, void *data, int err) rp.instance = cp->instance; if (err) - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err)); else - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -9089,10 +9067,10 @@ static void remove_advertising_complete(struct hci_dev *hdev, void *data, rp.instance = cp->instance; if (err) - mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err)); else - mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, MGMT_STATUS_SUCCESS, &rp, sizeof(rp)); mgmt_pending_free(cmd); @@ -9364,7 +9342,7 @@ void mgmt_index_removed(struct hci_dev *hdev) if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) return; - mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match); + mgmt_pending_foreach(0, hdev, true, cmd_complete_rsp, &match); if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, @@ -9402,7 +9380,8 @@ void mgmt_power_on(struct hci_dev *hdev, int err) hci_update_passive_scan(hdev); } - mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, true, settings_rsp, + &match); new_settings(hdev, match.sk); @@ -9417,7 +9396,8 @@ void __mgmt_power_off(struct hci_dev *hdev) struct cmd_lookup match = { NULL, hdev }; u8 zero_cod[] = { 0, 0, 0 }; - mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, true, settings_rsp, + &match); /* If the power off is because of hdev unregistration let * use the appropriate INVALID_INDEX status. Otherwise use @@ -9431,7 +9411,7 @@ void __mgmt_power_off(struct hci_dev *hdev) else match.mgmt_status = MGMT_STATUS_NOT_POWERED; - mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match); + mgmt_pending_foreach(0, hdev, true, cmd_complete_rsp, &match); if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) { mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, @@ -9672,7 +9652,6 @@ static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data) device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk); cmd->cmd_complete(cmd, 0); - mgmt_pending_remove(cmd); } bool mgmt_powering_down(struct hci_dev *hdev) @@ -9728,8 +9707,8 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, struct mgmt_cp_disconnect *cp; struct mgmt_pending_cmd *cmd; - mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, - hdev); + mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, true, + unpair_device_rsp, hdev); cmd = pending_find(MGMT_OP_DISCONNECT, hdev); if (!cmd) @@ -9922,7 +9901,7 @@ void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) if (status) { u8 mgmt_err = mgmt_status(status); - mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, + mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, true, cmd_status_rsp, &mgmt_err); return; } @@ -9932,8 +9911,8 @@ void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) else changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY); - mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp, - &match); + mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, true, + settings_rsp, &match); if (changed) new_settings(hdev, match.sk); @@ -9957,9 +9936,12 @@ void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, { struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; - mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); - mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); - mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); + mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, false, sk_lookup, + &match); + mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, false, sk_lookup, + &match); + mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, false, sk_lookup, + &match); if (!status) { mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, diff --git a/net/bluetooth/mgmt_util.c b/net/bluetooth/mgmt_util.c index 3713ff490c65..a88a07da3947 100644 --- a/net/bluetooth/mgmt_util.c +++ b/net/bluetooth/mgmt_util.c @@ -217,30 +217,47 @@ int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode, struct hci_dev *hdev) { - struct mgmt_pending_cmd *cmd; + struct mgmt_pending_cmd *cmd, *tmp; + + mutex_lock(&hdev->mgmt_pending_lock); - list_for_each_entry(cmd, &hdev->mgmt_pending, list) { + list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { if (hci_sock_get_channel(cmd->sk) != channel) continue; - if (cmd->opcode == opcode) + + if (cmd->opcode == opcode) { + mutex_unlock(&hdev->mgmt_pending_lock); return cmd; + } } + mutex_unlock(&hdev->mgmt_pending_lock); + return NULL; } -void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, +void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, bool remove, void (*cb)(struct mgmt_pending_cmd *cmd, void *data), void *data) { struct mgmt_pending_cmd *cmd, *tmp; + mutex_lock(&hdev->mgmt_pending_lock); + list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { if (opcode > 0 && cmd->opcode != opcode) continue; + if (remove) + list_del(&cmd->list); + cb(cmd, data); + + if (remove) + mgmt_pending_free(cmd); } + + mutex_unlock(&hdev->mgmt_pending_lock); } struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode, @@ -254,7 +271,7 @@ struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode, return NULL; cmd->opcode = opcode; - cmd->index = hdev->id; + cmd->hdev = hdev; cmd->param = kmemdup(data, len, GFP_KERNEL); if (!cmd->param) { @@ -280,7 +297,9 @@ struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, if (!cmd) return NULL; + mutex_lock(&hdev->mgmt_pending_lock); list_add_tail(&cmd->list, &hdev->mgmt_pending); + mutex_unlock(&hdev->mgmt_pending_lock); return cmd; } @@ -294,7 +313,10 @@ void mgmt_pending_free(struct mgmt_pending_cmd *cmd) void mgmt_pending_remove(struct mgmt_pending_cmd *cmd) { + mutex_lock(&cmd->hdev->mgmt_pending_lock); list_del(&cmd->list); + mutex_unlock(&cmd->hdev->mgmt_pending_lock); + mgmt_pending_free(cmd); } diff --git a/net/bluetooth/mgmt_util.h b/net/bluetooth/mgmt_util.h index f2ba994ab1d8..024e51dd6937 100644 --- a/net/bluetooth/mgmt_util.h +++ b/net/bluetooth/mgmt_util.h @@ -33,7 +33,7 @@ struct mgmt_mesh_tx { struct mgmt_pending_cmd { struct list_head list; u16 opcode; - int index; + struct hci_dev *hdev; void *param; size_t param_len; struct sock *sk; @@ -54,7 +54,7 @@ int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode, struct hci_dev *hdev); -void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, +void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, bool remove, void (*cb)(struct mgmt_pending_cmd *cmd, void *data), void *data); struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, diff --git a/net/core/filter.c b/net/core/filter.c index 327ca73f9cd7..7a72f766aacf 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -3233,6 +3233,13 @@ static const struct bpf_func_proto bpf_skb_vlan_pop_proto = { .arg1_type = ARG_PTR_TO_CTX, }; +static void bpf_skb_change_protocol(struct sk_buff *skb, u16 proto) +{ + skb->protocol = htons(proto); + if (skb_valid_dst(skb)) + skb_dst_drop(skb); +} + static int bpf_skb_generic_push(struct sk_buff *skb, u32 off, u32 len) { /* Caller already did skb_cow() with len as headroom, @@ -3329,7 +3336,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb) } } - skb->protocol = htons(ETH_P_IPV6); + bpf_skb_change_protocol(skb, ETH_P_IPV6); skb_clear_hash(skb); return 0; @@ -3359,7 +3366,7 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb) } } - skb->protocol = htons(ETH_P_IP); + bpf_skb_change_protocol(skb, ETH_P_IP); skb_clear_hash(skb); return 0; @@ -3550,10 +3557,10 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff, /* Match skb->protocol to new outer l3 protocol */ if (skb->protocol == htons(ETH_P_IP) && flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6) - skb->protocol = htons(ETH_P_IPV6); + bpf_skb_change_protocol(skb, ETH_P_IPV6); else if (skb->protocol == htons(ETH_P_IPV6) && flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4) - skb->protocol = htons(ETH_P_IP); + bpf_skb_change_protocol(skb, ETH_P_IP); } if (skb_is_gso(skb)) { @@ -3606,10 +3613,10 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff, /* Match skb->protocol to new outer l3 protocol */ if (skb->protocol == htons(ETH_P_IP) && flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV6) - skb->protocol = htons(ETH_P_IPV6); + bpf_skb_change_protocol(skb, ETH_P_IPV6); else if (skb->protocol == htons(ETH_P_IPV6) && flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4) - skb->protocol = htons(ETH_P_IP); + bpf_skb_change_protocol(skb, ETH_P_IP); if (skb_is_gso(skb)) { struct skb_shared_info *shinfo = skb_shinfo(skb); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 39ec920f5de7..71c828d0bf31 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1083,7 +1083,8 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, ethtool_get_flow_spec_ring(info.fs.ring_cookie)) return -EINVAL; - if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context)) + if (info.rss_context && + !xa_load(&dev->ethtool->rss_ctx, info.rss_context)) return -EINVAL; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 0143262094b0..79c8f1acf8a3 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3737,6 +3737,53 @@ void fib6_nh_release_dsts(struct fib6_nh *fib6_nh) } } +static int fib6_config_validate(struct fib6_config *cfg, + struct netlink_ext_ack *extack) +{ + /* RTF_PCPU is an internal flag; can not be set by userspace */ + if (cfg->fc_flags & RTF_PCPU) { + NL_SET_ERR_MSG(extack, "Userspace can not set RTF_PCPU"); + goto errout; + } + + /* RTF_CACHE is an internal flag; can not be set by userspace */ + if (cfg->fc_flags & RTF_CACHE) { + NL_SET_ERR_MSG(extack, "Userspace can not set RTF_CACHE"); + goto errout; + } + + if (cfg->fc_type > RTN_MAX) { + NL_SET_ERR_MSG(extack, "Invalid route type"); + goto errout; + } + + if (cfg->fc_dst_len > 128) { + NL_SET_ERR_MSG(extack, "Invalid prefix length"); + goto errout; + } + +#ifdef CONFIG_IPV6_SUBTREES + if (cfg->fc_src_len > 128) { + NL_SET_ERR_MSG(extack, "Invalid source address length"); + goto errout; + } + + if (cfg->fc_nh_id && cfg->fc_src_len) { + NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing"); + goto errout; + } +#else + if (cfg->fc_src_len) { + NL_SET_ERR_MSG(extack, + "Specifying source address requires IPV6_SUBTREES to be enabled"); + goto errout; + } +#endif + return 0; +errout: + return -EINVAL; +} + static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, gfp_t gfp_flags, struct netlink_ext_ack *extack) @@ -3886,6 +3933,10 @@ int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags, struct fib6_info *rt; int err; + err = fib6_config_validate(cfg, extack); + if (err) + return err; + rt = ip6_route_info_create(cfg, gfp_flags, extack); if (IS_ERR(rt)) return PTR_ERR(rt); @@ -4479,53 +4530,6 @@ void rt6_purge_dflt_routers(struct net *net) rcu_read_unlock(); } -static int fib6_config_validate(struct fib6_config *cfg, - struct netlink_ext_ack *extack) -{ - /* RTF_PCPU is an internal flag; can not be set by userspace */ - if (cfg->fc_flags & RTF_PCPU) { - NL_SET_ERR_MSG(extack, "Userspace can not set RTF_PCPU"); - goto errout; - } - - /* RTF_CACHE is an internal flag; can not be set by userspace */ - if (cfg->fc_flags & RTF_CACHE) { - NL_SET_ERR_MSG(extack, "Userspace can not set RTF_CACHE"); - goto errout; - } - - if (cfg->fc_type > RTN_MAX) { - NL_SET_ERR_MSG(extack, "Invalid route type"); - goto errout; - } - - if (cfg->fc_dst_len > 128) { - NL_SET_ERR_MSG(extack, "Invalid prefix length"); - goto errout; - } - -#ifdef CONFIG_IPV6_SUBTREES - if (cfg->fc_src_len > 128) { - NL_SET_ERR_MSG(extack, "Invalid source address length"); - goto errout; - } - - if (cfg->fc_nh_id && cfg->fc_src_len) { - NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing"); - goto errout; - } -#else - if (cfg->fc_src_len) { - NL_SET_ERR_MSG(extack, - "Specifying source address requires IPV6_SUBTREES to be enabled"); - goto errout; - } -#endif - return 0; -errout: - return -EINVAL; -} - static void rtmsg_to_fib6_config(struct net *net, struct in6_rtmsg *rtmsg, struct fib6_config *cfg) @@ -4563,10 +4567,6 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, struct in6_rtmsg *rtmsg) switch (cmd) { case SIOCADDRT: - err = fib6_config_validate(&cfg, NULL); - if (err) - break; - /* Only do the default setting of fc_metric in route adding */ if (cfg.fc_metric == 0) cfg.fc_metric = IP6_RT_PRIO_USER; @@ -5402,6 +5402,10 @@ static int ip6_route_multipath_add(struct fib6_config *cfg, int nhn = 0; int err; + err = fib6_config_validate(cfg, extack); + if (err) + return err; + replace = (cfg->fc_nlinfo.nlh && (cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_REPLACE)); @@ -5636,10 +5640,6 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, if (err < 0) return err; - err = fib6_config_validate(&cfg, extack); - if (err) - return err; - if (cfg.fc_metric == 0) cfg.fc_metric = IP6_RT_PRIO_USER; diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c index 2c069f0181c6..037f764822b9 100644 --- a/net/sched/sch_ets.c +++ b/net/sched/sch_ets.c @@ -661,7 +661,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, for (i = q->nbands; i < oldbands; i++) { if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) list_del_init(&q->classes[i].alist); - qdisc_tree_flush_backlog(q->classes[i].qdisc); + qdisc_purge_queue(q->classes[i].qdisc); } WRITE_ONCE(q->nstrict, nstrict); memcpy(q->prio2band, priomap, sizeof(priomap)); diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index cc30f7a32f1a..9e2b9a490db2 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -211,7 +211,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt, memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); for (i = q->bands; i < oldbands; i++) - qdisc_tree_flush_backlog(q->queues[i]); + qdisc_purge_queue(q->queues[i]); for (i = oldbands; i < q->bands; i++) { q->queues[i] = queues[i]; diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 339d70b4a4c5..479c42d11083 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -285,7 +285,7 @@ static int __red_change(struct Qdisc *sch, struct nlattr **tb, q->userbits = userbits; q->limit = ctl->limit; if (child) { - qdisc_tree_flush_backlog(q->qdisc); + qdisc_purge_queue(q->qdisc); old_child = q->qdisc; q->qdisc = child; } diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index a8081492d671..96eb2f122973 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -310,7 +310,10 @@ drop: /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */ x = q->tail->next; slot = &q->slots[x]; - q->tail->next = slot->next; + if (slot->next == x) + q->tail = NULL; /* no more active slots */ + else + q->tail->next = slot->next; q->ht[slot->hash] = SFQ_EMPTY_SLOT; goto drop; } @@ -653,6 +656,14 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt, NL_SET_ERR_MSG_MOD(extack, "invalid quantum"); return -EINVAL; } + + if (ctl->perturb_period < 0 || + ctl->perturb_period > INT_MAX / HZ) { + NL_SET_ERR_MSG_MOD(extack, "invalid perturb period"); + return -EINVAL; + } + perturb_period = ctl->perturb_period * HZ; + if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max, ctl_v1->Wlog, ctl_v1->Scell_log, NULL)) return -EINVAL; @@ -669,14 +680,12 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt, headdrop = q->headdrop; maxdepth = q->maxdepth; maxflows = q->maxflows; - perturb_period = q->perturb_period; quantum = q->quantum; flags = q->flags; /* update and validate configuration */ if (ctl->quantum) quantum = ctl->quantum; - perturb_period = ctl->perturb_period * HZ; if (ctl->flows) maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); if (ctl->divisor) { diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index dc26b22d53c7..4c977f049670 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -452,7 +452,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt, sch_tree_lock(sch); if (child) { - qdisc_tree_flush_backlog(q->qdisc); + qdisc_purge_queue(q->qdisc); old = q->qdisc; q->qdisc = child; } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 2e2e9997a68e..22e170fb5dda 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1971,7 +1971,8 @@ static void unix_maybe_add_creds(struct sk_buff *skb, const struct sock *sk, if (UNIXCB(skb).pid) return; - if (unix_may_passcred(sk) || unix_may_passcred(other)) { + if (unix_may_passcred(sk) || unix_may_passcred(other) || + !other->sk_socket) { UNIXCB(skb).pid = get_pid(task_tgid(current)); current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid); } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fd5f79266471..85f139016da2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1583,7 +1583,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev, return result; error: - kfree(result); + kfree_sensitive(result); return ERR_PTR(err); } diff --git a/rust/helpers/cpu.c b/rust/helpers/cpu.c new file mode 100644 index 000000000000..824e0adb19d4 --- /dev/null +++ b/rust/helpers/cpu.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/smp.h> + +unsigned int rust_helper_raw_smp_processor_id(void) +{ + return raw_smp_processor_id(); +} diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 0f1b5d115985..16fa9bca5949 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -13,6 +13,7 @@ #include "build_assert.c" #include "build_bug.c" #include "clk.c" +#include "cpu.c" #include "cpufreq.c" #include "cpumask.c" #include "cred.c" diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs index 6041c6d07527..fbcea31dbcca 100644 --- a/rust/kernel/clk.rs +++ b/rust/kernel/clk.rs @@ -30,39 +30,43 @@ use crate::ffi::c_ulong; pub struct Hertz(pub c_ulong); impl Hertz { + const KHZ_TO_HZ: c_ulong = 1_000; + const MHZ_TO_HZ: c_ulong = 1_000_000; + const GHZ_TO_HZ: c_ulong = 1_000_000_000; + /// Create a new instance from kilohertz (kHz) - pub fn from_khz(khz: c_ulong) -> Self { - Self(khz * 1_000) + pub const fn from_khz(khz: c_ulong) -> Self { + Self(khz * Self::KHZ_TO_HZ) } /// Create a new instance from megahertz (MHz) - pub fn from_mhz(mhz: c_ulong) -> Self { - Self(mhz * 1_000_000) + pub const fn from_mhz(mhz: c_ulong) -> Self { + Self(mhz * Self::MHZ_TO_HZ) } /// Create a new instance from gigahertz (GHz) - pub fn from_ghz(ghz: c_ulong) -> Self { - Self(ghz * 1_000_000_000) + pub const fn from_ghz(ghz: c_ulong) -> Self { + Self(ghz * Self::GHZ_TO_HZ) } /// Get the frequency in hertz - pub fn as_hz(&self) -> c_ulong { + pub const fn as_hz(&self) -> c_ulong { self.0 } /// Get the frequency in kilohertz - pub fn as_khz(&self) -> c_ulong { - self.0 / 1_000 + pub const fn as_khz(&self) -> c_ulong { + self.0 / Self::KHZ_TO_HZ } /// Get the frequency in megahertz - pub fn as_mhz(&self) -> c_ulong { - self.0 / 1_000_000 + pub const fn as_mhz(&self) -> c_ulong { + self.0 / Self::MHZ_TO_HZ } /// Get the frequency in gigahertz - pub fn as_ghz(&self) -> c_ulong { - self.0 / 1_000_000_000 + pub const fn as_ghz(&self) -> c_ulong { + self.0 / Self::GHZ_TO_HZ } } @@ -132,11 +136,7 @@ mod common_clk { /// /// [`clk_get`]: https://docs.kernel.org/core-api/kernel-api.html#c.clk_get pub fn get(dev: &Device, name: Option<&CStr>) -> Result<Self> { - let con_id = if let Some(name) = name { - name.as_ptr() - } else { - ptr::null() - }; + let con_id = name.map_or(ptr::null(), |n| n.as_ptr()); // SAFETY: It is safe to call [`clk_get`] for a valid device pointer. // @@ -304,11 +304,7 @@ mod common_clk { /// [`clk_get_optional`]: /// https://docs.kernel.org/core-api/kernel-api.html#c.clk_get_optional pub fn get(dev: &Device, name: Option<&CStr>) -> Result<Self> { - let con_id = if let Some(name) = name { - name.as_ptr() - } else { - ptr::null() - }; + let con_id = name.map_or(ptr::null(), |n| n.as_ptr()); // SAFETY: It is safe to call [`clk_get_optional`] for a valid device pointer. // diff --git a/rust/kernel/cpu.rs b/rust/kernel/cpu.rs index 10c5c3b25873..b75403b0eb56 100644 --- a/rust/kernel/cpu.rs +++ b/rust/kernel/cpu.rs @@ -6,6 +6,127 @@ use crate::{bindings, device::Device, error::Result, prelude::ENODEV}; +/// Returns the maximum number of possible CPUs in the current system configuration. +#[inline] +pub fn nr_cpu_ids() -> u32 { + #[cfg(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS))] + { + bindings::NR_CPUS + } + + #[cfg(not(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS)))] + // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel. + unsafe { + bindings::nr_cpu_ids + } +} + +/// The CPU ID. +/// +/// Represents a CPU identifier as a wrapper around an [`u32`]. +/// +/// # Invariants +/// +/// The CPU ID lies within the range `[0, nr_cpu_ids())`. +/// +/// # Examples +/// +/// ``` +/// use kernel::cpu::CpuId; +/// +/// let cpu = 0; +/// +/// // SAFETY: 0 is always a valid CPU number. +/// let id = unsafe { CpuId::from_u32_unchecked(cpu) }; +/// +/// assert_eq!(id.as_u32(), cpu); +/// assert!(CpuId::from_i32(0).is_some()); +/// assert!(CpuId::from_i32(-1).is_none()); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct CpuId(u32); + +impl CpuId { + /// Creates a new [`CpuId`] from the given `id` without checking bounds. + /// + /// # Safety + /// + /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`). + #[inline] + pub unsafe fn from_i32_unchecked(id: i32) -> Self { + debug_assert!(id >= 0); + debug_assert!((id as u32) < nr_cpu_ids()); + + // INVARIANT: The function safety guarantees `id` is a valid CPU id. + Self(id as u32) + } + + /// Creates a new [`CpuId`] from the given `id`, checking that it is valid. + pub fn from_i32(id: i32) -> Option<Self> { + if id < 0 || id as u32 >= nr_cpu_ids() { + None + } else { + // INVARIANT: `id` has just been checked as a valid CPU ID. + Some(Self(id as u32)) + } + } + + /// Creates a new [`CpuId`] from the given `id` without checking bounds. + /// + /// # Safety + /// + /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`). + #[inline] + pub unsafe fn from_u32_unchecked(id: u32) -> Self { + debug_assert!(id < nr_cpu_ids()); + + // Ensure the `id` fits in an [`i32`] as it's also representable that way. + debug_assert!(id <= i32::MAX as u32); + + // INVARIANT: The function safety guarantees `id` is a valid CPU id. + Self(id) + } + + /// Creates a new [`CpuId`] from the given `id`, checking that it is valid. + pub fn from_u32(id: u32) -> Option<Self> { + if id >= nr_cpu_ids() { + None + } else { + // INVARIANT: `id` has just been checked as a valid CPU ID. + Some(Self(id)) + } + } + + /// Returns CPU number. + #[inline] + pub fn as_u32(&self) -> u32 { + self.0 + } + + /// Returns the ID of the CPU the code is currently running on. + /// + /// The returned value is considered unstable because it may change + /// unexpectedly due to preemption or CPU migration. It should only be + /// used when the context ensures that the task remains on the same CPU + /// or the users could use a stale (yet valid) CPU ID. + pub fn current() -> Self { + // SAFETY: raw_smp_processor_id() always returns a valid CPU ID. + unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) } + } +} + +impl From<CpuId> for u32 { + fn from(id: CpuId) -> Self { + id.as_u32() + } +} + +impl From<CpuId> for i32 { + fn from(id: CpuId) -> Self { + id.as_u32() as i32 + } +} + /// Creates a new instance of CPU's device. /// /// # Safety @@ -17,9 +138,9 @@ use crate::{bindings, device::Device, error::Result, prelude::ENODEV}; /// Callers must ensure that the CPU device is not used after it has been unregistered. /// This can be achieved, for example, by registering a CPU hotplug notifier and removing /// any references to the CPU device within the notifier's callback. -pub unsafe fn from_cpu(cpu: u32) -> Result<&'static Device> { +pub unsafe fn from_cpu(cpu: CpuId) -> Result<&'static Device> { // SAFETY: It is safe to call `get_cpu_device()` for any CPU. - let ptr = unsafe { bindings::get_cpu_device(cpu) }; + let ptr = unsafe { bindings::get_cpu_device(u32::from(cpu)) }; if ptr.is_null() { return Err(ENODEV); } diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index b0a9c6182aec..11b03e9d7e89 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -10,6 +10,7 @@ use crate::{ clk::Hertz, + cpu::CpuId, cpumask, device::{Bound, Device}, devres::Devres, @@ -465,8 +466,9 @@ impl Policy { /// Returns the primary CPU for the [`Policy`]. #[inline] - pub fn cpu(&self) -> u32 { - self.as_ref().cpu + pub fn cpu(&self) -> CpuId { + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. + unsafe { CpuId::from_u32_unchecked(self.as_ref().cpu) } } /// Returns the minimum frequency for the [`Policy`]. @@ -525,7 +527,7 @@ impl Policy { #[inline] pub fn generic_get(&self) -> Result<u32> { // SAFETY: By the type invariant, the pointer stored in `self` is valid. - Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) }) + Ok(unsafe { bindings::cpufreq_generic_get(u32::from(self.cpu())) }) } /// Provides a wrapper to the register with energy model using the OPP core. @@ -678,9 +680,9 @@ impl Policy { struct PolicyCpu<'a>(&'a mut Policy); impl<'a> PolicyCpu<'a> { - fn from_cpu(cpu: u32) -> Result<Self> { + fn from_cpu(cpu: CpuId) -> Result<Self> { // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU. - let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?; + let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(u32::from(cpu)) })?; Ok(Self( // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of @@ -1055,8 +1057,11 @@ impl<T: Driver> Registration<T> { impl<T: Driver> Registration<T> { /// Driver's `init` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { from_result(|| { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. @@ -1070,8 +1075,11 @@ impl<T: Driver> Registration<T> { /// Driver's `exit` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. let policy = unsafe { Policy::from_raw_mut(ptr) }; @@ -1082,8 +1090,11 @@ impl<T: Driver> Registration<T> { /// Driver's `online` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { from_result(|| { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. @@ -1094,8 +1105,13 @@ impl<T: Driver> Registration<T> { /// Driver's `offline` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn offline_callback( + ptr: *mut bindings::cpufreq_policy, + ) -> kernel::ffi::c_int { from_result(|| { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. @@ -1106,8 +1122,13 @@ impl<T: Driver> Registration<T> { /// Driver's `suspend` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn suspend_callback( + ptr: *mut bindings::cpufreq_policy, + ) -> kernel::ffi::c_int { from_result(|| { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. @@ -1118,8 +1139,11 @@ impl<T: Driver> Registration<T> { /// Driver's `resume` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { from_result(|| { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. @@ -1130,8 +1154,11 @@ impl<T: Driver> Registration<T> { /// Driver's `ready` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. let policy = unsafe { Policy::from_raw_mut(ptr) }; @@ -1140,8 +1167,13 @@ impl<T: Driver> Registration<T> { /// Driver's `verify` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> kernel::ffi::c_int { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn verify_callback( + ptr: *mut bindings::cpufreq_policy_data, + ) -> kernel::ffi::c_int { from_result(|| { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. @@ -1152,8 +1184,13 @@ impl<T: Driver> Registration<T> { /// Driver's `setpolicy` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn setpolicy_callback( + ptr: *mut bindings::cpufreq_policy, + ) -> kernel::ffi::c_int { from_result(|| { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. @@ -1164,8 +1201,11 @@ impl<T: Driver> Registration<T> { /// Driver's `target` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn target_callback( + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn target_callback( ptr: *mut bindings::cpufreq_policy, target_freq: u32, relation: u32, @@ -1180,8 +1220,11 @@ impl<T: Driver> Registration<T> { /// Driver's `target_index` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn target_index_callback( + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn target_index_callback( ptr: *mut bindings::cpufreq_policy, index: u32, ) -> kernel::ffi::c_int { @@ -1200,8 +1243,11 @@ impl<T: Driver> Registration<T> { /// Driver's `fast_switch` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn fast_switch_callback( + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn fast_switch_callback( ptr: *mut bindings::cpufreq_policy, target_freq: u32, ) -> kernel::ffi::c_uint { @@ -1212,21 +1258,31 @@ impl<T: Driver> Registration<T> { } /// Driver's `adjust_perf` callback. - extern "C" fn adjust_perf_callback( + /// + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + unsafe extern "C" fn adjust_perf_callback( cpu: u32, min_perf: usize, target_perf: usize, capacity: usize, ) { - if let Ok(mut policy) = PolicyCpu::from_cpu(cpu) { + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. + let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) }; + + if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) { T::adjust_perf(&mut policy, min_perf, target_perf, capacity); } } /// Driver's `get_intermediate` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn get_intermediate_callback( + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn get_intermediate_callback( ptr: *mut bindings::cpufreq_policy, index: u32, ) -> kernel::ffi::c_uint { @@ -1243,8 +1299,11 @@ impl<T: Driver> Registration<T> { /// Driver's `target_intermediate` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn target_intermediate_callback( + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn target_intermediate_callback( ptr: *mut bindings::cpufreq_policy, index: u32, ) -> kernel::ffi::c_int { @@ -1262,12 +1321,24 @@ impl<T: Driver> Registration<T> { } /// Driver's `get` callback. - extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint { - PolicyCpu::from_cpu(cpu).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f)) + /// + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + unsafe extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint { + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. + let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) }; + + PolicyCpu::from_cpu(cpu_id).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f)) } /// Driver's `update_limit` callback. - extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) { + /// + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. let policy = unsafe { Policy::from_raw_mut(ptr) }; @@ -1276,10 +1347,16 @@ impl<T: Driver> Registration<T> { /// Driver's `bios_limit` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int { + // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. + let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) }; + from_result(|| { - let mut policy = PolicyCpu::from_cpu(cpu as u32)?; + let mut policy = PolicyCpu::from_cpu(cpu_id)?; // SAFETY: `limit` is guaranteed by the C code to be valid. T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0) @@ -1288,8 +1365,11 @@ impl<T: Driver> Registration<T> { /// Driver's `set_boost` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn set_boost_callback( + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn set_boost_callback( ptr: *mut bindings::cpufreq_policy, state: i32, ) -> kernel::ffi::c_int { @@ -1303,8 +1383,11 @@ impl<T: Driver> Registration<T> { /// Driver's `register_em` callback. /// - /// SAFETY: Called from C. Inputs must be valid pointers. - extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) { + /// # Safety + /// + /// - This function may only be called from the cpufreq C infrastructure. + /// - The pointer arguments must be valid pointers. + unsafe extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) { // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the // lifetime of `policy`. let policy = unsafe { Policy::from_raw_mut(ptr) }; diff --git a/rust/kernel/cpumask.rs b/rust/kernel/cpumask.rs index c90bfac9346a..19c607709b5f 100644 --- a/rust/kernel/cpumask.rs +++ b/rust/kernel/cpumask.rs @@ -6,6 +6,7 @@ use crate::{ alloc::{AllocError, Flags}, + cpu::CpuId, prelude::*, types::Opaque, }; @@ -35,9 +36,10 @@ use core::ops::{Deref, DerefMut}; /// /// ``` /// use kernel::bindings; +/// use kernel::cpu::CpuId; /// use kernel::cpumask::Cpumask; /// -/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: u32, clear_cpu: i32) { +/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: CpuId, clear_cpu: CpuId) { /// // SAFETY: The `ptr` is valid for writing and remains valid for the lifetime of the /// // returned reference. /// let mask = unsafe { Cpumask::as_mut_ref(ptr) }; @@ -90,9 +92,9 @@ impl Cpumask { /// This mismatches kernel naming convention and corresponds to the C /// function `__cpumask_set_cpu()`. #[inline] - pub fn set(&mut self, cpu: u32) { + pub fn set(&mut self, cpu: CpuId) { // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `__cpumask_set_cpu`. - unsafe { bindings::__cpumask_set_cpu(cpu, self.as_raw()) }; + unsafe { bindings::__cpumask_set_cpu(u32::from(cpu), self.as_raw()) }; } /// Clear `cpu` in the cpumask. @@ -101,19 +103,19 @@ impl Cpumask { /// This mismatches kernel naming convention and corresponds to the C /// function `__cpumask_clear_cpu()`. #[inline] - pub fn clear(&mut self, cpu: i32) { + pub fn clear(&mut self, cpu: CpuId) { // SAFETY: By the type invariant, `self.as_raw` is a valid argument to // `__cpumask_clear_cpu`. - unsafe { bindings::__cpumask_clear_cpu(cpu, self.as_raw()) }; + unsafe { bindings::__cpumask_clear_cpu(i32::from(cpu), self.as_raw()) }; } /// Test `cpu` in the cpumask. /// /// Equivalent to the kernel's `cpumask_test_cpu` API. #[inline] - pub fn test(&self, cpu: i32) -> bool { + pub fn test(&self, cpu: CpuId) -> bool { // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_test_cpu`. - unsafe { bindings::cpumask_test_cpu(cpu, self.as_raw()) } + unsafe { bindings::cpumask_test_cpu(i32::from(cpu), self.as_raw()) } } /// Set all CPUs in the cpumask. @@ -178,21 +180,40 @@ impl Cpumask { /// The following example demonstrates how to create and update a [`CpumaskVar`]. /// /// ``` +/// use kernel::cpu::CpuId; /// use kernel::cpumask::CpumaskVar; /// /// let mut mask = CpumaskVar::new_zero(GFP_KERNEL).unwrap(); /// /// assert!(mask.empty()); -/// mask.set(2); -/// assert!(mask.test(2)); -/// mask.set(3); -/// assert!(mask.test(3)); -/// assert_eq!(mask.weight(), 2); +/// let mut count = 0; +/// +/// let cpu2 = CpuId::from_u32(2); +/// if let Some(cpu) = cpu2 { +/// mask.set(cpu); +/// assert!(mask.test(cpu)); +/// count += 1; +/// } +/// +/// let cpu3 = CpuId::from_u32(3); +/// if let Some(cpu) = cpu3 { +/// mask.set(cpu); +/// assert!(mask.test(cpu)); +/// count += 1; +/// } +/// +/// assert_eq!(mask.weight(), count); /// /// let mask2 = CpumaskVar::try_clone(&mask).unwrap(); -/// assert!(mask2.test(2)); -/// assert!(mask2.test(3)); -/// assert_eq!(mask2.weight(), 2); +/// +/// if let Some(cpu) = cpu2 { +/// assert!(mask2.test(cpu)); +/// } +/// +/// if let Some(cpu) = cpu3 { +/// assert!(mask2.test(cpu)); +/// } +/// assert_eq!(mask2.weight(), count); /// ``` pub struct CpumaskVar { #[cfg(CONFIG_CPUMASK_OFFSTACK)] diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs index 9df3dcd2fa39..36e1290cd079 100644 --- a/rust/kernel/time/hrtimer.rs +++ b/rust/kernel/time/hrtimer.rs @@ -517,7 +517,7 @@ macro_rules! impl_has_hr_timer { ) -> *mut Self { // SAFETY: As per the safety requirement of this function, `ptr` // is pointing inside a `$timer_type`. - unsafe { ::kernel::container_of!(ptr, $timer_type, $field).cast_mut() } + unsafe { ::kernel::container_of!(ptr, $timer_type, $field) } } } } diff --git a/scripts/gendwarfksyms/gendwarfksyms.h b/scripts/gendwarfksyms/gendwarfksyms.h index 7dd03ffe0c5c..d9c06d2cb1df 100644 --- a/scripts/gendwarfksyms/gendwarfksyms.h +++ b/scripts/gendwarfksyms/gendwarfksyms.h @@ -216,24 +216,14 @@ int cache_get(struct cache *cache, unsigned long key); void cache_init(struct cache *cache); void cache_free(struct cache *cache); -static inline void __cache_mark_expanded(struct cache *cache, uintptr_t addr) -{ - cache_set(cache, addr, 1); -} - -static inline bool __cache_was_expanded(struct cache *cache, uintptr_t addr) -{ - return cache_get(cache, addr) == 1; -} - static inline void cache_mark_expanded(struct cache *cache, void *addr) { - __cache_mark_expanded(cache, (uintptr_t)addr); + cache_set(cache, (unsigned long)addr, 1); } static inline bool cache_was_expanded(struct cache *cache, void *addr) { - return __cache_was_expanded(cache, (uintptr_t)addr); + return cache_get(cache, (unsigned long)addr) == 1; } /* diff --git a/scripts/gendwarfksyms/types.c b/scripts/gendwarfksyms/types.c index 39ce1770e463..7bd459ea6c59 100644 --- a/scripts/gendwarfksyms/types.c +++ b/scripts/gendwarfksyms/types.c @@ -333,37 +333,11 @@ static void calculate_version(struct version *version, cache_free(&expansion_cache); } -static void __type_expand(struct die *cache, struct type_expansion *type, - bool recursive); - -static void type_expand_child(struct die *cache, struct type_expansion *type, - bool recursive) -{ - struct type_expansion child; - char *name; - - name = get_type_name(cache); - if (!name) { - __type_expand(cache, type, recursive); - return; - } - - if (recursive && !__cache_was_expanded(&expansion_cache, cache->addr)) { - __cache_mark_expanded(&expansion_cache, cache->addr); - type_expansion_init(&child); - __type_expand(cache, &child, true); - type_map_add(name, &child); - type_expansion_free(&child); - } - - type_expansion_append(type, name, name); -} - -static void __type_expand(struct die *cache, struct type_expansion *type, - bool recursive) +static void __type_expand(struct die *cache, struct type_expansion *type) { struct die_fragment *df; struct die *child; + char *name; list_for_each_entry(df, &cache->fragments, list) { switch (df->type) { @@ -379,7 +353,12 @@ static void __type_expand(struct die *cache, struct type_expansion *type, error("unknown child: %" PRIxPTR, df->data.addr); - type_expand_child(child, type, recursive); + name = get_type_name(child); + if (name) + type_expansion_append(type, name, name); + else + __type_expand(child, type); + break; case FRAGMENT_LINEBREAK: /* @@ -397,12 +376,17 @@ static void __type_expand(struct die *cache, struct type_expansion *type, } } -static void type_expand(struct die *cache, struct type_expansion *type, - bool recursive) +static void type_expand(const char *name, struct die *cache, + struct type_expansion *type) { + const char *override; + type_expansion_init(type); - __type_expand(cache, type, recursive); - cache_free(&expansion_cache); + + if (stable && kabi_get_type_string(name, &override)) + type_parse(name, override, type); + else + __type_expand(cache, type); } static void type_parse(const char *name, const char *str, @@ -416,8 +400,6 @@ static void type_parse(const char *name, const char *str, if (!*str) error("empty type string override for '%s'", name); - type_expansion_init(type); - for (pos = 0; str[pos]; ++pos) { bool empty; char marker = ' '; @@ -478,7 +460,6 @@ static void type_parse(const char *name, const char *str, static void expand_type(struct die *cache, void *arg) { struct type_expansion type; - const char *override; char *name; if (cache->mapped) @@ -504,11 +485,7 @@ static void expand_type(struct die *cache, void *arg) debug("%s", name); - if (stable && kabi_get_type_string(name, &override)) - type_parse(name, override, &type); - else - type_expand(cache, &type, true); - + type_expand(name, cache, &type); type_map_add(name, &type); type_expansion_free(&type); free(name); @@ -518,7 +495,6 @@ static void expand_symbol(struct symbol *sym, void *arg) { struct type_expansion type; struct version version; - const char *override; struct die *cache; /* @@ -532,10 +508,7 @@ static void expand_symbol(struct symbol *sym, void *arg) if (__die_map_get(sym->die_addr, DIE_SYMBOL, &cache)) return; /* We'll warn about missing CRCs later. */ - if (stable && kabi_get_type_string(sym->name, &override)) - type_parse(sym->name, override, &type); - else - type_expand(cache, &type, false); + type_expand(sym->name, cache, &type); /* If the symbol already has a version, don't calculate it again. */ if (sym->state != SYMBOL_PROCESSED) { diff --git a/scripts/misc-check b/scripts/misc-check index a74450e799d1..84f08da17b2c 100755 --- a/scripts/misc-check +++ b/scripts/misc-check @@ -62,6 +62,15 @@ check_unnecessary_include_linux_export_h () { xargs -r printf "%s: warning: EXPORT_SYMBOL() is not used, but #include <linux/export.h> is present\n" >&2 } -check_tracked_ignored_files -check_missing_include_linux_export_h -check_unnecessary_include_linux_export_h +case "${KBUILD_EXTRA_WARN}" in +*1*) + check_tracked_ignored_files + ;; +esac + +case "${KBUILD_EXTRA_WARN}" in +*2*) + check_missing_include_linux_export_h + check_unnecessary_include_linux_export_h + ;; +esac diff --git a/security/keys/gc.c b/security/keys/gc.c index f27223ea4578..748e83818a76 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -218,8 +218,8 @@ continue_scanning: key = rb_entry(cursor, struct key, serial_node); cursor = rb_next(cursor); - if (test_bit(KEY_FLAG_FINAL_PUT, &key->flags)) { - smp_mb(); /* Clobber key->user after FINAL_PUT seen. */ + if (!test_bit_acquire(KEY_FLAG_USER_ALIVE, &key->flags)) { + /* Clobber key->user after final put seen. */ goto found_unreferenced_key; } diff --git a/security/keys/key.c b/security/keys/key.c index 7198cd2ac3a3..3bbdde778631 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -298,6 +298,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->restrict_link = restrict_link; key->last_used_at = ktime_get_real_seconds(); + key->flags |= 1 << KEY_FLAG_USER_ALIVE; if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) key->flags |= 1 << KEY_FLAG_IN_QUOTA; if (flags & KEY_ALLOC_BUILT_IN) @@ -658,8 +659,8 @@ void key_put(struct key *key) key->user->qnbytes -= key->quotalen; spin_unlock_irqrestore(&key->user->lock, flags); } - smp_mb(); /* key->user before FINAL_PUT set. */ - set_bit(KEY_FLAG_FINAL_PUT, &key->flags); + /* Mark key as safe for GC after key->user done. */ + clear_bit_unlock(KEY_FLAG_USER_ALIVE, &key->flags); schedule_work(&key_gc_work); } } diff --git a/tools/bpf/resolve_btfids/Makefile b/tools/bpf/resolve_btfids/Makefile index afbddea3a39c..ce1b556dfa90 100644 --- a/tools/bpf/resolve_btfids/Makefile +++ b/tools/bpf/resolve_btfids/Makefile @@ -17,7 +17,7 @@ endif # Overrides for the prepare step libraries. HOST_OVERRIDES := AR="$(HOSTAR)" CC="$(HOSTCC)" LD="$(HOSTLD)" ARCH="$(HOSTARCH)" \ - CROSS_COMPILE="" EXTRA_CFLAGS="$(HOSTCFLAGS)" + CROSS_COMPILE="" CLANG_CROSS_FLAGS="" EXTRA_CFLAGS="$(HOSTCFLAGS)" RM ?= rm HOSTCC ?= gcc diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index f1d495dc66bb..37682908cb0f 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -1384,12 +1384,12 @@ static struct btf *btf_parse_raw_mmap(const char *path, struct btf *base_btf) fd = open(path, O_RDONLY); if (fd < 0) - return libbpf_err_ptr(-errno); + return ERR_PTR(-errno); if (fstat(fd, &st) < 0) { err = -errno; close(fd); - return libbpf_err_ptr(err); + return ERR_PTR(err); } data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); @@ -1397,7 +1397,7 @@ static struct btf *btf_parse_raw_mmap(const char *path, struct btf *base_btf) close(fd); if (data == MAP_FAILED) - return libbpf_err_ptr(err); + return ERR_PTR(err); btf = btf_new(data, st.st_size, base_btf, true); if (IS_ERR(btf)) diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index be8dfac14076..c43db1c41205 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -73,6 +73,7 @@ sbindir ?= /usr/sbin mandir ?= /usr/man libdir ?= /usr/lib libexecdir ?= /usr/libexec +unitdir ?= /usr/lib/systemd/system includedir ?= /usr/include localedir ?= /usr/share/locale docdir ?= /usr/share/doc/packages/cpupower @@ -309,9 +310,9 @@ install-tools: $(OUTPUT)cpupower $(INSTALL_DATA) cpupower-service.conf '$(DESTDIR)${confdir}' $(INSTALL) -d $(DESTDIR)${libexecdir} $(INSTALL_PROGRAM) cpupower.sh '$(DESTDIR)${libexecdir}/cpupower' - $(INSTALL) -d $(DESTDIR)${libdir}/systemd/system - sed 's|___CDIR___|${confdir}|; s|___LDIR___|${libexecdir}|' cpupower.service.in > '$(DESTDIR)${libdir}/systemd/system/cpupower.service' - $(SETPERM_DATA) '$(DESTDIR)${libdir}/systemd/system/cpupower.service' + $(INSTALL) -d $(DESTDIR)${unitdir} + sed 's|___CDIR___|${confdir}|; s|___LDIR___|${libexecdir}|' cpupower.service.in > '$(DESTDIR)${unitdir}/cpupower.service' + $(SETPERM_DATA) '$(DESTDIR)${unitdir}/cpupower.service' install-man: $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 @@ -348,7 +349,7 @@ uninstall: - rm -f $(DESTDIR)${bindir}/utils/cpupower - rm -f $(DESTDIR)${confdir}cpupower-service.conf - rm -f $(DESTDIR)${libexecdir}/cpupower - - rm -f $(DESTDIR)${libdir}/systemd/system/cpupower.service + - rm -f $(DESTDIR)${unitdir}/cpupower.service - rm -f $(DESTDIR)${mandir}/man1/cpupower.1 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1 diff --git a/tools/testing/selftests/drivers/net/hw/rss_ctx.py b/tools/testing/selftests/drivers/net/hw/rss_ctx.py index ca60ae325c22..7bb552f8b182 100755 --- a/tools/testing/selftests/drivers/net/hw/rss_ctx.py +++ b/tools/testing/selftests/drivers/net/hw/rss_ctx.py @@ -747,6 +747,62 @@ def test_rss_ntuple_addition(cfg): 'noise' : (0,) }) +def test_rss_default_context_rule(cfg): + """ + Allocate a port, direct this port to context 0, then create a new RSS + context and steer all TCP traffic to it (context 1). Verify that: + * Traffic to the specific port continues to use queues of the main + context (0/1). + * Traffic to any other TCP port is redirected to the new context + (queues 2/3). + """ + + require_ntuple(cfg) + + queue_cnt = len(_get_rx_cnts(cfg)) + if queue_cnt < 4: + try: + ksft_pr(f"Increasing queue count {queue_cnt} -> 4") + ethtool(f"-L {cfg.ifname} combined 4") + defer(ethtool, f"-L {cfg.ifname} combined {queue_cnt}") + except Exception as exc: + raise KsftSkipEx("Not enough queues for the test") from exc + + # Use queues 0 and 1 for the main context + ethtool(f"-X {cfg.ifname} equal 2") + defer(ethtool, f"-X {cfg.ifname} default") + + # Create a new RSS context that uses queues 2 and 3 + ctx_id = ethtool_create(cfg, "-X", "context new start 2 equal 2") + defer(ethtool, f"-X {cfg.ifname} context {ctx_id} delete") + + # Generic low-priority rule: redirect all TCP traffic to the new context. + # Give it an explicit higher location number (lower priority). + flow_generic = f"flow-type tcp{cfg.addr_ipver} dst-ip {cfg.addr} context {ctx_id} loc 1" + ethtool(f"-N {cfg.ifname} {flow_generic}") + defer(ethtool, f"-N {cfg.ifname} delete 1") + + # Specific high-priority rule for a random port that should stay on context 0. + # Assign loc 0 so it is evaluated before the generic rule. + port_main = rand_port() + flow_main = f"flow-type tcp{cfg.addr_ipver} dst-ip {cfg.addr} dst-port {port_main} context 0 loc 0" + ethtool(f"-N {cfg.ifname} {flow_main}") + defer(ethtool, f"-N {cfg.ifname} delete 0") + + _ntuple_rule_check(cfg, 1, ctx_id) + + # Verify that traffic matching the specific rule still goes to queues 0/1 + _send_traffic_check(cfg, port_main, "context 0", + { 'target': (0, 1), + 'empty' : (2, 3) }) + + # And that traffic for any other port is steered to the new context + port_other = rand_port() + _send_traffic_check(cfg, port_other, f"context {ctx_id}", + { 'target': (2, 3), + 'noise' : (0, 1) }) + + def main() -> None: with NetDrvEpEnv(__file__, nsim_test=False) as cfg: cfg.context_cnt = None @@ -760,7 +816,8 @@ def main() -> None: test_rss_context_overlap, test_rss_context_overlap2, test_rss_context_out_of_order, test_rss_context4_create_with_cfg, test_flow_add_context_missing, - test_delete_rss_context_busy, test_rss_ntuple_addition], + test_delete_rss_context_busy, test_rss_ntuple_addition, + test_rss_default_context_rule], args=(cfg, )) ksft_exit() diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c index a36a7e2db434..b4d22b3ab7cc 100644 --- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c +++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c @@ -22,7 +22,8 @@ #include "gic.h" #include "vgic.h" -static const uint64_t CVAL_MAX = ~0ULL; +/* Depends on counter width. */ +static uint64_t CVAL_MAX; /* tval is a signed 32-bit int. */ static const int32_t TVAL_MAX = INT32_MAX; static const int32_t TVAL_MIN = INT32_MIN; @@ -30,8 +31,8 @@ static const int32_t TVAL_MIN = INT32_MIN; /* After how much time we say there is no IRQ. */ static const uint32_t TIMEOUT_NO_IRQ_US = 50000; -/* A nice counter value to use as the starting one for most tests. */ -static const uint64_t DEF_CNT = (CVAL_MAX / 2); +/* Counter value to use as the starting one for most tests. Set to CVAL_MAX/2 */ +static uint64_t DEF_CNT; /* Number of runs. */ static const uint32_t NR_TEST_ITERS_DEF = 5; @@ -191,8 +192,8 @@ static void set_tval_irq(enum arch_timer timer, uint64_t tval_cycles, { atomic_set(&shared_data.handled, 0); atomic_set(&shared_data.spurious, 0); - timer_set_ctl(timer, ctl); timer_set_tval(timer, tval_cycles); + timer_set_ctl(timer, ctl); } static void set_xval_irq(enum arch_timer timer, uint64_t xval, uint32_t ctl, @@ -732,12 +733,6 @@ static void test_move_counters_ahead_of_timers(enum arch_timer timer) test_set_cnt_after_tval(timer, 0, tval, (uint64_t) tval + 1, wm); } - - for (i = 0; i < ARRAY_SIZE(sleep_method); i++) { - sleep_method_t sm = sleep_method[i]; - - test_set_cnt_after_cval_no_irq(timer, 0, DEF_CNT, CVAL_MAX, sm); - } } /* @@ -849,17 +844,17 @@ static void guest_code(enum arch_timer timer) GUEST_DONE(); } +static cpu_set_t default_cpuset; + static uint32_t next_pcpu(void) { uint32_t max = get_nprocs(); uint32_t cur = sched_getcpu(); uint32_t next = cur; - cpu_set_t cpuset; + cpu_set_t cpuset = default_cpuset; TEST_ASSERT(max > 1, "Need at least two physical cpus"); - sched_getaffinity(0, sizeof(cpuset), &cpuset); - do { next = (next + 1) % CPU_SETSIZE; } while (!CPU_ISSET(next, &cpuset)); @@ -975,6 +970,8 @@ static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu, test_init_timer_irq(*vm, *vcpu); vgic_v3_setup(*vm, 1, 64); sync_global_to_guest(*vm, test_args); + sync_global_to_guest(*vm, CVAL_MAX); + sync_global_to_guest(*vm, DEF_CNT); } static void test_print_help(char *name) @@ -986,7 +983,7 @@ static void test_print_help(char *name) pr_info("\t-b: Test both physical and virtual timers (default: true)\n"); pr_info("\t-l: Delta (in ms) used for long wait time test (default: %u)\n", LONG_WAIT_TEST_MS); - pr_info("\t-l: Delta (in ms) used for wait times (default: %u)\n", + pr_info("\t-w: Delta (in ms) used for wait times (default: %u)\n", WAIT_TEST_MS); pr_info("\t-p: Test physical timer (default: true)\n"); pr_info("\t-v: Test virtual timer (default: true)\n"); @@ -1035,6 +1032,17 @@ static bool parse_args(int argc, char *argv[]) return false; } +static void set_counter_defaults(void) +{ + const uint64_t MIN_ROLLOVER_SECS = 40ULL * 365 * 24 * 3600; + uint64_t freq = read_sysreg(CNTFRQ_EL0); + uint64_t width = ilog2(MIN_ROLLOVER_SECS * freq); + + width = clamp(width, 56, 64); + CVAL_MAX = GENMASK_ULL(width - 1, 0); + DEF_CNT = CVAL_MAX / 2; +} + int main(int argc, char *argv[]) { struct kvm_vcpu *vcpu; @@ -1046,6 +1054,9 @@ int main(int argc, char *argv[]) if (!parse_args(argc, argv)) exit(KSFT_SKIP); + sched_getaffinity(0, sizeof(default_cpuset), &default_cpuset); + set_counter_defaults(); + if (test_args.test_virtual) { test_vm_create(&vm, &vcpu, VIRTUAL); test_run(vm, vcpu); diff --git a/tools/testing/selftests/mm/gup_longterm.c b/tools/testing/selftests/mm/gup_longterm.c index 8a97ac5176a4..29047d2e0c49 100644 --- a/tools/testing/selftests/mm/gup_longterm.c +++ b/tools/testing/selftests/mm/gup_longterm.c @@ -298,8 +298,11 @@ static void run_with_memfd(test_fn fn, const char *desc) log_test_start("%s ... with memfd", desc); fd = memfd_create("test", 0); - if (fd < 0) + if (fd < 0) { ksft_print_msg("memfd_create() failed (%s)\n", strerror(errno)); + log_test_result(KSFT_SKIP); + return; + } fn(fd, pagesize); close(fd); @@ -366,6 +369,8 @@ static void run_with_memfd_hugetlb(test_fn fn, const char *desc, fd = memfd_create("test", flags); if (fd < 0) { ksft_print_msg("memfd_create() failed (%s)\n", strerror(errno)); + log_test_result(KSFT_SKIP); + return; } fn(fd, hugetlbsize); diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index ea84b88bcb30..ab996bd22a5f 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -27,6 +27,7 @@ TEST_PROGS += amt.sh TEST_PROGS += unicast_extensions.sh TEST_PROGS += udpgro_fwd.sh TEST_PROGS += udpgro_frglist.sh +TEST_PROGS += nat6to4.sh TEST_PROGS += veth.sh TEST_PROGS += ioam6.sh TEST_PROGS += gro.sh diff --git a/tools/testing/selftests/net/nat6to4.sh b/tools/testing/selftests/net/nat6to4.sh new file mode 100755 index 000000000000..0ee859b622a4 --- /dev/null +++ b/tools/testing/selftests/net/nat6to4.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +NS="ns-peer-$(mktemp -u XXXXXX)" + +ip netns add "${NS}" +ip -netns "${NS}" link set lo up +ip -netns "${NS}" route add default via 127.0.0.2 dev lo + +tc -n "${NS}" qdisc add dev lo ingress +tc -n "${NS}" filter add dev lo ingress prio 4 protocol ip \ + bpf object-file nat6to4.bpf.o section schedcls/egress4/snat4 direct-action + +ip netns exec "${NS}" \ + bash -c 'echo 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789abc | socat - UDP4-DATAGRAM:224.1.0.1:6666,ip-multicast-loop=1' diff --git a/tools/testing/vma/vma_internal.h b/tools/testing/vma/vma_internal.h index 4505b1c31be1..14718ca23a05 100644 --- a/tools/testing/vma/vma_internal.h +++ b/tools/testing/vma/vma_internal.h @@ -159,6 +159,14 @@ typedef __bitwise unsigned int vm_fault_t; #define ASSERT_EXCLUSIVE_WRITER(x) +/** + * swap - swap values of @a and @b + * @a: first value + * @b: second value + */ +#define swap(a, b) \ + do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) + struct kref { refcount_t refcount; }; @@ -1468,4 +1476,12 @@ static inline void fixup_hugetlb_reservations(struct vm_area_struct *vma) (void)vma; } +static inline void vma_set_file(struct vm_area_struct *vma, struct file *file) +{ + /* Changing an anonymous vma with this is illegal */ + get_file(file); + swap(vma->vm_file, file); + fput(file); +} + #endif /* __MM_VMA_INTERNAL_H */ |