mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Linux 7.2-rc1
-----BEGIN PGP SIGNATURE----- iQFSBAABCgA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAmpBb4seHHRvcnZhbGRz QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiGjV8H/iFiGxRTgdNwWJsH 5BQpc9kAmQHBMuzc2yM1HeeKVOm+zfxEmZV7kFabPEGYB1ltV52vspKI5vPUCWhP 9VVqhIQy8ZfALEUIhQOoieJAboRgNDySldnuS8E2MFyfgKC0Tg8dkolmRFuh8Xhu R88kBeS1+DfpjFrnNLH98iUdtE9HabVt2VGfdrIpTYLC8VqyyuI77dXTEFkkwSCp NacpX5KYzD9dlDjlH6Hpqy/jqv7Y7JsEynFVUU05IQU9VojV7o1cbMQlKoe1yNeU dCoDCSwHhc8DUrGx1Tj6lsAS8k0R2it5FIW1eCF7cVKzZ8CbojyhluW6YPCOC0wE 0louZxg= =5vas -----END PGP SIGNATURE----- Merge tag 'v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux into gpio/for-current Linux 7.2-rc1
This commit is contained in:
commit
2ed2e359de
3
.mailmap
3
.mailmap
|
|
@ -530,7 +530,8 @@ Luca Ceresoli <luca.ceresoli@bootlin.com> <luca@lucaceresoli.net>
|
|||
Luca Weiss <luca@lucaweiss.eu> <luca@z3ntu.xyz>
|
||||
Lucas De Marchi <demarchi@kernel.org> <lucas.demarchi@intel.com>
|
||||
Lukasz Luba <lukasz.luba@arm.com> <l.luba@partner.samsung.com>
|
||||
Luo Jie <quic_luoj@quicinc.com> <luoj@codeaurora.org>
|
||||
Luo Jie <jie.luo@oss.qualcomm.com> <luoj@codeaurora.org>
|
||||
Luo Jie <jie.luo@oss.qualcomm.com> <quic_luoj@quicinc.com>
|
||||
Lance Yang <lance.yang@linux.dev> <ioworker0@gmail.com>
|
||||
Lance Yang <lance.yang@linux.dev> <mingzhe.yang@ly.com>
|
||||
Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ properties:
|
|||
const: 1
|
||||
|
||||
clocks:
|
||||
minItems: 14
|
||||
minItems: 15
|
||||
items:
|
||||
- description: input oscillator
|
||||
- description: input sys clk
|
||||
|
|
@ -40,12 +40,13 @@ properties:
|
|||
- description: input gp1 pll
|
||||
- description: input mpll1
|
||||
- description: input mpll2
|
||||
- description: input mpll3
|
||||
- description: external input rmii oscillator (optional)
|
||||
- description: input video pll0 (optional)
|
||||
- description: external pad input for rtc (optional)
|
||||
|
||||
clock-names:
|
||||
minItems: 14
|
||||
minItems: 15
|
||||
items:
|
||||
- const: xtal
|
||||
- const: sys
|
||||
|
|
@ -61,6 +62,7 @@ properties:
|
|||
- const: gp1
|
||||
- const: mpll1
|
||||
- const: mpll2
|
||||
- const: mpll3
|
||||
- const: ext_rmii
|
||||
- const: vid_pll0
|
||||
- const: ext_rtc
|
||||
|
|
@ -97,7 +99,8 @@ examples:
|
|||
<&gp0 1>,
|
||||
<&gp1 1>,
|
||||
<&mpll 4>,
|
||||
<&mpll 6>;
|
||||
<&mpll 6>,
|
||||
<&mpll 8>;
|
||||
clock-names = "xtal",
|
||||
"sys",
|
||||
"fix",
|
||||
|
|
@ -111,6 +114,7 @@ examples:
|
|||
"gp0",
|
||||
"gp1",
|
||||
"mpll1",
|
||||
"mpll2";
|
||||
"mpll2",
|
||||
"mpll3";
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ allOf:
|
|||
contains:
|
||||
enum:
|
||||
- amlogic,t7-gp0-pll
|
||||
- amlogic,t7-gp1--pll
|
||||
- amlogic,t7-gp1-pll
|
||||
- amlogic,t7-hifi-pll
|
||||
- amlogic,t7-pcie-pll
|
||||
- amlogic,t7-mpll
|
||||
|
|
|
|||
59
Documentation/devicetree/bindings/clock/canaan,k230-clk.yaml
Normal file
59
Documentation/devicetree/bindings/clock/canaan,k230-clk.yaml
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/canaan,k230-clk.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Canaan Kendryte K230 Clock
|
||||
|
||||
maintainers:
|
||||
- Xukai Wang <kingxukai@zohomail.com>
|
||||
|
||||
description:
|
||||
The Canaan K230 clock controller generates various clocks for SoC
|
||||
peripherals. See include/dt-bindings/clock/canaan,k230-clk.h for
|
||||
valid clock IDs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: canaan,k230-clk
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: PLL control registers
|
||||
- description: Sysclk control registers
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Main external reference clock
|
||||
- description:
|
||||
External clock which used as the pulse input
|
||||
for the timer to provide timing signals.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: osc24m
|
||||
- const: timer-pulse-in
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clock-controller@91102000 {
|
||||
compatible = "canaan,k230-clk";
|
||||
reg = <0x91102000 0x40>,
|
||||
<0x91100000 0x108>;
|
||||
clocks = <&osc24m>, <&timerx_pulse_in>;
|
||||
clock-names = "osc24m", "timer-pulse-in";
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
|
@ -37,6 +37,9 @@ properties:
|
|||
'#power-domain-cells':
|
||||
const: 1
|
||||
|
||||
'#reset-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -44,16 +47,27 @@ required:
|
|||
|
||||
additionalProperties: false
|
||||
|
||||
if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: marvell,pxa1908-apmu
|
||||
|
||||
then:
|
||||
properties:
|
||||
'#power-domain-cells': false
|
||||
allOf:
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: marvell,pxa1908-apmu
|
||||
then:
|
||||
properties:
|
||||
'#power-domain-cells': false
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- marvell,pxa1908-apbc
|
||||
- marvell,pxa1908-apbcp
|
||||
then:
|
||||
properties:
|
||||
'#reset-cells': false
|
||||
|
||||
examples:
|
||||
# APMU block:
|
||||
|
|
|
|||
|
|
@ -42,12 +42,6 @@ properties:
|
|||
- const: cfg_ahb_clk
|
||||
- const: gcc_disp_gpll0_div_clk_src
|
||||
|
||||
'#clock-cells':
|
||||
const: 1
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 1
|
||||
|
||||
power-domains:
|
||||
description:
|
||||
A phandle and PM domain specifier for the CX power domain.
|
||||
|
|
@ -58,18 +52,16 @@ properties:
|
|||
A phandle to an OPP node describing the power domain's performance point.
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#clock-cells'
|
||||
- '#power-domain-cells'
|
||||
|
||||
additionalProperties: false
|
||||
allOf:
|
||||
- $ref: qcom,gcc.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
@ -101,6 +93,7 @@ examples:
|
|||
power-domains = <&rpmpd SM6125_VDDCX>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
...
|
||||
|
|
|
|||
63
Documentation/devicetree/bindings/clock/qcom,hawi-gcc.yaml
Normal file
63
Documentation/devicetree/bindings/clock/qcom,hawi-gcc.yaml
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/qcom,hawi-gcc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Global Clock & Reset Controller on Hawi
|
||||
|
||||
maintainers:
|
||||
- Vivek Aknurwar <vivek.aknurwar@oss.qualcomm.com>
|
||||
|
||||
description: |
|
||||
Qualcomm global clock control module provides the clocks, resets and power
|
||||
domains on Hawi.
|
||||
|
||||
See also: include/dt-bindings/clock/qcom,hawi-gcc.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,hawi-gcc
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Board XO source
|
||||
- description: Board Always On XO source
|
||||
- description: Sleep clock source
|
||||
- description: PCIE 0 Pipe clock source
|
||||
- description: PCIE 1 Pipe clock source
|
||||
- description: UFS PHY RX symbol 0 clock
|
||||
- description: UFS PHY RX symbol 1 clock
|
||||
- description: UFS PHY TX symbol 0 clock
|
||||
- description: USB3 PHY wrapper pipe clock
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
- '#power-domain-cells'
|
||||
|
||||
allOf:
|
||||
- $ref: qcom,gcc.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
clock-controller@100000 {
|
||||
compatible = "qcom,hawi-gcc";
|
||||
reg = <0x00100000 0x1f4200>;
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>,
|
||||
<&rpmhcc RPMH_CXO_CLK_A>,
|
||||
<&sleep_clk>,
|
||||
<&pcie0_phy>,
|
||||
<&pcie1_phy>,
|
||||
<&ufs_mem_phy 0>,
|
||||
<&ufs_mem_phy 1>,
|
||||
<&ufs_mem_phy 2>,
|
||||
<&usb_1_qmpphy>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
...
|
||||
|
|
@ -8,7 +8,7 @@ title: Qualcomm CMN PLL Clock Controller on IPQ SoC
|
|||
|
||||
maintainers:
|
||||
- Bjorn Andersson <andersson@kernel.org>
|
||||
- Luo Jie <quic_luoj@quicinc.com>
|
||||
- Luo Jie <jie.luo@oss.qualcomm.com>
|
||||
|
||||
description:
|
||||
The CMN (or common) PLL clock controller expects a reference
|
||||
|
|
@ -25,6 +25,7 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- qcom,ipq5018-cmn-pll
|
||||
- qcom,ipq5332-cmn-pll
|
||||
- qcom,ipq5424-cmn-pll
|
||||
- qcom,ipq6018-cmn-pll
|
||||
- qcom,ipq8074-cmn-pll
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ required:
|
|||
- power-domains
|
||||
- '#power-domain-cells'
|
||||
|
||||
unevaluatedProperties: false
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ properties:
|
|||
- description: Sleep clock source
|
||||
- description: Camera AHB clock from GCC
|
||||
|
||||
interconnects:
|
||||
items:
|
||||
- description: Interconnect path to enable the MultiMedia NoC
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
|
|
@ -37,12 +41,16 @@ unevaluatedProperties: false
|
|||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,milos-gcc.h>
|
||||
#include <dt-bindings/interconnect/qcom,icc.h>
|
||||
#include <dt-bindings/interconnect/qcom,milos-rpmh.h>
|
||||
clock-controller@adb0000 {
|
||||
compatible = "qcom,milos-camcc";
|
||||
reg = <0x0adb0000 0x40000>;
|
||||
clocks = <&bi_tcxo_div2>,
|
||||
<&sleep_clk>,
|
||||
<&gcc GCC_CAMERA_AHB_CLK>;
|
||||
interconnects = <&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS
|
||||
&mmss_noc SLAVE_MNOC_HF_MEM_NOC QCOM_ICC_TAG_ALWAYS>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/clock/qcom,milos-gxclkctl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Graphics Power Domain Controller on Milos
|
||||
|
||||
maintainers:
|
||||
- Luca Weiss <luca.weiss@fairphone.com>
|
||||
|
||||
description: |
|
||||
Qualcomm GX(graphics) is a clock controller which has PLLs, clocks and
|
||||
Power domains (GDSC). This module provides the power domains control
|
||||
of gxclkctl on Qualcomm SoCs which helps the recovery of Graphics subsystem.
|
||||
|
||||
See also:
|
||||
include/dt-bindings/clock/qcom,kaanapali-gxclkctl.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,milos-gxclkctl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
description:
|
||||
Power domains required for the clock controller to operate
|
||||
items:
|
||||
- description: GFX power domain
|
||||
- description: GPUCC(CX) power domain
|
||||
|
||||
'#power-domain-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- power-domains
|
||||
- '#power-domain-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
clock-controller@3d64000 {
|
||||
compatible = "qcom,milos-gxclkctl";
|
||||
reg = <0x0 0x03d64000 0x0 0x6000>;
|
||||
power-domains = <&rpmhpd RPMHPD_GFX>,
|
||||
<&gpucc 0>;
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -8,7 +8,7 @@ title: Qualcomm NSS Clock & Reset Controller on QCA8386/QCA8084
|
|||
|
||||
maintainers:
|
||||
- Bjorn Andersson <andersson@kernel.org>
|
||||
- Luo Jie <quic_luoj@quicinc.com>
|
||||
- Luo Jie <jie.luo@oss.qualcomm.com>
|
||||
|
||||
description: |
|
||||
Qualcomm NSS clock control module provides the clocks and resets
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ properties:
|
|||
enum:
|
||||
- qcom,eliza-rpmh-clk
|
||||
- qcom,glymur-rpmh-clk
|
||||
- qcom,hawi-rpmh-clk
|
||||
- qcom,kaanapali-rpmh-clk
|
||||
- qcom,milos-rpmh-clk
|
||||
- qcom,nord-rpmh-clk
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ description: |
|
|||
include/dt-bindings/clock/qcom,sm8450-videocc.h
|
||||
include/dt-bindings/clock/qcom,sm8650-videocc.h
|
||||
include/dt-bindings/clock/qcom,sm8750-videocc.h
|
||||
include/dt-bindings/clock/qcom,x1p42100-videocc.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -32,6 +33,7 @@ properties:
|
|||
- qcom,sm8650-videocc
|
||||
- qcom,sm8750-videocc
|
||||
- qcom,x1e80100-videocc
|
||||
- qcom,x1p42100-videocc
|
||||
|
||||
clocks:
|
||||
items:
|
||||
|
|
@ -70,6 +72,7 @@ allOf:
|
|||
- qcom,sm8450-videocc
|
||||
- qcom,sm8550-videocc
|
||||
- qcom,sm8750-videocc
|
||||
- qcom,x1p42100-videocc
|
||||
then:
|
||||
required:
|
||||
- required-opps
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ description: |
|
|||
See also:
|
||||
- include/dt-bindings/clock/qcom,eliza-tcsr.h
|
||||
- include/dt-bindings/clock/qcom,glymur-tcsr.h
|
||||
- include/dt-bindings/clock/qcom,hawi-tcsrcc.h
|
||||
- include/dt-bindings/clock/qcom,nord-tcsrcc.h
|
||||
- include/dt-bindings/clock/qcom,sm8550-tcsr.h
|
||||
- include/dt-bindings/clock/qcom,sm8650-tcsr.h
|
||||
|
|
@ -28,6 +29,7 @@ properties:
|
|||
- enum:
|
||||
- qcom,eliza-tcsr
|
||||
- qcom,glymur-tcsr
|
||||
- qcom,hawi-tcsrcc
|
||||
- qcom,kaanapali-tcsr
|
||||
- qcom,milos-tcsr
|
||||
- qcom,nord-tcsrcc
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ properties:
|
|||
compatible:
|
||||
enum:
|
||||
- qcom,x1e80100-camcc
|
||||
- qcom,x1p42100-camcc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ examples:
|
|||
clock-output-names = "main", "pll0", "pll1", "pll2",
|
||||
"pll2s", "pll2h", "z", "z2",
|
||||
"i", "m3", "b", "m1", "m2",
|
||||
"zx", "zs", "hp";
|
||||
"zx", "zs", "hp", "ztr", "zt";
|
||||
};
|
||||
|
||||
sdhi2_clk: sdhi2_clk@e615007c {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ properties:
|
|||
|
||||
fan-supply:
|
||||
description: Phandle to the regulator that powers the fan.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
|||
title: Qualcomm IPQ packet process engine (PPE)
|
||||
|
||||
maintainers:
|
||||
- Luo Jie <quic_luoj@quicinc.com>
|
||||
- Luo Jie <jie.luo@oss.qualcomm.com>
|
||||
- Lei Wei <quic_leiwei@quicinc.com>
|
||||
- Suruchi Agarwal <quic_suruchia@quicinc.com>
|
||||
- Pavithra R <quic_pavir@quicinc.com>
|
||||
|
|
|
|||
|
|
@ -121,8 +121,7 @@ examples:
|
|||
#size-cells = <0>;
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
compatible = "ethernet-phy-id0022.1537",
|
||||
"ethernet-phy-ieee802.3-c22";
|
||||
compatible = "ethernet-phy-id0022.1537";
|
||||
reg = <1>;
|
||||
interrupt-parent = <&irqc0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/sprd,sc2730-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Unisoc SC2730 Power Management IC regulators
|
||||
|
||||
maintainers:
|
||||
- Otto Pflüger <otto.pflueger@abscue.de>
|
||||
|
||||
patternProperties:
|
||||
"^dcdc-(core|cpu|gen[0-1]|gpu|mem|memq|modem|sram)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-avdd(12|18)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-vdd(18-dcxo|28)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-vdd(emmccore|kpled|ldo[0-2]|sd(core|io)|sim[0-2]|usb33|wcn|wifipa)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-vddcam(a0|a1|d0|d1|io|mot)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"^ldo-vddrf(1v25|18)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
...
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
Epson RX6110 Real Time Clock
|
||||
============================
|
||||
|
||||
The Epson RX6110 can be used with SPI or I2C busses. The kind of
|
||||
bus depends on the SPISEL pin and can not be configured via software.
|
||||
|
||||
I2C mode
|
||||
--------
|
||||
|
||||
Required properties:
|
||||
- compatible: should be: "epson,rx6110"
|
||||
- reg : the I2C address of the device for I2C
|
||||
|
||||
Example:
|
||||
|
||||
rtc: rtc@32 {
|
||||
compatible = "epson,rx6110"
|
||||
reg = <0x32>;
|
||||
};
|
||||
|
||||
SPI mode
|
||||
--------
|
||||
|
||||
Required properties:
|
||||
- compatible: should be: "epson,rx6110"
|
||||
- reg: chip select number
|
||||
- spi-cs-high: RX6110 needs chipselect high
|
||||
- spi-cpha: RX6110 works with SPI shifted clock phase
|
||||
- spi-cpol: RX6110 works with SPI inverse clock polarity
|
||||
|
||||
Example:
|
||||
|
||||
rtc: rtc@3 {
|
||||
compatible = "epson,rx6110"
|
||||
reg = <3>
|
||||
spi-cs-high;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
};
|
||||
68
Documentation/devicetree/bindings/rtc/epson,rx6110.yaml
Normal file
68
Documentation/devicetree/bindings/rtc/epson,rx6110.yaml
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rtc/epson,rx6110.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Epson RX6110 Real Time Clock
|
||||
|
||||
description:
|
||||
The Epson RX6110 can be used with SPI or I2C busses. The kind of bus depends
|
||||
on the SPISEL pin and cannot be configured via software.
|
||||
|
||||
maintainers:
|
||||
- Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||
|
||||
allOf:
|
||||
- $ref: rtc.yaml#
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: epson,rx6110
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-cs-high: true
|
||||
spi-cpha: true
|
||||
spi-cpol: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
dependencies:
|
||||
spi-cs-high: [ spi-cpha, spi-cpol ]
|
||||
spi-cpha: [ spi-cs-high, spi-cpol ]
|
||||
spi-cpol: [ spi-cs-high, spi-cpha ]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
# I2C mode
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
rtc@32 {
|
||||
compatible = "epson,rx6110";
|
||||
reg = <0x32>;
|
||||
};
|
||||
};
|
||||
|
||||
# SPI mode
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
rtc@3 {
|
||||
compatible = "epson,rx6110";
|
||||
reg = <3>;
|
||||
spi-cs-high;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
};
|
||||
};
|
||||
|
|
@ -31,6 +31,7 @@ properties:
|
|||
- epson,rx8025
|
||||
- isil,isl12057
|
||||
- epson,rx8130
|
||||
- epson,rx8901
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
|
|
|
|||
50
Documentation/devicetree/bindings/rtc/st,m41t93.yaml
Normal file
50
Documentation/devicetree/bindings/rtc/st,m41t93.yaml
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/rtc/st,m41t93.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ST M41T93 RTC and compatible
|
||||
|
||||
maintainers:
|
||||
- Akhilesh Patil <akhilesh@ee.iitb.ac.in>
|
||||
|
||||
description:
|
||||
ST M41T93 is spi based Real Time Clock (RTC) with time, date,
|
||||
alarm, watchdog, square wave clock output, 8 bit timer and
|
||||
7 bytes of user SRAM.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- st,m41t93
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: rtc.yaml
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
rtc@0 {
|
||||
compatible = "st,m41t93";
|
||||
reg = <0>;
|
||||
#clock-cells = <0>;
|
||||
spi-max-frequency = <2000000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -30,6 +30,8 @@ properties:
|
|||
- aspeed,ast2500-rtc
|
||||
# ASPEED BMC ast2600 Real-time Clock
|
||||
- aspeed,ast2600-rtc
|
||||
# ASPEED BMC ast2700 Real-time Clock
|
||||
- aspeed,ast2700-rtc
|
||||
# Conexant Digicolor Real Time Clock Controller
|
||||
- cnxt,cx92755-rtc
|
||||
# I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
|
||||
|
|
|
|||
|
|
@ -54,6 +54,12 @@ properties:
|
|||
- sophgo,sg2042-spi
|
||||
- thead,th1520-spi
|
||||
- const: snps,dw-apb-ssi
|
||||
- description: Vendor controllers which use snps,dwc-ssi-2.00a as fallback
|
||||
items:
|
||||
- enum:
|
||||
- starfive,jhb100-spi
|
||||
- const: snps,dwc-ssi-2.00a
|
||||
- const: snps,dwc-ssi-1.01a
|
||||
- description: Intel Keem Bay SPI Controller
|
||||
const: intel,keembay-ssi
|
||||
- description: Intel Mount Evans Integrated Management Complex SPI Controller
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ properties:
|
|||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,hawi-spmi-pmic-arb
|
||||
- qcom,kaanapali-spmi-pmic-arb
|
||||
- const: qcom,glymur-spmi-pmic-arb
|
||||
- enum:
|
||||
|
|
|
|||
|
|
@ -87,9 +87,12 @@ examples:
|
|||
amlogic,ao-secure = <&sec_AO>;
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/clock/amlogic,t7-peripherals-clkc.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
temperature-sensor@20000 {
|
||||
compatible = "amlogic,t7-thermal";
|
||||
reg = <0x0 0x20000 0x0 0x50>;
|
||||
reg = <0x20000 0x50>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clkc_periphs CLKID_TS>;
|
||||
#thermal-sensor-cells = <0>;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
| arm64: | ok |
|
||||
| csky: | TODO |
|
||||
| hexagon: | TODO |
|
||||
| loongarch: | TODO |
|
||||
| loongarch: | ok |
|
||||
| m68k: | TODO |
|
||||
| microblaze: | TODO |
|
||||
| mips: | TODO |
|
||||
|
|
|
|||
|
|
@ -433,6 +433,8 @@ exceptions) notifiers run under the instance lock. Please extend this
|
|||
documentation whenever you make explicit assumption about lock being held
|
||||
from a notifier.
|
||||
|
||||
Drivers **must not** generate nested notifications of the ops-locked types.
|
||||
|
||||
NETDEV_INTERNAL symbol namespace
|
||||
================================
|
||||
|
||||
|
|
|
|||
|
|
@ -6840,7 +6840,7 @@ s390 specific.
|
|||
} s390_ucontrol;
|
||||
|
||||
s390 specific. A page fault has occurred for a user controlled virtual
|
||||
machine (KVM_VM_S390_UNCONTROL) on its host page table that cannot be
|
||||
machine (KVM_VM_S390_UCONTROL) on its host page table that cannot be
|
||||
resolved by the kernel.
|
||||
The program code and the translation exception code that were placed
|
||||
in the cpu's lowcore are presented here as defined by the z Architecture
|
||||
|
|
|
|||
|
|
@ -22323,9 +22323,9 @@ F: Documentation/devicetree/bindings/power/supply/qcom,pmi8998-charger.yaml
|
|||
F: drivers/power/supply/qcom_smbx.c
|
||||
|
||||
QUALCOMM PPE DRIVER
|
||||
M: Luo Jie <quic_luoj@quicinc.com>
|
||||
M: Luo Jie <jie.luo@oss.qualcomm.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
|
||||
F: Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
|
||||
F: drivers/net/ethernet/qualcomm/ppe/
|
||||
|
|
@ -26001,9 +26001,8 @@ S: Maintained
|
|||
F: drivers/net/ethernet/dlink/sundance.c
|
||||
|
||||
SUNPLUS ETHERNET DRIVER
|
||||
M: Wells Lu <wellslutw@gmail.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
W: https://sunplus.atlassian.net/wiki/spaces/doc/overview
|
||||
F: Documentation/devicetree/bindings/net/sunplus,sp7021-emac.yaml
|
||||
F: drivers/net/ethernet/sunplus/
|
||||
|
|
|
|||
4
Makefile
4
Makefile
|
|
@ -1,8 +1,8 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 7
|
||||
PATCHLEVEL = 1
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = -rc1
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -559,6 +559,15 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
|
|||
else
|
||||
alignment_mask = 0x7;
|
||||
offset = hw->address & alignment_mask;
|
||||
|
||||
/*
|
||||
* BAS is an 8-bit field in WCR/BCR; the shift below would
|
||||
* silently drop the high bits of ctrl.len when offset + len
|
||||
* exceeds 8, programming hardware to watch fewer bytes than
|
||||
* the user requested.
|
||||
*/
|
||||
if (((u32)hw->ctrl.len << offset) > ARM_BREAKPOINT_LEN_8)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw->address &= ~alignment_mask;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <linux/static_call.h>
|
||||
#include <linux/memory.h>
|
||||
#include <asm/text-patching.h>
|
||||
#include <asm/insn.h>
|
||||
|
||||
void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1198,11 +1198,6 @@ static void __init map_mem(void)
|
|||
__map_memblock(start, end, pgprot_tagged(PAGE_KERNEL),
|
||||
flags);
|
||||
}
|
||||
|
||||
/* Map the kernel data/bss read-only in the linear map */
|
||||
__map_memblock(init_end, kernel_end, PAGE_KERNEL_RO, flags);
|
||||
flush_tlb_kernel_range((unsigned long)lm_alias(__init_end),
|
||||
(unsigned long)lm_alias(__bss_stop));
|
||||
}
|
||||
|
||||
void mark_rodata_ro(void)
|
||||
|
|
@ -1221,6 +1216,12 @@ void mark_rodata_ro(void)
|
|||
update_mapping_prot(__pa_symbol(_text), (unsigned long)_text,
|
||||
(unsigned long)_stext - (unsigned long)_text,
|
||||
PAGE_KERNEL_RO);
|
||||
|
||||
/* Map the kernel data/bss read-only in the linear map */
|
||||
update_mapping_prot(__pa_symbol(__init_end),
|
||||
(unsigned long)lm_alias(__init_end),
|
||||
(unsigned long)__bss_stop - (unsigned long)__init_end,
|
||||
PAGE_KERNEL_RO);
|
||||
}
|
||||
|
||||
static void __init declare_vma(struct vm_struct *vma,
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ config LOONGARCH
|
|||
select SYSCTL_ARCH_UNALIGN_NO_WARN
|
||||
select SYSCTL_EXCEPTION_TRACE
|
||||
select SWIOTLB if 64BIT
|
||||
select THREAD_INFO_IN_TASK
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
select USE_PERCPU_NUMA_NODE_ID
|
||||
select USER_STACKTRACE_SUPPORT
|
||||
|
|
|
|||
|
|
@ -405,6 +405,8 @@ uart0: serial@1ff40800 {
|
|||
i2c0: i2c@1ff48000 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff48000 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <14>;
|
||||
status = "disabled";
|
||||
|
|
@ -413,6 +415,8 @@ i2c0: i2c@1ff48000 {
|
|||
i2c@1ff48800 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff48800 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <15>;
|
||||
status = "disabled";
|
||||
|
|
@ -421,6 +425,8 @@ i2c@1ff48800 {
|
|||
i2c@1ff49000 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff49000 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <16>;
|
||||
status = "disabled";
|
||||
|
|
@ -429,6 +435,8 @@ i2c@1ff49000 {
|
|||
i2c@1ff49800 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff49800 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <17>;
|
||||
status = "disabled";
|
||||
|
|
@ -437,6 +445,8 @@ i2c@1ff49800 {
|
|||
i2c@1ff4a000 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff4a000 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <18>;
|
||||
status = "disabled";
|
||||
|
|
@ -445,6 +455,8 @@ i2c@1ff4a000 {
|
|||
i2c@1ff4a800 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1ff4a800 0x0 0x0800>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&eiointc>;
|
||||
interrupts = <19>;
|
||||
status = "disabled";
|
||||
|
|
|
|||
|
|
@ -311,6 +311,8 @@ uart0: serial@1fe20000 {
|
|||
i2c2: i2c@1fe21000 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1fe21000 0x0 0x8>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&liointc0>;
|
||||
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
|
|
@ -319,6 +321,8 @@ i2c2: i2c@1fe21000 {
|
|||
i2c3: i2c@1fe21800 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1fe21800 0x0 0x8>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_APB_CLK>;
|
||||
interrupt-parent = <&liointc0>;
|
||||
interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
|
|
|
|||
|
|
@ -239,6 +239,8 @@ rtc0: rtc@100d0100 {
|
|||
i2c@1fe00120 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1fe00120 0x0 0x8>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_MISC_CLK>;
|
||||
interrupt-parent = <&liointc>;
|
||||
interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
|
|
@ -247,6 +249,8 @@ i2c@1fe00120 {
|
|||
i2c@1fe00130 {
|
||||
compatible = "loongson,ls2k-i2c";
|
||||
reg = <0x0 0x1fe00130 0x0 0x8>;
|
||||
clock-frequency = <100000>;
|
||||
clocks = <&clk LOONGSON2_MISC_CLK>;
|
||||
interrupt-parent = <&liointc>;
|
||||
interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ static inline bool acpi_has_cpu_in_madt(void)
|
|||
extern struct list_head acpi_wakeup_device_list;
|
||||
extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC];
|
||||
|
||||
extern void acpi_add_early_pio(void);
|
||||
extern void acpi_remove_early_pio(void);
|
||||
extern int __init parse_acpi_topology(void);
|
||||
|
||||
#endif /* !CONFIG_ACPI */
|
||||
|
|
|
|||
31
arch/loongarch/include/asm/current.h
Normal file
31
arch/loongarch/include/asm/current.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_LOONGARCH_CURRENT_H
|
||||
#define __ASM_LOONGARCH_CURRENT_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <asm/percpu.h>
|
||||
|
||||
struct task_struct;
|
||||
|
||||
DECLARE_PER_CPU(struct task_struct *, cpu_tasks);
|
||||
|
||||
register struct task_struct *current_thread_pointer __asm__("$tp");
|
||||
|
||||
static __always_inline struct task_struct *get_current(void)
|
||||
{
|
||||
return current_thread_pointer;
|
||||
}
|
||||
|
||||
#define current get_current()
|
||||
|
||||
static __always_inline void set_current(struct task_struct *task)
|
||||
{
|
||||
__this_cpu_write(cpu_tasks, task);
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* __ASM_LOONGARCH_CURRENT_H */
|
||||
|
|
@ -41,6 +41,8 @@ struct kimage_arch {
|
|||
unsigned long systable_ptr;
|
||||
};
|
||||
|
||||
struct kimage;
|
||||
|
||||
#ifdef CONFIG_KEXEC_FILE
|
||||
extern const struct kexec_file_ops kexec_efi_ops;
|
||||
extern const struct kexec_file_ops kexec_elf_ops;
|
||||
|
|
@ -59,7 +61,6 @@ typedef void (*do_kexec_t)(unsigned long efi_boot,
|
|||
unsigned long start_addr,
|
||||
unsigned long first_ind_entry);
|
||||
|
||||
struct kimage;
|
||||
extern const unsigned char relocate_new_kernel[];
|
||||
extern const size_t relocate_new_kernel_size;
|
||||
extern void kexec_reboot(void);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#ifndef __ASM_PERCPU_H
|
||||
#define __ASM_PERCPU_H
|
||||
|
||||
#include <asm/cmpxchg.h>
|
||||
#include <asm/loongarch.h>
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -429,6 +429,8 @@ static inline pte_t pte_mkwrite_novma(pte_t pte)
|
|||
|
||||
static inline pte_t pte_wrprotect(pte_t pte)
|
||||
{
|
||||
if (pte_val(pte) & _PAGE_DIRTY)
|
||||
pte_val(pte) |= _PAGE_MODIFIED;
|
||||
pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
|
||||
return pte;
|
||||
}
|
||||
|
|
@ -535,6 +537,8 @@ static inline pmd_t pmd_mkwrite_novma(pmd_t pmd)
|
|||
|
||||
static inline pmd_t pmd_wrprotect(pmd_t pmd)
|
||||
{
|
||||
if (pmd_val(pmd) & _PAGE_DIRTY)
|
||||
pmd_val(pmd) |= _PAGE_MODIFIED;
|
||||
pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
|
||||
return pmd;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,8 +81,9 @@ extern int __cpu_logical_map[NR_CPUS];
|
|||
struct seq_file;
|
||||
|
||||
struct secondary_data {
|
||||
unsigned long task;
|
||||
unsigned long stack;
|
||||
unsigned long thread_info;
|
||||
unsigned long offset;
|
||||
};
|
||||
extern struct secondary_data cpuboot_data;
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@
|
|||
.cfi_rel_offset ra, PT_ERA
|
||||
.endif
|
||||
cfi_st tp, PT_R2, \docfi
|
||||
cfi_st u0, PT_R21, \docfi
|
||||
cfi_st fp, PT_R22, \docfi
|
||||
|
||||
/* Set thread_info if we're coming from user mode */
|
||||
|
|
@ -191,10 +192,13 @@
|
|||
andi t0, t0, 0x3 /* extract pplv bit */
|
||||
beqz t0, 9f
|
||||
|
||||
LONG_LI tp, ~_THREAD_MASK
|
||||
and tp, tp, sp
|
||||
cfi_st u0, PT_R21, \docfi
|
||||
csrrd u0, PERCPU_BASE_KS
|
||||
|
||||
la_abs t1, cpu_tasks
|
||||
#ifdef CONFIG_SMP
|
||||
LONG_ADD t1, t1, u0
|
||||
#endif
|
||||
LONG_L tp, t1, 0
|
||||
9:
|
||||
#ifdef CONFIG_KGDB
|
||||
li.w t0, CSR_CRMD_WE
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ struct task_struct;
|
|||
* __switch_to - switch execution of a task
|
||||
* @prev: The task previously executed.
|
||||
* @next: The task to begin executing.
|
||||
* @next_ti: task_thread_info(next).
|
||||
* @sched_ra: __schedule return address.
|
||||
* @sched_cfa: __schedule call frame address.
|
||||
*
|
||||
|
|
@ -23,8 +22,7 @@ struct task_struct;
|
|||
* the context of next. Returns prev.
|
||||
*/
|
||||
extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
|
||||
struct task_struct *next, struct thread_info *next_ti,
|
||||
void *sched_ra, void *sched_cfa);
|
||||
struct task_struct *next, void *sched_ra, void *sched_cfa);
|
||||
|
||||
/*
|
||||
* For newly created kernel threads switch_to() will return to
|
||||
|
|
@ -37,7 +35,8 @@ do { \
|
|||
lose_fpu_inatomic(1, prev); \
|
||||
lose_lbt_inatomic(1, prev); \
|
||||
hw_breakpoint_thread_switch(next); \
|
||||
(last) = __switch_to(prev, next, task_thread_info(next), \
|
||||
set_current(next); \
|
||||
(last) = __switch_to(prev, next, \
|
||||
__builtin_return_address(0), __builtin_frame_address(0)); \
|
||||
} while (0)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
* must also be changed
|
||||
*/
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
unsigned long tp_value; /* thread pointer */
|
||||
__u32 cpu; /* current CPU */
|
||||
|
|
@ -37,20 +36,11 @@ struct thread_info {
|
|||
*/
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.flags = _TIF_FIXADE, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
}
|
||||
|
||||
/* How to get the thread information struct from C. */
|
||||
register struct thread_info *__current_thread_info __asm__("$tp");
|
||||
|
||||
static inline struct thread_info *current_thread_info(void)
|
||||
{
|
||||
return __current_thread_info;
|
||||
}
|
||||
|
||||
register unsigned long current_stack_pointer __asm__("$sp");
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/memblock.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/numa.h>
|
||||
#include <asm/loongson.h>
|
||||
|
|
@ -59,6 +60,33 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
|
|||
return ioremap_cache(phys, size);
|
||||
}
|
||||
|
||||
#define PIO_BASE (unsigned long)PCI_IOBASE
|
||||
#define PIO_SIZE ALIGN(ISA_IOSIZE, PAGE_SIZE)
|
||||
|
||||
static bool acpi_pio;
|
||||
|
||||
/* Add PIO for early access */
|
||||
void acpi_add_early_pio(void)
|
||||
{
|
||||
if (!acpi_disabled) {
|
||||
acpi_pio = true;
|
||||
vmap_page_range(PIO_BASE, PIO_BASE + PIO_SIZE,
|
||||
LOONGSON_LIO_BASE, pgprot_device(PAGE_KERNEL));
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove PIO for PCI register */
|
||||
void acpi_remove_early_pio(void)
|
||||
{
|
||||
if (!acpi_pio)
|
||||
return;
|
||||
|
||||
if (!acpi_disabled) {
|
||||
acpi_pio = false;
|
||||
vunmap_range(PIO_BASE, PIO_BASE + PIO_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static int set_processor_mask(u32 id, u32 pass)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ static void __used output_task_defines(void)
|
|||
{
|
||||
COMMENT("LoongArch task_struct offsets.");
|
||||
OFFSET(TASK_STATE, task_struct, __state);
|
||||
OFFSET(TASK_THREAD_INFO, task_struct, stack);
|
||||
OFFSET(TASK_STACK, task_struct, stack);
|
||||
OFFSET(TASK_FLAGS, task_struct, flags);
|
||||
OFFSET(TASK_MM, task_struct, mm);
|
||||
OFFSET(TASK_PID, task_struct, pid);
|
||||
|
|
@ -84,7 +84,6 @@ static void __used output_task_defines(void)
|
|||
static void __used output_thread_info_defines(void)
|
||||
{
|
||||
COMMENT("LoongArch thread_info offsets.");
|
||||
OFFSET(TI_TASK, thread_info, task);
|
||||
OFFSET(TI_FLAGS, thread_info, flags);
|
||||
OFFSET(TI_TP_VALUE, thread_info, tp_value);
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
|
|
@ -266,8 +265,9 @@ static void __used output_signal_defines(void)
|
|||
static void __used output_smpboot_defines(void)
|
||||
{
|
||||
COMMENT("Linux smp cpu boot offsets.");
|
||||
OFFSET(CPU_BOOT_TASK, secondary_data, task);
|
||||
OFFSET(CPU_BOOT_STACK, secondary_data, stack);
|
||||
OFFSET(CPU_BOOT_TINFO, secondary_data, thread_info);
|
||||
OFFSET(CPU_BOOT_OFFSET, secondary_data, offset);
|
||||
BLANK();
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -67,8 +67,11 @@ SYM_CODE_START(handle_syscall)
|
|||
#endif
|
||||
|
||||
move u0, t0
|
||||
LONG_LI tp, ~_THREAD_MASK
|
||||
and tp, tp, sp
|
||||
la_abs t1, cpu_tasks
|
||||
#ifdef CONFIG_SMP
|
||||
LONG_ADD t1, t1, u0
|
||||
#endif
|
||||
LONG_L tp, t1, 0
|
||||
|
||||
move a0, sp
|
||||
bl do_syscall
|
||||
|
|
|
|||
|
|
@ -74,10 +74,11 @@ SYM_CODE_START(kernel_entry) # kernel entry point
|
|||
/* GPR21 used for percpu base (runtime), initialized as 0 */
|
||||
move u0, zero
|
||||
|
||||
la.pcrel tp, init_thread_union
|
||||
/* Set the SP after an empty pt_regs. */
|
||||
PTR_LI sp, (_THREAD_SIZE - PT_SIZE)
|
||||
PTR_ADD sp, sp, tp
|
||||
la.pcrel tp, init_task
|
||||
la.pcrel t0, init_stack
|
||||
PTR_LI t1, _THREAD_SIZE
|
||||
PTR_ADD t0, t0, t1
|
||||
PTR_ADDI sp, t0, -PT_SIZE
|
||||
set_saved_sp sp, t0, t1
|
||||
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
|
|
@ -86,8 +87,10 @@ SYM_CODE_START(kernel_entry) # kernel entry point
|
|||
|
||||
#ifdef CONFIG_RANDOMIZE_BASE
|
||||
/* Repoint the sp into the new kernel */
|
||||
PTR_LI sp, (_THREAD_SIZE - PT_SIZE)
|
||||
PTR_ADD sp, sp, tp
|
||||
LONG_LPTR t0, tp, TASK_STACK
|
||||
PTR_LI t1, _THREAD_SIZE
|
||||
PTR_ADD t0, t0, t1
|
||||
PTR_ADDI sp, t0, -PT_SIZE
|
||||
set_saved_sp sp, t0, t1
|
||||
|
||||
/* Jump to the new kernel: new_pc = current_pc + random_offset */
|
||||
|
|
@ -127,8 +130,9 @@ SYM_CODE_START(smpboot_entry)
|
|||
csrxchg t0, t1, LOONGARCH_CSR_IMPCTL1
|
||||
#endif
|
||||
la.pcrel t0, cpuboot_data
|
||||
ld.d tp, t0, CPU_BOOT_TASK
|
||||
ld.d sp, t0, CPU_BOOT_STACK
|
||||
ld.d tp, t0, CPU_BOOT_TINFO
|
||||
ld.d u0, t0, CPU_BOOT_OFFSET
|
||||
|
||||
bl start_secondary
|
||||
ASM_BUG()
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ unsigned long __stack_chk_guard __read_mostly;
|
|||
EXPORT_SYMBOL(__stack_chk_guard);
|
||||
#endif
|
||||
|
||||
DEFINE_PER_CPU(struct task_struct *, cpu_tasks);
|
||||
|
||||
/*
|
||||
* Idle related variables and functions
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ unsigned long __init relocate_kernel(void)
|
|||
reloc_offset += random_offset;
|
||||
|
||||
/* The current thread is now within the relocated kernel */
|
||||
__current_thread_info = RELOCATED_KASLR(__current_thread_info);
|
||||
current_thread_pointer = RELOCATED_KASLR(current_thread_pointer);
|
||||
|
||||
update_reloc_offset(&reloc_offset, random_offset);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -502,6 +502,8 @@ static __init int arch_reserve_pio_range(void)
|
|||
{
|
||||
struct device_node *np;
|
||||
|
||||
acpi_add_early_pio();
|
||||
|
||||
for_each_node_by_name(np, "isa") {
|
||||
struct of_range range;
|
||||
struct of_range_parser parser;
|
||||
|
|
@ -593,6 +595,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
{
|
||||
cpu_probe();
|
||||
unwind_init();
|
||||
set_current(current);
|
||||
|
||||
init_environ();
|
||||
efi_init();
|
||||
|
|
|
|||
|
|
@ -400,8 +400,9 @@ void loongson_boot_secondary(int cpu, struct task_struct *idle)
|
|||
pr_info("Booting CPU#%d...\n", cpu);
|
||||
|
||||
entry = __pa_symbol((unsigned long)&smpboot_entry);
|
||||
cpuboot_data.stack = (unsigned long)__KSTK_TOS(idle);
|
||||
cpuboot_data.thread_info = (unsigned long)task_thread_info(idle);
|
||||
cpuboot_data.task = (unsigned long)idle;
|
||||
cpuboot_data.stack = (unsigned long)task_pt_regs(idle);
|
||||
cpuboot_data.offset = per_cpu_offset(cpu);
|
||||
|
||||
csr_mail_send(entry, cpu_logical_map(cpu), 0);
|
||||
|
||||
|
|
@ -663,6 +664,7 @@ asmlinkage void start_secondary(void)
|
|||
set_my_cpu_offset(per_cpu_offset(cpu));
|
||||
|
||||
cpu_probe();
|
||||
set_current(current);
|
||||
constant_clockevent_init();
|
||||
loongson_init_secondary();
|
||||
|
||||
|
|
@ -705,6 +707,7 @@ static void stop_this_cpu(void *dummy)
|
|||
set_cpu_online(smp_processor_id(), false);
|
||||
calculate_cpu_foreign_map();
|
||||
local_irq_disable();
|
||||
rcutree_report_cpu_dead();
|
||||
while (true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
/*
|
||||
* task_struct *__switch_to(task_struct *prev, task_struct *next,
|
||||
* struct thread_info *next_ti, void *sched_ra, void *sched_cfa)
|
||||
* void *sched_ra, void *sched_cfa)
|
||||
*/
|
||||
.align 5
|
||||
SYM_FUNC_START(__switch_to)
|
||||
|
|
@ -24,8 +24,8 @@ SYM_FUNC_START(__switch_to)
|
|||
LONG_SPTR t1, a0, (THREAD_CSRPRMD - TASK_STRUCT_OFFSET)
|
||||
|
||||
cpu_save_nonscratch a0
|
||||
LONG_SPTR a3, a0, (THREAD_SCHED_RA - TASK_STRUCT_OFFSET)
|
||||
LONG_SPTR a4, a0, (THREAD_SCHED_CFA - TASK_STRUCT_OFFSET)
|
||||
LONG_SPTR a2, a0, (THREAD_SCHED_RA - TASK_STRUCT_OFFSET)
|
||||
LONG_SPTR a3, a0, (THREAD_SCHED_CFA - TASK_STRUCT_OFFSET)
|
||||
|
||||
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
|
||||
la t7, __stack_chk_guard
|
||||
|
|
@ -33,11 +33,12 @@ SYM_FUNC_START(__switch_to)
|
|||
LONG_SPTR t8, t7, 0
|
||||
#endif
|
||||
|
||||
move tp, a2
|
||||
move tp, a1
|
||||
cpu_restore_nonscratch a1
|
||||
|
||||
li.w t0, _THREAD_SIZE
|
||||
PTR_ADD t0, t0, tp
|
||||
LONG_LPTR t0, a1, (TASK_STACK - TASK_STRUCT_OFFSET)
|
||||
PTR_LI t1, _THREAD_SIZE
|
||||
PTR_ADD t0, t0, t1
|
||||
set_saved_sp t0, t1, t2
|
||||
|
||||
LONG_LPTR t1, a1, (THREAD_CSRPRMD - TASK_STRUCT_OFFSET)
|
||||
|
|
@ -45,6 +46,7 @@ SYM_FUNC_START(__switch_to)
|
|||
|
||||
#ifdef CONFIG_32BIT
|
||||
PTR_ADDI a0, a0, -TASK_STRUCT_OFFSET
|
||||
PTR_ADDI tp, tp, -TASK_STRUCT_OFFSET
|
||||
#endif
|
||||
jr ra
|
||||
SYM_FUNC_END(__switch_to)
|
||||
|
|
|
|||
|
|
@ -107,6 +107,12 @@ static void show_stacktrace(struct task_struct *task,
|
|||
unsigned long stackdata;
|
||||
unsigned long *sp = (unsigned long *)regs->regs[3];
|
||||
|
||||
if (!task)
|
||||
task = current;
|
||||
|
||||
if (!try_get_task_stack(task))
|
||||
return;
|
||||
|
||||
printk("%sStack :", loglvl);
|
||||
i = 0;
|
||||
while ((unsigned long) sp & (PAGE_SIZE - 1)) {
|
||||
|
|
@ -129,6 +135,8 @@ static void show_stacktrace(struct task_struct *task,
|
|||
}
|
||||
pr_cont("\n");
|
||||
show_backtrace(task, regs, loglvl, user);
|
||||
|
||||
put_task_stack(task);
|
||||
}
|
||||
|
||||
void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
|
||||
|
|
|
|||
|
|
@ -234,5 +234,5 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
|
|||
clear = __pgprot(_PAGE_PRESENT | _PAGE_VALID);
|
||||
}
|
||||
|
||||
return __set_memory(addr, 1, set, clear);
|
||||
return __set_memory(addr, nr, set, clear);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,18 @@
|
|||
* Copyright (C) 2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#include <linux/memory.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include "bpf_jit.h"
|
||||
|
||||
#define LOONGARCH_MAX_REG_ARGS 8
|
||||
|
||||
#define LOONGARCH_SAVE_RA_NINSNS 1
|
||||
#define LOONGARCH_LONG_JUMP_NINSNS 5
|
||||
#define LOONGARCH_TCC_SLOT_NINSNS 1
|
||||
|
||||
#define LOONGARCH_PROLOGUE_SKIP_INSNS \
|
||||
(LOONGARCH_SAVE_RA_NINSNS + LOONGARCH_LONG_JUMP_NINSNS + LOONGARCH_TCC_SLOT_NINSNS)
|
||||
|
||||
#define LOONGARCH_LONG_JUMP_NBYTES (LOONGARCH_LONG_JUMP_NINSNS * 4)
|
||||
|
||||
#define LOONGARCH_FENTRY_NINSNS 2
|
||||
|
|
@ -143,8 +150,13 @@ static void build_prologue(struct jit_ctx *ctx)
|
|||
stack_adjust = round_up(stack_adjust, 16);
|
||||
stack_adjust += bpf_stack_adjust;
|
||||
|
||||
/*
|
||||
* Save the original return address to a temporary register to prevent
|
||||
* it from being overwritten, then reserve space for the long jump and
|
||||
* fentry trampoline slot for dynamically patching by ftrace at runtime.
|
||||
* These instructions are bypassed during a tail call invocation.
|
||||
*/
|
||||
move_reg(ctx, LOONGARCH_GPR_T0, LOONGARCH_GPR_RA);
|
||||
/* Reserve space for the move_imm + jirl instruction */
|
||||
for (i = 0; i < LOONGARCH_LONG_JUMP_NINSNS; i++)
|
||||
emit_insn(ctx, nop);
|
||||
|
||||
|
|
@ -253,10 +265,11 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
|
|||
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0);
|
||||
} else {
|
||||
/*
|
||||
* Call the next bpf prog and skip the first instruction
|
||||
* of TCC initialization.
|
||||
* Tail call to the next BPF program, passing offset in number
|
||||
* of instructions to jirl to bypass the initial setup slots.
|
||||
*/
|
||||
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 7);
|
||||
emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO,
|
||||
LOONGARCH_GPR_T3, LOONGARCH_PROLOGUE_SKIP_INSNS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -312,12 +325,12 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
|
|||
*/
|
||||
emit_insn(ctx, ldd, REG_TCC, LOONGARCH_GPR_SP, tcc_ptr_off);
|
||||
emit_insn(ctx, ldd, t3, REG_TCC, 0);
|
||||
emit_insn(ctx, addid, t3, t3, 1);
|
||||
emit_insn(ctx, std, t3, REG_TCC, 0);
|
||||
emit_insn(ctx, addid, t2, LOONGARCH_GPR_ZERO, MAX_TAIL_CALL_CNT);
|
||||
if (emit_tailcall_jmp(ctx, BPF_JSGT, t3, t2, jmp_offset) < 0)
|
||||
if (emit_tailcall_jmp(ctx, BPF_JSGE, t3, t2, jmp_offset) < 0)
|
||||
goto toofar;
|
||||
|
||||
emit_insn(ctx, addid, t3, t3, 1);
|
||||
|
||||
/*
|
||||
* prog = array->ptrs[index];
|
||||
* if (!prog)
|
||||
|
|
@ -330,6 +343,8 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn)
|
|||
if (emit_tailcall_jmp(ctx, BPF_JEQ, t2, LOONGARCH_GPR_ZERO, jmp_offset) < 0)
|
||||
goto toofar;
|
||||
|
||||
emit_insn(ctx, std, t3, REG_TCC, 0);
|
||||
|
||||
/* goto *(prog->bpf_func + 4); */
|
||||
off = offsetof(struct bpf_prog, bpf_func);
|
||||
emit_insn(ctx, ldd, t3, t2, off);
|
||||
|
|
@ -1147,6 +1162,19 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
|
|||
|
||||
/* function call */
|
||||
case BPF_JMP | BPF_CALL:
|
||||
/* Implement helper call to bpf_get_current_task/_btf() inline */
|
||||
if (insn->src_reg == 0 && (insn->imm == BPF_FUNC_get_current_task ||
|
||||
insn->imm == BPF_FUNC_get_current_task_btf)) {
|
||||
move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_TP);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Implement helper call to bpf_get_smp_processor_id() inline */
|
||||
if (insn->src_reg == 0 && insn->imm == BPF_FUNC_get_smp_processor_id) {
|
||||
emit_insn(ctx, ldwu, regmap[BPF_REG_0], LOONGARCH_GPR_TP, TI_CPU);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass,
|
||||
&func_addr, &func_addr_fixed);
|
||||
if (ret < 0)
|
||||
|
|
@ -2367,3 +2395,15 @@ bool bpf_jit_supports_subprog_tailcalls(void)
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpf_jit_inlines_helper_call(s32 imm)
|
||||
{
|
||||
switch (imm) {
|
||||
case BPF_FUNC_get_current_task:
|
||||
case BPF_FUNC_get_current_task_btf:
|
||||
case BPF_FUNC_get_smp_processor_id:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci)
|
|||
struct resource_entry *entry, *tmp;
|
||||
struct acpi_device *device = ci->bridge;
|
||||
|
||||
acpi_remove_early_pio();
|
||||
|
||||
status = acpi_pci_probe_root_resources(ci);
|
||||
if (status > 0) {
|
||||
acpi_evaluate_integer(device->handle, "PCIH", NULL, &pci_h);
|
||||
|
|
|
|||
|
|
@ -7,9 +7,12 @@
|
|||
|
||||
#include <asm/vdso/vdso.h>
|
||||
|
||||
#include <linux/build-salt.h>
|
||||
#include <linux/elfnote.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
ELFNOTE_START(Linux, 0, "a")
|
||||
.long LINUX_VERSION_CODE
|
||||
ELFNOTE_END
|
||||
|
||||
BUILD_SALT
|
||||
|
|
|
|||
|
|
@ -980,6 +980,8 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
|
|||
|
||||
static inline void set_pte(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
if (pte_present(pte))
|
||||
pte = clear_pte_bit(pte, __pgprot(_PAGE_UNUSED));
|
||||
WRITE_ONCE(*ptep, pte);
|
||||
}
|
||||
|
||||
|
|
@ -1359,8 +1361,6 @@ pgprot_t pgprot_writecombine(pgprot_t prot);
|
|||
static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t entry, unsigned int nr)
|
||||
{
|
||||
if (pte_present(entry))
|
||||
entry = clear_pte_bit(entry, __pgprot(_PAGE_UNUSED));
|
||||
page_table_check_ptes_set(mm, addr, ptep, entry, nr);
|
||||
for (;;) {
|
||||
set_pte(ptep, entry);
|
||||
|
|
|
|||
|
|
@ -1209,7 +1209,7 @@ int dat_peek_cmma(gfn_t start, union asce asce, unsigned int *count, u8 *values)
|
|||
int rc;
|
||||
|
||||
rc = _dat_walk_gfn_range(start, start + *count, asce, &ops, DAT_WALK_DEFAULT, &state);
|
||||
*count = state.end - start;
|
||||
*count = state.end >= start ? state.end - start : 0;
|
||||
/* Return success if at least one value was saved, otherwise an error. */
|
||||
return (rc == -EFAULT && *count > 0) ? 0 : rc;
|
||||
}
|
||||
|
|
@ -1253,6 +1253,9 @@ int dat_get_cmma(union asce asce, gfn_t *start, unsigned int *count, u8 *values,
|
|||
};
|
||||
|
||||
_dat_walk_gfn_range(*start, asce_end(asce), asce, &ops, DAT_WALK_IGN_HOLES, &state);
|
||||
/* If no dirty pages were found, wrap around and continue searching */
|
||||
if (*start && state.start == -1)
|
||||
_dat_walk_gfn_range(0, *start, asce, &ops, DAT_WALK_IGN_HOLES, &state);
|
||||
|
||||
if (state.start == -1) {
|
||||
*count = 0;
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ static long gmap_clear_young_crste(union crste *crstep, gfn_t gfn, gfn_t end, st
|
|||
new.h.i = 1;
|
||||
new.s.fc1.y = 0;
|
||||
new.s.fc1.prefix_notif = 0;
|
||||
if (new.s.fc1.d || !new.h.p)
|
||||
if ((new.s.fc1.d || !new.h.p) && !new.s.fc1.s)
|
||||
folio_set_dirty(phys_to_folio(crste_origin_large(crste)));
|
||||
new.s.fc1.d = 0;
|
||||
new.h.p = 1;
|
||||
|
|
@ -1098,23 +1098,46 @@ int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gf
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long __set_cmma_dirty_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
|
||||
static long __set_cmma_clean_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
|
||||
{
|
||||
__atomic64_or(PGSTE_CMMA_D_BIT, &pgste_of(ptep)->val);
|
||||
union pgste pgste;
|
||||
|
||||
pgste = pgste_get_lock(ptep);
|
||||
pgste.cmma_d = 0;
|
||||
pgste_set_unlock(ptep, pgste);
|
||||
|
||||
if (need_resched())
|
||||
return next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gmap_set_cmma_all_dirty(struct gmap *gmap)
|
||||
static long __set_cmma_dirty_pte(union pte *ptep, gfn_t gfn, gfn_t next, struct dat_walk *walk)
|
||||
{
|
||||
const struct dat_walk_ops ops = { .pte_entry = __set_cmma_dirty_pte, };
|
||||
union pgste pgste;
|
||||
|
||||
pgste = pgste_get_lock(ptep);
|
||||
if (!pgste.cmma_d)
|
||||
atomic64_inc(walk->priv);
|
||||
pgste.cmma_d = 1;
|
||||
pgste_set_unlock(ptep, pgste);
|
||||
|
||||
if (need_resched())
|
||||
return next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _gmap_set_cmma_all(struct gmap *gmap, bool dirty)
|
||||
{
|
||||
const struct dat_walk_ops ops = {
|
||||
.pte_entry = dirty ? __set_cmma_dirty_pte : __set_cmma_clean_pte,
|
||||
};
|
||||
gfn_t gfn = 0;
|
||||
|
||||
do {
|
||||
scoped_guard(read_lock, &gmap->kvm->mmu_lock)
|
||||
gfn = _dat_walk_gfn_range(gfn, asce_end(gmap->asce), gmap->asce, &ops,
|
||||
DAT_WALK_IGN_HOLES, NULL);
|
||||
DAT_WALK_IGN_HOLES,
|
||||
&gmap->kvm->arch.cmma_dirty_pages);
|
||||
cond_resched();
|
||||
} while (gfn);
|
||||
}
|
||||
|
|
@ -1287,7 +1310,7 @@ static int gmap_protect_asce_top_level(struct kvm_s390_mmu_cache *mc, struct gma
|
|||
/* Pairs with the smp_wmb() in kvm_mmu_invalidate_end(). */
|
||||
smp_rmb();
|
||||
|
||||
rc = kvm_s390_get_guest_pages(sg->kvm, context.f, asce.rsto, asce.dt + 1, false);
|
||||
rc = kvm_s390_get_guest_pages(sg->kvm, context.f, asce.rsto, asce.tl + 1, false);
|
||||
if (rc > 0)
|
||||
rc = -EFAULT;
|
||||
if (!rc)
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ int gmap_insert_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn
|
|||
gfn_t r_gfn, int level);
|
||||
int gmap_protect_rmap(struct kvm_s390_mmu_cache *mc, struct gmap *sg, gfn_t p_gfn, gfn_t r_gfn,
|
||||
kvm_pfn_t pfn, int level, bool wr);
|
||||
void gmap_set_cmma_all_dirty(struct gmap *gmap);
|
||||
void _gmap_set_cmma_all(struct gmap *gmap, bool dirty);
|
||||
void _gmap_handle_vsie_unshadow_event(struct gmap *parent, gfn_t gfn);
|
||||
struct gmap *gmap_create_shadow(struct kvm_s390_mmu_cache *mc, struct gmap *gmap,
|
||||
union asce asce, int edat_level);
|
||||
|
|
@ -198,6 +198,16 @@ static inline bool pte_needs_unshadow(union pte oldpte, union pte newpte, union
|
|||
return !newpte.h.p || !newpte.s.pr;
|
||||
}
|
||||
|
||||
static inline void gmap_set_cmma_all_dirty(struct gmap *gmap)
|
||||
{
|
||||
_gmap_set_cmma_all(gmap, true);
|
||||
}
|
||||
|
||||
static inline void gmap_set_cmma_all_clean(struct gmap *gmap)
|
||||
{
|
||||
_gmap_set_cmma_all(gmap, false);
|
||||
}
|
||||
|
||||
static inline union pgste _gmap_ptep_xchg(struct gmap *gmap, union pte *ptep, union pte newpte,
|
||||
union pgste pgste, gfn_t gfn, bool needs_lock)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1022,9 +1022,11 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
|
|||
if (!kvm->arch.use_cmma)
|
||||
break;
|
||||
|
||||
guard(mutex)(&kvm->lock);
|
||||
VM_EVENT(kvm, 3, "%s", "RESET: CMMA states");
|
||||
do {
|
||||
start_gfn = dat_reset_cmma(kvm->arch.gmap->asce, start_gfn);
|
||||
scoped_guard(read_lock, &kvm->mmu_lock)
|
||||
start_gfn = dat_reset_cmma(kvm->arch.gmap->asce, start_gfn);
|
||||
cond_resched();
|
||||
} while (start_gfn);
|
||||
ret = 0;
|
||||
|
|
@ -1217,13 +1219,13 @@ static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
|
|||
|
||||
/*
|
||||
* Must be called with kvm->srcu held to avoid races on memslots, and with
|
||||
* kvm->slots_lock to avoid races with ourselves and kvm_s390_vm_stop_migration.
|
||||
* kvm->slots_lock to avoid races with ourselves, kvm_s390_vm_stop_migration(),
|
||||
* and kvm_s390_get_cmma_bits().
|
||||
*/
|
||||
static int kvm_s390_vm_start_migration(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_memory_slot *ms;
|
||||
struct kvm_memslots *slots;
|
||||
unsigned long ram_pages = 0;
|
||||
int bkt;
|
||||
|
||||
/* migration mode already enabled */
|
||||
|
|
@ -1240,28 +1242,54 @@ static int kvm_s390_vm_start_migration(struct kvm *kvm)
|
|||
kvm_for_each_memslot(ms, bkt, slots) {
|
||||
if (!ms->dirty_bitmap)
|
||||
return -EINVAL;
|
||||
ram_pages += ms->npages;
|
||||
}
|
||||
/* mark all the pages as dirty */
|
||||
gmap_set_cmma_all_dirty(kvm->arch.gmap);
|
||||
atomic64_set(&kvm->arch.cmma_dirty_pages, ram_pages);
|
||||
kvm->arch.migration_mode = 1;
|
||||
/*
|
||||
* Set the flag and let KVM handle ESSA manually, potentially setting
|
||||
* the cmma_d bit in some PGSTEs and increasing cmma_dirty_pages.
|
||||
* At this point cmma_dirty_pages is still 0, and all existing PGSTEs
|
||||
* have their cmma_d bit set to 0.
|
||||
* Any newly allocated page table has its entries marked as cmma-clean,
|
||||
* which is fine because the CMMA values are not dirty.
|
||||
*/
|
||||
WRITE_ONCE(kvm->arch.migration_mode, 1);
|
||||
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_START_MIGRATION);
|
||||
/*
|
||||
* Mark all PGSTEs as cmma-dirty, increasing cmma_dirty_pages as needed,
|
||||
* but without double-counting pages that have become dirty on their own
|
||||
* in the meantime.
|
||||
* At this point some pages might have become dirty on their own already
|
||||
* and cmma_dirty_pages might therefore be non-zero.
|
||||
*/
|
||||
gmap_set_cmma_all_dirty(kvm->arch.gmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be called with kvm->slots_lock to avoid races with ourselves and
|
||||
* kvm_s390_vm_start_migration.
|
||||
* Must be called with kvm->slots_lock to avoid races with ourselves,
|
||||
* kvm_s390_vm_start_migration() and kvm_s390_get_cmma_bits().
|
||||
*/
|
||||
static int kvm_s390_vm_stop_migration(struct kvm *kvm)
|
||||
{
|
||||
/* migration mode already disabled */
|
||||
if (!kvm->arch.migration_mode)
|
||||
return 0;
|
||||
kvm->arch.migration_mode = 0;
|
||||
/*
|
||||
* Unset the flag and propagate to all vCPUs. From now on the cmma_d
|
||||
* bit will not be touched on any PGSTE.
|
||||
* At this point cmma_dirty_pages is possibly non-zero, and thus some
|
||||
* PGSTEs might have cmma_d set.
|
||||
*/
|
||||
WRITE_ONCE(kvm->arch.migration_mode, 0);
|
||||
if (kvm->arch.use_cmma)
|
||||
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION);
|
||||
/* Clear cmma_d on all existing PGSTEs and set cmma_dirty_pages to 0. */
|
||||
gmap_set_cmma_all_clean(kvm->arch.gmap);
|
||||
atomic64_set(&kvm->arch.cmma_dirty_pages, 0);
|
||||
/*
|
||||
* At this point the system has the expected state: migration_mode is 0,
|
||||
* cmma_dirty_pages is 0, and all existing PGSTEs have their cmma_d bit
|
||||
* set to 0.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2317,8 +2345,8 @@ static int kvm_s390_get_cmma_bits(struct kvm *kvm,
|
|||
static int kvm_s390_set_cmma_bits(struct kvm *kvm,
|
||||
const struct kvm_s390_cmma_log *args)
|
||||
{
|
||||
struct kvm_s390_mmu_cache *mc;
|
||||
u8 *bits = NULL;
|
||||
struct kvm_s390_mmu_cache *mc __free(kvm_s390_mmu_cache) = NULL;
|
||||
u8 *bits __free(kvfree) = NULL;
|
||||
int r = 0;
|
||||
|
||||
if (!kvm->arch.use_cmma)
|
||||
|
|
@ -2338,18 +2366,16 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
|
|||
return -ENOMEM;
|
||||
bits = vmalloc(array_size(sizeof(*bits), args->count));
|
||||
if (!bits)
|
||||
goto out;
|
||||
return -ENOMEM;
|
||||
|
||||
r = copy_from_user(bits, (void __user *)args->values, args->count);
|
||||
if (r) {
|
||||
r = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
if (r)
|
||||
return -EFAULT;
|
||||
|
||||
do {
|
||||
r = kvm_s390_mmu_cache_topup(mc);
|
||||
if (r)
|
||||
break;
|
||||
return r;
|
||||
scoped_guard(read_lock, &kvm->mmu_lock) {
|
||||
r = dat_set_cmma_bits(mc, kvm->arch.gmap->asce, args->start_gfn,
|
||||
args->count, args->mask, bits);
|
||||
|
|
@ -2357,9 +2383,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
|
|||
} while (r == -ENOMEM);
|
||||
|
||||
set_bit(GMAP_FLAG_USES_CMM, &kvm->arch.gmap->flags);
|
||||
out:
|
||||
kvm_s390_free_mmu_cache(mc);
|
||||
vfree(bits);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -3584,7 +3608,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
|
|||
vcpu->arch.gmap = vcpu->kvm->arch.gmap;
|
||||
sca_add_vcpu(vcpu);
|
||||
}
|
||||
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0)
|
||||
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0 ||
|
||||
vcpu->kvm->arch.user_operexec)
|
||||
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -366,7 +366,9 @@ static int handle_sske(struct kvm_vcpu *vcpu)
|
|||
if (rc > 1)
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
|
||||
if (rc == -ENOMEM) {
|
||||
kvm_s390_mmu_cache_topup(vcpu->arch.mc);
|
||||
rc = kvm_s390_mmu_cache_topup(vcpu->arch.mc);
|
||||
if (rc)
|
||||
return rc;
|
||||
continue;
|
||||
}
|
||||
if (rc < 0)
|
||||
|
|
@ -1122,7 +1124,9 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
|
|||
if (rc > 1)
|
||||
return kvm_s390_inject_program_int(vcpu, rc);
|
||||
if (rc == -ENOMEM) {
|
||||
kvm_s390_mmu_cache_topup(vcpu->arch.mc);
|
||||
rc = kvm_s390_mmu_cache_topup(vcpu->arch.mc);
|
||||
if (rc)
|
||||
return rc;
|
||||
continue;
|
||||
}
|
||||
if (rc < 0)
|
||||
|
|
@ -1232,7 +1236,7 @@ static int handle_essa(struct kvm_vcpu *vcpu)
|
|||
: ESSA_SET_STABLE_IF_RESIDENT))
|
||||
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
|
||||
|
||||
if (!vcpu->kvm->arch.migration_mode) {
|
||||
if (!READ_ONCE(vcpu->kvm->arch.migration_mode)) {
|
||||
/*
|
||||
* CMMA is enabled in the KVM settings, but is disabled in
|
||||
* the SIE block and in the mm_context, and we are not doing
|
||||
|
|
|
|||
|
|
@ -181,7 +181,8 @@ void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr)
|
|||
if (IS_ERR_OR_NULL(ptep))
|
||||
return;
|
||||
|
||||
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
|
||||
if (pte_present(*ptep))
|
||||
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
|
||||
pte_unmap_unlock(ptep, ptl);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gmap_helper_try_set_pte_unused);
|
||||
|
|
|
|||
|
|
@ -1434,7 +1434,6 @@ enum kvm_mmu_type {
|
|||
};
|
||||
|
||||
struct kvm_arch {
|
||||
unsigned long n_used_mmu_pages;
|
||||
unsigned long n_requested_mmu_pages;
|
||||
unsigned long n_max_mmu_pages;
|
||||
unsigned int indirect_shadow_pages;
|
||||
|
|
@ -1700,6 +1699,7 @@ struct kvm_vm_stat {
|
|||
u64 mmu_recycled;
|
||||
u64 mmu_cache_miss;
|
||||
u64 mmu_unsync;
|
||||
u64 mmu_shadow_pages;
|
||||
union {
|
||||
struct {
|
||||
atomic64_t pages_4k;
|
||||
|
|
@ -2525,16 +2525,6 @@ static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
|
|||
kvm_x86_call(vcpu_unblocking)(vcpu);
|
||||
}
|
||||
|
||||
static inline int kvm_cpu_get_apicid(int mps_cpu)
|
||||
{
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
return default_cpu_present_to_apicid(mps_cpu);
|
||||
#else
|
||||
WARN_ON_ONCE(1);
|
||||
return BAD_APICID;
|
||||
#endif
|
||||
}
|
||||
|
||||
int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages);
|
||||
|
||||
#define KVM_CLOCK_VALID_FLAGS \
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ u32 default_cpu_present_to_apicid(int mps_cpu)
|
|||
else
|
||||
return BAD_APICID;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_KVM(default_cpu_present_to_apicid);
|
||||
|
||||
/*
|
||||
* Set up the logical destination ID when the APIC operates in logical
|
||||
|
|
|
|||
|
|
@ -194,7 +194,8 @@ int kvm_pic_set_irq(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
|
|||
int irq = e->irqchip.pin;
|
||||
int ret, irq_level;
|
||||
|
||||
BUG_ON(irq < 0 || irq >= PIC_NUM_PINS);
|
||||
if (WARN_ON_ONCE(irq < 0 || irq >= PIC_NUM_PINS))
|
||||
return -1;
|
||||
|
||||
pic_lock(s);
|
||||
irq_level = __kvm_irq_line_state(&s->irq_states[irq],
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic);
|
|||
|
||||
static void rtc_status_pending_eoi_check_valid(struct kvm_ioapic *ioapic)
|
||||
{
|
||||
if (WARN_ON(ioapic->rtc_status.pending_eoi < 0))
|
||||
if (WARN_ON_ONCE(ioapic->rtc_status.pending_eoi < 0))
|
||||
kvm_rtc_eoi_tracking_restore_all(ioapic);
|
||||
}
|
||||
|
||||
|
|
@ -484,7 +484,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
|
|||
* ensures that it is only called if it is >= zero, namely
|
||||
* if rtc_irq_check_coalesced returns false).
|
||||
*/
|
||||
BUG_ON(ioapic->rtc_status.pending_eoi != 0);
|
||||
WARN_ON_ONCE(ioapic->rtc_status.pending_eoi);
|
||||
ret = __kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
|
||||
&ioapic->rtc_status);
|
||||
ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret);
|
||||
|
|
@ -504,7 +504,8 @@ int kvm_ioapic_set_irq(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
|
|||
int irq = e->irqchip.pin;
|
||||
int ret, irq_level;
|
||||
|
||||
BUG_ON(irq < 0 || irq >= IOAPIC_NUM_PINS);
|
||||
if (WARN_ON_ONCE(irq < 0 || irq >= IOAPIC_NUM_PINS))
|
||||
return -1;
|
||||
|
||||
spin_lock(&ioapic->lock);
|
||||
irq_level = __kvm_irq_line_state(&ioapic->irq_states[irq],
|
||||
|
|
|
|||
|
|
@ -767,7 +767,7 @@ static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
|
|||
kvm_x86_call(hwapic_isr_update)(apic->vcpu, vec);
|
||||
else {
|
||||
++apic->isr_count;
|
||||
BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
|
||||
KVM_BUG_ON(apic->isr_count > MAX_APIC_VECTOR, apic->vcpu->kvm);
|
||||
/*
|
||||
* ISR (in service register) bit is set when injecting an interrupt.
|
||||
* The highest vector is injected. Thus the latest bit set matches
|
||||
|
|
@ -808,7 +808,7 @@ static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
|
|||
kvm_x86_call(hwapic_isr_update)(apic->vcpu, apic_find_highest_isr(apic));
|
||||
else {
|
||||
--apic->isr_count;
|
||||
BUG_ON(apic->isr_count < 0);
|
||||
KVM_BUG_ON(apic->isr_count < 0, apic->vcpu->kvm);
|
||||
apic->highest_isr_cache = -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -980,6 +980,8 @@ static void apic_update_ppr(struct kvm_lapic *apic)
|
|||
if (__apic_update_ppr(apic, &ppr) &&
|
||||
apic_has_interrupt_for_ppr(apic, ppr) != -1)
|
||||
kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
|
||||
else
|
||||
kvm_lapic_update_cr8_intercept(apic->vcpu);
|
||||
}
|
||||
|
||||
void kvm_apic_update_ppr(struct kvm_vcpu *vcpu)
|
||||
|
|
|
|||
|
|
@ -1802,13 +1802,13 @@ static void kvm_mmu_check_sptes_at_free(struct kvm_mmu_page *sp)
|
|||
|
||||
static void kvm_account_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
|
||||
{
|
||||
kvm->arch.n_used_mmu_pages++;
|
||||
kvm->stat.mmu_shadow_pages++;
|
||||
kvm_account_pgtable_pages((void *)sp->spt, +1);
|
||||
}
|
||||
|
||||
static void kvm_unaccount_mmu_page(struct kvm *kvm, struct kvm_mmu_page *sp)
|
||||
{
|
||||
kvm->arch.n_used_mmu_pages--;
|
||||
kvm->stat.mmu_shadow_pages--;
|
||||
kvm_account_pgtable_pages((void *)sp->spt, -1);
|
||||
}
|
||||
|
||||
|
|
@ -2836,9 +2836,9 @@ static unsigned long kvm_mmu_zap_oldest_mmu_pages(struct kvm *kvm,
|
|||
|
||||
static inline unsigned long kvm_mmu_available_pages(struct kvm *kvm)
|
||||
{
|
||||
if (kvm->arch.n_max_mmu_pages > kvm->arch.n_used_mmu_pages)
|
||||
if (kvm->arch.n_max_mmu_pages > kvm->stat.mmu_shadow_pages)
|
||||
return kvm->arch.n_max_mmu_pages -
|
||||
kvm->arch.n_used_mmu_pages;
|
||||
kvm->stat.mmu_shadow_pages;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2874,11 +2874,11 @@ void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned long goal_nr_mmu_pages)
|
|||
{
|
||||
write_lock(&kvm->mmu_lock);
|
||||
|
||||
if (kvm->arch.n_used_mmu_pages > goal_nr_mmu_pages) {
|
||||
kvm_mmu_zap_oldest_mmu_pages(kvm, kvm->arch.n_used_mmu_pages -
|
||||
if (kvm->stat.mmu_shadow_pages > goal_nr_mmu_pages) {
|
||||
kvm_mmu_zap_oldest_mmu_pages(kvm, kvm->stat.mmu_shadow_pages -
|
||||
goal_nr_mmu_pages);
|
||||
|
||||
goal_nr_mmu_pages = kvm->arch.n_used_mmu_pages;
|
||||
goal_nr_mmu_pages = kvm->stat.mmu_shadow_pages;
|
||||
}
|
||||
|
||||
kvm->arch.n_max_mmu_pages = goal_nr_mmu_pages;
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ TRACE_EVENT(
|
|||
|
||||
TP_fast_assign(
|
||||
__entry->mmu_valid_gen = kvm->arch.mmu_valid_gen;
|
||||
__entry->mmu_used_pages = kvm->arch.n_used_mmu_pages;
|
||||
__entry->mmu_used_pages = kvm->stat.mmu_shadow_pages;
|
||||
),
|
||||
|
||||
TP_printk("kvm-mmu-valid-gen %u used_pages %x",
|
||||
|
|
|
|||
|
|
@ -1410,9 +1410,10 @@ static bool wrprot_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
|
|||
u64 new_spte;
|
||||
bool spte_set = false;
|
||||
|
||||
rcu_read_lock();
|
||||
if (KVM_BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL, kvm))
|
||||
return false;
|
||||
|
||||
BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL);
|
||||
rcu_read_lock();
|
||||
|
||||
for_each_tdp_pte_min_level(iter, kvm, root, min_level, start, end) {
|
||||
retry:
|
||||
|
|
@ -1844,7 +1845,8 @@ static bool write_protect_gfn(struct kvm *kvm, struct kvm_mmu_page *root,
|
|||
u64 new_spte;
|
||||
bool spte_set = false;
|
||||
|
||||
BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL);
|
||||
if (KVM_BUG_ON(min_level > KVM_MAX_HUGEPAGE_LEVEL, kvm))
|
||||
return false;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
|
|
|
|||
|
|
@ -460,8 +460,8 @@ void avic_ring_doorbell(struct kvm_vcpu *vcpu)
|
|||
int cpu = READ_ONCE(vcpu->cpu);
|
||||
|
||||
if (cpu != get_cpu()) {
|
||||
wrmsrq(MSR_AMD64_SVM_AVIC_DOORBELL, kvm_cpu_get_apicid(cpu));
|
||||
trace_kvm_avic_doorbell(vcpu->vcpu_id, kvm_cpu_get_apicid(cpu));
|
||||
wrmsrq(MSR_AMD64_SVM_AVIC_DOORBELL, cpu_physical_id(cpu));
|
||||
trace_kvm_avic_doorbell(vcpu->vcpu_id, cpu_physical_id(cpu));
|
||||
}
|
||||
put_cpu();
|
||||
}
|
||||
|
|
@ -1013,7 +1013,7 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,
|
|||
enum avic_vcpu_action action)
|
||||
{
|
||||
struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
|
||||
int h_physical_id = kvm_cpu_get_apicid(cpu);
|
||||
int h_physical_id = cpu_physical_id(cpu);
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
unsigned long flags;
|
||||
u64 entry;
|
||||
|
|
|
|||
|
|
@ -2152,7 +2152,8 @@ static gpa_t svm_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
struct kvm_mmu *mmu = vcpu->arch.mmu;
|
||||
|
||||
BUG_ON(!mmu_is_nested(vcpu));
|
||||
if (WARN_ON_ONCE(!mmu_is_nested(vcpu)))
|
||||
return gpa;
|
||||
|
||||
/* Non-GMET walks are always user-walks */
|
||||
if (!(svm->nested.ctl.misc_ctl & SVM_MISC_ENABLE_GMET))
|
||||
|
|
|
|||
|
|
@ -7470,7 +7470,8 @@ static gpa_t vmx_translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|||
{
|
||||
struct kvm_mmu *mmu = vcpu->arch.mmu;
|
||||
|
||||
BUG_ON(!mmu_is_nested(vcpu));
|
||||
if (WARN_ON_ONCE(!mmu_is_nested(vcpu)))
|
||||
return gpa;
|
||||
|
||||
/*
|
||||
* MBEC differentiates based on the effective U/S bit of
|
||||
|
|
|
|||
|
|
@ -6873,11 +6873,10 @@ int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
|
|||
|
||||
void vmx_update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
|
||||
{
|
||||
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
|
||||
int tpr_threshold;
|
||||
|
||||
if (is_guest_mode(vcpu) &&
|
||||
nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
|
||||
nested_cpu_has(get_vmcs12(vcpu), CPU_BASED_TPR_SHADOW))
|
||||
return;
|
||||
|
||||
guard(vmx_vmcs01)(vcpu);
|
||||
|
|
|
|||
|
|
@ -244,6 +244,7 @@ const struct kvm_stats_desc kvm_vm_stats_desc[] = {
|
|||
STATS_DESC_COUNTER(VM, mmu_recycled),
|
||||
STATS_DESC_COUNTER(VM, mmu_cache_miss),
|
||||
STATS_DESC_ICOUNTER(VM, mmu_unsync),
|
||||
STATS_DESC_ICOUNTER(VM, mmu_shadow_pages),
|
||||
STATS_DESC_ICOUNTER(VM, pages_4k),
|
||||
STATS_DESC_ICOUNTER(VM, pages_2m),
|
||||
STATS_DESC_ICOUNTER(VM, pages_1g),
|
||||
|
|
@ -5317,7 +5318,6 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
|
|||
r = kvm_apic_set_state(vcpu, s);
|
||||
if (r)
|
||||
return r;
|
||||
kvm_lapic_update_cr8_intercept(vcpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -12418,8 +12418,6 @@ static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
|
|||
kvm_register_mark_dirty(vcpu, VCPU_REG_CR3);
|
||||
kvm_x86_call(post_set_cr3)(vcpu, sregs->cr3);
|
||||
|
||||
kvm_set_cr8(vcpu, sregs->cr8);
|
||||
|
||||
*mmu_reset_needed |= vcpu->arch.efer != sregs->efer;
|
||||
kvm_x86_call(set_efer)(vcpu, sregs->efer);
|
||||
|
||||
|
|
@ -12448,7 +12446,7 @@ static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
|
|||
kvm_set_segment(vcpu, &sregs->tr, VCPU_SREG_TR);
|
||||
kvm_set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR);
|
||||
|
||||
kvm_lapic_update_cr8_intercept(vcpu);
|
||||
kvm_set_cr8(vcpu, sregs->cr8);
|
||||
|
||||
/* Older userspace won't unhalt the vcpu on reset. */
|
||||
if (kvm_vcpu_is_bsp(vcpu) && kvm_rip_read(vcpu) == 0xfff0 &&
|
||||
|
|
|
|||
|
|
@ -550,13 +550,20 @@ static void bfq_pd_init(struct blkg_policy_data *pd)
|
|||
bfqg->rq_pos_tree = RB_ROOT;
|
||||
}
|
||||
|
||||
static void bfq_pd_free(struct blkg_policy_data *pd)
|
||||
static void bfqg_release(struct rcu_head *rcu)
|
||||
{
|
||||
struct blkg_policy_data *pd =
|
||||
container_of(rcu, struct blkg_policy_data, rcu_head);
|
||||
struct bfq_group *bfqg = pd_to_bfqg(pd);
|
||||
|
||||
bfqg_put(bfqg);
|
||||
}
|
||||
|
||||
static void bfq_pd_free(struct blkg_policy_data *pd)
|
||||
{
|
||||
call_rcu(&pd->rcu_head, bfqg_release);
|
||||
}
|
||||
|
||||
static void bfq_pd_reset_stats(struct blkg_policy_data *pd)
|
||||
{
|
||||
struct bfq_group *bfqg = pd_to_bfqg(pd);
|
||||
|
|
@ -936,14 +943,23 @@ static void bfq_pd_offline(struct blkg_policy_data *pd)
|
|||
|
||||
void bfq_end_wr_async(struct bfq_data *bfqd)
|
||||
{
|
||||
struct request_queue *q = bfqd->queue;
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
list_for_each_entry(blkg, &bfqd->queue->blkg_list, q_node) {
|
||||
mutex_lock(&q->blkcg_mutex);
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
spin_lock(&bfqd->lock);
|
||||
|
||||
list_for_each_entry(blkg, &q->blkg_list, q_node) {
|
||||
struct bfq_group *bfqg = blkg_to_bfqg(blkg);
|
||||
|
||||
bfq_end_wr_async_queues(bfqd, bfqg);
|
||||
}
|
||||
bfq_end_wr_async_queues(bfqd, bfqd->root_group);
|
||||
|
||||
spin_unlock(&bfqd->lock);
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
mutex_unlock(&q->blkcg_mutex);
|
||||
}
|
||||
|
||||
static int bfq_io_show_weight_legacy(struct seq_file *sf, void *v)
|
||||
|
|
@ -1147,16 +1163,18 @@ static u64 bfqg_prfill_stat_recursive(struct seq_file *sf,
|
|||
struct cgroup_subsys_state *pos_css;
|
||||
u64 sum = 0;
|
||||
|
||||
lockdep_assert_held(&blkg->q->queue_lock);
|
||||
|
||||
rcu_read_lock();
|
||||
blkg_for_each_descendant_pre(pos_blkg, pos_css, blkg) {
|
||||
struct blkg_policy_data *pd;
|
||||
struct bfq_stat *stat;
|
||||
|
||||
if (!pos_blkg->online)
|
||||
continue;
|
||||
|
||||
stat = (void *)blkg_to_pd(pos_blkg, &blkcg_policy_bfq) + off;
|
||||
pd = blkg_to_pd(pos_blkg, &blkcg_policy_bfq);
|
||||
if (!pd)
|
||||
continue;
|
||||
stat = (void *)pd + off;
|
||||
sum += bfq_stat_read(stat) + atomic64_read(&stat->aux_cnt);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
|
@ -1416,7 +1434,9 @@ void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) {}
|
|||
|
||||
void bfq_end_wr_async(struct bfq_data *bfqd)
|
||||
{
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
bfq_end_wr_async_queues(bfqd, bfqd->root_group);
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
}
|
||||
|
||||
struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
|
||||
|
|
|
|||
|
|
@ -2653,9 +2653,10 @@ static void bfq_end_wr(struct bfq_data *bfqd)
|
|||
}
|
||||
list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list)
|
||||
bfq_bfqq_end_wr(bfqq);
|
||||
bfq_end_wr_async(bfqd);
|
||||
|
||||
spin_unlock_irq(&bfqd->lock);
|
||||
|
||||
bfq_end_wr_async(bfqd);
|
||||
}
|
||||
|
||||
static sector_t bfq_io_struct_pos(void *io_struct, bool request)
|
||||
|
|
@ -7203,10 +7204,7 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
|
|||
return -ENOMEM;
|
||||
|
||||
eq->elevator_data = bfqd;
|
||||
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
q->elevator = eq;
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
|
||||
/*
|
||||
* Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues.
|
||||
|
|
@ -7239,7 +7237,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
|
|||
* If the disk supports multiple actuators, copy independent
|
||||
* access ranges from the request queue structure.
|
||||
*/
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
if (ia_ranges) {
|
||||
/*
|
||||
* Check if the disk ia_ranges size exceeds the current bfq
|
||||
|
|
@ -7265,7 +7262,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq)
|
|||
bfqd->sector[0] = 0;
|
||||
bfqd->nr_sectors[0] = get_capacity(q->disk);
|
||||
}
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
|
||||
INIT_LIST_HEAD(&bfqd->dispatch);
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ void bio_integrity_prep(struct bio *bio, unsigned int action)
|
|||
bio_integrity_init(bio, &bid->bip, &bid->bvec, 1);
|
||||
bid->bio = bio;
|
||||
bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY;
|
||||
bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO);
|
||||
bio_integrity_alloc_buf(bio, GFP_NOIO, action & BI_ACT_ZERO);
|
||||
if (action & BI_ACT_CHECK)
|
||||
bio_integrity_setup_default(bio);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ unsigned int fs_bio_integrity_alloc(struct bio *bio)
|
|||
if (!action)
|
||||
return 0;
|
||||
|
||||
iib = mempool_alloc(&fs_bio_integrity_pool, GFP_NOIO);
|
||||
iib = mempool_alloc(&fs_bio_integrity_pool, GFP_NOFS);
|
||||
bio_integrity_init(bio, &iib->bip, &iib->bvec, 1);
|
||||
|
||||
bio_integrity_alloc_buf(bio, action & BI_ACT_ZERO);
|
||||
bio_integrity_alloc_buf(bio, GFP_NOFS, action & BI_ACT_ZERO);
|
||||
if (action & BI_ACT_CHECK)
|
||||
bio_integrity_setup_default(bio);
|
||||
return action;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ unsigned int __bio_integrity_action(struct bio *bio)
|
|||
}
|
||||
return BI_ACT_BUFFER | BI_ACT_CHECK;
|
||||
case REQ_OP_WRITE:
|
||||
case REQ_OP_ZONE_APPEND:
|
||||
/*
|
||||
* Flush masquerading as write?
|
||||
*/
|
||||
|
|
@ -64,20 +65,18 @@ unsigned int __bio_integrity_action(struct bio *bio)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(__bio_integrity_action);
|
||||
|
||||
void bio_integrity_alloc_buf(struct bio *bio, bool zero_buffer)
|
||||
void bio_integrity_alloc_buf(struct bio *bio, gfp_t gfp, bool zero_buffer)
|
||||
{
|
||||
struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
|
||||
struct bio_integrity_payload *bip = bio_integrity(bio);
|
||||
unsigned int len = bio_integrity_bytes(bi, bio_sectors(bio));
|
||||
gfp_t gfp = GFP_NOIO | (zero_buffer ? __GFP_ZERO : 0);
|
||||
void *buf;
|
||||
|
||||
buf = kmalloc(len, (gfp & ~__GFP_DIRECT_RECLAIM) |
|
||||
__GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN);
|
||||
buf = kmalloc(len, gfp | __GFP_NOWARN | (zero_buffer ? __GFP_ZERO : 0));
|
||||
if (unlikely(!buf)) {
|
||||
struct page *page;
|
||||
|
||||
page = mempool_alloc(&integrity_buf_pool, GFP_NOFS);
|
||||
page = mempool_alloc(&integrity_buf_pool, gfp);
|
||||
if (zero_buffer)
|
||||
memset(page_address(page), 0, len);
|
||||
bvec_set_page(&bip->bip_vec[0], page, len, 0);
|
||||
|
|
|
|||
21
block/bio.c
21
block/bio.c
|
|
@ -1321,6 +1321,7 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
|
|||
|
||||
do {
|
||||
size_t this_len = min(total_len, SZ_1M);
|
||||
size_t copied;
|
||||
struct folio *folio;
|
||||
|
||||
if (this_len > minsize * 2)
|
||||
|
|
@ -1334,12 +1335,26 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
|
|||
break;
|
||||
bio_add_folio_nofail(bio, folio, this_len, 0);
|
||||
|
||||
if (copy_from_iter(folio_address(folio), this_len, iter) !=
|
||||
this_len) {
|
||||
if (iter->nofault)
|
||||
copied = copy_folio_from_iter_atomic(folio, 0, this_len,
|
||||
iter);
|
||||
else
|
||||
copied = copy_folio_from_iter(folio, 0, this_len, iter);
|
||||
if (copied < this_len) {
|
||||
/*
|
||||
* Need to revert the iov iter for all bytes we have
|
||||
* copied.
|
||||
*
|
||||
* However the bio size differs from the real copied
|
||||
* bytes as @this_len is queued but only advanced
|
||||
* less than that.
|
||||
* Need to compensate that for the revert.
|
||||
*/
|
||||
iov_iter_revert(iter, bio->bi_iter.bi_size - this_len +
|
||||
copied);
|
||||
bio_free_folios(bio);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
total_len -= this_len;
|
||||
} while (total_len && bio->bi_vcnt < bio->bi_max_vecs);
|
||||
|
||||
|
|
|
|||
|
|
@ -101,24 +101,27 @@ void blkg_rwstat_recursive_sum(struct blkcg_gq *blkg, struct blkcg_policy *pol,
|
|||
struct cgroup_subsys_state *pos_css;
|
||||
unsigned int i;
|
||||
|
||||
lockdep_assert_held(&blkg->q->queue_lock);
|
||||
WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
|
||||
memset(sum, 0, sizeof(*sum));
|
||||
rcu_read_lock();
|
||||
blkg_for_each_descendant_pre(pos_blkg, pos_css, blkg) {
|
||||
struct blkg_rwstat *rwstat;
|
||||
|
||||
if (!pos_blkg->online)
|
||||
continue;
|
||||
|
||||
if (pol)
|
||||
rwstat = (void *)blkg_to_pd(pos_blkg, pol) + off;
|
||||
else
|
||||
if (pol) {
|
||||
struct blkg_policy_data *pd = blkg_to_pd(pos_blkg, pol);
|
||||
|
||||
if (!pd)
|
||||
continue;
|
||||
rwstat = (void *)pd + off;
|
||||
} else {
|
||||
rwstat = (void *)pos_blkg + off;
|
||||
}
|
||||
|
||||
for (i = 0; i < BLKG_RWSTAT_NR; i++)
|
||||
sum->cnt[i] += blkg_rwstat_read_counter(rwstat, i);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(blkg_rwstat_recursive_sum);
|
||||
|
|
|
|||
|
|
@ -136,6 +136,11 @@ static void blkg_free_workfn(struct work_struct *work)
|
|||
spin_unlock_irq(&q->queue_lock);
|
||||
mutex_unlock(&q->blkcg_mutex);
|
||||
|
||||
/*
|
||||
* Release blkcg css ref only after blkg is removed from q->blkg_list,
|
||||
* so concurrent iterators won't see a blkg with a freed blkcg.
|
||||
*/
|
||||
css_put(&blkg->blkcg->css);
|
||||
blk_put_queue(q);
|
||||
free_percpu(blkg->iostat_cpu);
|
||||
percpu_ref_exit(&blkg->refcnt);
|
||||
|
|
@ -164,23 +169,11 @@ static void blkg_free(struct blkcg_gq *blkg)
|
|||
static void __blkg_release(struct rcu_head *rcu)
|
||||
{
|
||||
struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head);
|
||||
struct blkcg *blkcg = blkg->blkcg;
|
||||
int cpu;
|
||||
|
||||
#ifdef CONFIG_BLK_CGROUP_PUNT_BIO
|
||||
WARN_ON(!bio_list_empty(&blkg->async_bios));
|
||||
#endif
|
||||
/*
|
||||
* Flush all the non-empty percpu lockless lists before releasing
|
||||
* us, given these stat belongs to us.
|
||||
*
|
||||
* blkg_stat_lock is for serializing blkg stat update
|
||||
*/
|
||||
for_each_possible_cpu(cpu)
|
||||
__blkcg_rstat_flush(blkcg, cpu);
|
||||
|
||||
/* release the blkcg and parent blkg refs this blkg has been holding */
|
||||
css_put(&blkg->blkcg->css);
|
||||
blkg_free(blkg);
|
||||
}
|
||||
|
||||
|
|
@ -195,6 +188,17 @@ static void __blkg_release(struct rcu_head *rcu)
|
|||
static void blkg_release(struct percpu_ref *ref)
|
||||
{
|
||||
struct blkcg_gq *blkg = container_of(ref, struct blkcg_gq, refcnt);
|
||||
struct blkcg *blkcg = blkg->blkcg;
|
||||
int cpu;
|
||||
|
||||
/*
|
||||
* Flush all the non-empty percpu lockless lists before releasing
|
||||
* us, given these stat belongs to us.
|
||||
*
|
||||
* blkg_stat_lock is for serializing blkg stat update
|
||||
*/
|
||||
for_each_possible_cpu(cpu)
|
||||
__blkcg_rstat_flush(blkcg, cpu);
|
||||
|
||||
call_rcu(&blkg->rcu_head, __blkg_release);
|
||||
}
|
||||
|
|
@ -313,6 +317,9 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
|
|||
goto out_exit_refcnt;
|
||||
if (!blk_get_queue(disk->queue))
|
||||
goto out_free_iostat;
|
||||
/* blkg holds a reference to blkcg */
|
||||
if (!css_tryget_online(&blkcg->css))
|
||||
goto out_put_queue;
|
||||
|
||||
blkg->q = disk->queue;
|
||||
INIT_LIST_HEAD(&blkg->q_node);
|
||||
|
|
@ -353,6 +360,8 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
|
|||
while (--i >= 0)
|
||||
if (blkg->pd[i])
|
||||
blkcg_policy[i]->pd_free_fn(blkg->pd[i]);
|
||||
css_put(&blkcg->css);
|
||||
out_put_queue:
|
||||
blk_put_queue(disk->queue);
|
||||
out_free_iostat:
|
||||
free_percpu(blkg->iostat_cpu);
|
||||
|
|
@ -381,18 +390,12 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
|
|||
goto err_free_blkg;
|
||||
}
|
||||
|
||||
/* blkg holds a reference to blkcg */
|
||||
if (!css_tryget_online(&blkcg->css)) {
|
||||
ret = -ENODEV;
|
||||
goto err_free_blkg;
|
||||
}
|
||||
|
||||
/* allocate */
|
||||
if (!new_blkg) {
|
||||
new_blkg = blkg_alloc(blkcg, disk, GFP_NOWAIT);
|
||||
if (unlikely(!new_blkg)) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_css;
|
||||
goto err_free_blkg;
|
||||
}
|
||||
}
|
||||
blkg = new_blkg;
|
||||
|
|
@ -402,7 +405,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
|
|||
blkg->parent = blkg_lookup(blkcg_parent(blkcg), disk->queue);
|
||||
if (WARN_ON_ONCE(!blkg->parent)) {
|
||||
ret = -ENODEV;
|
||||
goto err_put_css;
|
||||
goto err_free_blkg;
|
||||
}
|
||||
blkg_get(blkg->parent);
|
||||
}
|
||||
|
|
@ -442,8 +445,6 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, struct gendisk *disk,
|
|||
blkg_put(blkg);
|
||||
return ERR_PTR(ret);
|
||||
|
||||
err_put_css:
|
||||
css_put(&blkcg->css);
|
||||
err_free_blkg:
|
||||
if (new_blkg)
|
||||
blkg_free(new_blkg);
|
||||
|
|
@ -468,22 +469,17 @@ static struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
|
|||
{
|
||||
struct request_queue *q = disk->queue;
|
||||
struct blkcg_gq *blkg;
|
||||
unsigned long flags;
|
||||
|
||||
WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
|
||||
blkg = blkg_lookup(blkcg, q);
|
||||
if (blkg)
|
||||
return blkg;
|
||||
|
||||
spin_lock_irqsave(&q->queue_lock, flags);
|
||||
rcu_read_lock();
|
||||
blkg = blkg_lookup(blkcg, q);
|
||||
if (blkg) {
|
||||
if (blkcg != &blkcg_root &&
|
||||
blkg != rcu_dereference(blkcg->blkg_hint))
|
||||
rcu_assign_pointer(blkcg->blkg_hint, blkg);
|
||||
goto found;
|
||||
rcu_read_unlock();
|
||||
return blkg;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/*
|
||||
* Create blkgs walking down from blkcg_root to @blkcg, so that all
|
||||
|
|
@ -515,8 +511,6 @@ static struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
|
|||
break;
|
||||
}
|
||||
|
||||
found:
|
||||
spin_unlock_irqrestore(&q->queue_lock, flags);
|
||||
return blkg;
|
||||
}
|
||||
|
||||
|
|
@ -698,9 +692,9 @@ const char *blkg_dev_name(struct blkcg_gq *blkg)
|
|||
*
|
||||
* This function invokes @prfill on each blkg of @blkcg if pd for the
|
||||
* policy specified by @pol exists. @prfill is invoked with @sf, the
|
||||
* policy data and @data and the matching queue lock held. If @show_total
|
||||
* is %true, the sum of the return values from @prfill is printed with
|
||||
* "Total" label at the end.
|
||||
* policy data and @data under RCU read lock. If @show_total is %true, the
|
||||
* sum of the return values from @prfill is printed with "Total" label at the
|
||||
* end.
|
||||
*
|
||||
* This is to be used to construct print functions for
|
||||
* cftype->read_seq_string method.
|
||||
|
|
@ -716,10 +710,14 @@ void blkcg_print_blkgs(struct seq_file *sf, struct blkcg *blkcg,
|
|||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(blkg, &blkcg->blkg_list, blkcg_node) {
|
||||
spin_lock_irq(&blkg->q->queue_lock);
|
||||
if (blkcg_policy_enabled(blkg->q, pol))
|
||||
total += prfill(sf, blkg->pd[pol->plid], data);
|
||||
spin_unlock_irq(&blkg->q->queue_lock);
|
||||
struct blkg_policy_data *pd;
|
||||
|
||||
if (!blkcg_policy_enabled(blkg->q, pol))
|
||||
continue;
|
||||
|
||||
pd = blkg_to_pd(blkg, pol);
|
||||
if (pd)
|
||||
total += prfill(sf, pd, data);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
@ -1190,13 +1188,10 @@ static int blkcg_print_stat(struct seq_file *sf, void *v)
|
|||
else
|
||||
css_rstat_flush(&blkcg->css);
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(blkg, &blkcg->blkg_list, blkcg_node) {
|
||||
spin_lock_irq(&blkg->q->queue_lock);
|
||||
guard(spinlock_irq)(&blkcg->lock);
|
||||
hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node)
|
||||
blkcg_print_one_stat(blkg, sf);
|
||||
spin_unlock_irq(&blkg->q->queue_lock);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1244,6 +1239,21 @@ struct list_head *blkcg_get_cgwb_list(struct cgroup_subsys_state *css)
|
|||
* This finally frees the blkcg.
|
||||
*/
|
||||
|
||||
static struct blkcg_gq *blkcg_get_first_blkg(struct blkcg *blkcg)
|
||||
{
|
||||
struct blkcg_gq *blkg = NULL;
|
||||
|
||||
spin_lock_irq(&blkcg->lock);
|
||||
if (!hlist_empty(&blkcg->blkg_list)) {
|
||||
blkg = hlist_entry(blkcg->blkg_list.first, struct blkcg_gq,
|
||||
blkcg_node);
|
||||
blkg_get(blkg);
|
||||
}
|
||||
spin_unlock_irq(&blkcg->lock);
|
||||
|
||||
return blkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* blkcg_destroy_blkgs - responsible for shooting down blkgs
|
||||
* @blkcg: blkcg of interest
|
||||
|
|
@ -1257,32 +1267,24 @@ struct list_head *blkcg_get_cgwb_list(struct cgroup_subsys_state *css)
|
|||
*/
|
||||
static void blkcg_destroy_blkgs(struct blkcg *blkcg)
|
||||
{
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
might_sleep();
|
||||
|
||||
spin_lock_irq(&blkcg->lock);
|
||||
|
||||
while (!hlist_empty(&blkcg->blkg_list)) {
|
||||
struct blkcg_gq *blkg = hlist_entry(blkcg->blkg_list.first,
|
||||
struct blkcg_gq, blkcg_node);
|
||||
while ((blkg = blkcg_get_first_blkg(blkcg))) {
|
||||
struct request_queue *q = blkg->q;
|
||||
|
||||
if (need_resched() || !spin_trylock(&q->queue_lock)) {
|
||||
/*
|
||||
* Given that the system can accumulate a huge number
|
||||
* of blkgs in pathological cases, check to see if we
|
||||
* need to rescheduling to avoid softlockup.
|
||||
*/
|
||||
spin_unlock_irq(&blkcg->lock);
|
||||
cond_resched();
|
||||
spin_lock_irq(&blkcg->lock);
|
||||
continue;
|
||||
}
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
spin_lock(&blkcg->lock);
|
||||
|
||||
blkg_destroy(blkg);
|
||||
spin_unlock(&q->queue_lock);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&blkcg->lock);
|
||||
spin_unlock(&blkcg->lock);
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
|
||||
blkg_put(blkg);
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1606,7 +1608,7 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
|
|||
|
||||
pd->blkg = blkg;
|
||||
pd->plid = pol->plid;
|
||||
blkg->pd[pol->plid] = pd;
|
||||
WRITE_ONCE(blkg->pd[pol->plid], pd);
|
||||
|
||||
if (pol->pd_init_fn)
|
||||
pol->pd_init_fn(pd);
|
||||
|
|
@ -1645,7 +1647,7 @@ int blkcg_activate_policy(struct gendisk *disk, const struct blkcg_policy *pol)
|
|||
pol->pd_offline_fn(pd);
|
||||
pd->online = false;
|
||||
pol->pd_free_fn(pd);
|
||||
blkg->pd[pol->plid] = NULL;
|
||||
WRITE_ONCE(blkg->pd[pol->plid], NULL);
|
||||
}
|
||||
spin_unlock(&blkcg->lock);
|
||||
}
|
||||
|
|
@ -2044,6 +2046,18 @@ void blkcg_add_delay(struct blkcg_gq *blkg, u64 now, u64 delta)
|
|||
atomic64_add(delta, &blkg->delay_nsec);
|
||||
}
|
||||
|
||||
static inline struct blkcg_gq *blkg_lookup_tryget(struct blkcg_gq *blkg)
|
||||
{
|
||||
retry:
|
||||
if (blkg_tryget(blkg))
|
||||
return blkg;
|
||||
|
||||
blkg = blkg->parent;
|
||||
if (blkg)
|
||||
goto retry;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/**
|
||||
* blkg_tryget_closest - try and get a blkg ref on the closet blkg
|
||||
* @bio: target bio
|
||||
|
|
@ -2056,20 +2070,30 @@ void blkcg_add_delay(struct blkcg_gq *blkg, u64 now, u64 delta)
|
|||
static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio,
|
||||
struct cgroup_subsys_state *css)
|
||||
{
|
||||
struct blkcg_gq *blkg, *ret_blkg = NULL;
|
||||
struct request_queue *q = bio->bi_bdev->bd_queue;
|
||||
struct blkcg *blkcg = css_to_blkcg(css);
|
||||
struct blkcg_gq *blkg;
|
||||
|
||||
rcu_read_lock();
|
||||
blkg = blkg_lookup_create(css_to_blkcg(css), bio->bi_bdev->bd_disk);
|
||||
while (blkg) {
|
||||
if (blkg_tryget(blkg)) {
|
||||
ret_blkg = blkg;
|
||||
break;
|
||||
}
|
||||
blkg = blkg->parent;
|
||||
}
|
||||
blkg = blkg_lookup(blkcg, q);
|
||||
if (likely(blkg))
|
||||
blkg = blkg_lookup_tryget(blkg);
|
||||
rcu_read_unlock();
|
||||
|
||||
return ret_blkg;
|
||||
if (blkg)
|
||||
return blkg;
|
||||
|
||||
/*
|
||||
* Fast path failed, we're probably issuing IO in this cgroup the first
|
||||
* time, hold lock to create new blkg.
|
||||
*/
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
blkg = blkg_lookup_create(blkcg, bio->bi_bdev->bd_disk);
|
||||
if (blkg)
|
||||
blkg = blkg_lookup_tryget(blkg);
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
|
||||
return blkg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2117,16 +2141,20 @@ void bio_associate_blkg(struct bio *bio)
|
|||
if (blk_op_is_passthrough(bio->bi_opf))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (bio->bi_blkg)
|
||||
if (bio->bi_blkg) {
|
||||
css = bio_blkcg_css(bio);
|
||||
else
|
||||
bio_associate_blkg_from_css(bio, css);
|
||||
} else {
|
||||
rcu_read_lock();
|
||||
css = blkcg_css();
|
||||
if (!css_tryget_online(css))
|
||||
css = NULL;
|
||||
rcu_read_unlock();
|
||||
|
||||
bio_associate_blkg_from_css(bio, css);
|
||||
|
||||
rcu_read_unlock();
|
||||
bio_associate_blkg_from_css(bio, css);
|
||||
if (css)
|
||||
css_put(css);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bio_associate_blkg);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ struct blkg_policy_data {
|
|||
struct blkcg_gq *blkg;
|
||||
int plid;
|
||||
bool online;
|
||||
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -282,9 +284,9 @@ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg,
|
|||
* Return pointer to private data associated with the @blkg-@pol pair.
|
||||
*/
|
||||
static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg,
|
||||
struct blkcg_policy *pol)
|
||||
const struct blkcg_policy *pol)
|
||||
{
|
||||
return blkg ? blkg->pd[pol->plid] : NULL;
|
||||
return blkg ? READ_ONCE(blkg->pd[pol->plid]) : NULL;
|
||||
}
|
||||
|
||||
static inline struct blkcg_policy_data *blkcg_to_cpd(struct blkcg *blkcg,
|
||||
|
|
@ -491,7 +493,7 @@ static inline void blkcg_deactivate_policy(struct gendisk *disk,
|
|||
const struct blkcg_policy *pol) { }
|
||||
|
||||
static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg,
|
||||
struct blkcg_policy *pol) { return NULL; }
|
||||
const struct blkcg_policy *pol) { return NULL; }
|
||||
static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd) { return NULL; }
|
||||
static inline void blkg_get(struct blkcg_gq *blkg) { }
|
||||
static inline void blkg_put(struct blkcg_gq *blkg) { }
|
||||
|
|
|
|||
|
|
@ -669,11 +669,6 @@ static inline blk_status_t blk_check_zone_append(struct request_queue *q,
|
|||
|
||||
static void __submit_bio(struct bio *bio)
|
||||
{
|
||||
/* If plug is not used, add new plug here to cache nsecs time. */
|
||||
struct blk_plug plug;
|
||||
|
||||
blk_start_plug(&plug);
|
||||
|
||||
if (!bdev_test_flag(bio->bi_bdev, BD_HAS_SUBMIT_BIO)) {
|
||||
blk_mq_submit_bio(bio);
|
||||
} else if (likely(bio_queue_enter(bio) == 0)) {
|
||||
|
|
@ -686,8 +681,6 @@ static void __submit_bio(struct bio *bio)
|
|||
disk->fops->submit_bio(bio);
|
||||
blk_queue_exit(disk->queue);
|
||||
}
|
||||
|
||||
blk_finish_plug(&plug);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -3050,6 +3050,16 @@ static void ioc_pd_init(struct blkg_policy_data *pd)
|
|||
spin_unlock_irqrestore(&ioc->lock, flags);
|
||||
}
|
||||
|
||||
static void iocg_release(struct rcu_head *rcu)
|
||||
{
|
||||
struct blkg_policy_data *pd =
|
||||
container_of(rcu, struct blkg_policy_data, rcu_head);
|
||||
struct ioc_gq *iocg = pd_to_iocg(pd);
|
||||
|
||||
free_percpu(iocg->pcpu_stat);
|
||||
kfree(iocg);
|
||||
}
|
||||
|
||||
static void ioc_pd_free(struct blkg_policy_data *pd)
|
||||
{
|
||||
struct ioc_gq *iocg = pd_to_iocg(pd);
|
||||
|
|
@ -3074,8 +3084,8 @@ static void ioc_pd_free(struct blkg_policy_data *pd)
|
|||
|
||||
hrtimer_cancel(&iocg->waitq_timer);
|
||||
}
|
||||
free_percpu(iocg->pcpu_stat);
|
||||
kfree(iocg);
|
||||
|
||||
call_rcu(&pd->rcu_head, iocg_release);
|
||||
}
|
||||
|
||||
static void ioc_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)
|
||||
|
|
@ -3211,7 +3221,7 @@ static u64 ioc_qos_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
|
|||
if (!dname)
|
||||
return 0;
|
||||
|
||||
spin_lock(&ioc->lock);
|
||||
spin_lock_irq(&ioc->lock);
|
||||
seq_printf(sf, "%s enable=%d ctrl=%s rpct=%u.%02u rlat=%u wpct=%u.%02u wlat=%u min=%u.%02u max=%u.%02u\n",
|
||||
dname, ioc->enabled, ioc->user_qos_params ? "user" : "auto",
|
||||
ioc->params.qos[QOS_RPPM] / 10000,
|
||||
|
|
@ -3224,7 +3234,7 @@ static u64 ioc_qos_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
|
|||
ioc->params.qos[QOS_MIN] % 10000 / 100,
|
||||
ioc->params.qos[QOS_MAX] / 10000,
|
||||
ioc->params.qos[QOS_MAX] % 10000 / 100);
|
||||
spin_unlock(&ioc->lock);
|
||||
spin_unlock_irq(&ioc->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3420,14 +3430,14 @@ static u64 ioc_cost_model_prfill(struct seq_file *sf,
|
|||
if (!dname)
|
||||
return 0;
|
||||
|
||||
spin_lock(&ioc->lock);
|
||||
spin_lock_irq(&ioc->lock);
|
||||
seq_printf(sf, "%s ctrl=%s model=linear "
|
||||
"rbps=%llu rseqiops=%llu rrandiops=%llu "
|
||||
"wbps=%llu wseqiops=%llu wrandiops=%llu\n",
|
||||
dname, ioc->user_cost_model ? "user" : "auto",
|
||||
u[I_LCOEF_RBPS], u[I_LCOEF_RSEQIOPS], u[I_LCOEF_RRANDIOPS],
|
||||
u[I_LCOEF_WBPS], u[I_LCOEF_WSEQIOPS], u[I_LCOEF_WRANDIOPS]);
|
||||
spin_unlock(&ioc->lock);
|
||||
spin_unlock_irq(&ioc->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1031,13 +1031,21 @@ static void iolatency_pd_offline(struct blkg_policy_data *pd)
|
|||
iolatency_clear_scaling(blkg);
|
||||
}
|
||||
|
||||
static void iolatency_pd_free(struct blkg_policy_data *pd)
|
||||
static void iolat_release(struct rcu_head *rcu)
|
||||
{
|
||||
struct blkg_policy_data *pd =
|
||||
container_of(rcu, struct blkg_policy_data, rcu_head);
|
||||
struct iolatency_grp *iolat = pd_to_lat(pd);
|
||||
|
||||
free_percpu(iolat->stats);
|
||||
kfree(iolat);
|
||||
}
|
||||
|
||||
static void iolatency_pd_free(struct blkg_policy_data *pd)
|
||||
{
|
||||
call_rcu(&pd->rcu_head, iolat_release);
|
||||
}
|
||||
|
||||
static struct cftype iolatency_files[] = {
|
||||
{
|
||||
.name = "latency",
|
||||
|
|
|
|||
|
|
@ -353,14 +353,23 @@ static void throtl_pd_online(struct blkg_policy_data *pd)
|
|||
tg_update_has_rules(tg);
|
||||
}
|
||||
|
||||
static void tg_release(struct rcu_head *rcu)
|
||||
{
|
||||
struct blkg_policy_data *pd =
|
||||
container_of(rcu, struct blkg_policy_data, rcu_head);
|
||||
struct throtl_grp *tg = pd_to_tg(pd);
|
||||
|
||||
blkg_rwstat_exit(&tg->stat_bytes);
|
||||
blkg_rwstat_exit(&tg->stat_ios);
|
||||
kfree(tg);
|
||||
}
|
||||
|
||||
static void throtl_pd_free(struct blkg_policy_data *pd)
|
||||
{
|
||||
struct throtl_grp *tg = pd_to_tg(pd);
|
||||
|
||||
timer_delete_sync(&tg->service_queue.pending_timer);
|
||||
blkg_rwstat_exit(&tg->stat_bytes);
|
||||
blkg_rwstat_exit(&tg->stat_ios);
|
||||
kfree(tg);
|
||||
call_rcu(&pd->rcu_head, tg_release);
|
||||
}
|
||||
|
||||
static struct throtl_grp *
|
||||
|
|
|
|||
|
|
@ -120,13 +120,13 @@ static void error_inject_removeall(struct gendisk *disk)
|
|||
struct blk_error_inject *inj;
|
||||
|
||||
mutex_lock(&disk->error_injection_lock);
|
||||
clear_bit(GD_ERROR_INJECT, &disk->state);
|
||||
if (test_and_clear_bit(GD_ERROR_INJECT, &disk->state))
|
||||
static_branch_dec(&blk_error_injection_enabled);
|
||||
while ((inj = list_first_entry_or_null(&disk->error_injection_list,
|
||||
struct blk_error_inject, entry))) {
|
||||
list_del_rcu(&inj->entry);
|
||||
kfree_rcu_mightsleep(inj);
|
||||
}
|
||||
static_branch_dec(&blk_error_injection_enabled);
|
||||
mutex_unlock(&disk->error_injection_lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -951,7 +951,7 @@ int blkdev_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
|
|||
u32 cmd_op = cmd->cmd_op;
|
||||
|
||||
/* Read what we need from the SQE on the first issue */
|
||||
if (!(issue_flags & IORING_URING_CMD_REISSUE)) {
|
||||
if (!(cmd->flags & IORING_URING_CMD_REISSUE)) {
|
||||
const struct io_uring_sqe *sqe = cmd->sqe;
|
||||
|
||||
if (unlikely(sqe->ioprio || sqe->__pad1 || sqe->len ||
|
||||
|
|
|
|||
|
|
@ -1300,7 +1300,7 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
|
|||
args->handle, args->offset, args->size);
|
||||
|
||||
if (args->direction == SYNC_DIRECT_FROM_DEVICE)
|
||||
ret = amdxdna_hwctx_sync_debug_bo(abo->client, args->handle);
|
||||
ret = amdxdna_hwctx_sync_debug_bo(client, args->handle);
|
||||
|
||||
put_obj:
|
||||
drm_gem_object_put(gobj);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user